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