def getScreen(self, anaconda):
        self.intf = anaconda.intf
        self.anaconda = anaconda
        self.hostname = network.getDefaultHostname(anaconda)

        # load the UI
        (self.xml, self.align) = gui.getGladeWidget("network.glade",
                                                    "network_align")
        self.icon = self.xml.get_widget("icon")
        self.hostnameEntry = self.xml.get_widget("hostnameEntry")
        self.hostnameEntry.set_text(self.hostname)

        self.netconfButton = self.xml.get_widget("netconfButton")
        self.netconfButton.connect("clicked", self._setupNetwork)
        if len(self.anaconda.network.netdevices) == 0 or flags.imageInstall:
            self.netconfButton.set_sensitive(False)

        # pressing Enter in confirm == clicking Next
        self.hostnameEntry.connect("activate",
                                   lambda w: self.ics.setGrabNext(1))

        # load the icon
        gui.readImageFromFile("network.png", image=self.icon)

        return self.align
def addDrive(anaconda):
    (dxml, dialog) = gui.getGladeWidget("adddrive.glade", "addDriveDialog")
    gui.addFrame(dialog)
    dialog.show_all()
    if not iutil.isS390():
        dxml.get_widget("zfcpRadio").hide()
        dxml.get_widget("zfcpRadio").set_group(None)

    if not pyanaconda.storage.iscsi.has_iscsi():
        dxml.get_widget("iscsiRadio").set_sensitive(False)
        dxml.get_widget("iscsiRadio").set_active(False)
        dxml.get_widget("iscsiBindCheck").set_sensitive(False)
    else:
        dxml.get_widget("iscsiBindCheck").set_active(bool(pyanaconda.storage.iscsi.iscsi().ifaces))
        dxml.get_widget("iscsiBindCheck").set_sensitive(pyanaconda.storage.iscsi.iscsi().mode == "none")

    if not pyanaconda.storage.fcoe.has_fcoe():
        dxml.get_widget("fcoeRadio").set_sensitive(False)
        dxml.get_widget("fcoeRadio").set_active(False)

    def update_active_ifaces():
        active_ifaces = network.getActiveNetDevs()
        dxml.get_widget("ifaceLabel").set_text(", ".join(active_ifaces))

    def netconfButton_clicked(*args):
        from pyanaconda.iw.network_gui import setupNetwork
        setupNetwork(anaconda.intf)
        update_active_ifaces()

    dxml.get_widget("netconfButton").connect("clicked", netconfButton_clicked)
    update_active_ifaces()

    #figure out what advanced devices we have available and put focus on the first one
    group = dxml.get_widget("iscsiRadio").get_group()
    for button in reversed(group):
        if button is not None and button.get_property("sensitive"):
            button.set_active(True)
            button.grab_focus()
            break

    rc = dialog.run()
    dialog.hide()

    if rc in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT]:
        return False

    if dxml.get_widget("iscsiRadio").get_active() and pyanaconda.storage.iscsi.has_iscsi():
        bind = dxml.get_widget("iscsiBindCheck").get_active()
        rc = addIscsiDrive(anaconda, bind)
    elif dxml.get_widget("fcoeRadio").get_active() and pyanaconda.storage.fcoe.has_fcoe():
        rc = addFcoeDrive(anaconda)
    elif dxml.get_widget("zfcpRadio") is not None and dxml.get_widget("zfcpRadio").get_active():
        rc = addZfcpDrive(anaconda)

    dialog.destroy()

    if rc in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT]:
        return False
    else:
        return True
Beispiel #3
0
    def __init__(self, anaconda, repoObj):
        self.anaconda = anaconda
        self.backend = self.anaconda.backend
        self.intf = self.anaconda.intf
        self.repo = repoObj

        (self.dxml, self.dialog) = gui.getGladeWidget("addrepo.glade",
                                                      "addRepoDialog")
        self.dxml.signal_autoconnect(self)

        self.notebook = self.dxml.get_widget("typeNotebook")
        self.nameEntry = self.dxml.get_widget("nameEntry")
        self.typeComboBox = self.dxml.get_widget("typeComboBox")

        self.baseurlEntry = self.dxml.get_widget("baseurlEntry")
        self.mirrorlistCheckbox = self.dxml.get_widget("mirrorlistCheckbox")
        self.proxyCheckbox = self.dxml.get_widget("proxyCheckbox")
        self.proxyEntry = self.dxml.get_widget("proxyEntry")
        self.proxyTable = self.dxml.get_widget("proxyTable")
        self.usernameEntry = self.dxml.get_widget("usernameEntry")
        self.passwordEntry = self.dxml.get_widget("passwordEntry")

        self.nfsServerEntry = self.dxml.get_widget("nfsServerEntry")
        self.nfsPathEntry = self.dxml.get_widget("nfsPathEntry")
        self.nfsOptionsEntry = self.dxml.get_widget("nfsOptionsEntry")

        self.partitionComboBox = self.dxml.get_widget("partitionComboBox")
        self.directoryChooser = self.dxml.get_widget("directoryChooserButton")

        self.dialog.set_title(_("Edit Repository"))

        # Remove these until they are actually implemented
        self.typeComboBox.remove_text(3)
    def __init__(self, anaconda, repoObj):
        self.anaconda = anaconda
        self.backend = self.anaconda.backend
        self.intf = self.anaconda.intf
        self.repo = repoObj

        (self.dxml, self.dialog) = gui.getGladeWidget("addrepo.glade", "addRepoDialog")
        self.dxml.signal_autoconnect(self)

        self.notebook = self.dxml.get_widget("typeNotebook")
        self.nameEntry = self.dxml.get_widget("nameEntry")
        self.typeComboBox = self.dxml.get_widget("typeComboBox")

        self.baseurlEntry = self.dxml.get_widget("baseurlEntry")
        self.mirrorlistCheckbox = self.dxml.get_widget("mirrorlistCheckbox")
        self.proxyCheckbox = self.dxml.get_widget("proxyCheckbox")
        self.proxyEntry = self.dxml.get_widget("proxyEntry")
        self.proxyTable = self.dxml.get_widget("proxyTable")
        self.usernameEntry = self.dxml.get_widget("usernameEntry")
        self.passwordEntry = self.dxml.get_widget("passwordEntry")

        self.nfsServerEntry = self.dxml.get_widget("nfsServerEntry")
        self.nfsPathEntry = self.dxml.get_widget("nfsPathEntry")
        self.nfsOptionsEntry = self.dxml.get_widget("nfsOptionsEntry")

        self.partitionComboBox = self.dxml.get_widget("partitionComboBox")
        self.directoryChooser = self.dxml.get_widget("directoryChooserButton")

        self.dialog.set_title(_("Edit Repository"))

        # Remove these until they are actually implemented
        self.typeComboBox.remove_text(3)
Beispiel #5
0
    def getScreen(self, anaconda):
        self.intf = anaconda.intf
        self.anaconda = anaconda
        self.hostname = network.getDefaultHostname(anaconda)

        # load the UI
        (self.xml, self.align) = gui.getGladeWidget("network.glade",
                                                    "network_align")
        self.icon = self.xml.get_widget("icon")
        self.hostnameEntry = self.xml.get_widget("hostnameEntry")
        self.hostnameEntry.set_text(self.hostname)

        self.netconfButton = self.xml.get_widget("netconfButton")
        self.netconfButton.connect("clicked", self._setupNetwork)
        if len(self.anaconda.network.netdevices) == 0 or flags.imageInstall:
            self.netconfButton.set_sensitive(False)

        # pressing Enter in confirm == clicking Next
        self.hostnameEntry.connect("activate",
                                   lambda w: self.ics.setGrabNext(1))

        # load the icon
        gui.readImageFromFile("network.png", image=self.icon)

        return self.align
    def getScreen (self, anaconda):
        self.intf = anaconda.intf
        self.dispatch = anaconda.dispatch
        self.backend = anaconda.backend
        self.anaconda = anaconda

        self.tasks = anaconda.instClass.tasks
        self.repos = anaconda.backend.ayum.repos

        (self.xml, vbox) = gui.getGladeWidget("tasksel.glade", "taskBox")

        lbl = self.xml.get_widget("mainLabel")
        if anaconda.instClass.description:
            lbl.set_text(_(anaconda.instClass.description))
        else:
            txt = lbl.get_text()
            lbl.set_text(txt %(productName,))

        custom = not self.dispatch.stepInSkipList("group-selection")
        if custom:
            self.xml.get_widget("customRadio").set_active(True)
        else:
            self.xml.get_widget("customRadio").set_active(False)

        self.ts = self._createTaskStore()
        self.rs = self._createRepoStore()

        if len(self.ts.get_model()) == 0:
            self.xml.get_widget("cbVBox").hide()
            self.xml.get_widget("mainLabel").hide()

        self.xml.get_widget("addRepoButton").connect("clicked", self._addRepo)
        self.xml.get_widget("editRepoButton").connect("clicked", self._editRepo, self.rs)

        return vbox
def addZfcpDrive(anaconda):
    (dxml, dialog) = gui.getGladeWidget("zfcp-config.glade", "zfcpDialog")
    gui.addFrame(dialog)
    dialog.show_all()
    sg = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
    for w in ["devnumEntry", "wwpnEntry", "fcplunEntry"]:
        sg.add_widget(dxml.get_widget(w))

    while True:
        dialog.present()
        rc = dialog.run()
        if rc != gtk.RESPONSE_APPLY:
            break

        devnum = dxml.get_widget("devnumEntry").get_text().strip()
        wwpn = dxml.get_widget("wwpnEntry").get_text().strip()
        fcplun = dxml.get_widget("fcplunEntry").get_text().strip()

        try:
            anaconda.storage.zfcp.addFCP(devnum, wwpn, fcplun)
        except ValueError as e:
            anaconda.intf.messageWindow(_("Error"), str(e))
            continue

        break

    dialog.destroy()
    return rc
def addZfcpDrive(anaconda):
    (dxml, dialog) = gui.getGladeWidget("zfcp-config.glade", "zfcpDialog")
    gui.addFrame(dialog)
    dialog.show_all()
    sg = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
    for w in ["devnumEntry", "wwpnEntry", "fcplunEntry"]:
        sg.add_widget(dxml.get_widget(w))

    while True:
        dialog.present()
        rc = dialog.run()
        if rc != gtk.RESPONSE_APPLY:
            break

        devnum = dxml.get_widget("devnumEntry").get_text().strip()
        wwpn = dxml.get_widget("wwpnEntry").get_text().strip()
        fcplun = dxml.get_widget("fcplunEntry").get_text().strip()

        try:
            anaconda.storage.zfcp.addFCP(devnum, wwpn, fcplun)
        except ValueError as e:
            anaconda.intf.messageWindow(_("Error"), str(e))
            continue

        break

    dialog.destroy()
    return rc
 def __init__(self):
     super(iSCSILoginDialog, self).__init__()
     (xml, self.dialog) = gui.getGladeWidget("iscsi-dialogs.glade", "login_dialog")
     # take credentials from the discovery dialog
     (self.credentials_xml, credentials_table) = gui.getGladeWidget("iscsi-dialogs.glade", "table_credentials")
     (credentials, rev_credentials) = self._credentials_widgets(self.credentials_xml)
     # and put them into the login dialog alignment
     alignment = xml.get_widget("login_credentials_alignment")
     alignment.add(credentials_table)
     # setup the combobox
     self.combobox = self._combo_box([
             pih.CRED_NONE,
             pih.CRED_ONE,
             pih.CRED_BOTH,
             pih.CRED_REUSE
             ], credentials, rev_credentials)
     vbox = xml.get_widget("d_login_vbox")
     vbox.pack_start(self.combobox, expand=False)
 def __init__(self):
     super(iSCSILoginDialog, self).__init__()
     (xml, self.dialog) = gui.getGladeWidget("iscsi-dialogs.glade",
                                             "login_dialog")
     # take credentials from the discovery dialog
     (self.credentials_xml,
      credentials_table) = gui.getGladeWidget("iscsi-dialogs.glade",
                                              "table_credentials")
     (credentials,
      rev_credentials) = self._credentials_widgets(self.credentials_xml)
     # and put them into the login dialog alignment
     alignment = xml.get_widget("login_credentials_alignment")
     alignment.add(credentials_table)
     # setup the combobox
     self.combobox = self._combo_box(
         [pih.CRED_NONE, pih.CRED_ONE, pih.CRED_BOTH, pih.CRED_REUSE],
         credentials, rev_credentials)
     vbox = xml.get_widget("d_login_vbox")
     vbox.pack_start(self.combobox, expand=False)
def addDrive(anaconda):
    (dxml, dialog) = gui.getGladeWidget("adddrive.glade", "addDriveDialog")
    gui.addFrame(dialog)
    dialog.show_all()
    if not iutil.isS390():
        dxml.get_widget("zfcpRadio").hide()
        dxml.get_widget("zfcpRadio").set_group(None)

    if not pyanaconda.storage.iscsi.has_iscsi():
        dxml.get_widget("iscsiRadio").set_sensitive(False)
        dxml.get_widget("iscsiRadio").set_active(False)

    if not pyanaconda.storage.fcoe.has_fcoe():
        dxml.get_widget("fcoeRadio").set_sensitive(False)
        dxml.get_widget("fcoeRadio").set_active(False)

    #figure out what advanced devices we have available and put focus on the first one
    group = dxml.get_widget("iscsiRadio").get_group()
    for button in reversed(group):
        if button is not None and button.get_property("sensitive"):
            button.set_active(True)
            button.grab_focus()
            break

    rc = dialog.run()
    dialog.hide()

    if rc in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT]:
        return False

    if dxml.get_widget("iscsiRadio").get_active(
    ) and pyanaconda.storage.iscsi.has_iscsi():
        rc = addIscsiDrive(anaconda)
    elif dxml.get_widget(
            "fcoeRadio").get_active() and pyanaconda.storage.fcoe.has_fcoe():
        rc = addFcoeDrive(anaconda)
    elif dxml.get_widget("zfcpRadio") is not None and dxml.get_widget(
            "zfcpRadio").get_active():
        rc = addZfcpDrive(anaconda)

    dialog.destroy()

    if rc in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT]:
        return False
    else:
        return True
    def __init__(self, initiator, initiator_set):
        super(iSCSIDiscoveryDialog, self).__init__()
        (self.xml, self.dialog) = gui.getGladeWidget("iscsi-dialogs.glade", "discovery_dialog")

        self.initiator = self.xml.get_widget("initiator")
        self.initiator.set_text(initiator)
        if initiator_set:
            self.initiator.set_sensitive(False)

        (credentials, rev_credentials) = self._credentials_widgets(self.xml)
        self.combobox = self._combo_box([
                pih.CRED_NONE,
                pih.CRED_ONE,
                pih.CRED_BOTH,
                ], credentials, rev_credentials)
        vbox = self.xml.get_widget("d_discovery_vbox")
        vbox.pack_start(self.combobox, expand=False)
    def display_nodes_dialog(self, found_nodes, ifaces):
        def _login_button_disabler(device_selector, login_button, checked, item):
            login_button.set_sensitive(len(device_selector.getSelected()) > 0)

        (xml, dialog) = gui.getGladeWidget("iscsi-dialogs.glade", "nodes_dialog")
        store = gtk.TreeStore(
            gobject.TYPE_PYOBJECT, # teh object
            gobject.TYPE_BOOLEAN,  # visible
            gobject.TYPE_BOOLEAN,  # active (checked)
            gobject.TYPE_BOOLEAN,  # immutable
            gobject.TYPE_STRING,   # node name
            gobject.TYPE_STRING    # node interface
            )
        map(lambda node : store.append(None, (
                    node,        # the object
                    True,        # visible
                    True,        # active
                    False,       # not immutable
                    node.name,   # node's name
                    ifaces.get(node.iface, node.iface))), # node's interface
            found_nodes)

        # create and setup the device selector
        model = store.filter_new()
        view = gtk.TreeView(model)
        ds = DeviceSelector.DeviceSelector(
            store,
            model,
            view)
        callback = functools.partial(_login_button_disabler,
                                     ds,
                                     xml.get_widget("button_login"))
        ds.createSelectionCol(toggledCB=callback)
        ds.addColumn(_("Interface"), self.NODE_INTERFACE_COL)
        # attach the treeview to the dialog
        sw = xml.get_widget("nodes_scrolled_window")
        sw.add(view)
        sw.show_all()

        # run the dialog
        rc = self._run_dialog(dialog)
        # filter out selected nodes:
        selected_nodes = map(lambda raw : raw[0], ds.getSelected())
        dialog.destroy()
        return (rc, selected_nodes)
    def __init__(self, initiator, initiator_set):
        super(iSCSIDiscoveryDialog, self).__init__()
        (self.xml, self.dialog) = gui.getGladeWidget("iscsi-dialogs.glade",
                                                     "discovery_dialog")

        self.initiator = self.xml.get_widget("initiator")
        self.initiator.set_text(initiator)
        if initiator_set:
            self.initiator.set_sensitive(False)

        (credentials, rev_credentials) = self._credentials_widgets(self.xml)
        self.combobox = self._combo_box([
            pih.CRED_NONE,
            pih.CRED_ONE,
            pih.CRED_BOTH,
        ], credentials, rev_credentials)
        vbox = self.xml.get_widget("d_discovery_vbox")
        vbox.pack_start(self.combobox, expand=False)
