Print this page
*** NO COMMENTS ***
| Split |
Close |
| Expand all |
| Collapse all |
--- old/src/gui/modules/installupdate.py
+++ new/src/gui/modules/installupdate.py
1 1 #!/usr/bin/python2.4
2 2 #
3 3 # CDDL HEADER START
4 4 #
5 5 # The contents of this file are subject to the terms of the
6 6 # Common Development and Distribution License (the "License").
7 7 # You may not use this file except in compliance with the License.
8 8 #
9 9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 # or http://www.opensolaris.org/os/licensing.
11 11 # See the License for the specific language governing permissions
12 12 # and limitations under the License.
13 13 #
14 14 # When distributing Covered Code, include this CDDL HEADER in each
15 15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 # If applicable, add the following below this CDDL HEADER, with the
17 17 # fields enclosed by brackets "[]" replaced with your own identifying
18 18 # information: Portions Copyright [yyyy] [name of copyright owner]
19 19 #
20 20 # CDDL HEADER END
21 21 #
22 22 # Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 # Use is subject to license terms.
24 24 #
25 25
26 26 MIN_IND_ELEMENTS_BOUNCE = 5 # During indexing the progress will be progressive if
27 27 # the number of indexing elements is greater then this,
28 28 # otherwise it will bounce
29 29
30 30 import errno
31 31 import os
32 32 import sys
33 33 import time
34 34 import pango
35 35 import datetime
36 36 import traceback
37 37 import string
38 38 from threading import Thread
39 39 try:
40 40 import gobject
41 41 import gtk
42 42 import gtk.glade
43 43 import pygtk
44 44 pygtk.require("2.0")
45 45 except ImportError:
46 46 sys.exit(1)
47 47 nobe = False
48 48 try:
49 49 import libbe as be
50 50 except ImportError:
51 51 nobe = True
52 52 import pkg.client.progress as progress
53 53 import pkg.misc
54 54 import pkg.client.api_errors as api_errors
55 55 import pkg.gui.beadmin as beadm
56 56 import pkg.gui.misc as gui_misc
57 57 import pkg.gui.enumerations as enumerations
58 58
59 59 ERROR_FORMAT = "<span color = \"red\">%s</span>"
60 60
61 61
62 62 class InstallUpdate(progress.ProgressTracker):
63 63 def __init__(self, list_of_packages, parent, api_o,
64 64 ips_update = False, action = -1, be_name = None,
65 65 parent_name = "", pkg_list = None, main_window = None,
66 66 icon_confirm_dialog = None, title = None, web_install = False):
67 67 if action == -1:
68 68 return
69 69 progress.ProgressTracker.__init__(self)
70 70 self.web_install = web_install
71 71 self.web_updates_list = None
72 72 api_o.progresstracker = self
73 73 self.api_o = api_o
74 74 self.parent = parent
75 75 self.be_list = None
76 76 self.be_name = be_name
77 77 self.parent_name = parent_name
78 78 self.ipkg_ipkgui_list = pkg_list
79 79 self.icon_confirm_dialog = icon_confirm_dialog
80 80 self.title = title
81 81 self.w_main_window = main_window
82 82 self.ips_update = ips_update
83 83 self.list_of_packages = list_of_packages
84 84 self.act_phase_last = None
85 85 self.action = action
86 86 self.canceling = False
87 87 self.current_stage_name = None
88 88 self.ind_started = None
89 89 self.ip = None
90 90 self.operations_done = False
91 91 self.prev_ind_phase = None
92 92 self.prev_pkg = None
93 93 self.progress_stop_timer_running = False
94 94 self.proposed_be_name = None
95 95 self.stages = {
96 96 1:[_("Preparing..."), _("Preparation")],
97 97 2:[_("Downloading..."), _("Download")],
98 98 3:[_("Installing..."), _("Install")],
99 99 }
100 100 self.stop_bouncing_progress = False
101 101 self.stopped_bouncing_progress = True
102 102 self.update_list = {}
103 103 gladefile = os.path.join(self.parent.application_dir,
104 104 "usr/share/package-manager/packagemanager.glade")
105 105 w_tree_dialog = gtk.glade.XML(gladefile, "createplandialog")
106 106 w_tree_uaconfirm = gtk.glade.XML(gladefile, "ua_confirm_dialog")
107 107 w_tree_removeconfirm = \
108 108 gtk.glade.XML(gladefile, "removeconfirmation")
109 109 self.w_dialog = w_tree_dialog.get_widget("createplandialog")
110 110 self.w_expander = w_tree_dialog.get_widget("expander3")
111 111 self.w_cancel_button = w_tree_dialog.get_widget("cancelcreateplan")
112 112 self.w_progressbar = w_tree_dialog.get_widget("createplanprogress")
113 113 self.w_details_textview = w_tree_dialog.get_widget("createplantextview")
114 114 self.w_removeconfirm_dialog = \
115 115 w_tree_removeconfirm.get_widget("removeconfirmation")
116 116 w_removeproceed_button = w_tree_removeconfirm.get_widget("remove_proceed")
117 117 w_remove_treeview = w_tree_removeconfirm.get_widget("removetreeview")
118 118 w_stage2 = w_tree_dialog.get_widget("stage2")
119 119 self.w_stages_box = w_tree_dialog.get_widget("stages_box")
120 120 self.w_stage1_label = w_tree_dialog.get_widget("label_stage1")
121 121 self.w_stage1_icon = w_tree_dialog.get_widget("icon_stage1")
122 122 self.w_stage2_label = w_tree_dialog.get_widget("label_stage2")
123 123 self.w_stage2_icon = w_tree_dialog.get_widget("icon_stage2")
124 124 self.w_stage3_label = w_tree_dialog.get_widget("label_stage3")
125 125 self.w_stage3_icon = w_tree_dialog.get_widget("icon_stage3")
126 126 self.w_stages_label = w_tree_dialog.get_widget("label_stages")
127 127 self.w_stages_icon = w_tree_dialog.get_widget("icon_stages")
128 128 self.current_stage_label = self.w_stage1_label
129 129 self.current_stage_icon = self.w_stage1_icon
130 130 self.current_stage_label_done = None
131 131
132 132 self.done_icon = gui_misc.get_icon(
133 133 self.parent.icon_theme, "progress_checkmark")
134 134 blank_icon = gui_misc.get_icon(
135 135 self.parent.icon_theme, "progress_blank")
136 136
137 137 self.w_stage1_icon.set_from_pixbuf(blank_icon)
138 138 self.w_stage2_icon.set_from_pixbuf(blank_icon)
139 139 self.w_stage3_icon.set_from_pixbuf(blank_icon)
140 140
141 141 infobuffer = self.w_details_textview.get_buffer()
142 142 infobuffer.create_tag("bold", weight=pango.WEIGHT_BOLD)
143 143 infobuffer.create_tag("level1", left_margin=30, right_margin=10)
144 144 infobuffer.create_tag("level2", left_margin=50, right_margin=10)
145 145 self.w_ua_dialog = w_tree_uaconfirm.get_widget("ua_confirm_dialog")
146 146 self.w_ua_error_label = w_tree_uaconfirm.get_widget(
147 147 "ua_confirm_error_label")
148 148 self.w_ua_proceed_button = w_tree_uaconfirm.get_widget(
149 149 "ua_proceed_button")
150 150 self.w_ua_be_name_entry = w_tree_uaconfirm.get_widget(
151 151 "ua_be_name_entry")
152 152 self.w_ua_be_name_box = w_tree_uaconfirm.get_widget(
153 153 "ua_be_name_box")
154 154
155 155 w_ua_proceed_button = w_tree_uaconfirm.get_widget("ua_proceed_button")
156 156 self.w_progressbar.set_pulse_step(0.02)
157 157 try:
158 158 dic_createplan = \
159 159 {
160 160 "on_cancelcreateplan_clicked": \
161 161 self.__on_cancelcreateplan_clicked,
162 162 "on_createplandialog_delete_event": \
163 163 self.__on_createplandialog_delete,
164 164 }
165 165 dic_uaconfirm = \
166 166 {
167 167 "on_ua_cancel_button_clicked": \
168 168 self.__on_ua_cancel_button_clicked,
169 169 "on_ua_proceed_button_clicked": \
170 170 self.__on_ua_proceed_button_clicked,
171 171 "on_ua_be_name_entry_changed": \
172 172 self.__on_ua_be_name_entry_changed,
173 173 "on_ua_help_button_clicked": \
174 174 self.__on_ua_help_button_clicked,
175 175 }
176 176 dic_removeconfirm = \
177 177 {
178 178 "on_proceed_button_clicked": \
179 179 self.__on_remove_proceed_button_clicked,
180 180 "on_cancel_button_clicked": \
181 181 self.__on_remove_cancel_button_clicked,
182 182 }
183 183 w_tree_dialog.signal_autoconnect(dic_createplan)
184 184 w_tree_uaconfirm.signal_autoconnect(dic_uaconfirm)
185 185 w_tree_removeconfirm.signal_autoconnect(dic_removeconfirm)
186 186 except AttributeError, error:
187 187 print _("GUI will not respond to any event! %s. "
188 188 "Check installupdate.py signals") \
189 189 % error
190 190
191 191
192 192 self.w_dialog.set_transient_for(self.w_main_window)
193 193 self.w_ua_dialog.set_transient_for(self.w_main_window)
194 194 if self.icon_confirm_dialog != None:
195 195 self.w_ua_dialog.set_icon(self.icon_confirm_dialog)
196 196
197 197 if self.action == enumerations.REMOVE:
198 198 #We are not showing the download stage in the main stage list
199 199 self.stages[3] = [_("Removing..."), _("Remove")]
200 200 self.w_stage3_label.set_text(self.stages[3][1])
201 201 w_stage2.hide()
202 202 self.w_dialog.set_title(_("Remove"))
203 203 w_removeproceed_button.grab_focus()
204 204 cell = gtk.CellRendererText()
205 205 remove_column = gtk.TreeViewColumn('Removed')
206 206 remove_column.pack_start(cell, True)
207 207 remove_column.add_attribute(cell, 'text', 0)
208 208 w_remove_treeview.append_column(remove_column)
209 209
210 210 liststore = gtk.ListStore(str)
211 211 for sel_pkg in list_of_packages:
212 212 liststore.append([sel_pkg])
213 213 w_remove_treeview.set_model(liststore)
214 214 w_remove_treeview.expand_all()
215 215 self.w_removeconfirm_dialog.show()
216 216
217 217 elif self.action == enumerations.IMAGE_UPDATE:
218 218 self.w_dialog.set_title(_("Update All"))
219 219 w_ua_proceed_button.grab_focus()
220 220 if not self.be_name:
221 221 if nobe or not "beVerifyBEName" in be.__dict__:
222 222 self.w_ua_be_name_box.set_property(
223 223 "visible", False)
224 224 else:
225 225 self.__setup_be_list()
226 226 self.w_ua_dialog.show()
227 227 else:
228 228 self.proposed_be_name = self.be_name
229 229 self.__proceed_with_stages()
230 230 else:
231 231 if self.title != None:
232 232 self.w_dialog.set_title(self.title)
233 233 else:
234 234 self.w_dialog.set_title(_("Install/Update"))
235 235 self.__proceed_with_stages()
236 236
237 237
238 238 def __on_createplandialog_delete(self, widget, event):
239 239 self.__on_cancelcreateplan_clicked(None)
240 240 return True
241 241
242 242 def __on_cancelcreateplan_clicked(self, widget):
243 243 '''Handler for signal send by cancel button, which user might press during
244 244 evaluation stage - while the dialog is creating plan'''
245 245 if self.api_o.can_be_canceled():
246 246 self.canceling = True
247 247 Thread(target = self.api_o.cancel, args = ()).start()
248 248 cancel_txt = _("Canceling...")
249 249 txt = "<b>" + self.current_stage_label_done + " - " \
250 250 + cancel_txt + "</b>"
251 251 gobject.idle_add(self.current_stage_label.set_markup, txt)
252 252 gobject.idle_add(self.current_stage_icon.set_from_stock,
253 253 gtk.STOCK_CANCEL, gtk.ICON_SIZE_MENU)
254 254 gobject.idle_add(self.w_stages_label.set_markup, cancel_txt)
255 255 self.w_cancel_button.set_sensitive(False)
256 256 if self.operations_done:
257 257 self.w_dialog.hide()
258 258 if self.web_install:
259 259 gobject.idle_add(self.parent.update_package_list,
260 260 self.web_updates_list)
261 261 return
262 262 gobject.idle_add(self.parent.update_package_list, None)
263 263
264 264 def __on_ua_help_button_clicked(self, widget):
265 265 gui_misc.display_help(self.parent.application_dir, "update_all")
266 266
267 267 def __on_ua_cancel_button_clicked(self, widget):
268 268 self.w_ua_dialog.hide()
269 269 if self.web_install:
270 270 gobject.idle_add(self.parent.update_package_list,
271 271 self.web_updates_list)
272 272 return
273 273 gobject.idle_add(self.parent.update_package_list, None)
274 274
275 275 def __on_ua_proceed_button_clicked(self, widget):
276 276 proposed_be_name = self.w_ua_be_name_entry.get_text()
277 277 if proposed_be_name != "":
278 278 self.proposed_be_name = proposed_be_name
279 279 self.w_ua_dialog.hide()
280 280 self.__proceed_with_stages()
281 281
282 282 def __setup_be_list(self):
283 283 be_list = be.beList()
284 284 error_code = None
285 285 if len(be_list) > 1 and type(be_list[0]) == type(-1):
286 286 error_code = be_list[0]
287 287 if error_code != None and error_code == 0:
288 288 self.be_list = be_list[1]
289 289 elif error_code == None:
290 290 self.be_list = be_list
291 291
292 292 # Now set proposed name in entry field.
293 293 active_name = None
294 294 for bee in self.be_list:
295 295 name = bee.get("orig_be_name")
296 296 if name:
297 297 if bee.get("active"):
298 298 active_name = name
299 299 break
300 300 if active_name != None:
301 301 proposed_name = None
302 302 list = string.rsplit(active_name, '-', 1)
303 303 if len(list) == 1:
304 304 proposed_name = self.__construct_be_name(
305 305 active_name, 0)
306 306 else:
307 307 try:
308 308 i = int(list[1])
309 309 proposed_name = self.__construct_be_name(
310 310 list[0], i)
311 311 except ValueError:
312 312 proposed_name = self.__construct_be_name(
313 313 active_name, 0)
314 314
315 315 if proposed_name != None:
316 316 self.w_ua_be_name_entry.set_text(proposed_name)
317 317
318 318
319 319 def __construct_be_name(self, name, i):
320 320 in_use = True
321 321 proposed_name = None
322 322 while in_use:
323 323 i += 1
324 324 proposed_name = name + '-' + str(i)
325 325 in_use = self.__is_be_name_in_use(proposed_name)
326 326 return proposed_name
327 327
328 328 def __is_be_name_in_use(self, name):
329 329 in_use = False
330 330 if name == "":
331 331 return in_use
332 332 for bee in self.be_list:
333 333 be_name = bee.get("orig_be_name")
334 334 if be_name == name:
335 335 in_use = True
336 336 break
337 337 return in_use
338 338
339 339 def __is_be_name_valid(self, name):
340 340 if name == "":
341 341 return True
342 342 return be.beVerifyBEName(name) == 0
343 343
344 344 def __validate_be_name(self, widget):
345 345 name = widget.get_text()
346 346 is_name_valid = self.__is_be_name_valid(name)
347 347 self.w_ua_error_label.hide()
348 348 error_str = None
349 349 if is_name_valid:
350 350 is_name_in_use = self.__is_be_name_in_use(name)
351 351 if is_name_in_use:
352 352 error_str = ERROR_FORMAT % _("BE name is in use")
353 353 else:
354 354 error_str = ERROR_FORMAT % _("BE name is invalid")
355 355 if error_str != None:
356 356 self.w_ua_error_label.set_markup(error_str)
357 357 self.w_ua_error_label.show()
358 358
359 359 self.w_ua_proceed_button.set_sensitive(error_str == None)
360 360
361 361 def __on_ua_be_name_entry_changed(self, widget):
362 362 self.__validate_be_name(widget)
363 363
364 364 def __on_remove_cancel_button_clicked(self, widget):
365 365 self.w_removeconfirm_dialog.hide()
366 366
367 367 def __on_remove_proceed_button_clicked(self, widget):
368 368 self.w_removeconfirm_dialog.hide()
369 369 self.__proceed_with_stages()
370 370
371 371 def __ipkg_ipkgui_uptodate(self):
372 372 if self.ipkg_ipkgui_list == None:
373 373 return True
374 374 upgrade_needed, cre = self.api_o.plan_install(
375 375 self.ipkg_ipkgui_list, filters = [])
376 376 return not upgrade_needed
377 377
378 378 def __proceed_with_stages(self):
379 379 self.__start_stage_one()
380 380 self.w_dialog.show()
381 381 Thread(target = self.__proceed_with_stages_thread_ex,
382 382 args = ()).start()
383 383
384 384 def __proceed_with_stages_thread_ex(self):
385 385 try:
386 386 if self.action == enumerations.IMAGE_UPDATE:
387 387 self.__start_substage(
388 388 _("Ensuring %s is up to date...") % self.parent_name,
389 389 bounce_progress=True)
390 390 opensolaris_image = True
391 391 ips_uptodate = True
392 392 notfound = self.__installed_fmris_from_args(
393 393 ["SUNWipkg", "SUNWcs"])
394 394 if notfound:
395 395 opensolaris_image = False
396 396 if opensolaris_image:
|
↓ open down ↓ |
396 lines elided |
↑ open up ↑ |
397 397 ips_uptodate = self.__ipkg_ipkgui_uptodate()
398 398 if not ips_uptodate:
399 399 #Do the stuff with installing ipkg ipkggui and
400 400 #restart in the special mode
401 401 self.ips_update = True
402 402 self.__proceed_with_ipkg_thread()
403 403 return
404 404 else:
405 405 self.api_o.reset()
406 406 self.__proceed_with_stages_thread()
407 - except api_errors.CertificateError:
408 - self.stop_bouncing_progress = True
409 - msg = _("Accessing this restricted repository failed."
410 - "\nYou either need to register to access this repository,"
411 - "\nthe certificate expired, or you need to accept the"
412 - " repository\ncertificate.")
413 - self.__g_error_stage(msg)
407 + except api_errors.CertificateError, e:
408 + self.__g_error_stage(str(e))
414 409 return
415 410 except api_errors.PlanCreationException, e:
416 411 self.__g_error_stage(str(e))
417 412 return
418 413 except api_errors.InventoryException, e:
419 414 msg = _("Inventory exception:\n")
420 415 if e.illegal:
421 416 for i in e.illegal:
422 417 msg += "\tpkg:\t" + i +"\n"
423 418 self.__g_error_stage(msg)
424 419 return
425 420 except api_errors.CatalogRefreshException, e:
426 421 msg = _("Please check the network "
427 422 "connection.\nIs the repository accessible?")
428 423 if e.message and len(e.message) > 0:
429 424 msg = e.message
430 425 self.__g_error_stage(msg)
431 426 return
432 427 except api_errors.TransportError, ex:
433 428 msg = _("Please check the network "
434 429 "connection.\nIs the repository accessible?\n\n"
435 430 "%s") % str(ex)
436 431 self.__g_error_stage(msg)
437 432 return
438 433 except api_errors.InvalidDepotResponseException, e:
439 434 msg = _("\nUnable to contact a valid package depot. "
440 435 "Please check your network\nsettings and "
441 436 "attempt to contact the server using a web "
442 437 "browser.\n\n%s") % str(e)
443 438 self.__g_error_stage(msg)
444 439 return
445 440 except api_errors.IpkgOutOfDateException:
446 441 msg = _("pkg(5) appears to be out of "
447 442 "date and should be\nupdated before running "
448 443 "Update All.\nPlease update SUNWipkg package")
449 444 self.__g_error_stage(msg)
450 445 return
451 446 except api_errors.NonLeafPackageException, nlpe:
452 447 msg = _("Cannot remove:\n\t%s\n"
453 448 "Due to the following packages that "
454 449 "depend on it:\n") % nlpe[0].get_name()
455 450 for pkg_a in nlpe[1]:
456 451 msg += "\t" + pkg_a.get_name() + "\n"
457 452 self.__g_error_stage(msg)
458 453 return
459 454 except api_errors.ProblematicPermissionsIndexException, err:
460 455 msg = str(err)
461 456 msg += _("\nFailure of consistent use of pfexec or gksu when "
462 457 "running\n%s is often a source of this problem.") % \
463 458 self.parent_name
464 459 msg += _("\nTo rebuild index, please use the terminal command:")
465 460 msg += _("\n\tpfexec pkg rebuild-index")
466 461 self.__g_error_stage(msg)
467 462 return
468 463 except api_errors.CorruptedIndexException:
469 464 msg = _("There was an error during installation. The search\n"
470 465 "index is corrupted. You might want try to fix this\n"
471 466 "problem by running command:\n"
472 467 "\tpfexec pkg rebuild-index")
473 468 self.__g_error_stage(msg)
474 469 return
475 470 except api_errors.ImageUpdateOnLiveImageException:
476 471 msg = _("This is an Live Image. The install"
477 472 "\noperation can't be performed.")
478 473 self.__g_error_stage(msg)
479 474 return
480 475 except api_errors.PlanMissingException:
481 476 msg = _("There was an error during installation.\n"
482 477 "The Plan of the operation is missing and the operation\n"
483 478 "can't be finished. You might want try to fix this\n"
484 479 "problem by restarting %s\n") % self.parent_name
485 480 self.__g_error_stage(msg)
486 481 return
487 482 except api_errors.ImageplanStateException:
488 483 msg = _("There was an error during installation.\n"
489 484 "The State of the image is incorrect and the operation\n"
490 485 "can't be finished. You might want try to fix this\n"
491 486 "problem by restarting %s\n") % self.parent_name
492 487 self.__g_error_stage(msg)
493 488 return
494 489 except api_errors.CanceledException:
495 490 gobject.idle_add(self.w_dialog.hide)
496 491 self.stop_bouncing_progress = True
497 492 return
498 493 except api_errors.BENamingNotSupported:
499 494 msg = _("Specifying BE Name not supported.\n")
500 495 self.__g_error_stage(msg)
501 496 return
502 497 except api_errors.InvalidBENameException:
503 498 msg = _("Invalid BE Name: %s.\n") % self.proposed_be_name
504 499 self.__g_error_stage(msg)
505 500 return
506 501 except api_errors.PermissionsException, pex:
507 502 msg = str(pex)
508 503 self.__g_error_stage(msg)
509 504 return
510 505 except (api_errors.UnableToCopyBE,
511 506 api_errors.UnableToMountBE,
512 507 api_errors.BENameGivenOnDeadBE,
513 508 api_errors.UnableToRenameBE), ex:
514 509 msg = str(ex)
515 510 self.__g_error_stage(msg)
516 511 return
517 512 except Exception, uex:
518 513 # We do want to prompt user to load BE admin if there is
519 514 # not enough disk space. This error can either come as an
520 515 # error within API exception, see bug #7642 or as a standalone
521 516 # error, that is why we need to check for both situations.
522 517 if ("error" in uex.__dict__ and isinstance(uex.error, OSError)
523 518 and ("args" in uex.error.__dict__ and uex.error.args and \
524 519 (uex.error.args[0] == errno.EDQUOT or
525 520 uex.error.args[0] == errno.ENOSPC))) \
526 521 or ("args" in uex.__dict__ and uex.args and (uex.args[0] ==
527 522 errno.EDQUOT or uex.args[0] == errno.ENOSPC)):
528 523 gobject.idle_add(self.__prompt_to_load_beadm)
529 524 gobject.idle_add(self.w_dialog.hide)
530 525 self.stop_bouncing_progress = True
531 526 else:
532 527 traceback_lines = traceback.format_exc().splitlines()
533 528 traceback_str = ""
534 529 for line in traceback_lines:
535 530 traceback_str += line + "\n"
536 531 self.__g_exception_stage(traceback_str)
537 532 sys.exc_clear()
538 533
539 534 def __proceed_with_ipkg_thread(self):
540 535 self.__start_substage(_("Updating %s") % self.parent_name,
541 536 bounce_progress=True)
542 537 self.__afterplan_information()
543 538 self.prev_pkg = None
544 539 self.__start_substage(_("Downloading..."), bounce_progress=False)
545 540 self.api_o.prepare()
546 541 self.__start_substage(_("Executing..."), bounce_progress=False)
547 542 self.api_o.execute_plan()
548 543 gobject.idle_add(self.__operations_done)
549 544
550 545
551 546 def __proceed_with_stages_thread(self):
552 547 self.__start_substage(
553 548 _("Gathering package information, please wait..."))
554 549 stuff_todo = self.__plan_stage()
555 550 if stuff_todo:
556 551 self.__afterplan_information()
557 552 self.prev_pkg = None
558 553 # The api.prepare() mostly is downloading the files so we are
559 554 # Not showing this stage in the main stage dialog. If download
560 555 # is necessary, then we are showing it in the details view
561 556 if not self.action == enumerations.REMOVE:
562 557 self.__start_stage_two()
563 558 self.__start_substage(None,
564 559 bounce_progress=False)
565 560 self.api_o.prepare()
566 561 self.__start_stage_three()
567 562 self.__start_substage(None,
568 563 bounce_progress=False)
569 564 self.api_o.execute_plan()
570 565 gobject.idle_add(self.__operations_done)
571 566 else:
572 567 if self.web_install:
573 568 gobject.idle_add(self.w_expander.hide)
574 569 gobject.idle_add(self.__operations_done,
575 570 _("All packages already installed."))
576 571 return
577 572
578 573 msg = None
579 574 if self.action == enumerations.INSTALL_UPDATE:
580 575 msg = _("Selected package(s) cannot be updated on "
581 576 "their own.\nClick Update All to update all packages.")
582 577 elif self.action == enumerations.IMAGE_UPDATE:
583 578 msg = _("Your system has already been updated.")
584 579 self.__g_error_stage(msg)
585 580
586 581 def __start_stage_one(self):
587 582 self.current_stage_label = self.w_stage1_label
588 583 self.current_stage_icon = self.w_stage1_icon
589 584 self.__start_stage(self.stages.get(1))
590 585 self.__g_update_details_text(self.stages.get(1)[0]+"\n", "bold")
591 586
592 587 def __start_stage_two(self):
593 588 # End previous stage
594 589 self.__end_stage()
595 590 self.current_stage_label = self.w_stage2_label
596 591 self.current_stage_icon = self.w_stage2_icon
597 592 self.__start_stage(self.stages.get(2))
598 593 self.__g_update_details_text(self.stages.get(2)[0]+"\n", "bold")
599 594
600 595 def __start_stage_three(self):
601 596 self.__end_stage()
602 597 self.current_stage_label = self.w_stage3_label
603 598 self.current_stage_icon = self.w_stage3_icon
604 599 self.__start_stage(self.stages.get(3))
605 600 self.__g_update_details_text(self.stages.get(3)[0]+"\n", "bold")
606 601
607 602 def __start_stage(self, stage_text):
608 603 self.current_stage_label_done = stage_text[1]
609 604 gobject.idle_add(self.current_stage_label.set_markup,
610 605 "<b>"+stage_text[0]+"</b>")
611 606 gobject.idle_add(self.current_stage_icon.set_from_stock,
612 607 gtk.STOCK_GO_FORWARD, gtk.ICON_SIZE_MENU)
613 608
614 609 def __end_stage(self):
615 610 gobject.idle_add(self.current_stage_label.set_text,
616 611 self.current_stage_label_done)
617 612 gobject.idle_add(self.current_stage_icon.set_from_pixbuf, self.done_icon)
618 613
619 614 def __g_error_stage(self, msg):
620 615 if msg == None or len(msg) == 0:
621 616 msg = _("No futher information available")
622 617 self.operations_done = True
623 618 self.stop_bouncing_progress = True
624 619 self.__g_update_details_text(_("\nError:\n"), "bold")
625 620 self.__g_update_details_text("%s" % msg, "level1")
626 621 self.__g_update_details_text("\n")
627 622 txt = "<b>" + self.current_stage_label_done + _(" - Failed </b>")
628 623 gobject.idle_add(self.current_stage_label.set_markup, txt)
629 624 gobject.idle_add(self.current_stage_icon.set_from_stock,
630 625 gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_MENU)
631 626 gobject.idle_add(self.w_expander.set_expanded, True)
632 627 gobject.idle_add(self.w_cancel_button.set_sensitive, True)
633 628
634 629 def __g_exception_stage(self, tracebk):
635 630 self.operations_done = True
636 631 self.stop_bouncing_progress = True
637 632 txt = "<b>" + self.current_stage_label_done + _(" - Failed </b>")
638 633 gobject.idle_add(self.current_stage_label.set_markup, txt)
639 634 gobject.idle_add(self.current_stage_icon.set_from_stock,
640 635 gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_MENU)
641 636 msg_1 = _("An unknown error occurred in the %s stage.\n"
642 637 "Please let the developers know about this problem\n"
643 638 "by filing a bug together with exception value at:\n"
644 639 ) % self.current_stage_name
645 640 msg_2 = _("http://defect.opensolaris.org\n\n")
646 641 msg_3 = _("Exception value:\n")
647 642 self.__g_update_details_text(_("\nError:\n"), "bold")
648 643 self.__g_update_details_text("%s" % msg_1, "level1")
649 644 self.__g_update_details_text("%s" % msg_2, "bold", "level2")
650 645 if tracebk:
651 646 msg = _("Exception traceback:\n")
652 647 self.__g_update_details_text("%s" % msg,
653 648 "bold","level1")
654 649 self.__g_update_details_text("%s\n" % tracebk, "level2")
655 650 else:
656 651 msg = _("No futher information available")
657 652 self.__g_update_details_text("%s\n" % msg, "level2")
658 653 gobject.idle_add(self.w_expander.set_expanded, True)
659 654 gobject.idle_add(self.w_cancel_button.set_sensitive, True)
660 655
661 656 def __start_substage(self, text, bounce_progress=True):
662 657 if text:
663 658 gobject.idle_add(self.__stages_label_set_markup, text)
664 659 self.__g_update_details_text(text + "\n")
665 660 if bounce_progress:
666 661 if self.stopped_bouncing_progress:
667 662 self.__start_bouncing_progress()
668 663 else:
669 664 self.stop_bouncing_progress = True
670 665
671 666 def __stages_label_set_markup(self, markup_text):
672 667 if not self.canceling == True:
673 668 self.w_stages_label.set_markup(markup_text)
674 669
675 670 def __start_bouncing_progress(self):
676 671 self.stop_bouncing_progress = False
677 672 self.stopped_bouncing_progress = False
678 673 Thread(target =
679 674 self.__g_progressdialog_progress_pulse).start()
680 675
681 676 def __g_progressdialog_progress_pulse(self):
682 677 while not self.stop_bouncing_progress:
683 678 gobject.idle_add(self.w_progressbar.pulse)
684 679 time.sleep(0.1)
685 680 self.stopped_bouncing_progress = True
686 681
687 682 def __g_update_details_text(self, text, *tags):
688 683 gobject.idle_add(self.__update_details_text, text, *tags)
689 684
690 685 def __update_details_text(self, text, *tags):
691 686 buf = self.w_details_textview.get_buffer()
692 687 textiter = buf.get_end_iter()
693 688 if tags:
694 689 buf.insert_with_tags_by_name(textiter, text, *tags)
695 690 else:
696 691 buf.insert(textiter, text)
697 692 self.w_details_textview.scroll_to_iter(textiter, 0.0)
698 693
699 694 def __update_download_progress(self, cur_bytes, total_bytes):
700 695 prog = float(cur_bytes)/total_bytes
701 696 self.w_progressbar.set_fraction(prog)
702 697 size_a_str = ""
703 698 size_b_str = ""
704 699 if cur_bytes >= 0:
705 700 size_a_str = pkg.misc.bytes_to_str(cur_bytes)
706 701 if total_bytes >= 0:
707 702 size_b_str = pkg.misc.bytes_to_str(total_bytes)
708 703 c = _("Downloaded %(current)s of %(total)s") % \
709 704 {"current" : size_a_str,
710 705 "total" : size_b_str}
711 706 self.__stages_label_set_markup(c)
712 707
713 708 def __update_install_progress(self, current, total):
714 709 prog = float(current)/total
715 710 self.w_progressbar.set_fraction(prog)
716 711
717 712 def __plan_stage(self):
718 713 '''Function which plans the image'''
719 714 stuff_to_do = False
720 715 if self.action == enumerations.INSTALL_UPDATE:
721 716 stuff_to_do, cre = self.api_o.plan_install(
722 717 self.list_of_packages, refresh_catalogs = False,
723 718 filters = [])
724 719 if cre and not cre.succeeded:
725 720 # cre is either None or a catalog refresh exception
726 721 # which was caught while planning.
727 722 raise api_errors.CatalogRefreshException(None, None, None
728 723 ,_("Catalog refresh failed during install."))
729 724 elif self.action == enumerations.REMOVE:
730 725 plan_uninstall = self.api_o.plan_uninstall
731 726 stuff_to_do = \
732 727 plan_uninstall(self.list_of_packages, False, False)
733 728 elif self.action == enumerations.IMAGE_UPDATE:
734 729 # we are passing force, since we already checked if the
735 730 # SUNWipkg and SUNWipkg-gui are up to date.
736 731 stuff_to_do, opensolaris_image, cre = \
737 732 self.api_o.plan_update_all(sys.argv[0],
738 733 refresh_catalogs = False,
739 734 noexecute = False, force = True,
740 735 be_name = self.proposed_be_name)
741 736 if cre and not cre.succeeded:
742 737 raise api_errors.CatalogRefreshException(None, None, None
743 738 ,_("Catalog refresh failed during Update All."))
744 739 return stuff_to_do
745 740
746 741 def __operations_done(self, alternate_done_txt = None):
747 742 done_txt = _("Installation completed successfully.")
748 743 if self.action == enumerations.REMOVE:
749 744 done_txt = _("Packages removed successfully.")
750 745 elif self.action == enumerations.IMAGE_UPDATE:
751 746 done_txt = _("Packages updated successfully.")
752 747 if alternate_done_txt != None:
753 748 done_txt = alternate_done_txt
754 749 self.w_stages_box.hide()
755 750 self.w_stages_icon.set_from_stock(
756 751 gtk.STOCK_OK, gtk.ICON_SIZE_DND)
757 752 self.w_stages_icon.show()
758 753 self.__stages_label_set_markup(done_txt)
759 754 self.__update_details_text("\n"+ done_txt, "bold")
760 755 self.w_cancel_button.set_label("gtk-close")
761 756 self.w_progressbar.hide()
762 757 self.stop_bouncing_progress = True
763 758 self.operations_done = True
764 759 if self.parent != None:
765 760 if not self.web_install and not self.ips_update \
766 761 and not self.action == enumerations.IMAGE_UPDATE:
767 762 self.parent.update_package_list(self.update_list)
768 763 if self.web_install:
769 764 self.web_updates_list = self.update_list
770 765 if self.ips_update:
771 766 self.w_dialog.hide()
772 767 self.parent.restart_after_ips_update(self.proposed_be_name)
773 768 elif self.action == enumerations.IMAGE_UPDATE:
774 769 self.w_dialog.hide()
775 770 self.parent.shutdown_after_image_update()
776 771
777 772 def __prompt_to_load_beadm(self):
778 773 msgbox = gtk.MessageDialog(parent = self.w_main_window,
779 774 buttons = gtk.BUTTONS_OK_CANCEL, flags = gtk.DIALOG_MODAL,
780 775 type = gtk.MESSAGE_ERROR,
781 776 message_format = _(
782 777 "Not enough disk space, the selected action cannot "
783 778 "be performed.\n\n"
784 779 "Click OK to manage your existing BEs and free up disk space or "
785 780 "Cancel to cancel the action."))
786 781 msgbox.set_title(_("Not Enough Disk Space"))
787 782 result = msgbox.run()
788 783 msgbox.destroy()
789 784 if result == gtk.RESPONSE_OK:
790 785 beadm.Beadmin(self.parent)
791 786
792 787 def __afterplan_information(self):
793 788 install_iter = None
794 789 update_iter = None
795 790 remove_iter = None
796 791 plan = self.api_o.describe().get_changes()
797 792 self.__g_update_details_text("\n")
798 793 for pkg_plan in plan:
799 794 origin_fmri = pkg_plan[0]
800 795 destination_fmri = pkg_plan[1]
801 796 if origin_fmri and destination_fmri:
802 797 if not update_iter:
803 798 update_iter = True
804 799 txt = _("Packages To Be Updated:\n")
805 800 self.__g_update_details_text(txt, "bold")
806 801 pkg_a = self.__get_pkgstr_from_pkginfo(destination_fmri)
807 802 self.__g_update_details_text(pkg_a+"\n", "level1")
808 803 elif not origin_fmri and destination_fmri:
809 804 if not install_iter:
810 805 install_iter = True
811 806 txt = _("Packages To Be Installed:\n")
812 807 self.__g_update_details_text(txt, "bold")
813 808 pkg_a = self.__get_pkgstr_from_pkginfo(destination_fmri)
814 809 self.__g_update_details_text(pkg_a+"\n", "level1")
815 810 elif origin_fmri and not destination_fmri:
816 811 if not remove_iter:
817 812 remove_iter = True
818 813 txt = _("Packages To Be Removed:\n")
819 814 self.__g_update_details_text(txt, "bold")
820 815 pkg_a = self.__get_pkgstr_from_pkginfo(origin_fmri)
821 816 self.__g_update_details_text(pkg_a+"\n", "level1")
822 817 self.__g_update_details_text("\n")
823 818
824 819 def __get_pkgstr_from_pkginfo(self, pkginfo):
825 820 dt_str = self.get_datetime(pkginfo.packaging_date)
826 821 if not dt_str:
827 822 dt_str = ""
828 823 s_ver = pkginfo.version
829 824 s_bran = pkginfo.branch
830 825 pkg_name = pkginfo.pkg_stem
831 826 pkg_publisher = pkginfo.publisher
832 827 if not pkg_publisher in self.update_list:
833 828 self.update_list[pkg_publisher] = []
834 829 pub_list = self.update_list.get(pkg_publisher)
835 830 if not pkg_name in pub_list:
836 831 pub_list.append(pkg_name)
837 832 l_ver = 0
838 833 version_pref = ""
839 834 while l_ver < len(s_ver) -1:
840 835 version_pref += "%d%s" % (s_ver[l_ver],".")
841 836 l_ver += 1
842 837 version_pref += "%d%s" % (s_ver[l_ver],"-")
843 838 l_ver = 0
844 839 version_suf = ""
845 840 if s_bran != None:
846 841 while l_ver < len(s_bran) -1:
847 842 version_suf += "%d%s" % (s_bran[l_ver],".")
848 843 l_ver += 1
849 844 version_suf += "%d" % s_bran[l_ver]
850 845 pkg_version = version_pref + version_suf + dt_str
851 846 return pkg_name + "@" + pkg_version
852 847
853 848 def act_output(self):
854 849 if self.act_phase != self.act_phase_last:
855 850 self.act_phase_last = self.act_phase
856 851 gobject.idle_add(self.__stages_label_set_markup, self.act_phase)
857 852 self.__g_update_details_text(_("%s\n") % self.act_phase, "level1")
858 853 gobject.idle_add(self.__update_install_progress,
859 854 self.act_cur_nactions, self.act_goal_nactions)
860 855 return
861 856
862 857 def act_output_done(self):
863 858 return
864 859
865 860 def cat_output_start(self):
866 861 return
867 862
868 863 def cat_output_done(self):
869 864 return
870 865
871 866 def cache_cats_output_start(self):
872 867 return
873 868
874 869 def cache_cats_output_done(self):
875 870 return
876 871
877 872 def load_cat_cache_output_start(self):
878 873 return
879 874
880 875 def load_cat_cache_output_done(self):
881 876 return
882 877
883 878 def dl_output(self):
884 879 gobject.idle_add(self.__update_download_progress, \
885 880 self.dl_cur_nbytes, self.dl_goal_nbytes)
886 881 if self.prev_pkg != self.dl_cur_pkg:
887 882 self.prev_pkg = self.dl_cur_pkg
888 883 self.__g_update_details_text(
889 884 _("Package %d of %d: %s\n") % (self.dl_cur_npkgs+1,
890 885 self.dl_goal_npkgs, self.dl_cur_pkg), "level1")
891 886
892 887 def dl_output_done(self):
893 888 self.__g_update_details_text("\n")
894 889
895 890 def eval_output_start(self):
896 891 '''Called by progress tracker when the evaluation of the packages just
897 892 started.'''
898 893 return
899 894
900 895 def eval_output_progress(self):
901 896 '''Called by progress tracker each time some package was evaluated. The
902 897 call is being done by calling progress tracker evaluate_progress()
903 898 function'''
904 899 if self.prev_pkg != self.eval_cur_fmri:
905 900 self.prev_pkg = self.eval_cur_fmri
906 901 self.__g_update_details_text("%s\n" % self.eval_cur_fmri,
907 902 "level1")
908 903 text = _("Evaluating: %s") % self.eval_cur_fmri.get_name()
909 904 gobject.idle_add(self.__stages_label_set_markup, text)
910 905
911 906 def eval_output_done(self):
912 907 return
913 908
914 909 def ind_output(self):
915 910 if self.ind_started != self.ind_phase:
916 911 self.ind_started = self.ind_phase
917 912 gobject.idle_add(self.__stages_label_set_markup, self.ind_phase)
918 913 self.__g_update_details_text(
919 914 _("%s\n") % (self.ind_phase), "level1")
920 915 gobject.idle_add(self.__indexing_progress)
921 916
922 917 def __indexing_progress(self):
923 918 #It doesn't look nice if the progressive is just for few elements
924 919 if self.ind_goal_nitems > MIN_IND_ELEMENTS_BOUNCE:
925 920 gobject.idle_add(self.__update_install_progress,
926 921 self.ind_cur_nitems-1, self.ind_goal_nitems)
927 922 else:
928 923 if self.stopped_bouncing_progress:
929 924 self.__start_bouncing_progress()
930 925
931 926 def ind_output_done(self):
932 927 gobject.idle_add(self.__update_install_progress, self.ind_cur_nitems,
933 928 self.ind_goal_nitems)
934 929
935 930 def ver_output(self):
936 931 return
937 932
938 933 def ver_output_error(self, actname, errors):
939 934 return
940 935
941 936 @staticmethod
942 937 def get_datetime(date_time):
943 938 '''Support function for getting date from the API.'''
944 939 date_tmp = None
945 940 try:
946 941 date_tmp = time.strptime(date_time, "%a %b %d %H:%M:%S %Y")
947 942 except ValueError:
948 943 return None
949 944 if date_tmp:
950 945 date_tmp2 = datetime.datetime(*date_tmp[0:5])
951 946 return date_tmp2.strftime(":%m%d")
952 947 return None
953 948
954 949 def __installed_fmris_from_args(self, args_f):
955 950 found = []
956 951 notfound = []
957 952 try:
958 953 for m in self.api_o.img.inventory(args_f):
959 954 found.append(m[0])
960 955 except api_errors.InventoryException, e:
961 956 notfound = e.notfound
962 957 return notfound
963 958
|
↓ open down ↓ |
540 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX