1 #!/usr/bin/python2.4
   2 #
   3 # CDDL HEADER START
   4 #
   5 # The contents of this file are subject to the terms of the
   6 # Common Development and Distribution License (the "License").
   7 # You may not use this file except in compliance with the License.
   8 #
   9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10 # or http://www.opensolaris.org/os/licensing.
  11 # See the License for the specific language governing permissions
  12 # and limitations under the License.
  13 #
  14 # When distributing Covered Code, include this CDDL HEADER in each
  15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16 # If applicable, add the following below this CDDL HEADER, with the
  17 # fields enclosed by brackets "[]" replaced with your own identifying
  18 # information: Portions Copyright [yyyy] [name of copyright owner]
  19 #
  20 # CDDL HEADER END
  21 #
  22 # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23 # Use is subject to license terms.
  24 #
  25 
  26 import sys
  27 import pango
  28 import time
  29 import datetime
  30 import locale
  31 import pkg.pkgsubprocess as subprocess
  32 from threading import Thread
  33 
  34 try:
  35         import gobject
  36         gobject.threads_init()
  37         import gnome
  38         import gtk
  39         import gtk.glade
  40         import pygtk
  41         pygtk.require("2.0")
  42 except ImportError:
  43         sys.exit(1)
  44 import pkg.gui.misc as gui_misc
  45 
  46 nobe = False
  47 
  48 try:
  49         import libbe as be
  50 except ImportError:
  51         # All actions are disabled when libbe can't be imported. 
  52         nobe = True
  53 import pkg.misc
  54 
  55 #BE_LIST
  56 (
  57 BE_ID,
  58 BE_MARKED,
  59 BE_NAME,
  60 BE_ORIG_NAME,
  61 BE_DATE_TIME,
  62 BE_CURRENT_PIXBUF,
  63 BE_ACTIVE_DEFAULT,
  64 BE_SIZE,
  65 BE_EDITABLE
  66 ) = range(9)
  67 
  68 class Beadmin:
  69         def __init__(self, parent):
  70                 self.parent = parent
  71 
  72                 if nobe:
  73                         msg = _("The <b>libbe</b> library was not "
  74                             "found on your system."
  75                             "\nAll functions for managing Boot Environments are disabled")
  76                         msgbox = gtk.MessageDialog(
  77                             buttons = gtk.BUTTONS_CLOSE,
  78                             flags = gtk.DIALOG_MODAL, type = gtk.MESSAGE_INFO,
  79                             message_format = None)
  80                         msgbox.set_markup(msg)
  81                         msgbox.set_title(_("BE management"))
  82                         msgbox.run()
  83                         msgbox.destroy()
  84                         return
  85 
  86                 self.be_list = \
  87                     gtk.ListStore(
  88                         gobject.TYPE_INT,         # BE_ID
  89                         gobject.TYPE_BOOLEAN,     # BE_MARKED
  90                         gobject.TYPE_STRING,      # BE_NAME
  91                         gobject.TYPE_STRING,      # BE_ORIG_NAME
  92                         gobject.TYPE_STRING,      # BE_DATE_TIME
  93                         gtk.gdk.Pixbuf,           # BE_CURRENT_PIXBUF
  94                         gobject.TYPE_BOOLEAN,     # BE_ACTIVE_DEFAULT
  95                         gobject.TYPE_STRING,      # BE_SIZE
  96                         gobject.TYPE_BOOLEAN,     # BE_EDITABLE
  97                         )
  98                 self.progress_stop_thread = False
  99                 self.initial_active = 0
 100                 self.initial_default = 0
 101                 w_tree_beadmin = gtk.glade.XML(parent.gladefile, "beadmin")
 102                 w_tree_progress = gtk.glade.XML(parent.gladefile, "progressdialog")
 103                 w_tree_beconfirmation = gtk.glade.XML(parent.gladefile,
 104                     "beconfirmationdialog")
 105                 self.w_beadmin_dialog = w_tree_beadmin.get_widget("beadmin")
 106                 self.w_be_treeview = w_tree_beadmin.get_widget("betreeview")
 107                 self.w_cancel_button = w_tree_beadmin.get_widget("cancelbebutton")
 108                 self.w_ok_button = w_tree_beadmin.get_widget("okbebutton")
 109                 w_active_gtkimage = w_tree_beadmin.get_widget("activebeimage")
 110                 self.w_progress_dialog = w_tree_progress.get_widget("progressdialog")
 111                 self.w_progress_dialog.connect('delete-event', lambda stub1, stub2: True)
 112                 self.w_progressinfo_label = w_tree_progress.get_widget("progressinfo")
 113                 progress_button = w_tree_progress.get_widget("progresscancel")
 114                 self.w_progressbar = w_tree_progress.get_widget("progressbar")
 115                 self.w_beconfirmation_dialog =  \
 116                     w_tree_beconfirmation.get_widget("beconfirmationdialog")
 117                 self.w_beconfirmation_textview = \
 118                     w_tree_beconfirmation.get_widget("beconfirmtext")
 119                 self.w_cancelbe_button = w_tree_beconfirmation.get_widget("cancel_be")
 120                 self.w_ok_button.set_sensitive(False)
 121                 progress_button.hide()
 122                 self.w_progressbar.set_pulse_step(0.1)
 123                 self.list_filter = self.be_list.filter_new()
 124                 self.w_be_treeview.set_model(self.list_filter)
 125                 self.__init_tree_views()
 126                 self.active_image = gui_misc.get_icon(
 127                     self.parent.icon_theme, "status_checkmark")
 128                 w_active_gtkimage.set_from_pixbuf(self.active_image)
 129 
 130                 bebuffer = self.w_beconfirmation_textview.get_buffer()
 131                 bebuffer.create_tag("bold", weight=pango.WEIGHT_BOLD)
 132 
 133                 try:
 134                         dic = \
 135                             {
 136                                 "on_cancel_be_clicked": \
 137                                     self.__on_cancel_be_clicked,
 138                                 "on_ok_be_clicked": \
 139                                     self.__on_ok_be_clicked,
 140                                 "on_help_bebutton_clicked": \
 141                                     self.__on_help_bebutton_clicked,
 142                             }
 143                         dic_conf = \
 144                             {
 145                                 "on_cancel_be_conf_clicked": \
 146                                     self.__on_cancel_be_conf_clicked,
 147                                 "on_ok_be_conf_clicked": \
 148                                     self.__on_ok_be_conf_clicked,
 149                                 "on_beconfirmationdialog_delete_event": \
 150                                     self.__on_beconfirmationdialog_delete_event,
 151                             }            
 152                         w_tree_beadmin.signal_autoconnect(dic)
 153                         w_tree_beconfirmation.signal_autoconnect(dic_conf)
 154                 except AttributeError, error:
 155                         print _("GUI will not respond to any event! %s. "
 156                             "Check beadmin.py signals") \
 157                             % error
 158                 Thread(target = self.__progress_pulse).start()
 159                 Thread(target = self.__prepare_beadmin_list).start()
 160                 sel = self.w_be_treeview.get_selection()
 161                 self.w_cancel_button.grab_focus()
 162                 sel.set_mode(gtk.SELECTION_SINGLE)
 163                 self.w_beadmin_dialog.show_all()
 164                 self.w_progress_dialog.set_title(
 165                     _("Loading Boot Environment Information"))
 166                 self.w_progressinfo_label.set_text(
 167                     _("Fetching BE entries..."))
 168                 self.w_progress_dialog.show()
 169 
 170         def __progress_pulse(self):
 171                 while not self.progress_stop_thread:
 172                         gobject.idle_add(self.w_progressbar.pulse)
 173                         time.sleep(0.1)
 174                 gobject.idle_add(self.w_progress_dialog.hide)
 175 
 176         def __prepare_beadmin_list(self):
 177                 be_list = be.beList()
 178                 gobject.idle_add(self.__create_view_with_be, be_list)
 179                 self.progress_stop_thread = True
 180                 return
 181 
 182         def __init_tree_views(self):
 183                 model = self.w_be_treeview.get_model()
 184 
 185                 column = gtk.TreeViewColumn()
 186                 column.set_title("")
 187                 render_pixbuf = gtk.CellRendererPixbuf()
 188                 column.pack_start(render_pixbuf, expand = True)
 189                 column.add_attribute(render_pixbuf, "pixbuf", BE_CURRENT_PIXBUF)
 190                 self.w_be_treeview.append_column(column)
 191 
 192                 name_renderer = gtk.CellRendererText()
 193                 name_renderer.connect('edited', self.__be_name_edited, model)
 194                 column = gtk.TreeViewColumn(_("Boot Environment"),
 195                     name_renderer, text = BE_NAME)
 196                 column.set_cell_data_func(name_renderer, self.__cell_data_function, None)
 197                 column.set_expand(True)
 198                 if "beVerifyBEName" in be.__dict__:
 199                         column.add_attribute(name_renderer, "editable", 
 200                             BE_EDITABLE)
 201                 self.w_be_treeview.append_column(column)
 202                 
 203                 datetime_renderer = gtk.CellRendererText()
 204                 datetime_renderer.set_property('xalign', 0.0)
 205                 column = gtk.TreeViewColumn(_("Created"), datetime_renderer,
 206                     text = BE_DATE_TIME)
 207                 column.set_cell_data_func(datetime_renderer,
 208                     self.__cell_data_function, None)
 209                 column.set_expand(True)
 210                 self.w_be_treeview.append_column(column)
 211 
 212                 size_renderer = gtk.CellRendererText()
 213                 size_renderer.set_property('xalign', 1.0)
 214                 column = gtk.TreeViewColumn(_("Size"), size_renderer,
 215                     text = BE_SIZE)
 216                 column.set_cell_data_func(size_renderer, self.__cell_data_function, None)
 217                 column.set_expand(False)
 218                 self.w_be_treeview.append_column(column)
 219               
 220                 radio_renderer = gtk.CellRendererToggle()
 221                 radio_renderer.connect('toggled', self.__active_pane_default, model)
 222                 column = gtk.TreeViewColumn(_("Active on Reboot"),
 223                     radio_renderer, active = BE_ACTIVE_DEFAULT)
 224                 radio_renderer.set_property("activatable", True)
 225                 radio_renderer.set_property("radio", True)
 226                 column.set_cell_data_func(radio_renderer,
 227                     self.__cell_data_default_function, None)
 228                 column.set_expand(False)
 229                 self.w_be_treeview.append_column(column)
 230 
 231                 toggle_renderer = gtk.CellRendererToggle()
 232                 toggle_renderer.connect('toggled', self.__active_pane_toggle, model)
 233                 column = gtk.TreeViewColumn(_("Delete"), toggle_renderer,
 234                     active = BE_MARKED)
 235                 toggle_renderer.set_property("activatable", True)
 236                 column.set_cell_data_func(toggle_renderer,
 237                     self.__cell_data_delete_function, None)
 238                 column.set_expand(False)
 239                 self.w_be_treeview.append_column(column)
 240 
 241         def __on_help_bebutton_clicked(self, widget):
 242                 if self.parent != None:
 243                         gui_misc.display_help(self.parent.application_dir, "manage_be")
 244                 else:
 245                         gui_misc.display_help()
 246                 
 247         def __on_ok_be_clicked(self, widget):
 248                 self.w_progress_dialog.set_title(_("Applying changes"))
 249                 self.w_progressinfo_label.set_text(
 250                     _("Applying changes, please wait ..."))
 251                 if self.w_ok_button.get_property('sensitive') == 0:
 252                         self.progress_stop_thread = True
 253                         self.__on_beadmin_delete_event(None, None)
 254                         return
 255                 Thread(target = self.__activate).start()
 256                 
 257         def __on_cancel_be_clicked(self, widget):
 258                 self.__on_beadmin_delete_event(None, None)
 259                 return False
 260 
 261         def __on_beconfirmationdialog_delete_event(self, widget, event):
 262                 self.__on_cancel_be_conf_clicked(widget)
 263                 return True
 264 
 265         def __on_cancel_be_conf_clicked(self, widget):
 266                 self.w_beconfirmation_dialog.hide()
 267 
 268         def __on_ok_be_conf_clicked(self, widget):
 269                 self.w_beconfirmation_dialog.hide()
 270                 self.progress_stop_thread = False
 271                 Thread(target = self.__on_progressdialog_progress).start()
 272                 Thread(target = self.__delete_activate_be).start()
 273                 
 274         def __on_beadmin_delete_event(self, widget, event, stub=None):
 275                 self.w_beadmin_dialog.destroy()
 276                 return True
 277 
 278         def __activate(self):
 279                 active_text = _("Active on reboot:\n")
 280                 delete_text = _("Delete boot environments:\n")
 281                 rename_text = _("Rename boot environments:\n")
 282                 active = ""
 283                 delete = ""
 284                 rename = {}
 285                 for row in self.be_list:
 286 
 287                         if row[BE_MARKED]:
 288                                 delete += row[BE_NAME] + "\n"
 289                         if row[BE_ACTIVE_DEFAULT] == True and row[BE_ID] != \
 290                             self.initial_default:
 291                                 active += row[BE_NAME] + "\n"
 292                         if row[BE_NAME] != row[BE_ORIG_NAME]:
 293                                 rename[row[BE_ORIG_NAME]] = row[BE_NAME]
 294                 textbuf = self.w_beconfirmation_textview.get_buffer()
 295                 textbuf.set_text("")
 296                 textiter = textbuf.get_end_iter()
 297                 if len(active) > 0:
 298                         textbuf.insert_with_tags_by_name(textiter,
 299                             active_text, "bold")
 300                         textbuf.insert_with_tags_by_name(textiter,
 301                             active)
 302                 if len(delete) > 0:
 303                         if len(active) > 0:
 304                                 textbuf.insert_with_tags_by_name(textiter,
 305                                     "\n")                                
 306                         textbuf.insert_with_tags_by_name(textiter,
 307                             delete_text, "bold")
 308                         textbuf.insert_with_tags_by_name(textiter,
 309                             delete)
 310                 if len(rename) > 0:
 311                         if len(delete) > 0 or len(active) > 0:
 312                                 textbuf.insert_with_tags_by_name(textiter,
 313                                     "\n")                                
 314                         textbuf.insert_with_tags_by_name(textiter,
 315                             rename_text, "bold")
 316                         for orig in rename:
 317                                 textbuf.insert_with_tags_by_name(textiter,
 318                                     orig)
 319                                 textbuf.insert_with_tags_by_name(textiter,
 320                                     _(" to "), "bold")
 321                                 textbuf.insert_with_tags_by_name(textiter,
 322                                     rename.get(orig) + "\n")
 323                 self.w_cancelbe_button.grab_focus()
 324                 gobject.idle_add(self.w_beconfirmation_dialog.show)
 325                 self.progress_stop_thread = True                
 326 
 327         def __on_progressdialog_progress(self):
 328                 # This needs to be run in gobject.idle_add, otherwise we will get
 329                 # Xlib: unexpected async reply (sequence 0x2db0)!
 330                 gobject.idle_add(self.w_progress_dialog.show)
 331                 while not self.progress_stop_thread:
 332                         gobject.idle_add(self.w_progressbar.pulse)
 333                         time.sleep(0.1)
 334                 gobject.idle_add(self.w_progress_dialog.hide)
 335 
 336         def __delete_activate_be(self):
 337                 not_deleted = []
 338                 not_default = None
 339                 not_renamed = {}
 340                 # The while gtk.events_pending():
 341                 #        gtk.main_iteration(False)
 342                 # Is not working if we are calling libbe, so it is required
 343                 # To have sleep in few places in this function
 344                 # Remove
 345                 for row in self.be_list:
 346                         if row[BE_MARKED]:
 347                                 time.sleep(0.1)
 348                                 result = self.__destroy_be(row[BE_NAME])
 349                                 if result != 0:
 350                                         not_deleted.append(row[BE_NAME])
 351                 # Rename
 352                 for row in self.be_list:
 353                         if row[BE_NAME] != row[BE_ORIG_NAME]:
 354                                 time.sleep(0.1)
 355                                 result = self.__rename_be(row[BE_ORIG_NAME],
 356                                     row[BE_NAME])
 357                                 if result !=0:
 358                                         not_renamed[row[BE_ORIG_NAME]] = row[BE_NAME]
 359                 # Set active
 360                 for row in self.be_list:
 361                         if row[BE_ACTIVE_DEFAULT] == True and row[BE_ID] != \
 362                             self.initial_default:
 363                                 time.sleep(0.1)
 364                                 result = self.__set_default_be(row[BE_NAME])
 365                                 if result != 0:
 366                                         not_default = row[BE_NAME]
 367                 if len(not_deleted) == 0 and not_default == None \
 368                     and len(not_renamed) == 0:
 369                         self.progress_stop_thread = True
 370                 else:
 371                         self.progress_stop_thread = True
 372                         msg = ""
 373                         if not_default:
 374                                 msg += _("<b>Couldn't change Active "
 375                                     "Boot Environment to:</b>\n") + not_default
 376                         if len(not_deleted) > 0:
 377                                 if not_default:
 378                                         msg += "\n\n"
 379                                 msg += _("<b>Couldn't delete Boot "
 380                                     "Environments:</b>\n")
 381                                 for row in not_deleted:
 382                                         msg += row + "\n"
 383                         if len(not_renamed) > 0:
 384                                 if not_default or len(not_deleted):
 385                                         msg += "\n"
 386                                 msg += _("<b>Couldn't rename Boot "
 387                                     "Environments:</b>\n")
 388                                 for orig in not_renamed:
 389                                         msg += _("%s <b>to</b> %s\n") % (orig, 
 390                                             not_renamed.get(orig))                                
 391                         gobject.idle_add(self.__error_occurred, msg)
 392                         return
 393                 gobject.idle_add(self.__on_cancel_be_clicked, None)
 394                                 
 395         def __rename_cell(self, model, itr, new_name):
 396                 model.set_value(itr, BE_NAME, new_name)
 397 
 398         def __rename_be(self, orig_name, new_name):
 399                 return be.beRename(orig_name, new_name)
 400 
 401         def __error_occurred(self, error_msg, reset=True):
 402                 gui_misc.error_occurred(self.w_beadmin_dialog,
 403                     error_msg,
 404                     _("BE error"),
 405                     gtk.MESSAGE_ERROR,
 406                     True)
 407                 if reset:
 408                         self.__on_reset_be()
 409 
 410         def __on_reset_be(self):
 411                 self.be_list.clear()
 412                 self.w_progress_dialog.show()
 413                 self.progress_stop_thread = False
 414                 Thread(target = self.__progress_pulse).start()
 415                 Thread(target = self.__prepare_beadmin_list).start()
 416                 self.w_ok_button.set_sensitive(False)
 417 
 418         def __active_pane_toggle(self, cell, filtered_path, filtered_model):
 419                 model = filtered_model.get_model()
 420                 path = filtered_model.convert_path_to_child_path(filtered_path)
 421                 itr = model.get_iter(path)
 422                 if itr:
 423                         modified = model.get_value(itr, BE_MARKED)
 424                         # Do not allow to set active if selected for removal
 425                         model.set_value(itr, BE_MARKED, not modified)
 426                         # Do not allow to rename if we are removing be.
 427                         model.set_value(itr, BE_EDITABLE, modified)
 428                 self.__enable_disable_ok()
 429                 
 430         def __enable_disable_ok(self):
 431                 for row in self.be_list:
 432                         if row[BE_MARKED] == True:
 433                                 self.w_ok_button.set_sensitive(True)
 434                                 return
 435                         if row[BE_ID] == self.initial_default:
 436                                 if row[BE_ACTIVE_DEFAULT] == False:
 437                                         self.w_ok_button.set_sensitive(True)
 438                                         return
 439                         if row[BE_NAME] != row[BE_ORIG_NAME]:
 440                                 self.w_ok_button.set_sensitive(True)
 441                                 return
 442                 self.w_ok_button.set_sensitive(False)
 443                 return
 444 
 445         def __be_name_edited(self, cell, filtered_path, new_name, filtered_model):
 446                 model = filtered_model.get_model()
 447                 path = filtered_model.convert_path_to_child_path(filtered_path)
 448                 itr = model.get_iter(path)
 449                 if itr:
 450                         if model.get_value(itr, BE_NAME) == new_name:
 451                                 return
 452                         if self.__verify_be_name(new_name) != 0:
 453                                 return
 454                         self.__rename_cell(model, itr, new_name)
 455                         self.__enable_disable_ok()                
 456                         return
 457 
 458         #TBD: Notify user if name clash using same logic as Repo Add and warning text
 459         def __verify_be_name(self, new_name):
 460                 if be.beVerifyBEName(new_name) != 0:
 461                         return -1
 462                 for row in self.be_list:
 463                         if new_name == row[BE_NAME]:
 464                                 return -1
 465                 return 0
 466 
 467         def __active_pane_default(self, cell, filtered_path, filtered_model):
 468                 model = filtered_model.get_model()
 469                 path = filtered_model.convert_path_to_child_path(filtered_path)
 470                 for row in model:
 471                         row[BE_ACTIVE_DEFAULT] = False
 472                 itr = model.get_iter(path)
 473                 if itr:
 474                         modified = model.get_value(itr, BE_ACTIVE_DEFAULT)
 475                         model.set_value(itr, BE_ACTIVE_DEFAULT, not modified)
 476                         self.__enable_disable_ok()
 477 
 478         def __create_view_with_be(self, be_list):
 479                 dates = None
 480                 i = 0
 481                 j = 0
 482                 error_code = None
 483                 be_list_loop = None
 484                 if len(be_list) > 1 and type(be_list[0]) == type(-1):
 485                         error_code = be_list[0]
 486                 if error_code != None and error_code == 0:
 487                         be_list_loop = be_list[1]
 488                 elif error_code != None and error_code != 0:
 489                         msg = _("The <b>libbe</b> library couldn't  "
 490                             "prepare list of Boot Environments."
 491                             "\nAll functions for managing Boot Environments are disabled")
 492                         self.__error_occurred(msg, False)
 493                         return
 494                 else:
 495                         be_list_loop = be_list
 496 
 497                 for bee in be_list_loop:
 498                         if bee.get("orig_be_name"):
 499                                 name = bee.get("orig_be_name")
 500                                 active = bee.get("active")
 501                                 active_boot = bee.get("active_boot")
 502                                 be_size = bee.get("space_used")
 503                                 be_date = bee.get("date")
 504                                 converted_size = \
 505                                     self.__convert_size_of_be_to_string(be_size)
 506                                 active_img = None
 507                                 if not be_date and j == 0:
 508                                         dates = self.__get_dates_of_creation(be_list_loop)
 509                                 if dates:
 510                                         try:
 511                                                 date_time = repr(dates[i])[1:-3]
 512                                                 date_tmp = time.strptime(date_time, \
 513                                                     "%a %b %d %H:%M %Y")
 514                                                 date_tmp2 = \
 515                                                         datetime.datetime(*date_tmp[0:5])
 516                                                 try:
 517                                                         date_format = \
 518                                                         unicode(
 519                                                             _("%m/%d/%y %H:%M"),
 520                                                             "utf-8").encode(
 521                                                             locale.getpreferredencoding())
 522                                                 except (UnicodeError, LookupError,
 523                                                     locale.Error):
 524                                                         date_format = "%F %H:%M"
 525                                                 date_time = \
 526                                                     date_tmp2.strftime(date_format)
 527                                                 i += 1
 528                                         except (NameError, ValueError, TypeError):
 529                                                 date_time = None
 530                                 else:
 531                                         date_tmp = time.localtime(be_date)
 532                                         try:
 533                                                 date_format = \
 534                                                     unicode(
 535                                                         _("%m/%d/%y %H:%M"),
 536                                                         "utf-8").encode(
 537                                                         locale.getpreferredencoding())
 538                                         except (UnicodeError, LookupError, locale.Error):
 539                                                 date_format = "%F %H:%M"
 540                                         date_time = \
 541                                             time.strftime(date_format, date_tmp)
 542                                 if active:
 543                                         active_img = self.active_image
 544                                         self.initial_active = j
 545                                 if active_boot:
 546                                         self.initial_default = j
 547                                 if date_time != None:
 548                                         try:
 549                                                 date_time = unicode(date_time,
 550                                                 locale.getpreferredencoding()).encode(
 551                                                         "utf-8")
 552                                         except (UnicodeError, LookupError, locale.Error):
 553                                                 pass 
 554                                 self.be_list.insert(j, [j, False,
 555                                     name, name,
 556                                     date_time, active_img,
 557                                     active_boot, converted_size, active_img == None])
 558                                 j += 1
 559                 self.w_be_treeview.set_cursor(self.initial_active, None,
 560                     start_editing=True)
 561                 self.w_be_treeview.scroll_to_cell(self.initial_active)
 562 
 563         def __destroy_be(self, be_name):
 564                 return be.beDestroy(be_name, 1, True)
 565 
 566         def __set_default_be(self, be_name):
 567                 return be.beActivate(be_name)
 568 
 569         def __cell_data_default_function(self, column, renderer, model, itr, data):
 570                 if itr:
 571                         if model.get_value(itr, BE_MARKED):
 572                                 self.__set_renderer_active(renderer, False)
 573                         else:
 574                                 self.__set_renderer_active(renderer, True)
 575                                 
 576         def __cell_data_delete_function(self, column, renderer, model, itr, data):
 577                 if itr:
 578                         if model.get_value(itr, BE_ACTIVE_DEFAULT) or \
 579                             (self.initial_active == model.get_value(itr, BE_ID)) or \
 580                             (model.get_value(itr, BE_NAME) !=
 581                             model.get_value(itr, BE_ORIG_NAME)):
 582                                 self.__set_renderer_active(renderer, False)
 583                         else:
 584                                 self.__set_renderer_active(renderer, True)
 585 
 586         @staticmethod
 587         def __set_renderer_active(renderer, active):
 588                 if active:
 589                         renderer.set_property("sensitive", True)
 590                         renderer.set_property("mode", gtk.CELL_RENDERER_MODE_ACTIVATABLE)
 591                 else:
 592                         renderer.set_property("sensitive", False)
 593                         renderer.set_property("mode", gtk.CELL_RENDERER_MODE_INERT)
 594 
 595         @staticmethod
 596         def __get_dates_of_creation(be_list):
 597                 #zfs list -H -o creation rpool/ROOT/opensolaris-1
 598                 cmd = [ "/sbin/zfs", "list", "-H", "-o","creation" ]
 599                 for bee in be_list:
 600                         if bee.get("orig_be_name"):
 601                                 name = bee.get("orig_be_name")
 602                                 pool = bee.get("orig_be_pool")
 603                                 cmd += [pool+"/ROOT/"+name]
 604                 if len(cmd) <= 5:
 605                         return None
 606                 list_of_dates = []
 607                 try:
 608                         proc = subprocess.Popen(cmd, stdout = subprocess.PIPE,
 609                             stderr = subprocess.PIPE,)
 610                         line_out = proc.stdout.readline()
 611                         while line_out:
 612                                 list_of_dates.append(line_out)
 613                                 line_out =  proc.stdout.readline()
 614                 except OSError:
 615                         return list_of_dates
 616                 return list_of_dates
 617 
 618         @staticmethod
 619         def __convert_size_of_be_to_string(be_size):
 620                 if not be_size:
 621                         be_size = 0
 622                 return pkg.misc.bytes_to_str(be_size)
 623 
 624         @staticmethod
 625         def __cell_data_function(column, renderer, model, itr, data):
 626                 if itr:
 627                         if model.get_value(itr, BE_CURRENT_PIXBUF):
 628                                 renderer.set_property("weight", pango.WEIGHT_BOLD)
 629                         else:
 630                                 renderer.set_property("weight", pango.WEIGHT_NORMAL)