def addDrive(anaconda):
    (dxml, dialog) = gui.getGladeWidget("adddrive.glade", "addDriveDialog")
    gui.addFrame(dialog)
    dialog.show_all()
    if not iutil.isS390():
        dxml.get_widget("zfcpRadio").hide()
        dxml.get_widget("zfcpRadio").set_group(None)

    if not pyanaconda.storage.iscsi.has_iscsi():
        dxml.get_widget("iscsiRadio").set_sensitive(False)
        dxml.get_widget("iscsiRadio").set_active(False)

    if not pyanaconda.storage.fcoe.has_fcoe():
        dxml.get_widget("fcoeRadio").set_sensitive(False)
        dxml.get_widget("fcoeRadio").set_active(False)

    #figure out what advanced devices we have available and put focus on the first one
    group = dxml.get_widget("iscsiRadio").get_group()
    for button in reversed(group):
        if button is not None and button.get_property("sensitive"):
            button.set_active(True)
            button.grab_focus()
            break

    rc = dialog.run()
    dialog.hide()

    if rc in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT]:
        return False

    if dxml.get_widget("iscsiRadio").get_active() and pyanaconda.storage.iscsi.has_iscsi():
        rc = addIscsiDrive(anaconda)
    elif dxml.get_widget("fcoeRadio").get_active() and pyanaconda.storage.fcoe.has_fcoe():
        rc = addFcoeDrive(anaconda)
    elif dxml.get_widget("zfcpRadio") is not None and dxml.get_widget("zfcpRadio").get_active():
        rc = addZfcpDrive(anaconda)

    dialog.destroy()

    if rc in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT]:
        return False
    else:
        return True
    def display_success_dialog(self, success_nodes, fail_nodes, fail_reason,
                               ifaces):
        (xml, dialog) = gui.getGladeWidget("iscsi-dialogs.glade", "success_dialog")
        w_success = xml.get_widget("label_success")
        w_success_win = xml.get_widget("scroll_window_success")
        w_success_val = xml.get_widget("text_success")
        w_fail = xml.get_widget("label_fail")
        w_fail_win = xml.get_widget("scroll_window_fail")
        w_fail_val = xml.get_widget("text_fail")
        w_reason = xml.get_widget("label_reason")
        w_reason_val = xml.get_widget("label_reason_val")
        w_retry = xml.get_widget("button_retry")
        w_separator = xml.get_widget("separator")

        if success_nodes:
            markup = "\n".join(map(lambda n: "%s via %s" % (n.name, ifaces.get(n.iface, n.iface)), success_nodes))
            buf = gtk.TextBuffer()
            buf.set_text(markup)
            w_success.show()
            w_success_val.set_buffer(buf)
            w_success_win.show()
        if fail_nodes:
            markup = "\n".join(map(lambda n: "%s via %s" % (n.name, ifaces.get(n.iface, n.iface)), fail_nodes))
            buf = gtk.TextBuffer()
            buf.set_text(markup)
            w_fail.show()
            w_fail_val.set_buffer(buf)
            w_fail_win.show()
            w_retry.show()
        if fail_reason:
            w_reason.show()
            w_reason_val.set_markup(fail_reason)
            w_reason_val.show()
        if success_nodes and fail_nodes:
            # only if there's anything to be separated display the separator
            w_separator.show()
        
        rc = self._run_dialog(dialog)
        dialog.destroy()
        return rc
    def display_success_dialog(self, success_nodes, fail_nodes, fail_reason):
        (xml, dialog) = gui.getGladeWidget("iscsi-dialogs.glade",
                                           "success_dialog")
        w_success = xml.get_widget("label_success")
        w_success_win = xml.get_widget("scroll_window_success")
        w_success_val = xml.get_widget("text_success")
        w_fail = xml.get_widget("label_fail")
        w_fail_win = xml.get_widget("scroll_window_fail")
        w_fail_val = xml.get_widget("text_fail")
        w_reason = xml.get_widget("label_reason")
        w_reason_val = xml.get_widget("label_reason_val")
        w_retry = xml.get_widget("button_retry")
        w_separator = xml.get_widget("separator")

        if success_nodes:
            markup = "\n".join(map(lambda n: n.name, success_nodes))
            buf = gtk.TextBuffer()
            buf.set_text(markup)
            w_success.show()
            w_success_val.set_buffer(buf)
            w_success_win.show()
        if fail_nodes:
            markup = "\n".join(map(lambda n: n.name, fail_nodes))
            buf = gtk.TextBuffer()
            buf.set_text(markup)
            w_fail.show()
            w_fail_val.set_buffer(buf)
            w_fail_win.show()
            w_retry.show()
        if fail_reason:
            w_reason.show()
            w_reason_val.set_markup(fail_reason)
            w_reason_val.show()
        if success_nodes and fail_nodes:
            # only if there's anything to be separated display the separator
            w_separator.show()

        rc = self._run_dialog(dialog)
        dialog.destroy()
        return rc
    def getScreen(self, anaconda):
        self.anaconda = anaconda
        self.intf = anaconda.intf

        (self.xml, self.align) = gui.getGladeWidget("account.glade",
                                                    "account_align")
        self.icon = self.xml.get_widget("icon")
        self.capslock = self.xml.get_widget("capslock")
        self.pwlabel = self.xml.get_widget("pwlabel")
        self.pw = self.xml.get_widget("pw")
        self.confirmlabel = self.xml.get_widget("confirmlabel")
        self.confirm = self.xml.get_widget("confirm")

        # load the icon
        gui.readImageFromFile("root-password.png", image=self.icon)

        # connect hotkeys
        self.pwlabel.set_text_with_mnemonic(_("Root _Password:"******"_Confirm:"))
        self.confirmlabel.set_mnemonic_widget(self.confirm)

        # watch for Caps Lock so we can warn the user
        self.intf.icw.window.connect("key-release-event",
            lambda w, e: self.handleCapsLockRelease(w, e, self.capslock))

        # we might have a root password already
        if not self.anaconda.users.rootPassword['isCrypted']:
            self.pw.set_text(self.anaconda.users.rootPassword['password'])
            self.confirm.set_text(self.anaconda.users.rootPassword['password'])

        # pressing Enter in confirm == clicking Next
        vbox = self.xml.get_widget("account_box")
        self.confirm.connect("activate", lambda widget,
                             vbox=vbox: self.ics.setGrabNext(1))

        # set initial caps lock label text
        self.setCapsLockLabel()

        return self.align
    def display_nodes_dialog(self, found_nodes):
        (xml, dialog) = gui.getGladeWidget("iscsi-dialogs.glade",
                                           "nodes_dialog")
        store = gtk.TreeStore(
            gobject.TYPE_PYOBJECT,  # teh object
            gobject.TYPE_BOOLEAN,  # visible
            gobject.TYPE_BOOLEAN,  # active (checked)
            gobject.TYPE_BOOLEAN,  # immutable
            gobject.TYPE_STRING  # node name
        )
        map(
            lambda node: store.append(
                None,
                (
                    node,  # the object
                    True,  # visible
                    True,  # active
                    False,  # not immutable
                    node.name)),  # node's name
            found_nodes)

        # create and setup the device selector
        model = store.filter_new()
        view = gtk.TreeView(model)
        ds = DeviceSelector.DeviceSelector(store, model, view)
        ds.createSelectionCol()
        ds.addColumn(_("Node Name"), self.NODE_NAME_COL)
        # attach the treeview to the dialog
        sw = xml.get_widget("nodes_scrolled_window")
        sw.add(view)
        sw.show_all()

        # run the dialog
        rc = self._run_dialog(dialog)
        # filter out selected nodes:
        selected_nodes = map(lambda raw: raw[0], ds.getSelected())
        dialog.destroy()
        return (rc, selected_nodes)
    def display_nodes_dialog(self, found_nodes):
        (xml, dialog) = gui.getGladeWidget("iscsi-dialogs.glade", "nodes_dialog")
        store = gtk.TreeStore(
            gobject.TYPE_PYOBJECT, # teh object
            gobject.TYPE_BOOLEAN,  # visible
            gobject.TYPE_BOOLEAN,  # active (checked)
            gobject.TYPE_BOOLEAN,  # immutable
            gobject.TYPE_STRING    # node name
            )
        map(lambda node : store.append(None, (
                    node,        # the object
                    True,        # visible
                    True,        # active
                    False,       # not immutable
                    node.name)),  # node's name
            found_nodes)
        
        # create and setup the device selector
        model = store.filter_new()
        view = gtk.TreeView(model)
        ds = DeviceSelector.DeviceSelector(
            store,
            model,
            view)
        ds.createSelectionCol()
        ds.addColumn(_("Node Name"), self.NODE_NAME_COL)
        # attach the treeview to the dialog
        sw = xml.get_widget("nodes_scrolled_window")
        sw.add(view)
        sw.show_all()

        # run the dialog
        rc = self._run_dialog(dialog)
        # filter out selected nodes:
        selected_nodes = map(lambda raw : raw[0], ds.getSelected())
        dialog.destroy()
        return (rc, selected_nodes)
    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
