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