def _add_advanced_clicked(self, button): from advanced_storage import addDrive if not addDrive(self.anaconda): return udev_trigger(subsystem="block", action="change") new_disks = self._getFilterDisks() mcw = MultipathConfigWriter() cfg = mcw.write() open("/etc/multipath.conf", "w+").write(cfg) del cfg del mcw topology = MultipathTopology(new_disks) (new_raids, new_nonraids) = self.split_list(lambda d: isRAID(d) and not isCCISS(d), topology.singlepaths_iter()) nonraids = filter(lambda d: d not in self._cachedDevices, new_nonraids) raids = filter(lambda d: d not in self._cachedRaidDevices, new_raids) # The end result of the loop below is that mpaths is a list of lists of # components. That's what populate expects. mpaths = [] for mp in topology.multipaths_iter(): for d in mp: # If all components of this multipath device are in the # cache, skip it. Otherwise, it's a new device and needs to # be populated into the UI. if d not in self._cachedMPaths: mpaths.append(mp) break self.populate(nonraids, mpaths, raids, activeByDefault=True) # Make sure to update the size label at the bottom. self.pages[0].cb.update() self._cachedDevices.extend(nonraids) self._cachedRaidDevices.extend(raids) # And then we need to do the same list flattening trick here as in # getScreen. lst = list(itertools.chain(*mpaths)) self._cachedMPaths.extend(lst)
def getScreen(self, anaconda): # We skip the filter UI in basic storage mode if anaconda.simpleFilter: anaconda.storage.config.exclusiveDisks = [] return None (self.xml, self.vbox) = gui.getGladeWidget("filter.glade", "vbox") self.buttonBox = self.xml.get_widget("buttonBox") self.notebook = self.xml.get_widget("notebook") self.addAdvanced = self.xml.get_widget("addAdvancedButton") self.notebook.connect("switch-page", self._page_switched) self.addAdvanced.connect("clicked", self._add_advanced_clicked) self.pages = [] self.anaconda = anaconda # One common store that all the views on all the notebook tabs share. # Yes, this means a whole lot of columns that are going to be empty or # unused much of the time. Oh well. # Object, # visible, active (checked), immutable, # device, model, capacity, vendor, interconnect, serial number, wwid # paths, port, target, lun self.store = gtk.TreeStore(gobject.TYPE_PYOBJECT, gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) self.store.set_sort_column_id(MODEL_COL, gtk.SORT_ASCENDING) # if we've already populated the device tree at least once we should # do our best to make sure any active devices get deactivated anaconda.storage.devicetree.teardownAll() # So that drives onlined by these show up in the filter UI iscsi.iscsi().startup(anaconda.intf) fcoe.fcoe().startup(anaconda.intf) zfcp.ZFCP().startup(anaconda.intf) dasd.DASD().startup(anaconda.intf, anaconda.storage.config.exclusiveDisks, anaconda.storage.config.zeroMbr) disks = self._getFilterDisks() mcw = MultipathConfigWriter() cfg = mcw.write() open("/etc/multipath.conf", "w+").write(cfg) del cfg del mcw topology = MultipathTopology(disks) # The device list could be really long, so we really only want to # iterate over it the bare minimum of times. Dividing this list up # now means fewer elements to iterate over later. singlepaths = filter(lambda info: self._device_size_is_nonzero(info), topology.singlepaths_iter()) (raids, nonraids) = self.split_list(lambda d: isRAID(d) and not isCCISS(d), singlepaths) self.pages = [self._makeBasic(), self._makeRAID(), self._makeMPath(), self._makeOther(), self._makeSearch()] self.populate(nonraids, topology.multipaths_iter(), raids) # If the "Add Advanced" button is ever clicked, we need to have a list # of what devices previously existed so we know what's new. Then we # can just add the new devices to the UI. This is going to be slow, # but the user has to click a button to get to the slow part. self._cachedDevices = NameCache(singlepaths) self._cachedRaidDevices = NameCache(raids) # Multipath is a little more complicated. Since mpaths is a list of # lists, we can't directly store that into the cache. Instead we want # to flatten it into a single list of all components of all multipaths # and store that. mpath_chain = itertools.chain(*topology.multipaths_iter()) self._cachedMPaths = NameCache(mpath_chain) # Switch to the first notebook page that displays any devices. i = 0 for pg in self.pages: if pg.getNVisible(): self.notebook.set_current_page(i) break i += 1 return self.vbox