def whichToShrink(storage, intf):
    def getActive(combo):
        act = combo.get_active_iter()
        return combo.get_model().get_value(act, 1)

    def comboCB(combo, shrinkSB):
        # partition to resize changed, let's update our spinbutton
        newSize = shrinkSB.get_value_as_int()

        part = getActive(combo)
        (reqlower, requpper) = getResizeMinMax(part)

        adj = shrinkSB.get_adjustment()
        adj.lower = max(1,reqlower)
        adj.upper = requpper
        adj.set_value(reqlower)


    (dxml, dialog) = gui.getGladeWidget("autopart.glade", "shrinkDialog")

    store = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
    combo = dxml.get_widget("shrinkPartCombo")
    combo.set_model(store)
    crt = gtk.CellRendererText()
    combo.pack_start(crt, True)
    combo.set_attributes(crt, text = 0)
    combo.connect("changed", comboCB, dxml.get_widget("shrinkSB"))

    biggest = -1
    for part in storage.partitions:
        if not part.exists:
            continue

        entry = None
        if part.resizable and part.format.resizable:
            entry = ("%s (%s, %d MB)" % (part.name,
                                         part.format.name,
                                         math.floor(part.format.size)),
                     part)

        if entry:
            i = store.append(None)
            store[i] = entry
            combo.set_active_iter(i)

            if biggest == -1:
                biggest = i
            else:
                current = store.get_value(biggest, 1)
                if part.format.targetSize > current.format.targetSize:
                    biggest = i

    if biggest > -1:
        combo.set_active_iter(biggest)

    if len(store) == 0:
        dialog.destroy()
        intf.messageWindow(_("Error"),
                           _("No partitions are available to resize.  Only "
                             "physical partitions with specific filesystems "
                             "can be resized."),
                             type="warning", custom_icon="error")
        return (gtk.RESPONSE_CANCEL, [])

    gui.addFrame(dialog)
    dialog.show_all()
    runResize = True

    while runResize:
        rc = dialog.run()
        if rc != gtk.RESPONSE_OK:
            dialog.destroy()
            return (rc, [])

        request = getActive(combo)
        sb = dxml.get_widget("shrinkSB")
        sb.update()
        newSize = sb.get_value_as_int()
        actions = []

        try:
            actions.append(ActionResizeFormat(request, newSize))
        except ValueError as e:
            intf.messageWindow(_("Resize FileSystem Error"),
                               _("%(device)s: %(msg)s")
                                 % {'device': request.format.device,
                                    'msg': e.message},
                               type="warning", custom_icon="error")
            continue

        try:
            actions.append(ActionResizeDevice(request, newSize))
        except ValueError as e:
            intf.messageWindow(_("Resize Device Error"),
                               _("%(name)s: %(msg)s")
                                 % {'name': request.name, 'msg': e.message},
                               type="warning", custom_icon="error")
            continue
        else:
            # aligning the new partition end sector may have changed its size
            if request.targetSize != request.format.targetSize:
                request.format.targetSize = request.targetSize

        runResize = False

    dialog.destroy()
    return (rc, actions)
    def getScreen(self, anaconda):
        self.anaconda = anaconda
        self.storage = anaconda.storage
        self.intf = anaconda.intf
        self.dispatch = anaconda.dispatch

        if self.anaconda.dir == DISPATCH_FORWARD:
            # Save system's partition type setting and restore user's
            self.anaconda.clearPartTypeSystem = self.storage.clearPartType
            if self.anaconda.clearPartTypeSelection is not None:
                self.storage.clearPartType = self.anaconda.clearPartTypeSelection

        (self.xml, vbox) = gui.getGladeWidget("autopart.glade",
                                              "parttypeTable")
        self.encryptButton = self.xml.get_widget("encryptButton")
        self.reviewButton = self.xml.get_widget("reviewButton")
        self.table = self.xml.get_widget("parttypeTable")

        self.prevrev = None
        self.reviewButton.set_active(
            not self.dispatch.stepInSkipList("partition"))
        self.encryptButton.set_active(self.storage.encryptedAutoPart)

        self.buttonGroup = pixmapRadioButtonGroup()
        self.buttonGroup.addEntry(
            "all",
            _("Use All Space"),
            pixmap=gui.readImageFromFile("partscheme-all.png"),
            descr=_("Removes all partitions on the selected "
                    "device(s).  This includes partitions "
                    "created by other operating systems.\n\n"
                    "<b>Tip:</b> This option will remove "
                    "data from the selected device(s).  Make "
                    "sure you have backups."))
        self.buttonGroup.addEntry(
            "replace",
            _("Replace Existing Linux System(s)"),
            pixmap=gui.readImageFromFile("partscheme-replace.png"),
            descr=_("Removes all Linux partitions on the "
                    "selected device(s). This does "
                    "not remove other partitions you may have "
                    "on your storage device(s) (such as VFAT or "
                    "FAT32).\n\n"
                    "<b>Tip:</b> This option will remove "
                    "data from the selected device(s).  Make "
                    "sure you have backups."))
        self.buttonGroup.addEntry(
            "shrink",
            _("Shrink Current System"),
            pixmap=gui.readImageFromFile("partscheme-shrink.png"),
            descr=_("Shrinks existing partitions to create free "
                    "space for the default layout."))
        self.buttonGroup.addEntry(
            "freespace",
            _("Use Free Space"),
            pixmap=gui.readImageFromFile("partscheme-freespace.png"),
            descr=_("Retains your current data and partitions and "
                    "uses only the unpartitioned space on the "
                    "selected device(s), assuming you have enough "
                    "free space available."))
        self.buttonGroup.addEntry(
            "custom",
            _("Create Custom Layout"),
            pixmap=gui.readImageFromFile("partscheme-custom.png"),
            descr=_("Manually create your own custom layout on "
                    "the selected device(s) using our partitioning "
                    "tool."))

        self.buttonGroup.setToggleCallback(self.typeChanged)

        widget = self.buttonGroup.render()
        self.table.attach(widget, 0, 1, 1, 2)

        # if not set in ks, use UI default
        if self.storage.clearPartChoice:
            self.buttonGroup.setCurrent(self.storage.clearPartChoice)
        else:
            if self.storage.clearPartType is None or self.storage.clearPartType == CLEARPART_TYPE_LINUX:
                self.buttonGroup.setCurrent("replace")
            elif self.storage.clearPartType == CLEARPART_TYPE_NONE:
                self.buttonGroup.setCurrent("freespace")
            elif self.storage.clearPartType == CLEARPART_TYPE_ALL:
                self.buttonGroup.setCurrent("all")

        if self.buttonGroup.getCurrent() == "custom":
            # make sure reviewButton is active and not sensitive
            if self.prevrev == None:
                self.prevrev = self.reviewButton.get_active()

            self.reviewButton.set_active(True)
            self.reviewButton.set_sensitive(False)
            self.encryptButton.set_sensitive(False)

        return vbox
def addIscsiDrive(anaconda):
    if not network.hasActiveNetDev():
        if not anaconda.intf.enableNetwork():
            return gtk.RESPONSE_CANCEL
        urlgrabber.grabber.reset_curl_obj()

    (dxml, dialog) = gui.getGladeWidget("iscsi-config.glade", "iscsiDialog")
    gui.addFrame(dialog)
    dialog.show_all()
    sg = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
    for w in [
            "iscsiAddrEntry", "iscsiInitiatorEntry", "userEntry", "passEntry",
            "userinEntry", "passinEntry"
    ]:
        sg.add_widget(dxml.get_widget(w))

    # get the initiator name if it exists and don't allow changing
    # once set
    initiator_entry = dxml.get_widget("iscsiInitiatorEntry")
    initiator_entry.set_text(anaconda.storage.iscsi.initiator)
    if anaconda.storage.iscsi.initiatorSet:
        initiator_entry.set_sensitive(False)

    while True:
        rc = dialog.run()
        if rc in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT]:
            break

        initiator = initiator_entry.get_text().strip()
        if len(initiator) == 0:
            anaconda.intf.messageWindow(
                _("Invalid Initiator Name"),
                _("You must provide an initiator name."))
            continue

        anaconda.storage.iscsi.initiator = initiator

        target = dxml.get_widget("iscsiAddrEntry").get_text().strip()
        user = dxml.get_widget("userEntry").get_text().strip()
        pw = dxml.get_widget("passEntry").get_text().strip()
        user_in = dxml.get_widget("userinEntry").get_text().strip()
        pw_in = dxml.get_widget("passinEntry").get_text().strip()

        try:
            count = len(target.split(":"))
            idx = target.rfind("]:")
            # Check for IPV6 [IPV6-ip]:port
            if idx != -1:
                ip = target[1:idx]
                port = target[idx + 2:]
            # Check for IPV4 aaa.bbb.ccc.ddd:port
            elif count == 2:
                idx = target.rfind(":")
                ip = target[:idx]
                port = target[idx + 1:]
            else:
                ip = target
                port = "3260"

            network.sanityCheckIPString(ip)
        except (network.IPMissing, network.IPError) as msg:
            anaconda.intf.messageWindow(_("Error with Data"), msg)
            continue

        try:
            anaconda.storage.iscsi.addTarget(ip, port, user, pw, user_in,
                                             pw_in, anaconda.intf)
        except ValueError as e:
            anaconda.intf.messageWindow(_("Error"), str(e))
            continue
        except IOError as e:
            anaconda.intf.messageWindow(_("Error"), str(e))
            rc = gtk.RESPONSE_CANCEL

        break

    dialog.destroy()
    return rc
