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