#!/usr/bin/python2.4
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
MIN_IND_ELEMENTS_BOUNCE = 5 # During indexing the progress will be progressive if
# the number of indexing elements is greater then this,
# otherwise it will bounce
import errno
import sys
import time
import pango
import datetime
import traceback
import string
from threading import Thread
from urllib2 import URLError
try:
import gobject
import gtk
import gtk.glade
import pygtk
pygtk.require("2.0")
except ImportError:
sys.exit(1)
nobe = False
try:
import libbe as be
except ImportError:
nobe = True
import pkg.client.progress as progress
import pkg.misc
from pkg.client.retrieve import ManifestRetrievalError
from pkg.client.retrieve import DatastreamRetrievalError
from pkg.client.filelist import FileListRetrievalError
import pkg.client.api_errors as api_errors
from pkg.misc import TransferTimedOutException, TransportException
import pkg.gui.beadmin as beadm
import pkg.gui.misc as gui_misc
import pkg.gui.enumerations as enumerations
ERROR_FORMAT = "%s"
class InstallUpdate(progress.ProgressTracker):
def __init__(self, list_of_packages, parent, api_o,
ips_update = False, action = -1, be_name = None,
parent_name = "", pkg_list = None, main_window = None,
icon_confirm_dialog = None, title = None, web_install = False):
if action == -1:
return
progress.ProgressTracker.__init__(self)
self.web_install = web_install
self.web_updates_list = None
api_o.progresstracker = self
self.api_o = api_o
self.parent = parent
self.be_list = None
self.be_name = be_name
self.parent_name = parent_name
self.ipkg_ipkgui_list = pkg_list
self.icon_confirm_dialog = icon_confirm_dialog
self.title = title
self.w_main_window = main_window
self.ips_update = ips_update
self.list_of_packages = list_of_packages
self.act_phase_last = None
self.action = action
self.canceling = False
self.current_stage_name = None
self.ind_started = None
self.ip = None
self.operations_done = False
self.prev_ind_phase = None
self.prev_pkg = None
self.progress_stop_timer_running = False
self.proposed_be_name = None
self.stages = {
1:[_("Preparing..."), _("Preparation")],
2:[_("Downloading..."), _("Download")],
3:[_("Installing..."), _("Install")],
}
self.stop_bouncing_progress = False
self.stopped_bouncing_progress = True
self.update_list = {}
gladefile = os.path.join(self.parent.application_dir,
"usr/share/package-manager/packagemanager.glade")
w_tree_dialog = gtk.glade.XML(gladefile, "createplandialog")
w_tree_uaconfirm = gtk.glade.XML(gladefile, "ua_confirm_dialog")
w_tree_removeconfirm = \
gtk.glade.XML(gladefile, "removeconfirmation")
self.w_dialog = w_tree_dialog.get_widget("createplandialog")
self.w_expander = w_tree_dialog.get_widget("expander3")
self.w_cancel_button = w_tree_dialog.get_widget("cancelcreateplan")
self.w_progressbar = w_tree_dialog.get_widget("createplanprogress")
self.w_details_textview = w_tree_dialog.get_widget("createplantextview")
self.w_removeconfirm_dialog = \
w_tree_removeconfirm.get_widget("removeconfirmation")
w_removeproceed_button = w_tree_removeconfirm.get_widget("remove_proceed")
w_remove_treeview = w_tree_removeconfirm.get_widget("removetreeview")
w_stage2 = w_tree_dialog.get_widget("stage2")
self.w_stages_box = w_tree_dialog.get_widget("stages_box")
self.w_stage1_label = w_tree_dialog.get_widget("label_stage1")
self.w_stage1_icon = w_tree_dialog.get_widget("icon_stage1")
self.w_stage2_label = w_tree_dialog.get_widget("label_stage2")
self.w_stage2_icon = w_tree_dialog.get_widget("icon_stage2")
self.w_stage3_label = w_tree_dialog.get_widget("label_stage3")
self.w_stage3_icon = w_tree_dialog.get_widget("icon_stage3")
self.w_stages_label = w_tree_dialog.get_widget("label_stages")
self.w_stages_icon = w_tree_dialog.get_widget("icon_stages")
self.current_stage_label = self.w_stage1_label
self.current_stage_icon = self.w_stage1_icon
self.current_stage_label_done = None
self.done_icon = gui_misc.get_icon(
self.parent.icon_theme, "progress_checkmark")
blank_icon = gui_misc.get_icon(
self.parent.icon_theme, "progress_blank")
self.w_stage1_icon.set_from_pixbuf(blank_icon)
self.w_stage2_icon.set_from_pixbuf(blank_icon)
self.w_stage3_icon.set_from_pixbuf(blank_icon)
infobuffer = self.w_details_textview.get_buffer()
infobuffer.create_tag("bold", weight=pango.WEIGHT_BOLD)
infobuffer.create_tag("level1", left_margin=30, right_margin=10)
infobuffer.create_tag("level2", left_margin=50, right_margin=10)
self.w_ua_dialog = w_tree_uaconfirm.get_widget("ua_confirm_dialog")
self.w_ua_error_label = w_tree_uaconfirm.get_widget(
"ua_confirm_error_label")
self.w_ua_proceed_button = w_tree_uaconfirm.get_widget(
"ua_proceed_button")
self.w_ua_be_name_entry = w_tree_uaconfirm.get_widget(
"ua_be_name_entry")
self.w_ua_be_name_box = w_tree_uaconfirm.get_widget(
"ua_be_name_box")
w_ua_proceed_button = w_tree_uaconfirm.get_widget("ua_proceed_button")
self.w_progressbar.set_pulse_step(0.02)
try:
dic_createplan = \
{
"on_cancelcreateplan_clicked": \
self.__on_cancelcreateplan_clicked,
"on_createplandialog_delete_event": \
self.__on_createplandialog_delete,
}
dic_uaconfirm = \
{
"on_ua_cancel_button_clicked": \
self.__on_ua_cancel_button_clicked,
"on_ua_proceed_button_clicked": \
self.__on_ua_proceed_button_clicked,
"on_ua_be_name_entry_changed": \
self.__on_ua_be_name_entry_changed,
"on_ua_help_button_clicked": \
self.__on_ua_help_button_clicked,
}
dic_removeconfirm = \
{
"on_proceed_button_clicked": \
self.__on_remove_proceed_button_clicked,
"on_cancel_button_clicked": \
self.__on_remove_cancel_button_clicked,
}
w_tree_dialog.signal_autoconnect(dic_createplan)
w_tree_uaconfirm.signal_autoconnect(dic_uaconfirm)
w_tree_removeconfirm.signal_autoconnect(dic_removeconfirm)
except AttributeError, error:
print _("GUI will not respond to any event! %s. "
"Check installupdate.py signals") \
% error
self.w_dialog.set_transient_for(self.w_main_window)
self.w_ua_dialog.set_transient_for(self.w_main_window)
if self.icon_confirm_dialog != None:
self.w_ua_dialog.set_icon(self.icon_confirm_dialog)
if self.action == enumerations.REMOVE:
#We are not showing the download stage in the main stage list
self.stages[3] = [_("Removing..."), _("Remove")]
self.w_stage3_label.set_text(self.stages[3][1])
w_stage2.hide()
self.w_dialog.set_title(_("Remove"))
w_removeproceed_button.grab_focus()
cell = gtk.CellRendererText()
remove_column = gtk.TreeViewColumn('Removed')
remove_column.pack_start(cell, True)
remove_column.add_attribute(cell, 'text', 0)
w_remove_treeview.append_column(remove_column)
liststore = gtk.ListStore(str)
for sel_pkg in list_of_packages:
liststore.append([sel_pkg])
w_remove_treeview.set_model(liststore)
w_remove_treeview.expand_all()
self.w_removeconfirm_dialog.show()
elif self.action == enumerations.IMAGE_UPDATE:
self.w_dialog.set_title(_("Update All"))
w_ua_proceed_button.grab_focus()
if not self.be_name:
if nobe or not "beVerifyBEName" in be.__dict__:
self.w_ua_be_name_box.set_property(
"visible", False)
else:
self.__setup_be_list()
self.w_ua_dialog.show()
else:
self.proposed_be_name = self.be_name
self.__proceed_with_stages()
else:
if self.title != None:
self.w_dialog.set_title(self.title)
else:
self.w_dialog.set_title(_("Install/Update"))
self.__proceed_with_stages()
def __on_createplandialog_delete(self, widget, event):
self.__on_cancelcreateplan_clicked(None)
return True
def __on_cancelcreateplan_clicked(self, widget):
'''Handler for signal send by cancel button, which user might press during
evaluation stage - while the dialog is creating plan'''
if self.api_o.can_be_canceled():
self.canceling = True
Thread(target = self.api_o.cancel, args = ()).start()
cancel_txt = _("Canceling...")
txt = "" + self.current_stage_label_done + " - " \
+ cancel_txt + ""
gobject.idle_add(self.current_stage_label.set_markup, txt)
gobject.idle_add(self.current_stage_icon.set_from_stock,
gtk.STOCK_CANCEL, gtk.ICON_SIZE_MENU)
gobject.idle_add(self.w_stages_label.set_markup, cancel_txt)
self.w_cancel_button.set_sensitive(False)
if self.operations_done:
self.w_dialog.hide()
if self.web_install:
gobject.idle_add(self.parent.update_package_list,
self.web_updates_list)
return
gobject.idle_add(self.parent.update_package_list, None)
def __on_ua_help_button_clicked(self, widget):
gui_misc.display_help(self.parent.application_dir, "update_all")
def __on_ua_cancel_button_clicked(self, widget):
self.w_ua_dialog.hide()
if self.web_install:
gobject.idle_add(self.parent.update_package_list,
self.web_updates_list)
return
gobject.idle_add(self.parent.update_package_list, None)
def __on_ua_proceed_button_clicked(self, widget):
proposed_be_name = self.w_ua_be_name_entry.get_text()
if proposed_be_name != "":
self.proposed_be_name = proposed_be_name
self.w_ua_dialog.hide()
self.__proceed_with_stages()
def __setup_be_list(self):
be_list = be.beList()
error_code = None
if len(be_list) > 1 and type(be_list[0]) == type(-1):
error_code = be_list[0]
if error_code != None and error_code == 0:
self.be_list = be_list[1]
elif error_code == None:
self.be_list = be_list
# Now set proposed name in entry field.
active_name = None
for bee in self.be_list:
name = bee.get("orig_be_name")
if name:
if bee.get("active"):
active_name = name
break
if active_name != None:
proposed_name = None
list = string.rsplit(active_name, '-', 1)
if len(list) == 1:
proposed_name = self.__construct_be_name(
active_name, 0)
else:
try:
i = int(list[1])
proposed_name = self.__construct_be_name(
list[0], i)
except ValueError:
proposed_name = self.__construct_be_name(
active_name, 0)
if proposed_name != None:
self.w_ua_be_name_entry.set_text(proposed_name)
def __construct_be_name(self, name, i):
in_use = True
proposed_name = None
while in_use:
i += 1
proposed_name = name + '-' + str(i)
in_use = self.__is_be_name_in_use(proposed_name)
return proposed_name
def __is_be_name_in_use(self, name):
in_use = False
if name == "":
return in_use
for bee in self.be_list:
be_name = bee.get("orig_be_name")
if be_name == name:
in_use = True
break
return in_use
def __is_be_name_valid(self, name):
if name == "":
return True
return be.beVerifyBEName(name) == 0
def __validate_be_name(self, widget):
name = widget.get_text()
is_name_valid = self.__is_be_name_valid(name)
self.w_ua_error_label.hide()
error_str = None
if is_name_valid:
is_name_in_use = self.__is_be_name_in_use(name)
if is_name_in_use:
error_str = ERROR_FORMAT % _("BE name is in use")
else:
error_str = ERROR_FORMAT % _("BE name is invalid")
if error_str != None:
self.w_ua_error_label.set_markup(error_str)
self.w_ua_error_label.show()
self.w_ua_proceed_button.set_sensitive(error_str == None)
def __on_ua_be_name_entry_changed(self, widget):
self.__validate_be_name(widget)
def __on_remove_cancel_button_clicked(self, widget):
self.w_removeconfirm_dialog.hide()
def __on_remove_proceed_button_clicked(self, widget):
self.w_removeconfirm_dialog.hide()
self.__proceed_with_stages()
def __ipkg_ipkgui_uptodate(self):
if self.ipkg_ipkgui_list == None:
return True
upgrade_needed, cre = self.api_o.plan_install(
self.ipkg_ipkgui_list, filters = [])
return not upgrade_needed
def __proceed_with_stages(self):
self.__start_stage_one()
self.w_dialog.show()
Thread(target = self.__proceed_with_stages_thread_ex,
args = ()).start()
def __proceed_with_stages_thread_ex(self):
try:
if self.action == enumerations.IMAGE_UPDATE:
self.__start_substage(
_("Ensuring %s is up to date...") % self.parent_name,
bounce_progress=True)
opensolaris_image = True
ips_uptodate = True
notfound = self.__installed_fmris_from_args(
["SUNWipkg", "SUNWcs"])
if notfound:
opensolaris_image = False
if opensolaris_image:
ips_uptodate = self.__ipkg_ipkgui_uptodate()
if not ips_uptodate:
#Do the stuff with installing ipkg ipkggui and
#restart in the special mode
self.ips_update = True
self.__proceed_with_ipkg_thread()
return
else:
self.api_o.reset()
self.__proceed_with_stages_thread()
except api_errors.CertificateError:
self.stop_bouncing_progress = True
msg = _("Accessing this restricted repository failed."
"\nYou either need to register to access this repository,"
"\nthe certificate expired, or you need to accept the"
" repository\ncertificate.")
self.__g_error_stage(msg)
return
except api_errors.PlanCreationException, e:
self.__g_error_stage(str(e))
return
except api_errors.InventoryException, e:
msg = _("Inventory exception:\n")
if e.illegal:
for i in e.illegal:
msg += "\tpkg:\t" + i +"\n"
self.__g_error_stage(msg)
return
except api_errors.CatalogRefreshException, e:
msg = _("Please check the network "
"connection.\nIs the repository accessible?")
if e.message and len(e.message) > 0:
msg = e.message
self.__g_error_stage(msg)
return
except (api_errors.NetworkUnavailableException,
TransferTimedOutException, TransportException, URLError,
ManifestRetrievalError, DatastreamRetrievalError,
FileListRetrievalError), ex:
msg = _("Please check the network "
"connection.\nIs the repository accessible?\n\n"
"%s") % str(ex)
self.__g_error_stage(msg)
return
except api_errors.InvalidDepotResponseException, e:
msg = _("\nUnable to contact a valid package depot. "
"Please check your network\nsettings and "
"attempt to contact the server using a web "
"browser.\n\n%s") % str(e)
self.__g_error_stage(msg)
return
except api_errors.IpkgOutOfDateException:
msg = _("pkg(5) appears to be out of "
"date and should be\nupdated before running "
"Update All.\nPlease update SUNWipkg package")
self.__g_error_stage(msg)
return
except api_errors.NonLeafPackageException, nlpe:
msg = _("Cannot remove:\n\t%s\n"
"Due to the following packages that "
"depend on it:\n") % nlpe[0].get_name()
for pkg_a in nlpe[1]:
msg += "\t" + pkg_a.get_name() + "\n"
self.__g_error_stage(msg)
return
except api_errors.ProblematicPermissionsIndexException, err:
msg = str(err)
msg += _("\nFailure of consistent use of pfexec or gksu when "
"running\n%s is often a source of this problem.") % \
self.parent_name
msg += _("\nTo rebuild index, please use the terminal command:")
msg += _("\n\tpfexec pkg rebuild-index")
self.__g_error_stage(msg)
return
except api_errors.CorruptedIndexException:
msg = _("There was an error during installation. The search\n"
"index is corrupted. You might want try to fix this\n"
"problem by running command:\n"
"\tpfexec pkg rebuild-index")
self.__g_error_stage(msg)
return
except api_errors.ImageUpdateOnLiveImageException:
msg = _("This is an Live Image. The install"
"\noperation can't be performed.")
self.__g_error_stage(msg)
return
except api_errors.PlanMissingException:
msg = _("There was an error during installation.\n"
"The Plan of the operation is missing and the operation\n"
"can't be finished. You might want try to fix this\n"
"problem by restarting %s\n") % self.parent_name
self.__g_error_stage(msg)
return
except api_errors.ImageplanStateException:
msg = _("There was an error during installation.\n"
"The State of the image is incorrect and the operation\n"
"can't be finished. You might want try to fix this\n"
"problem by restarting %s\n") % self.parent_name
self.__g_error_stage(msg)
return
except api_errors.CanceledException:
gobject.idle_add(self.w_dialog.hide)
self.stop_bouncing_progress = True
return
except api_errors.BENamingNotSupported:
msg = _("Specifying BE Name not supported.\n")
self.__g_error_stage(msg)
return
except api_errors.InvalidBENameException:
msg = _("Invalid BE Name: %s.\n") % self.proposed_be_name
self.__g_error_stage(msg)
return
except api_errors.PermissionsException, pex:
msg = str(pex)
self.__g_error_stage(msg)
return
except (api_errors.UnableToCopyBE,
api_errors.UnableToMountBE,
api_errors.BENameGivenOnDeadBE,
api_errors.UnableToRenameBE), ex:
msg = str(ex)
self.__g_error_stage(msg)
return
except Exception, uex:
# We do want to prompt user to load BE admin if there is
# not enough disk space. This error can either come as an
# error within API exception, see bug #7642 or as a standalone
# error, that is why we need to check for both situations.
if ("error" in uex.__dict__ and isinstance(uex.error, OSError)
and ("args" in uex.error.__dict__ and uex.error.args and \
(uex.error.args[0] == errno.EDQUOT or
uex.error.args[0] == errno.ENOSPC))) \
or ("args" in uex.__dict__ and uex.args and (uex.args[0] ==
errno.EDQUOT or uex.args[0] == errno.ENOSPC)):
gobject.idle_add(self.__prompt_to_load_beadm)
gobject.idle_add(self.w_dialog.hide)
self.stop_bouncing_progress = True
else:
traceback_lines = traceback.format_exc().splitlines()
traceback_str = ""
for line in traceback_lines:
traceback_str += line + "\n"
self.__g_exception_stage(traceback_str)
sys.exc_clear()
def __proceed_with_ipkg_thread(self):
self.__start_substage(_("Updating %s") % self.parent_name,
bounce_progress=True)
self.__afterplan_information()
self.prev_pkg = None
self.__start_substage(_("Downloading..."), bounce_progress=False)
self.api_o.prepare()
self.__start_substage(_("Executing..."), bounce_progress=False)
self.api_o.execute_plan()
gobject.idle_add(self.__operations_done)
def __proceed_with_stages_thread(self):
self.__start_substage(
_("Gathering package information, please wait..."))
stuff_todo = self.__plan_stage()
if stuff_todo:
self.__afterplan_information()
self.prev_pkg = None
# The api.prepare() mostly is downloading the files so we are
# Not showing this stage in the main stage dialog. If download
# is necessary, then we are showing it in the details view
if not self.action == enumerations.REMOVE:
self.__start_stage_two()
self.__start_substage(None,
bounce_progress=False)
self.api_o.prepare()
self.__start_stage_three()
self.__start_substage(None,
bounce_progress=False)
self.api_o.execute_plan()
gobject.idle_add(self.__operations_done)
else:
if self.web_install:
gobject.idle_add(self.w_expander.hide)
gobject.idle_add(self.__operations_done,
_("All packages already installed."))
return
msg = None
if self.action == enumerations.INSTALL_UPDATE:
msg = _("Selected package(s) cannot be updated on "
"their own.\nClick Update All to update all packages.")
elif self.action == enumerations.IMAGE_UPDATE:
msg = _("Your system has already been updated.")
self.__g_error_stage(msg)
def __start_stage_one(self):
self.current_stage_label = self.w_stage1_label
self.current_stage_icon = self.w_stage1_icon
self.__start_stage(self.stages.get(1))
self.__g_update_details_text(self.stages.get(1)[0]+"\n", "bold")
def __start_stage_two(self):
# End previous stage
self.__end_stage()
self.current_stage_label = self.w_stage2_label
self.current_stage_icon = self.w_stage2_icon
self.__start_stage(self.stages.get(2))
self.__g_update_details_text(self.stages.get(2)[0]+"\n", "bold")
def __start_stage_three(self):
self.__end_stage()
self.current_stage_label = self.w_stage3_label
self.current_stage_icon = self.w_stage3_icon
self.__start_stage(self.stages.get(3))
self.__g_update_details_text(self.stages.get(3)[0]+"\n", "bold")
def __start_stage(self, stage_text):
self.current_stage_label_done = stage_text[1]
gobject.idle_add(self.current_stage_label.set_markup,
""+stage_text[0]+"")
gobject.idle_add(self.current_stage_icon.set_from_stock,
gtk.STOCK_GO_FORWARD, gtk.ICON_SIZE_MENU)
def __end_stage(self):
gobject.idle_add(self.current_stage_label.set_text,
self.current_stage_label_done)
gobject.idle_add(self.current_stage_icon.set_from_pixbuf, self.done_icon)
def __g_error_stage(self, msg):
if msg == None or len(msg) == 0:
msg = _("No futher information available")
self.operations_done = True
self.stop_bouncing_progress = True
self.__g_update_details_text(_("\nError:\n"), "bold")
self.__g_update_details_text("%s" % msg, "level1")
self.__g_update_details_text("\n")
txt = "" + self.current_stage_label_done + _(" - Failed ")
gobject.idle_add(self.current_stage_label.set_markup, txt)
gobject.idle_add(self.current_stage_icon.set_from_stock,
gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_MENU)
gobject.idle_add(self.w_expander.set_expanded, True)
gobject.idle_add(self.w_cancel_button.set_sensitive, True)
def __g_exception_stage(self, tracebk):
self.operations_done = True
self.stop_bouncing_progress = True
txt = "" + self.current_stage_label_done + _(" - Failed ")
gobject.idle_add(self.current_stage_label.set_markup, txt)
gobject.idle_add(self.current_stage_icon.set_from_stock,
gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_MENU)
msg_1 = _("An unknown error occurred in the %s stage.\n"
"Please let the developers know about this problem\n"
"by filing a bug together with exception value at:\n"
) % self.current_stage_name
msg_2 = _("http://defect.opensolaris.org\n\n")
msg_3 = _("Exception value:\n")
self.__g_update_details_text(_("\nError:\n"), "bold")
self.__g_update_details_text("%s" % msg_1, "level1")
self.__g_update_details_text("%s" % msg_2, "bold", "level2")
if tracebk:
msg = _("Exception traceback:\n")
self.__g_update_details_text("%s" % msg,
"bold","level1")
self.__g_update_details_text("%s\n" % tracebk, "level2")
else:
msg = _("No futher information available")
self.__g_update_details_text("%s\n" % msg, "level2")
gobject.idle_add(self.w_expander.set_expanded, True)
gobject.idle_add(self.w_cancel_button.set_sensitive, True)
def __start_substage(self, text, bounce_progress=True):
if text:
gobject.idle_add(self.__stages_label_set_markup, text)
self.__g_update_details_text(text + "\n")
if bounce_progress:
if self.stopped_bouncing_progress:
self.__start_bouncing_progress()
else:
self.stop_bouncing_progress = True
def __stages_label_set_markup(self, markup_text):
if not self.canceling == True:
self.w_stages_label.set_markup(markup_text)
def __start_bouncing_progress(self):
self.stop_bouncing_progress = False
self.stopped_bouncing_progress = False
Thread(target =
self.__g_progressdialog_progress_pulse).start()
def __g_progressdialog_progress_pulse(self):
while not self.stop_bouncing_progress:
gobject.idle_add(self.w_progressbar.pulse)
time.sleep(0.1)
self.stopped_bouncing_progress = True
def __g_update_details_text(self, text, *tags):
gobject.idle_add(self.__update_details_text, text, *tags)
def __update_details_text(self, text, *tags):
buf = self.w_details_textview.get_buffer()
textiter = buf.get_end_iter()
if tags:
buf.insert_with_tags_by_name(textiter, text, *tags)
else:
buf.insert(textiter, text)
self.w_details_textview.scroll_to_iter(textiter, 0.0)
def __update_download_progress(self, cur_bytes, total_bytes):
prog = float(cur_bytes)/total_bytes
self.w_progressbar.set_fraction(prog)
size_a_str = ""
size_b_str = ""
if cur_bytes >= 0:
size_a_str = pkg.misc.bytes_to_str(cur_bytes)
if total_bytes >= 0:
size_b_str = pkg.misc.bytes_to_str(total_bytes)
c = _("Downloaded %(current)s of %(total)s") % \
{"current" : size_a_str,
"total" : size_b_str}
self.__stages_label_set_markup(c)
def __update_install_progress(self, current, total):
prog = float(current)/total
self.w_progressbar.set_fraction(prog)
def __plan_stage(self):
'''Function which plans the image'''
stuff_to_do = False
if self.action == enumerations.INSTALL_UPDATE:
stuff_to_do, cre = self.api_o.plan_install(
self.list_of_packages, refresh_catalogs = False,
filters = [])
if cre and not cre.succeeded:
# cre is either None or a catalog refresh exception
# which was caught while planning.
raise api_errors.CatalogRefreshException(None, None, None
,_("Catalog refresh failed during install."))
elif self.action == enumerations.REMOVE:
plan_uninstall = self.api_o.plan_uninstall
stuff_to_do = \
plan_uninstall(self.list_of_packages, False, False)
elif self.action == enumerations.IMAGE_UPDATE:
# we are passing force, since we already checked if the
# SUNWipkg and SUNWipkg-gui are up to date.
stuff_to_do, opensolaris_image, cre = \
self.api_o.plan_update_all(sys.argv[0],
refresh_catalogs = False,
noexecute = False, force = True,
be_name = self.proposed_be_name)
if cre and not cre.succeeded:
raise api_errors.CatalogRefreshException(None, None, None
,_("Catalog refresh failed during Update All."))
return stuff_to_do
def __operations_done(self, alternate_done_txt = None):
done_txt = _("Installation completed successfully.")
if self.action == enumerations.REMOVE:
done_txt = _("Packages removed successfully.")
elif self.action == enumerations.IMAGE_UPDATE:
done_txt = _("Packages updated successfully.")
if alternate_done_txt != None:
done_txt = alternate_done_txt
self.w_stages_box.hide()
self.w_stages_icon.set_from_stock(
gtk.STOCK_OK, gtk.ICON_SIZE_DND)
self.w_stages_icon.show()
self.__stages_label_set_markup(done_txt)
self.__update_details_text("\n"+ done_txt, "bold")
self.w_cancel_button.set_label("gtk-close")
self.w_progressbar.hide()
self.stop_bouncing_progress = True
self.operations_done = True
if self.parent != None:
if not self.web_install and not self.ips_update \
and not self.action == enumerations.IMAGE_UPDATE:
self.parent.update_package_list(self.update_list)
if self.web_install:
self.web_updates_list = self.update_list
if self.ips_update:
self.w_dialog.hide()
self.parent.restart_after_ips_update(self.proposed_be_name)
elif self.action == enumerations.IMAGE_UPDATE:
self.w_dialog.hide()
self.parent.shutdown_after_image_update()
def __prompt_to_load_beadm(self):
msgbox = gtk.MessageDialog(parent = self.w_main_window,
buttons = gtk.BUTTONS_OK_CANCEL, flags = gtk.DIALOG_MODAL,
type = gtk.MESSAGE_ERROR,
message_format = _(
"Not enough disk space, the selected action cannot "
"be performed.\n\n"
"Click OK to manage your existing BEs and free up disk space or "
"Cancel to cancel the action."))
msgbox.set_title(_("Not Enough Disk Space"))
result = msgbox.run()
msgbox.destroy()
if result == gtk.RESPONSE_OK:
beadm.Beadmin(self.parent)
def __afterplan_information(self):
install_iter = None
update_iter = None
remove_iter = None
plan = self.api_o.describe().get_changes()
self.__g_update_details_text("\n")
for pkg_plan in plan:
origin_fmri = pkg_plan[0]
destination_fmri = pkg_plan[1]
if origin_fmri and destination_fmri:
if not update_iter:
update_iter = True
txt = _("Packages To Be Updated:\n")
self.__g_update_details_text(txt, "bold")
pkg_a = self.__get_pkgstr_from_pkginfo(destination_fmri)
self.__g_update_details_text(pkg_a+"\n", "level1")
elif not origin_fmri and destination_fmri:
if not install_iter:
install_iter = True
txt = _("Packages To Be Installed:\n")
self.__g_update_details_text(txt, "bold")
pkg_a = self.__get_pkgstr_from_pkginfo(destination_fmri)
self.__g_update_details_text(pkg_a+"\n", "level1")
elif origin_fmri and not destination_fmri:
if not remove_iter:
remove_iter = True
txt = _("Packages To Be Removed:\n")
self.__g_update_details_text(txt, "bold")
pkg_a = self.__get_pkgstr_from_pkginfo(origin_fmri)
self.__g_update_details_text(pkg_a+"\n", "level1")
self.__g_update_details_text("\n")
def __get_pkgstr_from_pkginfo(self, pkginfo):
dt_str = self.get_datetime(pkginfo.packaging_date)
if not dt_str:
dt_str = ""
s_ver = pkginfo.version
s_bran = pkginfo.branch
pkg_name = pkginfo.pkg_stem
pkg_publisher = pkginfo.publisher
if not pkg_publisher in self.update_list:
self.update_list[pkg_publisher] = []
pub_list = self.update_list.get(pkg_publisher)
if not pkg_name in pub_list:
pub_list.append(pkg_name)
l_ver = 0
version_pref = ""
while l_ver < len(s_ver) -1:
version_pref += "%d%s" % (s_ver[l_ver],".")
l_ver += 1
version_pref += "%d%s" % (s_ver[l_ver],"-")
l_ver = 0
version_suf = ""
if s_bran != None:
while l_ver < len(s_bran) -1:
version_suf += "%d%s" % (s_bran[l_ver],".")
l_ver += 1
version_suf += "%d" % s_bran[l_ver]
pkg_version = version_pref + version_suf + dt_str
return pkg_name + "@" + pkg_version
def act_output(self):
if self.act_phase != self.act_phase_last:
self.act_phase_last = self.act_phase
gobject.idle_add(self.__stages_label_set_markup, self.act_phase)
self.__g_update_details_text(_("%s\n") % self.act_phase, "level1")
gobject.idle_add(self.__update_install_progress,
self.act_cur_nactions, self.act_goal_nactions)
return
def act_output_done(self):
return
def cat_output_start(self):
return
def cat_output_done(self):
return
def cache_cats_output_start(self):
return
def cache_cats_output_done(self):
return
def load_cat_cache_output_start(self):
return
def load_cat_cache_output_done(self):
return
def dl_output(self):
gobject.idle_add(self.__update_download_progress, \
self.dl_cur_nbytes, self.dl_goal_nbytes)
if self.prev_pkg != self.dl_cur_pkg:
self.prev_pkg = self.dl_cur_pkg
self.__g_update_details_text(
_("Package %d of %d: %s\n") % (self.dl_cur_npkgs+1,
self.dl_goal_npkgs, self.dl_cur_pkg), "level1")
def dl_output_done(self):
self.__g_update_details_text("\n")
def eval_output_start(self):
'''Called by progress tracker when the evaluation of the packages just
started.'''
return
def eval_output_progress(self):
'''Called by progress tracker each time some package was evaluated. The
call is being done by calling progress tracker evaluate_progress()
function'''
if self.prev_pkg != self.eval_cur_fmri:
self.prev_pkg = self.eval_cur_fmri
self.__g_update_details_text("%s\n" % self.eval_cur_fmri,
"level1")
text = _("Evaluating: %s") % self.eval_cur_fmri.get_name()
gobject.idle_add(self.__stages_label_set_markup, text)
def eval_output_done(self):
return
def ind_output(self):
if self.ind_started != self.ind_phase:
self.ind_started = self.ind_phase
gobject.idle_add(self.__stages_label_set_markup, self.ind_phase)
self.__g_update_details_text(
_("%s\n") % (self.ind_phase), "level1")
gobject.idle_add(self.__indexing_progress)
def __indexing_progress(self):
#It doesn't look nice if the progressive is just for few elements
if self.ind_goal_nitems > MIN_IND_ELEMENTS_BOUNCE:
gobject.idle_add(self.__update_install_progress,
self.ind_cur_nitems-1, self.ind_goal_nitems)
else:
if self.stopped_bouncing_progress:
self.__start_bouncing_progress()
def ind_output_done(self):
gobject.idle_add(self.__update_install_progress, self.ind_cur_nitems,
self.ind_goal_nitems)
def ver_output(self):
return
def ver_output_error(self, actname, errors):
return
@staticmethod
def get_datetime(date_time):
'''Support function for getting date from the API.'''
date_tmp = None
try:
date_tmp = time.strptime(date_time, "%a %b %d %H:%M:%S %Y")
except ValueError:
return None
if date_tmp:
date_tmp2 = datetime.datetime(*date_tmp[0:5])
return date_tmp2.strftime(":%m%d")
return None
def __installed_fmris_from_args(self, args_f):
found = []
notfound = []
try:
for m in self.api_o.img.inventory(args_f):
found.append(m[0])
except api_errors.InventoryException, e:
notfound = e.notfound
return notfound