Beispiel #25
0
    def getScreen(self, anaconda):
        # We skip the filter UI in basic storage mode
        if anaconda.simpleFilter:
            anaconda.storage.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()
        udev_trigger(subsystem="block", action="change")
        # 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.exclusiveDisks,
                            anaconda.storage.zeroMbr)
        disks = self._getFilterDisks()

        mcw = MultipathConfigWriter()
        cfg = mcw.write()
        open("/etc/multipath.conf", "w+").write(cfg)
        del cfg
        del mcw
        (singlepaths, mpaths, partitions) = identifyMultipaths(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),
                             singlepaths)
        (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, mpaths, 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.
        lst = list(itertools.chain(*mpaths))
        self._cachedMPaths = NameCache(lst)

        # 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
def addFcoeDrive(anaconda):
    (dxml, dialog) = gui.getGladeWidget("fcoe-config.glade", "fcoeDialog")
    combo = dxml.get_widget("fcoeNicCombo")
    dcb_cb = dxml.get_widget("dcbCheckbutton")

    # Populate the combo
    cell = gtk.CellRendererText()
    combo.pack_start(cell, True)
    combo.set_attributes(cell, text=0)
    cell.set_property("wrap-width", 525)
    combo.set_size_request(480, -1)
    store = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
    combo.set_model(store)

    netdevs = anaconda.network.netdevices
    keys = netdevs.keys()
    keys.sort()
    selected_interface = None
    for dev in keys:
        i = store.append(None)
        desc = netdevs[dev].description
        if desc:
            desc = "%s - %s" % (dev, desc)
        else:
            desc = "%s" % (dev, )

        mac = netdevs[dev].get("HWADDR")
        if mac:
            desc = "%s - %s" % (desc, mac)

        if selected_interface is None:
            selected_interface = i

        store[i] = (desc, dev)

    if selected_interface:
        combo.set_active_iter(selected_interface)
    else:
        combo.set_active(0)

    # Show the dialog
    gui.addFrame(dialog)
    dialog.show_all()
    sg = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
    sg.add_widget(dxml.get_widget("fcoeNicCombo"))

    while True:
        # make sure the dialog pops into foreground in case this is the second
        # time through the loop:
        dialog.present()
        rc = dialog.run()

        if rc in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT]:
            break

        iter = combo.get_active_iter()
        if iter is None:
            anaconda.intf.messageWindow(_("Error"),
                                        _("You must select a NIC to use."),
                                        type="warning",
                                        custom_icon="error")
            continue

        try:
            anaconda.storage.fcoe.addSan(store.get_value(iter, 1),
                                         dcb=dcb_cb.get_active(),
                                         intf=anaconda.intf)
        except IOError as e:
            anaconda.intf.messageWindow(_("Error"), str(e))
            rc = gtk.RESPONSE_CANCEL

        break

    dialog.destroy()
    return rc
    def _deviceChange(self, b, anaconda, *args):
        def __driveChange(combo, dxml, choices):
            if not choices.has_key("mbr"):
                return

            iter = combo.get_active_iter()
            if not iter:
                return

            first = combo.get_model()[iter][1]
            desc = choices["mbr"][1]
            dxml.get_widget("mbrRadio").set_label("%s - /dev/%s" %(_(desc), first))
            dxml.get_widget("mbrRadio").set_data("bootDevice", first)

        def __genStore(combo, disks, active):
            model = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
            combo.set_model(model)
            cell = gtk.CellRendererText()
            combo.pack_start(cell, True)
            combo.set_attributes(cell, text = 0)

            for disk in disks:
                i = model.append(None)
                model[i] = ("%s %8.0f MB %s" %(disk.name, disk.size,
                                               disk.description),
                            "%s" %(disk.name,))
                if disk.name == active:
                    combo.set_active_iter(i)

            return model

        (dxml, dialog) = gui.getGladeWidget("blwhere.glade",
                                            "blwhereDialog")
        gui.addFrame(dialog)
        dialog.set_transient_for(self.parent)
        dialog.show()

        choices = anaconda.platform.bootloaderChoices(self.bl)
        for t in ("mbr", "boot"):
            if not choices.has_key(t):
                continue
            (device, desc) = choices[t]
            w = dxml.get_widget("%sRadio" %(t,))
            w.set_label("%s - /dev/%s" %(_(desc), device))
            w.show()
            if self.bldev == device:
                w.set_active(True)
            else:
                w.set_active(False)
            w.set_data("bootDevice", device)

        for i in range(1, 5):
            if len(self.driveorder) < i:
                break
            combo = dxml.get_widget("bd%dCombo" %(i,))
            lbl = dxml.get_widget("bd%dLabel" %(i,))
            combo.show()
            lbl.show()
            partitioned = anaconda.storage.partitioned
            disks = anaconda.storage.disks
            bl_disks = [d for d in disks if d in partitioned]
            m = __genStore(combo, bl_disks, self.driveorder[i - 1])

        dxml.get_widget("bd1Combo").connect("changed", __driveChange, dxml, choices)
        __driveChange(dxml.get_widget("bd1Combo"), dxml, choices)

        while 1:
            rc = dialog.run()
            if rc in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT]:
                break

            # set the boot device based on what they chose
            if dxml.get_widget("bootRadio").get_active():
                self.bldev = dxml.get_widget("bootRadio").get_data("bootDevice")
            elif dxml.get_widget("mbrRadio").get_active():
                self.bldev = dxml.get_widget("mbrRadio").get_data("bootDevice")
            else:
                raise RuntimeError, "No radio button selected!"

            # and adjust the boot order
            neworder = []
            for i in range(1, 5):
                if len(self.driveorder) < i:
                    break

                combo = dxml.get_widget("bd%dCombo" %(i,))
                iter = combo.get_active_iter()
                if not iter:
                    continue

                act = combo.get_model()[iter][1]
                if act not in neworder:
                    neworder.append(act)
            for d in self.driveorder:
                if d not in neworder:
                    neworder.append(d)
            self.driveorder = neworder

            break

        dialog.destroy()
        self.grubCB.set_label(_("_Install boot loader on /dev/%s.") %
                              (self.bldev,))
        return rc
Beispiel #28
0
    def _deviceChange(self, b, anaconda, *args):
        def __driveChange(combo, dxml, choices):
            if not choices.has_key("mbr"):
                return

            iter = combo.get_active_iter()
            if not iter:
                return

            first = combo.get_model()[iter][1]
            desc = choices["mbr"][1]
            dxml.get_widget("mbrRadio").set_label("%s - /dev/%s" %
                                                  (_(desc), first))
            dxml.get_widget("mbrRadio").set_data("bootDevice", first)

        def __genStore(combo, disks, active):
            model = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
            combo.set_model(model)
            cell = gtk.CellRendererText()
            combo.pack_start(cell, True)
            combo.set_attributes(cell, text=0)

            for disk in disks:
                i = model.append(None)
                model[i] = ("%s %8.0f MB %s" %
                            (disk.name, disk.size, disk.description),
                            "%s" % (disk.name, ))
                if disk.name == active:
                    combo.set_active_iter(i)

            return model

        (dxml, dialog) = gui.getGladeWidget("blwhere.glade", "blwhereDialog")
        gui.addFrame(dialog)
        dialog.set_transient_for(self.parent)
        dialog.show()

        choices = anaconda.platform.bootloaderChoices(self.bl)
        for t in ("mbr", "boot"):
            if not choices.has_key(t):
                continue
            (device, desc) = choices[t]
            w = dxml.get_widget("%sRadio" % (t, ))
            w.set_label("%s - /dev/%s" % (_(desc), device))
            w.show()
            if self.bldev == device:
                w.set_active(True)
            else:
                w.set_active(False)
            w.set_data("bootDevice", device)

        for i in range(1, 5):
            if len(self.driveorder) < i:
                break
            combo = dxml.get_widget("bd%dCombo" % (i, ))
            lbl = dxml.get_widget("bd%dLabel" % (i, ))
            combo.show()
            lbl.show()
            partitioned = anaconda.storage.partitioned
            disks = anaconda.storage.disks
            bl_disks = [d for d in disks if d in partitioned]
            m = __genStore(combo, bl_disks, self.driveorder[i - 1])

        dxml.get_widget("bd1Combo").connect("changed", __driveChange, dxml,
                                            choices)
        __driveChange(dxml.get_widget("bd1Combo"), dxml, choices)

        while 1:
            rc = dialog.run()
            if rc in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT]:
                break

            # set the boot device based on what they chose
            if dxml.get_widget("bootRadio").get_active():
                self.bldev = dxml.get_widget("bootRadio").get_data(
                    "bootDevice")
            elif dxml.get_widget("mbrRadio").get_active():
                self.bldev = dxml.get_widget("mbrRadio").get_data("bootDevice")
            else:
                raise RuntimeError, "No radio button selected!"

            # and adjust the boot order
            neworder = []
            for i in range(1, 5):
                if len(self.driveorder) < i:
                    break

                combo = dxml.get_widget("bd%dCombo" % (i, ))
                iter = combo.get_active_iter()
                if not iter:
                    continue

                act = combo.get_model()[iter][1]
                if act not in neworder:
                    neworder.append(act)
            for d in self.driveorder:
                if d not in neworder:
                    neworder.append(d)
            self.driveorder = neworder

            break

        dialog.destroy()
        self.grubCB.set_label(
            _("_Install boot loader on /dev/%s.") % (self.bldev, ))
        return rc
def addFcoeDrive(anaconda):
    (dxml, dialog) = gui.getGladeWidget("fcoe-config.glade", "fcoeDialog")
    combo = dxml.get_widget("fcoeNicCombo")
    dcb_cb = dxml.get_widget("dcbCheckbutton")

    # Populate the combo
    cell = gtk.CellRendererText()
    combo.pack_start(cell, True)
    combo.set_attributes(cell, text = 0)
    cell.set_property("wrap-width", 525)
    combo.set_size_request(480, -1)
    store = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
    combo.set_model(store)

    netdevs = anaconda.network.netdevices
    keys = netdevs.keys()
    keys.sort()
    selected_interface = None
    for dev in keys:
        i = store.append(None)
        desc = netdevs[dev].description
        if desc:
            desc = "%s - %s" %(dev, desc)
        else:
            desc = "%s" %(dev,)

        mac = netdevs[dev].get("HWADDR")
        if mac:
            desc = "%s - %s" %(desc, mac)

        if selected_interface is None:
            selected_interface = i

        store[i] = (desc, dev)

    if selected_interface:
        combo.set_active_iter(selected_interface)
    else:
        combo.set_active(0)

    # Show the dialog
    gui.addFrame(dialog)
    dialog.show_all()
    sg = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
    sg.add_widget(dxml.get_widget("fcoeNicCombo"))

    while True:
        # make sure the dialog pops into foreground in case this is the second
        # time through the loop:
        dialog.present()
        rc = dialog.run()

        if rc in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT]:
            break

        iter = combo.get_active_iter()
        if iter is None:
            anaconda.intf.messageWindow(_("Error"),
                                        _("You must select a NIC to use."),
                                        type="warning", custom_icon="error")
            continue

        try:
            anaconda.storage.fcoe.addSan(store.get_value(iter, 1),
                                         dcb=dcb_cb.get_active(),
                                         intf=anaconda.intf)
        except IOError as e:
            anaconda.intf.messageWindow(_("Error"), str(e))
            rc = gtk.RESPONSE_CANCEL

        break

    dialog.destroy()
    return rc
    def getScreen (self, anaconda):
        # We can't just use exclusiveDisks here because of kickstart.  First,
        # the kickstart file could have used ignoredisk --drives= in which case
        # exclusiveDisks would be empty.  Second, ignoredisk is entirely
        # optional in which case neither list would be populated.  Luckily,
        # storage.disks takes isIgnored into account and that handles both these
        # issues.
        disks = filter(lambda d: not d.format.hidden, anaconda.storage.disks)

        self.anaconda = anaconda

        # Skip this screen as well if there's only one disk to use.
        if len(disks) == 1:
            self.resetStorage(clear=[disks[0].name], boot=disks[0].name)
            return None

        (xml, self.vbox) = gui.getGladeWidget("cleardisks.glade", "vbox")
        self.leftScroll = xml.get_widget("leftScroll")
        self.rightScroll = xml.get_widget("rightScroll")
        self.addButton = xml.get_widget("addButton")
        self.removeButton = xml.get_widget("removeButton")
        self.installTargetImage = xml.get_widget("installTargetImage")
        self.installTargetTip = xml.get_widget("installTargetTip")

        self.leftVisible = 1
        self.leftActive = 2
        self.rightVisible = 4
        self.rightActive = 5

        # One store for both views.  First the obejct, then a visible/active for
        # the left hand side, then a visible/active for the right hand side, then
        # all the other stuff.
        #
        # NOTE: the third boolean is a placeholder.  DeviceSelector uses the third
        # slot in the store to determine whether the row is immutable or not.  We
        # just need to put False in there for everything.
        self.store = gtk.TreeStore(gobject.TYPE_PYOBJECT,
                                   gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN,
                                   gobject.TYPE_BOOLEAN,
                                   gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN,
                                   gobject.TYPE_STRING, gobject.TYPE_STRING,
                                   gobject.TYPE_STRING, gobject.TYPE_STRING,
                                   gobject.TYPE_STRING)
        self.store.set_sort_column_id(6, gtk.SORT_ASCENDING)

        # The left view shows all the drives that will just be mounted, but
        # can still be moved to the right hand side.
        self.leftFilteredModel = self.store.filter_new()
        self.leftSortedModel = gtk.TreeModelSort(self.leftFilteredModel)
        self.leftTreeView = gtk.TreeView(self.leftSortedModel)

        self.leftFilteredModel.set_visible_func(lambda model, iter, view: model.get_value(iter, self.leftVisible), self.leftTreeView)

        self.leftScroll.add(self.leftTreeView)

        self.leftDS = DeviceSelector(self.store, self.leftSortedModel,
                                     self.leftTreeView, visible=self.leftVisible,
                                     active=self.leftActive)
        self.leftDS.createMenu()
        self.leftDS.addColumn(_("Model"), 6)
        self.leftDS.addColumn(_("Capacity"), 7)
        self.leftDS.addColumn(_("Vendor"), 8)
        self.leftDS.addColumn(_("Identifier"), 9)
        self.leftDS.addColumn(_("Interconnect"), 10, displayed=False)

        # The right view show all the drives that will be wiped during install.
        self.rightFilteredModel = self.store.filter_new()
        self.rightSortedModel = gtk.TreeModelSort(self.rightFilteredModel)
        self.rightTreeView = gtk.TreeView(self.rightSortedModel)

        self.rightFilteredModel.set_visible_func(lambda model, iter, view: model.get_value(iter, self.rightVisible), self.rightTreeView)

        self.rightScroll.add(self.rightTreeView)

        self.rightDS = DeviceSelector(self.store, self.rightSortedModel,
                                      self.rightTreeView, visible=self.rightVisible,
                                      active=self.rightActive)
        self.rightDS.createSelectionCol(title=_("Boot\nLoader"), radioButton=True)
        self.rightDS.createMenu()
        self.rightDS.addColumn(_("Model"), 6)
        self.rightDS.addColumn(_("Capacity"), 7)
        self.rightDS.addColumn(_("Identifier"), 9)

        # Store the first disk (according to bootloader ordering) for
        # auto boot device selection
        self.bootDisk = getattr(self.anaconda.bootloader.stage1_drive,
                                "name",
                                self.anaconda.bootloader.drives[0].name)

        if self.anaconda.storage.doAutoPart:
            use_disks = self.anaconda.storage.config.clearPartDisks
        else:
            use_disks = [d.name for d in disks if not d.protected]
            self.addButton.set_sensitive(False)
            self.removeButton.set_sensitive(False)

        # The device filtering UI set up exclusiveDisks as a list of the names
        # of all the disks we should use later on.  Now we need to go get those,
        # look up some more information in the devicetree, and set up the
        # selector.
        for d in disks:
            rightVisible = d.name in use_disks
            rightActive = rightVisible and d.name == self.bootDisk
            leftVisible = not rightVisible

            if hasattr(d, "wwid"):
                ident = d.wwid
            else:
                try:
                    ident = deviceNameToDiskByPath(d.name)
                    if ident.startswith("/dev/disk/by-path/"):
                        ident = ident.replace("/dev/disk/by-path/", "")
                except DeviceNotFoundError:
                    ident = d.name

            self.store.append(None, (d,
                                     leftVisible, True, False,
                                     rightVisible, rightActive,
                                     d.model,
                                     str(int(d.size)) + " MB",
                                     d.vendor, ident, d.bus))

        self.addButton.connect("clicked", self._add_clicked)
        self.removeButton.connect("clicked", self._remove_clicked)

        # Also allow moving devices back and forth with double click, enter, etc.
        self.leftTreeView.connect("row-activated", self._add_clicked)
        self.rightTreeView.disconnect(self.rightDS._activated_id)
        self.rightTreeView.connect("row-activated", self._remove_clicked)

        # And let the user select multiple devices at a time.
        self.leftTreeView.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
        self.rightTreeView.get_selection().set_mode(gtk.SELECTION_MULTIPLE)

        if self.anaconda.storage.config.clearPartType == CLEARPART_TYPE_LINUX:
            self.installTargetTip.set_markup(_("<b>Tip:</b> All Linux filesystems on the install target devices will be reformatted and wiped of any data.  Make sure you have backups."))
        elif self.anaconda.storage.config.clearPartType == CLEARPART_TYPE_ALL:
            self.installTargetTip.set_markup(_("<b>Tip:</b> The install target devices will be reformatted and wiped of any data.  Make sure you have backups."))
        else:
            self.installTargetTip.set_markup(_("<b>Tip:</b> Your filesystems on the install target devices will not be reformatted unless you choose to do so during customization."))

        return self.vbox
    def getScreen(self, anaconda):
        self.anaconda = anaconda
        self.storage = anaconda.storage
        self.intf = anaconda.intf
        self.dispatch = anaconda.dispatch

        if self.anaconda.dir == DISPATCH_FORWARD:
            # Save system's partition type setting and restore user's
            self.anaconda.clearPartTypeSystem = self.storage.config.clearPartType
            if self.anaconda.clearPartTypeSelection is not None:
                self.storage.config.clearPartType = self.anaconda.clearPartTypeSelection

        (self.xml, vbox) = gui.getGladeWidget("autopart.glade", "parttypeTable")
        self.encryptButton = self.xml.get_widget("encryptButton")
        self.reviewButton = self.xml.get_widget("reviewButton")
        self.lvmButton = self.xml.get_widget("lvmButton")
        self.table = self.xml.get_widget("parttypeTable")

        self.prevrev = None

        step_data = self.dispatch.step_data("parttype")
        self.reviewButton.set_active(
            step_data.get("review_checked", self.dispatch.step_enabled("partition")))
        self.encryptButton.set_active(self.storage.encryptedAutoPart)
        self.lvmButton.set_active(self.storage.autoPartType == AUTOPART_TYPE_LVM)

        self.buttonGroup = pixmapRadioButtonGroup()
        self.buttonGroup.addEntry("all", _("Use _All Space"),
                                  pixmap=gui.readImageFromFile("partscheme-all.png"),
                                  descr=_("Removes all partitions on the selected "
                                          "device(s).  This includes partitions "
                                          "created by other operating systems.\n\n"
                                          "<b>Tip:</b> This option will remove "
                                          "data from the selected device(s).  Make "
                                          "sure you have backups."))
        self.buttonGroup.addEntry("replace", _("Replace Existing _Linux System(s)"),
                                  pixmap=gui.readImageFromFile("partscheme-replace.png"),
                                  descr=_("Removes all Linux partitions on the "
                                          "selected device(s). This does "
                                          "not remove other partitions you may have "
                                          "on your storage device(s) (such as VFAT or "
                                          "FAT32).\n\n"
                                          "<b>Tip:</b> This option will remove "
                                          "data from the selected device(s).  Make "
                                          "sure you have backups."))
        self.buttonGroup.addEntry("shrink", _("_Shrink Current System"),
                                  pixmap=gui.readImageFromFile("partscheme-shrink.png"),
                                  descr=_("Shrinks existing partitions to create free "
                                          "space for the default layout."))
        self.buttonGroup.addEntry("freespace", _("Use _Free Space"),
                                  pixmap=gui.readImageFromFile("partscheme-freespace.png"),
                                  descr=_("Retains your current data and partitions and "
                                          "uses only the unpartitioned space on the "
                                          "selected device(s), assuming you have enough "
                                          "free space available."))
        self.buttonGroup.addEntry("custom", _("Create _Custom Layout"),
                                  pixmap=gui.readImageFromFile("partscheme-custom.png"),
                                  descr=_("Manually create your own custom layout on "
                                          "the selected device(s) using our partitioning "
                                          "tool."))

        self.buttonGroup.setToggleCallback(self.typeChanged)

        widget = self.buttonGroup.render()
        self.table.attach(widget, 0, 1, 1, 2)

        # if not set in ks, use UI default
        if self.storage.clearPartChoice:
            self.buttonGroup.setCurrent(self.storage.clearPartChoice)
        else:
            if self.storage.config.clearPartType in (None, CLEARPART_TYPE_LINUX):
                self.buttonGroup.setCurrent("replace")
            elif self.storage.config.clearPartType == CLEARPART_TYPE_NONE:
                self.buttonGroup.setCurrent("freespace")
            elif self.storage.config.clearPartType == CLEARPART_TYPE_ALL:
                self.buttonGroup.setCurrent("all")

        if self.buttonGroup.getCurrent() == "custom":
            # make sure reviewButton is active and not sensitive
            if self.prevrev == None:
                self.prevrev = self.reviewButton.get_active()

            self.reviewButton.set_active(True)
            self.reviewButton.set_sensitive(False)
            self.encryptButton.set_sensitive(False)
            self.lvmButton.set_sensitive(False)

        return vbox
def whichToShrink(storage, intf):
    def getActive(combo):
        act = combo.get_active_iter()
        return combo.get_model().get_value(act, 1)

    def comboCB(combo, shrinkSB):
        # partition to resize changed, let's update our spinbutton
        newSize = shrinkSB.get_value_as_int()

        part = getActive(combo)
        (reqlower, requpper) = getResizeMinMax(part)

        adj = shrinkSB.get_adjustment()
        adj.lower = max(1, reqlower)
        adj.upper = requpper
        adj.set_value(reqlower)

    (dxml, dialog) = gui.getGladeWidget("autopart.glade", "shrinkDialog")

    store = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
    combo = dxml.get_widget("shrinkPartCombo")
    combo.set_model(store)
    crt = gtk.CellRendererText()
    combo.pack_start(crt, True)
    combo.set_attributes(crt, text=0)
    combo.connect("changed", comboCB, dxml.get_widget("shrinkSB"))

    biggest = -1
    for part in storage.partitions:
        if not part.exists:
            continue

        entry = None
        if part.resizable and part.format.resizable:
            entry = (
                "%s (%s, %d MB)" %
                (part.name, part.format.name, math.floor(part.format.size)),
                part)

        if entry:
            i = store.append(None)
            store[i] = entry
            combo.set_active_iter(i)

            if biggest == -1:
                biggest = i
            else:
                current = store.get_value(biggest, 1)
                if part.format.targetSize > current.format.targetSize:
                    biggest = i

    if biggest > -1:
        combo.set_active_iter(biggest)

    if len(store) == 0:
        dialog.destroy()
        intf.messageWindow(_("Error"),
                           _("No partitions are available to resize.  Only "
                             "physical partitions with specific filesystems "
                             "can be resized."),
                           type="warning",
                           custom_icon="error")
        return (gtk.RESPONSE_CANCEL, [])

    gui.addFrame(dialog)
    dialog.show_all()
    runResize = True

    while runResize:
        rc = dialog.run()
        if rc != gtk.RESPONSE_OK:
            dialog.destroy()
            return (rc, [])

        request = getActive(combo)
        newSize = dxml.get_widget("shrinkSB").get_value_as_int()
        actions = []

        try:
            actions.append(ActionResizeFormat(request, newSize))
        except ValueError as e:
            intf.messageWindow(_("Resize FileSystem Error"),
                               _("%(device)s: %(msg)s") % {
                                   'device': request.format.device,
                                   'msg': e.message
                               },
                               type="warning",
                               custom_icon="error")
            continue

        try:
            actions.append(ActionResizeDevice(request, newSize))
        except ValueError as e:
            intf.messageWindow(_("Resize Device Error"),
                               _("%(name)s: %(msg)s") % {
                                   'name': request.name,
                                   'msg': e.message
                               },
                               type="warning",
                               custom_icon="error")
            continue

        runResize = False

    dialog.destroy()
    return (rc, actions)
Beispiel #33
0
    def getScreen (self, anaconda):
        # We can't just use exclusiveDisks here because of kickstart.  First,
        # the kickstart file could have used ignoredisk --drives= in which case
        # exclusiveDisks would be empty.  Second, ignoredisk is entirely
        # optional in which case neither list would be populated.  Luckily,
        # storage.disks takes isIgnored into account and that handles both these
        # issues.
        disks = filter(lambda d: not d.format.hidden, anaconda.storage.disks)

        # Skip this screen as well if there's only one disk to use.
        if len(disks) == 1:
            anaconda.storage.clearPartDisks = [disks[0].name]
            anaconda.bootloader.drivelist = [disks[0].name]
            return None

        (xml, self.vbox) = gui.getGladeWidget("cleardisks.glade", "vbox")
        self.leftScroll = xml.get_widget("leftScroll")
        self.rightScroll = xml.get_widget("rightScroll")
        self.addButton = xml.get_widget("addButton")
        self.removeButton = xml.get_widget("removeButton")
        self.installTargetImage = xml.get_widget("installTargetImage")
        self.installTargetTip = xml.get_widget("installTargetTip")

        self.anaconda = anaconda

        self.leftVisible = 1
        self.leftActive = 2
        self.rightVisible = 4
        self.rightActive = 5

        # One store for both views.  First the obejct, then a visible/active for
        # the left hand side, then a visible/active for the right hand side, then
        # all the other stuff.
        #
        # NOTE: the third boolean is a placeholder.  DeviceSelector uses the third
        # slot in the store to determine whether the row is immutable or not.  We
        # just need to put False in there for everything.
        self.store = gtk.TreeStore(gobject.TYPE_PYOBJECT,
                                   gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN,
                                   gobject.TYPE_BOOLEAN,
                                   gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN,
                                   gobject.TYPE_STRING, gobject.TYPE_STRING,
                                   gobject.TYPE_STRING, gobject.TYPE_STRING,
                                   gobject.TYPE_STRING)
        self.store.set_sort_column_id(6, gtk.SORT_ASCENDING)

        # The left view shows all the drives that will just be mounted, but
        # can still be moved to the right hand side.
        self.leftFilteredModel = self.store.filter_new()
        self.leftSortedModel = gtk.TreeModelSort(self.leftFilteredModel)
        self.leftTreeView = gtk.TreeView(self.leftSortedModel)

        self.leftFilteredModel.set_visible_func(lambda model, iter, view: model.get_value(iter, self.leftVisible), self.leftTreeView)

        self.leftScroll.add(self.leftTreeView)

        self.leftDS = DeviceSelector(self.store, self.leftSortedModel,
                                     self.leftTreeView, visible=self.leftVisible,
                                     active=self.leftActive)
        self.leftDS.createMenu()
        self.leftDS.addColumn(_("Model"), 6)
        self.leftDS.addColumn(_("Capacity"), 7)
        self.leftDS.addColumn(_("Vendor"), 8)
        self.leftDS.addColumn(_("Identifier"), 9)
        self.leftDS.addColumn(_("Interconnect"), 10, displayed=False)

        # The right view show all the drives that will be wiped during install.
        self.rightFilteredModel = self.store.filter_new()
        self.rightSortedModel = gtk.TreeModelSort(self.rightFilteredModel)
        self.rightTreeView = gtk.TreeView(self.rightSortedModel)

        self.rightFilteredModel.set_visible_func(lambda model, iter, view: model.get_value(iter, self.rightVisible), self.rightTreeView)

        self.rightScroll.add(self.rightTreeView)

        self.rightDS = DeviceSelector(self.store, self.rightSortedModel,
                                      self.rightTreeView, visible=self.rightVisible,
                                      active=self.rightActive)
        self.rightDS.createSelectionCol(title=_("Boot\nLoader"), radioButton=True)
        self.rightDS.createMenu()
        self.rightDS.addColumn(_("Model"), 6)
        self.rightDS.addColumn(_("Capacity"), 7)
        self.rightDS.addColumn(_("Identifier"), 9)

        # Store the first disk (according to our detected BIOS order) for
        # auto boot device selection
        names = map(lambda d: d.name, disks)
        self.bootDisk = sorted(names, self.anaconda.storage.compareDisks)[0]

        # The device filtering UI set up exclusiveDisks as a list of the names
        # of all the disks we should use later on.  Now we need to go get those,
        # look up some more information in the devicetree, and set up the
        # selector.
        for d in disks:
            rightVisible = d.name in self.anaconda.storage.clearPartDisks
            rightActive = rightVisible and \
                          d.name in self.anaconda.bootloader.drivelist[:1]
            leftVisible = not rightVisible

            if hasattr(d, "wwid"):
                ident = d.wwid
            else:
                try:
                    ident = deviceNameToDiskByPath(d.name)
                    if ident.startswith("/dev/disk/by-path/"):
                        ident = ident.replace("/dev/disk/by-path/", "")
                except DeviceNotFoundError:
                    ident = d.name

            self.store.append(None, (d,
                                     leftVisible, True, False,
                                     rightVisible, rightActive,
                                     d.model,
                                     str(int(d.size)) + " MB",
                                     d.vendor, ident, d.bus))

        self.addButton.connect("clicked", self._add_clicked)
        self.removeButton.connect("clicked", self._remove_clicked)

        # Also allow moving devices back and forth with double click, enter, etc.
        self.leftTreeView.connect("row-activated", self._add_clicked)
        self.rightTreeView.disconnect(self.rightDS._activated_id)
        self.rightTreeView.connect("row-activated", self._remove_clicked)

        # And let the user select multiple devices at a time.
        self.leftTreeView.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
        self.rightTreeView.get_selection().set_mode(gtk.SELECTION_MULTIPLE)

        if self.anaconda.storage.clearPartType == CLEARPART_TYPE_LINUX:
            self.installTargetTip.set_markup(_("<b>Tip:</b> All Linux filesystems on the install target devices will be reformatted and wiped of any data.  Make sure you have backups."))
        elif self.anaconda.storage.clearPartType == CLEARPART_TYPE_ALL:
            self.installTargetTip.set_markup(_("<b>Tip:</b> The install target devices will be reformatted and wiped of any data.  Make sure you have backups."))
        else:
            self.installTargetTip.set_markup(_("<b>Tip:</b> Your filesystems on the install target devices will not be reformatted unless you choose to do so during customization."))

        return self.vbox
    def _deviceChange(self, b, anaconda, *args):
        def __genStore(combo, disks, active):
            model = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
            combo.set_model(model)
            cell = gtk.CellRendererText()
            combo.pack_start(cell, True)
            combo.set_attributes(cell, text = 0)

            for disk in disks:
                i = model.append(None)
                model[i] = ("%s %8.0f MB %s" %(disk.name, disk.size,
                                               disk.description),
                            disk)
                if disk.name == active:
                    combo.set_active_iter(i)

            return model

        (dxml, dialog) = gui.getGladeWidget("blwhere.glade",
                                            "blwhereDialog")
        gui.addFrame(dialog)
        dialog.set_transient_for(self.parent)
        dialog.show()

        # XXX for md stage1, should we show md, first member disk, or first
        #     disk?
        stage1 = anaconda.storage.bootLoaderDevice
        stage1_desc = anaconda.bootloader.device_description(stage1)
        choices = {"mbr": (stage1, stage1_desc)}

        stage2 = anaconda.storage.bootDevice
        try:
            stage2_desc = anaconda.bootloader.device_description(stage2)
        except ValueError:
            # stage2's type isn't valid as stage1, so don't offer "boot".
            pass
        else:
            choices["boot"] = (stage2, stage2_desc)

        for t in ("mbr", "boot"):
            if not choices.has_key(t):
                continue
            (device, desc) = choices[t]
            w = dxml.get_widget("%sRadio" %(t,))
            w.set_label("%s - %s" %(desc, device.path))
            w.show()
            w.set_active(self.bldev == device)
            w.set_data("bootDevice", device)

        bl_disks = anaconda.bootloader.drives
        for i in range(1, 5):
            if len(self.driveorder) < i:
                break
            combo = dxml.get_widget("bd%dCombo" %(i,))
            lbl = dxml.get_widget("bd%dLabel" %(i,))
            combo.show()
            lbl.show()
            m = __genStore(combo, bl_disks, self.driveorder[i - 1])

        while True:
            rc = dialog.run()
            if rc in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT]:
                break

            # set the boot device based on what they chose
            if dxml.get_widget("bootRadio").get_active():
                self.bldev = dxml.get_widget("bootRadio").get_data("bootDevice")
            elif dxml.get_widget("mbrRadio").get_active():
                self.bldev = dxml.get_widget("mbrRadio").get_data("bootDevice")
            else:
                raise RuntimeError, "No radio button selected!"

            # and adjust the boot order
            neworder = []
            for i in range(1, 5):
                if len(self.driveorder) < i:
                    break

                combo = dxml.get_widget("bd%dCombo" %(i,))
                iter = combo.get_active_iter()
                if not iter:
                    continue

                act = combo.get_model()[iter][1].name
                if act not in neworder:
                    neworder.append(act)
            for d in self.driveorder:
                if d not in neworder:
                    neworder.append(d)
            self.driveorder = neworder
            break

        dialog.destroy()
        self.grubCB.set_label(_("_Install boot loader on %s.") %
                              (self.bldev.path,))
        return rc