Пример #1
0
    def status(self):
        """ Where we are in the process """
        if self.errors:
            return _("Error checking software selection")
        if not self.ready:
            return _("Processing...")
        if not self.txid_valid:
            return _("Source changed - please verify")

        ## FIXME:
        # quite ugly, but env isn't getting set to gnome (or anything) by
        # default, and it really should be so we can maintain consistency
        # with graphical behavior
        if self._selection >= 0 and not self.environment \
                and not self._kickstarted:
            self.apply()

        if not self.environment:
            # Ks installs with %packages will have an env selected, unless
            # they did an install without a desktop environment. This should
            # catch that one case.
            if self._kickstarted:
                return _("Custom software selected")
            return _("Nothing selected")

        return self.payload.environmentDescription(self.environment)[0]
Пример #2
0
    def _main_loop_handleException(self, dump_info):
        """
        Helper method with one argument only so that it can be registered
        with GLib.idle_add() to run on idle or called from a handler.

        :type dump_info: an instance of the meh.DumpInfo class

        """

        ty = dump_info.exc_info.type
        value = dump_info.exc_info.value

        if (issubclass(ty, blivet.errors.StorageError) and value.hardware_fault) or (
            issubclass(ty, OSError) and value.errno == errno.EIO
        ):
            # hardware fault or '[Errno 5] Input/Output error'
            hw_error_msg = _(
                "The installation was stopped due to what "
                "seems to be a problem with your hardware. "
                "The exact error message is:\n\n%s.\n\n "
                "The installer will now terminate."
            ) % str(value)
            self.intf.messageWindow(_("Hardware error occured"), hw_error_msg)
            sys.exit(0)
        elif isinstance(value, blivet.errors.UnusableConfigurationError):
            sys.exit(0)
        else:
            super(AnacondaExceptionHandler, self).handleException(dump_info)
            return False
Пример #3
0
    def _update_summary(self):
        """ Update the summary based on the UI. """
        count = 0
        capacity = 0
        free = Size(0)

        # pass in our disk list so hidden disks' free space is available
        free_space = self.storage.getFreeSpace(disks=self.disks)
        selected = [d for d in self.disks if d.name in self.selected_disks]

        for disk in selected:
            capacity += disk.size
            free += free_space[disk.name][0]
            count += 1

        summary = (P_(("%d disk selected; %s capacity; %s free ..."),
                      ("%d disks selected; %s capacity; %s free ..."),
                      count) % (count, str(Size(capacity)), free))

        if len(self.disks) == 0:
            summary = _("No disks detected.  Please shut down the computer, connect at least one disk, and restart to complete installation.")
        elif count == 0:
            summary = (_("No disks selected; please select at least one disk to install to."))

        # Append storage errors to the summary
        if self.errors:
            summary = summary + "\n" + "\n".join(self.errors)
        elif self.warnings:
            summary = summary + "\n" + "\n".join(self.warnings)

        return summary
Пример #4
0
    def initialize(self, actions):
        for (i, action) in enumerate(actions, start=1):
            mountpoint = ""

            if action.type in [ACTION_TYPE_DESTROY, ACTION_TYPE_RESIZE]:
                typeString = """<span foreground='red'>%s</span>""" % \
                        escape_markup(action.type_desc.title())
            else:
                typeString = """<span foreground='green'>%s</span>""" % \
                        escape_markup(action.type_desc.title())
                if action.obj == ACTION_OBJECT_FORMAT:
                    mountpoint = getattr(action.device.format, "mountpoint", "")

            if hasattr(action.device, "description"):
                desc = _("%(description)s (%(deviceName)s)") % {"deviceName": action.device.name,
                                                                "description": action.device.description}
                serial = action.device.serial
            elif hasattr(action.device, "disk"):
                desc = _("%(deviceName)s on %(container)s") % {"deviceName": action.device.name,
                                                               "container": action.device.disk.description}
                serial = action.device.disk.serial
            else:
                desc = action.device.name
                serial = action.device.serial

            self._store.append([i,
                                typeString,
                                action.object_type_string,
                                desc,
                                mountpoint,
                                serial])
Пример #5
0
    def refresh(self, args=None):
        NormalTUISpoke.refresh(self, args)

        # Join the initialization thread to block on it
        # This print is foul.  Need a better message display
        print(_(PAYLOAD_STATUS_PROBING_STORAGE))
        threadMgr.wait(THREAD_STORAGE_WATCHER)

        # synchronize our local data store with the global ksdata
        # Commment out because there is no way to select a disk right
        # now without putting it in ksdata.  Seems wrong?
        #self.selected_disks = self.data.ignoredisk.onlyuse[:]
        self.autopart = self.data.autopart.autopart

        message = self._update_summary()

        # loop through the disks and present them.
        for disk in self.disks:
            disk_info = self._format_disk_info(disk)
            c = CheckboxWidget(title="%i) %s" % (self.disks.index(disk) + 1, disk_info),
                               completed=(disk.name in self.selected_disks))
            self._window += [c, ""]

        # if we have more than one disk, present an option to just
        # select all disks
        if len(self.disks) > 1:
            c = CheckboxWidget(title="%i) %s" % (len(self.disks) + 1, _("Select all")),
                                completed=(self.selection == len(self.disks)))

            self._window += [c, ""]

        self._window += [TextWidget(message), ""]

        return True
Пример #6
0
    def refresh(self, args=None):
        """ Refresh screen. """
        self._load_new_devices()
        EditTUISpoke.refresh(self, args)

        summary = self._summary_text()
        self._window += [TextWidget(summary), ""]
        hostname = _("Host Name: %s\n") % self.data.network.hostname
        self._window += [TextWidget(hostname), ""]
        current_hostname = _("Current host name: %s\n") % network.current_hostname()
        self._window += [TextWidget(current_hostname), ""]

        # if we have any errors, display them
        while len(self.errors) > 0:
            self._window += [TextWidget(self.errors.pop()), ""]

        def _prep(i, w):
            """ Mangle our text to make it look pretty on screen. """
            number = TextWidget("%2d)" % (i + 1))
            return ColumnWidget([(4, [number]), (None, [w])], 1)

        _opts = [_("Set host name")]
        for devname in self.supported_devices:
            _opts.append(_("Configure device %s") % devname)
        text = [TextWidget(o) for o in _opts]

        # make everything presentable on screen
        choices = [_prep(i, w) for i, w in enumerate(text)]
        displayed = ColumnWidget([(78, choices)], 1)
        self._window += [displayed, ""]

        return True
Пример #7
0
 def status(self):
     if len(self.data.user.userList) == 0:
         return _("No user will be created")
     elif self._wheel.name in self.data.user.userList[0].groups:
         return _("Administrator %s will be created") % self.data.user.userList[0].name
     else:
         return _("User %s will be created") % self.data.user.userList[0].name
Пример #8
0
 def status(self):
     if self.errors:
         return _("Error setting up software source")
     elif not self._ready:
         return _("Processing...")
     else:
         return self._repo_status()
Пример #9
0
    def _activated_device_msg(self, devname):
        msg = _("Wired (%(interface_name)s) connected\n") \
                % {"interface_name": devname}

        ipv4config = nm.nm_device_ip_config(devname, version=4)
        ipv6config = nm.nm_device_ip_config(devname, version=6)

        if ipv4config and ipv4config[0]:
            addr_str, prefix, gateway_str = ipv4config[0][0]
            netmask_str = network.prefix2netmask(prefix)
            dnss_str = ",".join(ipv4config[1])
        else:
            addr_str = dnss_str = gateway_str = netmask_str = ""
        msg += _(" IPv4 Address: %(addr)s Netmask: %(netmask)s Gateway: %(gateway)s\n") % \
                {"addr": addr_str, "netmask": netmask_str, "gateway": gateway_str}
        msg += _(" DNS: %s\n") % dnss_str

        if ipv6config and ipv6config[0]:
            for ipv6addr in ipv6config[0]:
                addr_str, prefix, gateway_str = ipv6addr
                # Do not display link-local addresses
                if not addr_str.startswith("fe80:"):
                    msg += _(" IPv6 Address: %(addr)s/%(prefix)d\n") % \
                            {"addr": addr_str, "prefix": prefix}

            dnss_str = ",".join(ipv6config[1])

        return msg
Пример #10
0
    def refresh(self, args=None):
        """args is None if we want a list of zones or "zone" to show all timezones in that zone."""
        NormalTUISpoke.refresh(self, args)

        if args and args in self._timezones:
            self._window += [TextWidget(_("Available timezones in region %s") % args)]
            displayed = [TextWidget(z) for z in self._timezones[args]]
        else:
            self._window += [TextWidget(_("Available regions"))]
            displayed = [TextWidget(z) for z in self._regions]

        def _prep(i, w):
            number = TextWidget("%2d)" % (i + 1))
            return ColumnWidget([(4, [number]), (None, [w])], 1)

        # split zones to three columns
        middle = len(displayed) / 3
        left = [_prep(i, w) for i, w in enumerate(displayed) if i <= middle]
        center = [_prep(i, w) for i, w in enumerate(displayed) if i > middle and i <= 2*middle]
        right = [_prep(i, w) for i, w in enumerate(displayed) if i > 2*middle]

        c = ColumnWidget([(24, left), (24, center), (24, right)], 3)
        self._window.append(c)

        return True
Пример #11
0
    def check_password_empty(self, inputcheck):
        """Check whether a password has been specified at all.

           This check is used for both the password and the confirmation.
        """
        # If the password was set by kickstart, skip the strength check
        # pylint: disable=no-member
        if self.input_kickstarted and not self.policy.changesok:
            return InputCheck.CHECK_OK

        # Skip the check if no password is required
        if (not self.input_enabled) or self.input_kickstarted:
            return InputCheck.CHECK_OK
        # Also skip the check if the policy says that an empty password is fine
        # pylint: disable=no-member
        elif self.policy.emptyok:
            return InputCheck.CHECK_OK
        elif not self.get_input(inputcheck.input_obj):
            # pylint: disable=no-member
            if self.policy.strict:
                return _(constants.PASSWORD_EMPTY_ERROR)
            else:
                if self.waive_clicks > 1:
                    return InputCheck.CHECK_OK
                else:
                    return "%s %s" % (_(constants.PASSWORD_EMPTY_ERROR), _(constants.PASSWORD_DONE_TWICE))
        else:
            return InputCheck.CHECK_OK
Пример #12
0
    def on_info_bar_clicked(self, *args):
        if self.errors:
            label = _("The following errors were encountered when checking your storage "
                      "configuration.  You can modify your storage layout or quit the "
                      "installer.")

            dialog = DetailedErrorDialog(self.data, buttons=[_("_Quit"), _("_Modify Storage Layout")], label=label)
            with enlightbox(self.window, dialog.window):
                errors = "\n".join(self.errors)
                dialog.refresh(errors)
                rc = dialog.run()

            dialog.window.destroy()

            if rc == 0:
                # Quit.
                sys.exit(0)
        elif self.warnings:
            label = _("The following warnings were encountered when checking your storage "
                      "configuration.  These are not fatal, but you may wish to make "
                      "changes to your storage layout.")

            dialog = DetailedErrorDialog(self.data, buttons=[_("_OK")], label=label)
            with enlightbox(self.window, dialog.window):
                warnings = "\n".join(self.warnings)
                dialog.refresh(warnings)
                rc = dialog.run()

            dialog.window.destroy()
Пример #13
0
    def connectToView(self):
        """Attempt to connect to self.vncconnecthost"""

        maxTries = 10
        self.log.info(_("Attempting to connect to vnc client on host %s..."), self.vncconnecthost)

        if self.vncconnectport != "":
            hostarg = self.vncconnecthost + ":" + self.vncconnectport
        else:
            hostarg = self.vncconnecthost

        vncconfigcommand = [self.root+"/usr/bin/vncconfig", "-display", ":%s" % constants.X_DISPLAY_NUMBER, "-connect", hostarg]

        for _i in range(maxTries):
            vncconfp = iutil.startProgram(vncconfigcommand, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # vncconfig process
            err = vncconfp.communicate()[1].decode("utf-8")

            if err == '':
                self.log.info(_("Connected!"))
                return True
            elif err.startswith("connecting") and err.endswith("failed\n"):
                self.log.info(_("Will try to connect again in 15 seconds..."))
                time.sleep(15)
                continue
            else:
                log.critical(err)
                iutil.ipmi_abort(scripts=self.anaconda.ksdata.scripts)
                sys.exit(1)
        self.log.error(P_("Giving up attempting to connect after %d try!\n",
                          "Giving up attempting to connect after %d tries!\n",
                          maxTries), maxTries)
        return False
Пример #14
0
    def refresh(self):
        self.disks = getDisks(self.storage.devicetree)

        # synchronize our local data store with the global ksdata
        disk_names = [d.name for d in self.disks]
        # don't put disks with hidden formats in selected_disks
        self.selected_disks = [d for d in self.data.ignoredisk.onlyuse
                                    if d in disk_names]
        self.autopart = self.data.autopart.autopart
        self.autoPartType = self.data.autopart.type
        if self.autoPartType is None:
            # nkwin7 add begin
            # keywords: default partitioning; defaultFS; autopart type; 
            #           add combo; delete refresh button
            #reset autopart type to be AUTOPART_TYPE_PLAIN
            #self.autoPartType = AUTOPART_TYPE_LVM
            self.autoPartType = AUTOPART_TYPE_PLAIN
            # nkwin7 end
        self.encrypted = self.data.autopart.encrypted
        self.passphrase = self.data.autopart.passphrase

        self._previous_autopart = self.autopart

        # First, remove all non-button children.
        for child in self.localOverviews + self.advancedOverviews:
            child.destroy()

        # Then deal with local disks, which are really easy.  They need to be
        # handled here instead of refresh to take into account the user pressing
        # the rescan button on custom partitioning.
        for disk in filter(isLocalDisk, self.disks):
            self._add_disk_overview(disk, self.local_disks_box)

        # Advanced disks are different.  Because there can potentially be a lot
        # of them, we do not display them in the box by default.  Instead, only
        # those selected in the filter UI are displayed.  This means refresh
        # needs to know to create and destroy overviews as appropriate.
        for name in self.data.ignoredisk.onlyuse:
            obj = self.storage.devicetree.getDeviceByName(name, hidden=True)
            if isLocalDisk(obj):
                continue

            self._add_disk_overview(obj, self.specialized_disks_box)

        # update the selections in the ui
        for overview in self.localOverviews + self.advancedOverviews:
            name = overview.get_property("name")
            # nkwin7 add begin
            # keywords:indirect and direct; default selected disks; show correctly messages
            #overview.set_chosen(name in self.selected_disks)
            # we default select all disks.
            overview.set_chosen(True)
            # nkwin7 end

        self._update_summary()

        if self.errors:
            self.set_warning(_("Error checking storage configuration.  Click for details."))
        elif self.warnings:
            self.set_warning(_("Warning checking storage configuration.  Click for details."))
Пример #15
0
    def _update_summary(self):
        """ Update the summary based on the UI. """
        count = 0
        capacity = 0
        free = Size(bytes=0)

        # pass in our disk list so hidden disks' free space is available
        free_space = self.storage.getFreeSpace(disks=self.disks)
        selected = [d for d in self.disks if d.name in self.selected_disks]

        for disk in selected:
            capacity += disk.size
            free += free_space[disk.name][0]
            count += 1

        summary = (P_("%d disk selected; %s capacity; %s free",
                      "%d disks selected; %s capacity; %s free",
                      count) % (count, str(Size(spec="%s MB" % capacity)), free))
        summary_label = self.builder.get_object("summary_label")
        summary_label.set_text(summary)
        summary_label.set_sensitive(count > 0)

        summary_button = self.builder.get_object("summary_button")
        summary_button.set_visible(count > 0)

        if len(self.disks) == 0:
            self.set_warning(_("No disks detected.  Please shut down the computer, connect at least one disk, and restart to complete installation."))
        elif count == 0:
            self.set_warning(_("No disks selected; please select at least one disk to install to."))
        else:
            self.clear_info()
Пример #16
0
 def status(self):
     if self.data.rootpw.password:
         return _("Root password is set")
     elif self.data.rootpw.lock:
         return _("Root account is disabled")
     else:
         return _("Root password is not set")
Пример #17
0
    def refresh(self, required_space, auto_swap, disk_free, fs_free, autoPartType, encrypted):
        self.autoPartType = autoPartType
        self.autoPartTypeCombo = self.builder.get_object("options2_combo")
        self.autoPartTypeCombo.set_active(self.autoPartType)

        self.encrypted = encrypted
        self.encryptCheckbutton = self.builder.get_object("encryption2_checkbutton")
        self.encryptCheckbutton.set_active(self.encrypted)

        sw_text = self._get_sw_needs_text(required_space, auto_swap)
        label_text = _("%s The disks you've selected have the following "
                       "amounts of free space:") % sw_text
        label = self.builder.get_object("options2_label1")
        label.set_markup(label_text)
        label.set_tooltip_text(_("Please wait... software metadata still loading."))
        label.connect("activate-link", self._modify_sw_link_clicked)

        self.disk_free_label = self.builder.get_object("options2_disk_free_label")
        self.fs_free_label = self.builder.get_object("options2_fs_free_label")
        self._set_free_space_labels(disk_free, fs_free)

        label_text = _("<b>You don't have enough space available to install "
                       "%s</b>.  You can shrink or remove existing partitions "
                       "via our guided reclaim space tool, or you can adjust your "
                       "partitions on your own in the custom partitioning "
                       "interface.") % productName
        self.builder.get_object("options2_label2").set_markup(label_text)

        self._add_modify_watcher("options2_label1")
Пример #18
0
    def _do_check(self):
        self.clear_errors()
        StorageCheckHandler.errors = []
        StorageCheckHandler.warnings = []

        # We can't overwrite the main Storage instance because all the other
        # spokes have references to it that would get invalidated, but we can
        # achieve the same effect by updating/replacing a few key attributes.
        self.storage.devicetree._devices = self._storage_playground.devicetree._devices
        self.storage.devicetree._actions = self._storage_playground.devicetree._actions
        self.storage.devicetree._hidden = self._storage_playground.devicetree._hidden
        self.storage.devicetree.names = self._storage_playground.devicetree.names
        self.storage.roots = self._storage_playground.roots

        # set up bootloader and check the configuration
        try:
            self.storage.set_up_bootloader()
        except BootLoaderError as e:
            log.error("storage configuration failed: %s", e)
            StorageCheckHandler.errors = str(e).split("\n")
            self.data.bootloader.bootDrive = ""

        StorageCheckHandler.checkStorage(self)

        if self.errors:
            self.set_warning(_("Error checking storage configuration.  <a href=\"\">Click for details</a> or press Done again to continue."))
        elif self.warnings:
            self.set_warning(_("Warning checking storage configuration.  <a href=\"\">Click for details</a> or press Done again to continue."))

        # on_info_bar_clicked requires self._error to be set, so set it to the
        # list of all errors and warnings that storage checking found.
        self._error = "\n".join(self.errors + self.warnings)

        return self._error == ""
Пример #19
0
    def install(self):
        progressQ.send_message(_('Starting package installation process'))

        # Add the rpm macros to the global transaction environment
        for macro in self.rpmMacros:
            rpm.addMacro(macro[0], macro[1])

        if self.install_device:
            self._setupMedia(self.install_device)
        try:
            self.checkSoftwareSelection()
            self._download_location = self._pick_download_location()
        except packaging.PayloadError as e:
            if errors.errorHandler.cb(e) == errors.ERROR_RAISE:
                _failure_limbo()

        pkgs_to_download = self._base.transaction.install_set
        log.info('Downloading packages.')
        progressQ.send_message(_('Downloading packages'))
        progress = DownloadProgress()
        try:
            self._base.download_packages(pkgs_to_download, progress)
        except dnf.exceptions.DownloadError as e:
            msg = 'Failed to download the following packages: %s' % str(e)
            exc = packaging.PayloadInstallError(msg)
            if errors.errorHandler.cb(exc) == errors.ERROR_RAISE:
                _failure_limbo()

        log.info('Downloading packages finished.')

        pre_msg = _("Preparing transaction from installation source")
        progressQ.send_message(pre_msg)

        queue_instance = multiprocessing.Queue()
        process = multiprocessing.Process(target=do_transaction,
                                          args=(self._base, queue_instance))
        process.start()
        (token, msg) = queue_instance.get()
        while token not in ('post', 'quit'):
            if token == 'install':
                msg = _("Installing %s") % msg
                progressQ.send_message(msg)
            (token, msg) = queue_instance.get()

        if token == 'quit':
            _failure_limbo()

        post_msg = _("Performing post-installation setup tasks")
        progressQ.send_message(post_msg)
        process.join()
        self._base.close()
        if os.path.exists(self._download_location):
            log.info("Cleaning up downloaded packages: %s", self._download_location)
            shutil.rmtree(self._download_location)
        else:
            # Some installation sources, such as NFS, don't need to download packages to
            # local storage, so the download location might not always exist. So for now
            # warn about this, at least until the RFE in bug 1193121 is implemented and
            # we don't have to care about clearing the download location ourselves.
            log.warning("Can't delete nonexistent download location: %s", self._download_location)
Пример #20
0
    def refresh(self, args=None):
        NormalTUISpoke.refresh(self, args)

        # check if the storage refresh thread is running
        if threadMgr.get(THREAD_STORAGE_WATCHER):
            # storage refresh is running - just report it
            # so that the user can refresh until it is done
            # TODO: refresh once the thread is done ?
            message = _(PAYLOAD_STATUS_PROBING_STORAGE)
            self._window += [TextWidget(message), ""]
            return True

        # check if there are any mountable devices
        if self._mountable_devices:
            def _prep(i, w):
                """ Mangle our text to make it look pretty on screen. """
                number = TextWidget("%2d)" % (i + 1))
                return ColumnWidget([(4, [number]), (None, [w])], 1)

            devices = [TextWidget(d[1]) for d in self._mountable_devices]

            # gnarl and mangle all of our widgets so things look pretty on
            # screen
            choices = [_prep(i, w) for i, w in enumerate(devices)]

            displayed = ColumnWidget([(78, choices)], 1)
            self._window.append(displayed)

        else:
            message = _("No mountable devices found")
            self._window += [TextWidget(message), ""]
        return True
Пример #21
0
    def retranslate(self, lang):
        # Change the translations on labels and buttons that do not have
        # substitution text.
        for name in ["pickLanguageLabel", "betaWarnTitle", "betaWarnDesc",
                     "quitButton", "continueButton"]:
            self._retranslate_one(name)

        # The welcome label is special - it has text that needs to be
        # substituted.
        welcomeLabel = self.builder.get_object("welcomeLabel")

        if not welcomeLabel in self._origStrings:
            self._origStrings[welcomeLabel] = welcomeLabel.get_label()

        before = self._origStrings[welcomeLabel]
        # pylint: disable-msg=E1103
        xlated = _(before) % {"name" : productName.upper(), "version" : productVersion}
        welcomeLabel.set_label(xlated)

        # Retranslate the language (filtering) entry's placeholder text
        languageEntry = self.builder.get_object("languageEntry")
        if not languageEntry in self._origStrings:
            self._origStrings[languageEntry] = languageEntry.get_placeholder_text()

        languageEntry.set_placeholder_text(_(self._origStrings[languageEntry]))

        # And of course, don't forget the underlying window.
        self.window.set_property("distribution", distributionText().upper())
        self.window.retranslate(lang)
Пример #22
0
    def refresh(self, args=None):
        """
        args is None if we want a list of languages; or, it is a list of all
        locales for a language.
        """
        NormalTUISpoke.refresh(self, args)

        if args:
            self._window += [TextWidget(_("Available locales"))]
            displayed = [TextWidget(localization.get_english_name(z)) for z in args]
        else:
            self._window += [TextWidget(_("Available languages"))]
            displayed = [TextWidget(z) for z in self._langs]

        def _prep(i, w):
            """ make everything look nice """
            number = TextWidget("%2d)" % (i + 1))
            return ColumnWidget([(4, [number]), (None, [w])], 1)

        # split zones to three columns
        middle = len(displayed) / 3
        left = [_prep(i, w) for i, w in enumerate(displayed) if i <= middle]
        center = [_prep(i, w) for i, w in enumerate(displayed) if i > middle and i <= 2*middle]
        right = [_prep(i, w) for i, w in enumerate(displayed) if i > 2*middle]

        c = ColumnWidget([(24, left), (24, center), (24, right)], 3)
        self._window += [c, ""]

        return True
Пример #23
0
def verify_partition_format_sizes(storage, constraints, report_error, report_warning):
    """ Verify that the size of the device is allowed by the format used.

    :param storage: a storage to check
    :param constraints: a dictionary of constraints
    :param report_error: a function for error reporting
    :param report_warning: a function for warning reporting
    """
    # storage.mountpoints is a property that returns a new dict each time, so
    # iterating over it is thread-safe.
    filesystems = storage.mountpoints

    for (mount, device) in filesystems.items():
        problem = filesystems[mount].check_size()
        if problem < 0:
            report_error(_("Your %(mount)s partition is too small for "
                           "%(format)s formatting (allowable size is "
                           "%(minSize)s to %(maxSize)s)")
                         % {"mount": mount, "format": device.format.name,
                            "minSize": device.min_size, "maxSize": device.max_size})
        elif problem > 0:
            report_error(_("Your %(mount)s partition is too large for "
                           "%(format)s formatting (allowable size is "
                           "%(minSize)s to %(maxSize)s)")
                         % {"mount": mount, "format": device.format.name,
                            "minSize": device.min_size, "maxSize": device.max_size})
Пример #24
0
    def input(self, args, key):
        """Override input so that we can launch the VNC password spoke"""

        try:
            keyid = int(key) - 1
            if 0 <= keyid < len(self._choices):
                choice = self._choices[keyid]
                if choice == _(USETEXT):
                    self._usevnc = False
                else:
                    self._usevnc = True
                    newspoke = VNCPassSpoke(self.app, self.data, self.storage,
                                            self.payload, self.instclass)
                    self.app.switch_screen_modal(newspoke)

                self.apply()
                self.close()
            return INPUT_PROCESSED
        except ValueError:
            pass

        # TRANSLATORS: 'q' to quit
        if key.lower() == C_('TUI|Spoke Navigation', 'q'):
            d = YesNoDialog(self.app, _(self.app.quit_message))
            self.app.switch_screen_modal(d)
            if d.answer:
                iutil.ipmi_report(IPMI_ABORTED)
                if can_touch_runtime_system("Quit and Reboot"):
                    execWithRedirect("systemctl", ["--no-wall", "reboot"])
                else:
                    exit(1)
        else:
            return key
Пример #25
0
def verify_root(storage, constraints, report_error, report_warning):
    """ Verify the root.

    :param storage: a storage to check
    :param constraints: a dictionary of constraints
    :param report_error: a function for error reporting
    :param report_warning: a function for warning reporting
    """
    root = storage.fsset.root_device

    if root:
        if root.size < constraints[STORAGE_MIN_ROOT]:
            report_warning(_("Your root partition is less than %(size)s "
                             "which is usually too small to install "
                             "%(product)s.")
                           % {'size': constraints[STORAGE_MIN_ROOT],
                              'product': productName})
    else:
        report_error(_("You have not defined a root partition (/), "
                       "which is required for installation of %s"
                       " to continue.") % (productName,))

    if storage.root_device and storage.root_device.format.exists:
        e = storage.must_format(storage.root_device)
        if e:
            report_error(e)
Пример #26
0
def validate_mountpoint(mountpoint, used_mountpoints, strict=True):
    if strict:
        fake_mountpoints = []
    else:
        fake_mountpoints = ["swap", "biosboot", "prepboot"]

    if mountpoint in used_mountpoints:
        return _("That mount point is already in use. Try something else?")
    elif not mountpoint:
        return _("Please enter a valid mount point.")
    elif mountpoint in system_mountpoints:
        return _("That mount point is invalid. Try something else?")
    elif (lowerASCII(mountpoint) not in fake_mountpoints and
          ((len(mountpoint) > 1 and mountpoint.endswith("/")) or
           not mountpoint.startswith("/") or
           " " in mountpoint or
           re.search(r'/\.*/', mountpoint) or
           re.search(r'/\.+$', mountpoint))):
        # - does not end with '/' unless mountpoint _is_ '/'
        # - starts with '/' except for "swap", &c
        # - does not contain spaces
        # - does not contain pairs of '/' enclosing zero or more '.'
        # - does not end with '/' followed by one or more '.'
        return _("That mount point is invalid. Try something else?")
    else:
        return ""
Пример #27
0
    def _update_action_buttons(self, row):
        obj = PartStoreRow(*row)
        device = self.storage.devicetree.get_device_by_id(obj.id)

        # Disks themselves may be editable in certain ways, but they are never
        # shrinkable.
        self._preserveButton.set_sensitive(obj.editable)
        self._shrinkButton.set_sensitive(obj.editable and not device.is_disk)
        self._deleteButton.set_sensitive(obj.editable)
        self._resizeSlider.set_visible(False)

        if not obj.editable:
            return

        # If the selected filesystem does not support shrinking, make that
        # button insensitive.
        self._shrinkButton.set_sensitive(device.resizable)

        if device.resizable:
            self._setup_slider(device, Size(obj.target))

        # Then, disable the button for whatever action is currently selected.
        # It doesn't make a lot of sense to allow clicking that.
        if obj.action == _(PRESERVE):
            self._preserveButton.set_sensitive(False)
        elif obj.action == _(SHRINK):
            self._shrinkButton.set_sensitive(False)
            self._resizeSlider.set_visible(True)
        elif obj.action == _(DELETE):
            self._deleteButton.set_sensitive(False)
Пример #28
0
 def prompt(self, args=None):
     """ Customize default prompt. """
     prompt = NormalTUISpoke.prompt(self, args)
     prompt.set_message(_("Please select language support to install"))
     # TRANSLATORS: 'b' to go back
     prompt.add_option(C_("TUI|Spoke Navigation|Language Support", "b"), _("to return to language list"))
     return prompt
Пример #29
0
 def _doExecute(self):
     self._ready = False
     hubQ.send_not_ready(self.__class__.__name__)
     # on the off-chance dasdfmt is running, we can't proceed further
     threadMgr.wait(constants.THREAD_DASDFMT)
     hubQ.send_message(self.__class__.__name__, _("Saving storage configuration..."))
     try:
         doKickstartStorage(self.storage, self.data, self.instclass)
     except (StorageError, KickstartValueError) as e:
         log.error("storage configuration failed: %s", e)
         StorageChecker.errors = str(e).split("\n")
         hubQ.send_message(self.__class__.__name__, _("Failed to save storage configuration..."))
         self.data.bootloader.bootDrive = ""
         self.data.ignoredisk.drives = []
         self.data.ignoredisk.onlyuse = []
         self.storage.config.update(self.data)
         self.storage.reset()
         self.disks = getDisks(self.storage.devicetree)
         # now set ksdata back to the user's specified config
         applyDiskSelection(self.storage, self.data, self.selected_disks)
     except BootLoaderError as e:
         log.error("BootLoader setup failed: %s", e)
         StorageChecker.errors = str(e).split("\n")
         hubQ.send_message(self.__class__.__name__, _("Failed to save storage configuration..."))
         self.data.bootloader.bootDrive = ""
     else:
         if self.autopart:
             self.run()
     finally:
         resetCustomStorageData(self.data)
         self._ready = True
         hubQ.send_ready(self.__class__.__name__, True)
Пример #30
0
    def retranslate(self):
        # Change the translations on labels and buttons that do not have
        # substitution text.
        for name in ["pickLanguageLabel", "betaWarnTitle", "betaWarnDesc"]:
            self._retranslate_one(name)

        # It would be nice to be able to read the translation context from the
        # widget, but we live in an imperfect world.
        # See also: https://bugzilla.gnome.org/show_bug.cgi?id=729066
        for name in ["quitButton", "continueButton"]:
            self._retranslate_one(name, "GUI|Welcome|Beta Warn Dialog")

        # The welcome label is special - it has text that needs to be
        # substituted.
        welcomeLabel = self.builder.get_object("welcomeLabel")

        welcomeLabel.set_text(
            _("WELCOME TO %(name)s %(version)s.") % {"name": productName.upper(), "version": productVersion}
        )

        # Retranslate the language (filtering) entry's placeholder text
        languageEntry = self.builder.get_object("languageEntry")
        if not languageEntry in self._origStrings:
            self._origStrings[languageEntry] = languageEntry.get_placeholder_text()

        languageEntry.set_placeholder_text(_(self._origStrings[languageEntry]))

        # And of course, don't forget the underlying window.
        self.window.set_property("distribution", distributionText().upper())
        self.window.retranslate()
Пример #31
0
 def _checkStrength(self, inputcheck):
     if self._pwq_error:
         return ("dialog-error", _(ERROR_WEAK) % self._pwq_error)
     else:
         return InputCheck.CHECK_OK
Пример #32
0
class TUIHub(TUIObject, common.Hub):
    """Base Hub class implementing the pyanaconda.ui.common.Hub interface.
    It uses text based categories to look for relevant Spokes and manages
    all the spokes it finds to have the proper category.

    :param categories: list all the spoke categories to be displayed in this Hub
    :type categories: list of strings

    :param title: title for this Hub
    :type title: unicode

    """

    categories = []
    title = _("Default HUB title")

    def __init__(self, app, data, storage, payload, instclass):
        TUIObject.__init__(self, app, data)
        common.Hub.__init__(self, data, storage, payload, instclass)

        self._spokes = {}  # holds spokes referenced by their class name
        self._keys = {}  # holds spokes referenced by their user input key
        self._spoke_count = 0

    def setup(self, environment="anaconda"):
        # look for spokes having category present in self.categories
        for c in self.categories:
            spokes = collect_spokes(self.paths["spokes"], c)

            # sort them according to their priority
            for s in sorted(spokes, key=lambda s: s.title):
                # Check if this spoke is to be shown in anaconda
                if not s.should_run(environment, self.data):
                    continue

                spoke = s(self.app, self.data, self.storage, self.payload,
                          self.instclass)
                spoke.initialize()

                if not spoke.showable:
                    spoke.teardown()
                    del spoke
                    continue

                if spoke.indirect:
                    continue

                self._spoke_count += 1
                self._keys[self._spoke_count] = spoke
                self._spokes[spoke.__class__.__name__] = spoke

        # only schedule the hub if it has some spokes
        return self._spoke_count != 0

    def refresh(self, args=None):
        """This methods fills the self._window list by all the objects
        we want shown on this screen. Title and Spokes mostly."""
        TUIObject.refresh(self, args)

        def _prep(i, w):
            number = tui.TextWidget("%2d)" % i)
            return tui.ColumnWidget([(3, [number]), (None, [w])], 1)

        # split spokes to two columns
        left = [_prep(i, w) for i, w in self._keys.iteritems() if i % 2 == 1]
        right = [_prep(i, w) for i, w in self._keys.iteritems() if i % 2 == 0]

        c = tui.ColumnWidget([(39, left), (39, right)], 2)
        self._window.append(c)

        return True

    def input(self, args, key):
        """Handle user input. Numbers are used to show a spoke, the rest is passed
        to the higher level for processing."""

        try:
            number = int(key)
            self.app.switch_screen_with_return(self._keys[number])
            return None

        except (ValueError, KeyError):
            # If we get a continue, check for unfinished spokes.  If unfinished
            # don't continue
            # TRANSLATORS: 'c' to continue
            if key == _('c'):
                for spoke in self._spokes.values():
                    if not spoke.completed and spoke.mandatory:
                        print(
                            _("Please complete all spokes before continuing"))
                        return False
            return key
Пример #33
0
    def startServer(self):
        self.log.info(_("Starting VNC..."))
        network.wait_for_connectivity()

        # Lets call it from here for now.
        try:
            self.initialize()
        except (socket.herror, dbus.DBusException, ValueError) as e:
            stdoutLog.critical("Could not initialize the VNC server: %s", e)
            iutil.ipmi_report(constants.IPMI_ABORTED)
            sys.exit(1)

        if self.password and (len(self.password) < 6
                              or len(self.password) > 8):
            self.changeVNCPasswdWindow()

        if not self.password:
            SecurityTypes = "None"
            rfbauth = "0"
        else:
            SecurityTypes = "VncAuth"
            rfbauth = self.pw_file
            # Create the password file.
            self.setVNCPassword()

        # Lets start the xvnc.
        xvnccommand = [
            XVNC_BINARY_NAME,
            ":%s" % constants.X_DISPLAY_NUMBER, "-depth", "16", "-br",
            "IdleTimeout=0", "-auth", "/dev/null", "-once",
            "DisconnectClients=false",
            "desktop=%s" % (self.desktop, ),
            "SecurityTypes=%s" % SecurityTypes,
            "rfbauth=%s" % rfbauth
        ]

        try:
            iutil.startX(xvnccommand, output_redirect=self.openlogfile())
        except OSError:
            stdoutLog.critical("Could not start the VNC server.  Aborting.")
            iutil.ipmi_report(constants.IPMI_ABORTED)
            sys.exit(1)

        self.log.info(_("The VNC server is now running."))

        # Lets tell the user what we are going to do.
        if self.vncconnecthost != "":
            self.log.warning(
                _("\n\nYou chose to connect to a listening vncviewer. \n"
                  "This does not require a password to be set.  If you \n"
                  "set a password, it will be used in case the connection \n"
                  "to the vncviewer is unsuccessful\n\n"))
        elif self.password == "":
            self.log.warning(
                _("\n\nWARNING!!! VNC server running with NO PASSWORD!\n"
                  "You can use the vncpassword=<password> boot option\n"
                  "if you would like to secure the server.\n\n"))
        elif self.password != "":
            self.log.warning(
                _("\n\nYou chose to execute vnc with a password. \n\n"))
        else:
            self.log.warning(_("\n\nUnknown Error.  Aborting. \n\n"))
            iutil.ipmi_report(constants.IPMI_ABORTED)
            sys.exit(1)

        # Lets try to configure the vnc server to whatever the user specified
        if self.vncconnecthost != "":
            connected = self.connectToView()
            if not connected:
                self.VNCListen()
        else:
            self.VNCListen()

        # Start vncconfig for copy/paste
        self.startVncConfig()
Пример #34
0
 def _show_no_ntp_server_warning(self):
     self.set_warning(_("You have no working NTP server configured"))
Пример #35
0
 def _show_no_network_warning(self):
     self.set_warning(_("You need to set up networking first if you "\
                        "want to use NTP"))
Пример #36
0
def doConfiguration(storage, payload, ksdata, instClass):
    willWriteNetwork = not flags.flags.imageInstall and not flags.flags.dirInstall
    willRunRealmd = ksdata.realm.discovered

    # configure base, create users, configure addons, initramfs, post-install
    step_count = 5

    # network, maybe
    if willWriteNetwork:
        step_count += 1

    # if a realm was discovered,
    # increment the counter as the
    # real joining step will be executed
    if willRunRealmd:
        step_count += 1

    if ksdata.snapshot and ksdata.snapshot.has_snapshot(SNAPSHOT_WHEN_POST_INSTALL):
        step_count += 1

    progress_init(step_count)

    # Now run the execute methods of ksdata that require an installed system
    # to be present first.
    with progress_report(_("Configuring installed system")):
        ksdata.authconfig.execute(storage, ksdata, instClass)
        ksdata.selinux.execute(storage, ksdata, instClass)
        ksdata.firstboot.execute(storage, ksdata, instClass)
        ksdata.services.execute(storage, ksdata, instClass)
        ksdata.keyboard.execute(storage, ksdata, instClass)
        ksdata.timezone.execute(storage, ksdata, instClass)
        ksdata.lang.execute(storage, ksdata, instClass)
        ksdata.firewall.execute(storage, ksdata, instClass)
        ksdata.xconfig.execute(storage, ksdata, instClass)
        ksdata.skipx.execute(storage, ksdata, instClass)

    if willWriteNetwork:
        with progress_report(_("Writing network configuration")):
            ksdata.network.execute(storage, ksdata, instClass)

    # Creating users and groups requires some pre-configuration.
    with progress_report(_("Creating users")):
        createLuserConf(iutil.getSysroot(), algoname=getPassAlgo(ksdata.authconfig.authconfig))
        u = Users()
        ksdata.rootpw.execute(storage, ksdata, instClass, u)
        ksdata.group.execute(storage, ksdata, instClass, u)
        ksdata.user.execute(storage, ksdata, instClass, u)
        ksdata.sshkey.execute(storage, ksdata, instClass, u)

    with progress_report(_("Configuring addons")):
        ksdata.addons.execute(storage, ksdata, instClass, u, payload)

    with progress_report(_("Generating initramfs")):
        payload.recreateInitrds(force=True)

    if willRunRealmd:
        with progress_report(_("Joining realm: %s") % ksdata.realm.discovered):
            ksdata.realm.execute(storage, ksdata, instClass)

    with progress_report(_("Running post-installation scripts")):
        runPostScripts(ksdata.scripts)

    # setup kexec reboot if requested
    if flags.flags.kexec:
        setup_kexec()

    # Write the kickstart file to the installed system (or, copy the input
    # kickstart file over if one exists).
    if flags.flags.nosave_output_ks:
        # don't write the kickstart file to the installed system if this has
        # been disabled by the nosave option
        log.warning("Writing of the output kickstart to installed system has been disabled"
                    " by the nosave option.")
    else:
        _writeKS(ksdata)

    # write out the user interaction config file
    screen_access.sam.write_out_config_file()

    if ksdata.snapshot and ksdata.snapshot.has_snapshot(SNAPSHOT_WHEN_POST_INSTALL):
        with progress_report(N_("Creating snapshots")):
            ksdata.snapshot.execute(storage, ksdata, instClass)

    progress_complete()
Пример #37
0
def doInstall(storage, payload, ksdata, instClass):
    """Perform an installation.  This method takes the ksdata as prepared by
       the UI (the first hub, in graphical mode) and applies it to the disk.
       The two main tasks for this are putting filesystems onto disks and
       installing packages onto those filesystems.
    """
    willRunRealmd = ksdata.realm.join_realm
    willInstallBootloader = not flags.flags.dirInstall and (not ksdata.bootloader.disabled
                                                            and ksdata.bootloader != "none")

    # First save system time to HW clock.
    if flags.can_touch_runtime_system("save system time to HW clock"):
        timezone.save_hw_clock(ksdata.timezone)

    # We really only care about actions that affect filesystems, since
    # those are the ones that take the most time.
    steps = len(storage.devicetree.findActions(action_type="create", object_type="format")) + \
            len(storage.devicetree.findActions(action_type="resize", object_type="format"))

    # pre setup phase, pre install, post install
    steps += 3

    # realmd, maybe
    if willRunRealmd:
        steps += 1

    # bootloader, maybe
    if willInstallBootloader:
        steps += 1

    # This should be the only thread running, wait for the others to finish if not.
    if threadMgr.running > 1:
        progress_init(steps+1)

        with progress_report(_("Waiting for %s threads to finish") % (threadMgr.running-1)):
            map(log.debug, ("Thread %s is running" % n for n in threadMgr.names))
            threadMgr.wait_all()
    else:
        progress_init(steps)

    with progress_report(_("Setting up the installation environment")):
        ksdata.firstboot.setup(storage, ksdata, instClass)
        ksdata.addons.setup(storage, ksdata, instClass, payload)

    # put custom storage info into ksdata, but not if just assigning mount points
    if not ksdata.mount.dataList():
        storage.updateKSData()

    # Do partitioning.
    payload.preStorage()

    # callbacks for blivet
    message_clbk = lambda clbk_data: progress_message(clbk_data.msg)
    step_clbk = lambda clbk_data: progress_step(clbk_data.msg)
    entropy_wait_clbk = lambda clbk_data: wait_for_entropy(clbk_data.msg,
                                                           clbk_data.min_entropy, ksdata)
    callbacks_reg = callbacks.create_new_callbacks_register(create_format_pre=message_clbk,
                                                            create_format_post=step_clbk,
                                                            resize_format_pre=message_clbk,
                                                            resize_format_post=step_clbk,
                                                            wait_for_entropy=entropy_wait_clbk)

    turnOnFilesystems(storage, mountOnly=flags.flags.dirInstall, callbacks=callbacks_reg)
    write_storage_late = (flags.flags.livecdInstall or ksdata.ostreesetup.seen
                          or ksdata.method.method == "liveimg")
    if not write_storage_late and not flags.flags.dirInstall:
        storage.write()

    #
    # STACKI
    #
    # Check to see if we're running as a frontend
    #
    import os

    file = open('/proc/cmdline', 'r')
    args = file.readline().split()
    file.close()

    if 'frontend' in args:
	# If /export does not exist, create a symlink
	# to /state/partition1. If /state/partition1 doesn't
	# exist either, just ignore
	if not os.path.exists('/mnt/sysimage/export'):
		if os.path.exists('/mnt/sysimage/state/partition1'):
			pwd = os.getcwd()
			os.chdir('/mnt/sysimage')
			os.symlink('state/partition1',
				'export')
			os.chdir(pwd)
	
	# Enable all known repos
        for repo in payload._yum.repos.repos.values():
		payload.enableRepo(repo.id)
		log.debug('STACKI: repo.id (%s) - %s' % (repo.id, repo.isEnabled()))

    else:
	#
	# need to setup a symbolic link in order to store all the packages
	# downloaded by lighttpd
	#
	cmd = 'rm -rf /install ; '
	cmd += 'mkdir -p /mnt/sysimage/install ; '
	cmd += 'ln -s /mnt/sysimage/install /install'
	os.system(cmd)

    # STACKI

    # Run %pre-install scripts with the filesystem mounted and no packages
    with progress_report(_("Running pre-installation scripts")):
        runPreInstallScripts(ksdata.scripts)

    # Do packaging.

    # Discover information about realms to join,
    # to determine additional packages
    if willRunRealmd:
        with progress_report(_("Discovering realm to join")):
            ksdata.realm.setup()

    # make name resolution work for rpm scripts in chroot
    if flags.can_touch_runtime_system("copy /etc/resolv.conf to sysroot"):
        network.copyFileToPath("/etc/resolv.conf", iutil.getSysroot())

    # Check for additional packages
    ksdata.authconfig.setup()
    ksdata.firewall.setup()
    # Setup timezone and add chrony as package if timezone was set in KS
    # and "-chrony" wasn't in packages section and/or --nontp wasn't set.
    ksdata.timezone.setup(ksdata)

    # anaconda requires storage packages in order to make sure the target
    # system is bootable and configurable, and some other packages in order
    # to finish setting up the system.
    packages = storage.packages + ksdata.realm.packages
    packages += ksdata.authconfig.packages + ksdata.firewall.packages

    if willInstallBootloader:
        packages += storage.bootloader.packages

    if network.is_using_team_device():
        packages.append("teamd")

    # don't try to install packages from the install class' ignored list and the
    # explicitly excluded ones (user takes the responsibility)
    packages = [p for p in packages
                if p not in instClass.ignoredPackages and p not in ksdata.packages.excludedList]
    payload.preInstall(packages=packages, groups=payload.languageGroups())
    payload.install()

    if write_storage_late and not flags.flags.dirInstall:
        if iutil.getSysroot() != iutil.getTargetPhysicalRoot():
            blivet.setSysroot(iutil.getTargetPhysicalRoot(),
                              iutil.getSysroot())
            # Note this changed for RHEL 7.5; see comments in rpmostreepayload.py.
            payload.prepareMountTargets(storage)

        storage.write()

    # Do bootloader.
    if willInstallBootloader:
        with progress_report(_("Installing boot loader")):
            writeBootLoader(storage, payload, instClass, ksdata)

    with progress_report(_("Performing post-installation setup tasks")):
        payload.postInstall()

    progress_complete()
Пример #38
0
def progress_message(message):
    progressQ.send_message(_(message))
    log.info(message)
Пример #39
0
    def install(self):
        progress_message(N_('Starting package installation process'))

        # Add the rpm macros to the global transaction environment
        for macro in self.rpmMacros:
            rpm.addMacro(macro[0], macro[1])

        if self.install_device:
            self._setupMedia(self.install_device)
        try:
            self.checkSoftwareSelection()
            self._download_location = self._pick_download_location()
        except payload.PayloadError as e:
            if errors.errorHandler.cb(e) == errors.ERROR_RAISE:
                log.error("Installation failed: %r", e)
                _failure_limbo()

        pkgs_to_download = self._base.transaction.install_set
        log.info('Downloading packages to %s.', self._download_location)
        progressQ.send_message(_('Downloading packages'))
        progress = DownloadProgress()
        try:
            self._base.download_packages(pkgs_to_download, progress)
        except dnf.exceptions.DownloadError as e:
            msg = 'Failed to download the following packages: %s' % str(e)
            exc = payload.PayloadInstallError(msg)
            if errors.errorHandler.cb(exc) == errors.ERROR_RAISE:
                log.error("Installation failed: %r", exc)
                _failure_limbo()

        log.info('Downloading packages finished.')

        pre_msg = (N_("Preparing transaction from installation source"))
        progress_message(pre_msg)

        queue_instance = multiprocessing.Queue()
        process = multiprocessing.Process(target=do_transaction,
                                          args=(self._base, queue_instance))
        process.start()
        (token, msg) = queue_instance.get()
        # When the installation works correctly it will get 'install' updates
        # followed by a 'post' message and then a 'quit' message.
        # If the installation fails it will send 'quit' without 'post'
        while token:
            if token == 'install':
                msg = _("Installing %s") % msg
                progressQ.send_message(msg)
            elif token == 'log':
                log.info(msg)
            elif token == 'post':
                break  # Installation finished successfully
            elif token == 'quit':
                msg = (
                    "Payload error - DNF installation has ended up abruptly: %s"
                    % msg)
                raise payload.PayloadError(msg)
            elif token == 'error':
                exc = payload.PayloadInstallError("DNF error: %s" % msg)
                if errors.errorHandler.cb(exc) == errors.ERROR_RAISE:
                    log.error("Installation failed: %r", exc)
                    _failure_limbo()
            (token, msg) = queue_instance.get()

        post_msg = (N_("Performing post-installation setup tasks"))
        progress_message(post_msg)
        process.join()
        self._base.close()
        if os.path.exists(self._download_location):
            log.info("Cleaning up downloaded packages: %s",
                     self._download_location)
            shutil.rmtree(self._download_location)
        else:
            # Some installation sources, such as NFS, don't need to download packages to
            # local storage, so the download location might not always exist. So for now
            # warn about this, at least until the RFE in bug 1193121 is implemented and
            # we don't have to care about clearing the download location ourselves.
            log.warning("Can't delete nonexistent download location: %s",
                        self._download_location)
Пример #40
0
    def install(self):
        mainctx = GLib.MainContext.new()
        mainctx.push_thread_default()

        cancellable = None
        gi.require_version("OSTree", "1.0")
        gi.require_version("RpmOstree", "1.0")
        from gi.repository import OSTree, RpmOstree
        ostreesetup = self.data.ostreesetup
        log.info("executing ostreesetup=%r", ostreesetup)

        # Initialize the filesystem - this will create the repo as well
        self._safeExecWithRedirect("ostree", [
            "admin", "--sysroot=" + iutil.getTargetPhysicalRoot(), "init-fs",
            iutil.getTargetPhysicalRoot()
        ])

        # Here, we use the physical root as sysroot, because we haven't
        # yet made a deployment.
        sysroot_file = Gio.File.new_for_path(iutil.getTargetPhysicalRoot())
        sysroot = OSTree.Sysroot.new(sysroot_file)
        sysroot.load(cancellable)
        repo = sysroot.get_repo(None)[1]
        # We don't support resuming from interrupted installs
        repo.set_disable_fsync(True)

        self._remoteOptions = {}

        if hasattr(ostreesetup, 'nogpg') and ostreesetup.nogpg:
            self._remoteOptions['gpg-verify'] = GLib.Variant('b', False)

        if flags.noverifyssl:
            self._remoteOptions['tls-permissive'] = GLib.Variant('b', True)

        repo.remote_change(None, OSTree.RepoRemoteChange.ADD_IF_NOT_EXISTS,
                           ostreesetup.remote, ostreesetup.url,
                           GLib.Variant('a{sv}',
                                        self._remoteOptions), cancellable)

        # Variable substitute the ref: https://pagure.io/atomic-wg/issue/299
        ref = RpmOstree.varsubst_basearch(ostreesetup.ref)

        progressQ.send_message(_("Starting pull of %(branchName)s from %(source)s") % \
                               {"branchName": ref, "source": ostreesetup.remote})

        progress = OSTree.AsyncProgress.new()
        progress.connect('changed', self._pullProgressCb)

        pull_opts = {'refs': GLib.Variant('as', [ref])}
        # If we're doing a kickstart, we can at least use the content as a reference:
        # See <https://github.com/rhinstaller/anaconda/issues/1117>
        # The first path here is used by <https://pagure.io/fedora-lorax-templates>
        # and the second by <https://github.com/projectatomic/rpm-ostree-toolbox/>
        if OSTree.check_version(2017, 8):
            for path in ['/ostree/repo', '/install/ostree/repo']:
                if os.path.isdir(path + '/objects'):
                    pull_opts['localcache-repos'] = GLib.Variant('as', [path])
                    break

        try:
            repo.pull_with_options(ostreesetup.remote,
                                   GLib.Variant('a{sv}', pull_opts), progress,
                                   cancellable)
        except GLib.GError as e:
            exn = PayloadInstallError("Failed to pull from repository: %s" % e)
            log.error(str(exn))
            if errors.errorHandler.cb(exn) == errors.ERROR_RAISE:
                progressQ.send_quit(1)
                iutil.ipmi_abort(scripts=self.data.scripts)
                sys.exit(1)

        log.info("ostree pull: " + (progress.get_status() or ""))
        progressQ.send_message(_("Preparing deployment of %s") % (ref, ))

        # Now that we have the data pulled, delete the remote for now.
        # This will allow a remote configuration defined in the tree
        # (if any) to override what's in the kickstart.  Otherwise,
        # we'll re-add it in post.  Ideally, ostree would support a
        # pull without adding a remote, but that would get quite
        # complex.
        repo.remote_delete(self.data.ostreesetup.remote, None)

        self._safeExecWithRedirect("ostree", [
            "admin", "--sysroot=" + iutil.getTargetPhysicalRoot(), "os-init",
            ostreesetup.osname
        ])

        admin_deploy_args = [
            "admin", "--sysroot=" + iutil.getTargetPhysicalRoot(), "deploy",
            "--os=" + ostreesetup.osname
        ]

        admin_deploy_args.append(ostreesetup.remote + ':' + ref)

        log.info("ostree admin deploy starting")
        progressQ.send_message(_("Deployment starting: %s") % (ref, ))
        self._safeExecWithRedirect("ostree", admin_deploy_args)
        log.info("ostree admin deploy complete")
        progressQ.send_message(_("Deployment complete: %s") % (ref, ))

        # Reload now that we've deployed, find the path to the new deployment
        sysroot.load(None)
        deployments = sysroot.get_deployments()
        assert len(deployments) > 0
        deployment = deployments[0]
        deployment_path = sysroot.get_deployment_directory(deployment)
        iutil.setSysroot(deployment_path.get_path())

        try:
            self._copyBootloaderData()
        except (OSError, RuntimeError) as e:
            exn = PayloadInstallError("Failed to copy bootloader data: %s" % e)
            log.error(str(exn))
            if errors.errorHandler.cb(exn) == errors.ERROR_RAISE:
                progressQ.send_quit(1)
                iutil.ipmi_abort(scripts=self.data.scripts)
                sys.exit(1)

        mainctx.pop_thread_default()
Пример #41
0
 def preInstall(self, packages=None, groups=None):
     """ Perform pre-installation tasks. """
     super(LiveImagePayload, self).preInstall(packages=packages,
                                              groups=groups)
     progressQ.send_message(_("Installing software") + (" %d%%") % (0, ))
Пример #42
0
# common string needs to be easy to change
import product
productName = product.productName
productVersion = product.productVersion
productArch = product.productArch
bugzillaUrl = product.bugUrl
isFinal = product.isFinal
eulaLocation = "/usr/share/redhat-release/EULA"

# for use in device names, eg: "fedora", "rhel"
shortProductName = productName.lower()
if productName.count(" "):
    shortProductName = ''.join(s[0] for s in shortProductName.split())

exceptionText = _("An unhandled exception has occurred.  This "
                  "is most likely a bug.  Please save a copy of "
                  "the detailed exception and file a bug report")
if not bugzillaUrl:
    # this string will be combined with "An unhandled exception"...
    # the leading space is not a typo.
    exceptionText += _(" with the provider of this software.")
else:
    # this string will be combined with "An unhandled exception"...
    # the leading space is not a typo.
    exceptionText += _(" against anaconda at %s") %(bugzillaUrl,)

# DriverDisc Paths
DD_ALL = "/tmp/DD"
DD_EXTRACTED = re.compile("/lib/modules/[^/]+/updates/DD/(?P<moduledir>.*/)?(?P<modulename>[^/.]+).ko.*")
DD_FIRMWARE = "/tmp/DD/lib/firmware"
DD_RPMS = "/tmp/DD-*"
Пример #43
0
 def prompt(self, args = None):
     return(_("\tUse of this product is subject to the license agreement found at %s\n\n\tInstallation complete.  Press return to quit") % eulaLocation)
Пример #44
0
 def refresh(self, args=None):
     """ Refresh window. """
     EditTUISpoke.refresh(self, args)
     message = _("Configuring device %s.") % self.args.device
     self._window += [TextWidget(message), ""]
     return True
Пример #45
0
    def __init__(self, *args, **kwargs):
        # these are all absolutely required. not getting them is fatal.
        self._disks = kwargs.pop("disks")
        free = kwargs.pop("free")
        self.selected = kwargs.pop("selected")[:]
        self.name = kwargs.pop("name") or ""  # make sure it's a string
        self.device_type = kwargs.pop("device_type")
        self.storage = kwargs.pop("storage")

        # these are less critical
        self.raid_level = kwargs.pop("raid_level", None) or None  # not ""
        self.encrypted = kwargs.pop("encrypted", False)
        self.exists = kwargs.pop("exists", False)

        self.size_policy = kwargs.pop("size_policy", SIZE_POLICY_AUTO)
        self.size = kwargs.pop("size", Size(0))

        self._error = None
        GUIObject.__init__(self, *args, **kwargs)

        self._grabObjects()
        GUIDialogInputCheckHandler.__init__(self, self._save_button)

        # set up the dialog labels with device-type-specific text
        container_type = get_container_type(self.device_type)
        title_text = _(CONTAINER_DIALOG_TITLE) % {
            "container_type": container_type.name.upper()
        }
        self._title_label.set_text(title_text)

        dialog_text = _(CONTAINER_DIALOG_TEXT) % {
            "container_type": container_type.name.lower()
        }
        self._dialog_label.set_text(dialog_text)

        # populate the dialog widgets
        self._name_entry.set_text(self.name)

        # populate the store
        for disk in self._disks:
            self._store.append([
                disk.description,
                str(disk.size),
                str(free[disk.name][0]), disk.serial, disk.id
            ])

        model = self._treeview.get_model()
        itr = model.get_iter_first()

        selected_ids = [d.id for d in self.selected]
        selection = self._treeview.get_selection()
        while itr:
            disk_id = model.get_value(itr, 4)
            if disk_id in selected_ids:
                selection.select_iter(itr)

            itr = model.iter_next(itr)

        # XXX how will this be related to the device encryption setting?
        self._encryptCheckbutton.set_active(self.encrypted)

        # set up the raid level combo
        # XXX how will this be related to the device raid level setting?
        self._raidStoreFilter.set_visible_func(self._raid_level_visible)
        self._raidStoreFilter.refilter()
        self._populate_raid()

        self._original_size = self.size
        self._original_size_text = self.size.humanReadable(max_places=2)
        self._sizeEntry.set_text(self._original_size_text)
        if self.size_policy == SIZE_POLICY_AUTO:
            self._sizeCombo.set_active(0)
        elif self.size_policy == SIZE_POLICY_MAX:
            self._sizeCombo.set_active(1)
        else:
            self._sizeCombo.set_active(2)

        if self.exists:
            fancy_set_sensitive(self._name_entry, False)
            self._treeview.set_sensitive(False)
            fancy_set_sensitive(self._encryptCheckbutton, False)
            fancy_set_sensitive(self._sizeCombo, False)
            self._sizeEntry.set_sensitive(False)

        # Check that the container name configured is valid
        self.add_check(self._name_entry, self._checkNameEntry)
Пример #46
0
    def preInstall(self, *args, **kwargs):
        """ Get image and loopback mount it.

            This is called after partitioning is setup, we now have space to
            grab the image. If it is a network source Download it to sysroot
            and provide feedback during the download (using urlgrabber
            callback).

            If it is a file:// source then use the file directly.
        """
        error = None
        if self.data.method.url.startswith("file://"):
            self.image_path = self.data.method.url[7:]
        else:
            error = self._preInstall_url_image()

        if error:
            exn = PayloadInstallError(str(error))
            if errorHandler.cb(exn) == ERROR_RAISE:
                raise exn

        # Used to make install progress % look correct
        self._adj_size = os.stat(self.image_path)[stat.ST_SIZE]

        if self.data.method.checksum:
            progressQ.send_message(_("Checking image checksum"))
            sha256 = hashlib.sha256()
            with open(self.image_path, "rb") as f:
                while True:
                    data = f.read(1024 * 1024)
                    if not data:
                        break
                    sha256.update(data)
            filesum = sha256.hexdigest()
            log.debug("sha256 of %s is %s", self.data.method.url, filesum)

            if lowerASCII(self.data.method.checksum) != filesum:
                log.error("%s does not match checksum.",
                          self.data.method.checksum)
                exn = PayloadInstallError("Checksum of image does not match")
                if errorHandler.cb(exn) == ERROR_RAISE:
                    raise exn

        # If this looks like a tarfile, skip trying to mount it
        if self.is_tarfile:
            return

        # Mount the image and check to see if it is a LiveOS/*.img
        # style squashfs image. If so, move it to IMAGE_DIR and mount the real
        # root image on INSTALL_TREE
        rc = blivet.util.mount(self.image_path,
                               INSTALL_TREE,
                               fstype="auto",
                               options="ro")
        if rc != 0:
            log.error("mount error (%s) with %s", rc, self.image_path)
            exn = PayloadInstallError("mount error %s" % rc)
            if errorHandler.cb(exn) == ERROR_RAISE:
                raise exn

        # Nothing more to mount
        if not os.path.exists(INSTALL_TREE + "/LiveOS"):
            return

        # Mount the first .img in the directory on INSTALL_TREE
        img_files = glob.glob(INSTALL_TREE + "/LiveOS/*.img")
        if img_files:
            # move the mount to IMAGE_DIR
            os.makedirs(IMAGE_DIR, 0o755)
            # work around inability to move shared filesystems
            rc = iutil.execWithRedirect("mount", ["--make-rprivate", "/"])
            if rc == 0:
                rc = iutil.execWithRedirect(
                    "mount", ["--move", INSTALL_TREE, IMAGE_DIR])
            if rc != 0:
                log.error("error %s moving mount", rc)
                exn = PayloadInstallError("mount error %s" % rc)
                if errorHandler.cb(exn) == ERROR_RAISE:
                    raise exn

            img_file = IMAGE_DIR + "/LiveOS/" + os.path.basename(
                sorted(img_files)[0])
            rc = blivet.util.mount(img_file,
                                   INSTALL_TREE,
                                   fstype="auto",
                                   options="ro")
            if rc != 0:
                log.error("mount error (%s) with %s", rc, img_file)
                exn = PayloadInstallError("mount error %s with %s" %
                                          (rc, img_file))
                if errorHandler.cb(exn) == ERROR_RAISE:
                    raise exn

            source = iutil.eintr_retry_call(os.statvfs, INSTALL_TREE)
            self.source_size = source.f_frsize * (source.f_blocks -
                                                  source.f_bfree)
Пример #47
0
 def prompt(self, args=None):
     return _("Press Enter to exit.")
Пример #48
0
    def initialize(self):
        NormalSpoke.initialize(self)
        self.initialize_start()
        # get object references from the builders
        self._password_entry = self.builder.get_object("password_entry")
        self._password_confirmation_entry = self.builder.get_object("password_confirmation_entry")
        self._password_bar = self.builder.get_object("password_bar")
        self._password_label = self.builder.get_object("password_label")

        # set state based on kickstart
        self.password_kickstarted = self.data.rootpw.seen

        # Install the password checks:
        # - Has a password been specified?
        # - If a password has been specified and there is data in the confirm box, do they match?
        # - How strong is the password?
        # - Does the password contain non-ASCII characters?

        # Setup the password checker for password checking
        self._checker = input_checking.PasswordChecker(
                initial_password_content = self.password,
                initial_password_confirmation_content = self.password_confirmation,
                policy = input_checking.get_policy(self.data, "root")
        )
        # configure the checker for password checking
        self.checker.name_of_password = _(constants.NAME_OF_PASSWORD)
        self.checker.name_of_password_plural = _(constants.NAME_OF_PASSWORD_PLURAL)
        # remove any placeholder texts if either password or confirmation field changes content from initial state
        self.checker.password.changed_from_initial_state.connect(self.remove_placeholder_texts)
        self.checker.password_confirmation.changed_from_initial_state.connect(self.remove_placeholder_texts)
        # connect UI updates to check results
        self.checker.checks_done.connect(self._checks_done)

        # check that the password is not empty
        self._empty_check = input_checking.PasswordEmptyCheck()
        # check that the content of the password field & the conformation field are the same
        self._confirm_check = input_checking.PasswordConfirmationCheck()
        # regards both fields empty as success to let the user escape
        self._confirm_check.success_if_confirmation_empty = True
        # check password validity, quality and strength
        self._validity_check = input_checking.PasswordValidityCheck()
        # connect UI updates to validity check results
        self._validity_check.result.password_score_changed.connect(self.set_password_score)
        self._validity_check.result.status_text_changed.connect(self.set_password_status)
        # check if the password contains non-ascii characters
        self._ascii_check = input_checking.PasswordASCIICheck()

        # register the individual checks with the checker in proper order
        # 1) is the password non-empty ?
        # 2) are both entered passwords the same ?
        # 3) is the password valid according to the current password checking policy ?
        # 4) is the password free of non-ASCII characters ?
        self.checker.add_check(self._empty_check)
        self.checker.add_check(self._confirm_check)
        self.checker.add_check(self._validity_check)
        self.checker.add_check(self._ascii_check)

        # set placeholders if the password has been kickstarted as we likely don't know
        # nothing about it and can't really show it in the UI in any meaningful way
        password_set_message = _("The password was set by kickstart.")
        if self.password_kickstarted:
            self.password_entry.set_placeholder_text(password_set_message)
            self.password_confirmation_entry.set_placeholder_text(password_set_message)

        # Configure levels for the password bar
        self._password_bar.add_offset_value("low", 2)
        self._password_bar.add_offset_value("medium", 3)
        self._password_bar.add_offset_value("high", 4)

        # Send ready signal to main event loop
        hubQ.send_ready(self.__class__.__name__, False)

        # report that we are done
        self.initialize_done()
Пример #49
0
def distributionText():
    return _("%(productName)s %(productVersion)s INSTALLATION") % \
             {"productName": productName, "productVersion": productVersion}
Пример #50
0
def get_container_type(device_type):
    return CONTAINER_TYPES.get(device_type,
                               ContainerType(_("container"), _("container")))
Пример #51
0
    def _downloading_package_md(self):
        # Reset the error state from previous payloads
        self._error = False

        hubQ.send_message(self.__class__.__name__, _(constants.PAYLOAD_STATUS_PACKAGE_MD))
Пример #52
0
def translated_new_install_name():
    return _("New %(name)s %(version)s Installation") % \
        {"name" : productName, "version" : productVersion}
Пример #53
0
    def refresh(self):
        self._back_clicked = False

        self.disks = getDisks(self.storage.devicetree)

        # synchronize our local data store with the global ksdata
        disk_names = [d.name for d in self.disks]
        self.selected_disks = [
            d for d in self.data.ignoredisk.onlyuse if d in disk_names
        ]

        # unhide previously hidden disks so that they don't look like being
        # empty (because of all child devices hidden)
        self._unhide_disks()

        self.autopart = self.data.autopart.autopart
        self.autoPartType = self.data.autopart.type
        if self.autoPartType is None:
            self.autoPartType = AUTOPART_TYPE_LVM
        self.encrypted = self.data.autopart.encrypted
        self.passphrase = self.data.autopart.passphrase

        self._previous_autopart = self.autopart

        # First, remove all non-button children.
        for child in self.localOverviews + self.advancedOverviews:
            child.destroy()

        # Then deal with local disks, which are really easy.  They need to be
        # handled here instead of refresh to take into account the user pressing
        # the rescan button on custom partitioning.
        for disk in filter(isLocalDisk, self.disks):
            # While technically local disks, zFCP devices are specialized
            # storage and should not be shown here.
            if disk.type is not "zfcp":
                self._add_disk_overview(disk, self.local_disks_box)

        # Advanced disks are different.  Because there can potentially be a lot
        # of them, we do not display them in the box by default.  Instead, only
        # those selected in the filter UI are displayed.  This means refresh
        # needs to know to create and destroy overviews as appropriate.
        for name in self.data.ignoredisk.onlyuse:
            if name not in disk_names:
                continue
            obj = self.storage.devicetree.getDeviceByName(name, hidden=True)
            # since zfcp devices may be detected as local disks when added
            # manually, specifically check the disk type here to make sure
            # we won't accidentally bypass adding zfcp devices to the disk
            # overview
            if isLocalDisk(obj) and obj.type is not "zfcp":
                continue

            self._add_disk_overview(obj, self.specialized_disks_box)

        # update the selections in the ui
        for overview in self.localOverviews + self.advancedOverviews:
            name = overview.get_property("name")
            overview.set_chosen(name in self.selected_disks)

        # if encrypted is specified in kickstart, select the encryptionCheckbox in the GUI
        if self.encrypted:
            self._encrypted.set_active(True)

        self._customPart.set_active(not self.autopart)

        self._update_summary()

        if self.errors:
            self.set_warning(
                _("Error checking storage configuration.  <a href=\"\">Click for details.</a>"
                  ))
        elif self.warnings:
            self.set_warning(
                _("Warning checking storage configuration.  <a href=\"\">Click for details.</a>"
                  ))
Пример #54
0
 def _downloading_group_md(self):
     hubQ.send_message(self.__class__.__name__, _(constants.PAYLOAD_STATUS_GROUP_MD))
Пример #55
0
    def populate(self, disks):
        totalDisks = 0
        totalReclaimableSpace = Size(0)

        self._initialFreeSpace = Size(0)
        self._selectedReclaimableSpace = Size(0)

        canShrinkSomething = False

        free_space = self.storage.getFreeSpace(disks=disks)

        for disk in disks:
            # First add the disk itself.
            editable = not disk.protected

            if disk.partitioned:
                fstype = ""
                diskReclaimableSpace = Size(0)
            else:
                fstype = disk.format.name
                diskReclaimableSpace = disk.size

            itr = self._diskStore.append(None, [
                disk.id,
                "%s %s" %
                (disk.size.humanReadable(max_places=1), disk.description),
                fstype,
                "<span foreground='grey' style='italic'>%s total</span>",
                _(PRESERVE), editable, TY_NORMAL,
                self._get_tooltip(disk),
                int(disk.size), disk.name
            ])

            if disk.partitioned:
                # Then add all its partitions.
                for dev in self.storage.devicetree.getChildren(disk):
                    if dev.isExtended and disk.format.logicalPartitions:
                        continue

                    # Devices that are not resizable are still deletable.
                    if dev.resizable:
                        freeSize = dev.size - dev.minSize
                        resizeString = _("%(freeSize)s of %(devSize)s") \
                                       % {"freeSize": freeSize.humanReadable(max_places=1), "devSize": dev.size.humanReadable(max_places=1)}
                        if not dev.protected:
                            canShrinkSomething = True
                    else:
                        freeSize = dev.size
                        resizeString = "<span foreground='grey'>%s</span>" % \
                                escape_markup(_("Not resizeable"))

                    if dev.protected:
                        ty = TY_PROTECTED
                    else:
                        ty = TY_NORMAL

                    self._diskStore.append(itr, [
                        dev.id,
                        self._description(dev), dev.format.name, resizeString,
                        _(PRESERVE), not dev.protected, ty,
                        self._get_tooltip(dev),
                        int(dev.size), dev.name
                    ])
                    diskReclaimableSpace += freeSize

            # And then add another uneditable line that lists how much space is
            # already free in the disk.
            diskFree = free_space[disk.name][0]
            if diskFree >= Size("1MiB"):
                freeSpaceString = "<span foreground='grey' style='italic'>%s</span>" % \
                        escape_markup(_("Free space"))
                self._diskStore.append(itr, [
                    disk.id, freeSpaceString, "",
                    "<span foreground='grey' style='italic'>%s</span>" %
                    escape_markup(diskFree.humanReadable(max_places=1)),
                    NOTHING, False, TY_FREE_SPACE,
                    self._get_tooltip(disk), diskFree, ""
                ])
                self._initialFreeSpace += diskFree

            # And then go back and fill in the total reclaimable space for the
            # disk, now that we know what each partition has reclaimable.
            self._diskStore[itr][RECLAIMABLE_COL] = self._diskStore[itr][
                RECLAIMABLE_COL] % diskReclaimableSpace

            totalDisks += 1
            totalReclaimableSpace += diskReclaimableSpace

        self._update_labels(totalDisks, totalReclaimableSpace, 0)

        description = _(
            "You can remove existing file systems you no longer need to free up space "
            "for this installation.  Removing a file system will permanently delete all "
            "of the data it contains.")

        if canShrinkSomething:
            description += "\n\n"
            description += _(
                "There is also free space available in pre-existing file systems.  "
                "While it's risky and we recommend you back up your data first, you "
                "can recover that free disk space and make it available for this "
                "installation below.")

        self._reclaimDescLabel.set_text(description)
        self._update_reclaim_button(Size(0))
Пример #56
0
    def on_back_clicked(self, button):
        # We can't exit early if it looks like nothing has changed because the
        # user might want to change settings presented in the dialogs shown from
        # within this method.

        # Do not enter this method multiple times if user clicking multiple times
        # on back button
        if self._back_clicked:
            return
        else:
            self._back_clicked = True

        # make sure the snapshot of unmodified on-disk-storage model is created
        if not on_disk_storage.created:
            on_disk_storage.create_snapshot(self.storage)

        if self.autopart_missing_passphrase:
            self._setup_passphrase()
            NormalSpoke.on_back_clicked(self, button)
            return

        # No disks selected?  The user wants to back out of the storage spoke.
        if not self.selected_disks:
            NormalSpoke.on_back_clicked(self, button)
            return

        disk_selection_changed = False
        if self._last_selected_disks:
            disk_selection_changed = (self._last_selected_disks != set(
                self.selected_disks))

        # remember the disk selection for future decisions
        self._last_selected_disks = set(self.selected_disks)

        if disk_selection_changed:
            # Changing disk selection is really, really complicated and has
            # always been causing numerous hard bugs. Let's not play the hero
            # game and just revert everything and start over again.
            on_disk_storage.reset_to_snapshot(self.storage)
            self.disks = getDisks(self.storage.devicetree)
        else:
            # Remove all non-existing devices if autopart was active when we last
            # refreshed.
            if self._previous_autopart:
                self._previous_autopart = False
                self._remove_nonexistant_partitions()

        # hide disks as requested
        self._hide_disks()

        # make sure no containers were split up by the user's disk selection
        self.clear_info()

        # if there are some disk selection errors we don't let user to leave the
        # spoke, so these errors don't have to go to self.errors
        self.disks_errors = checkDiskSelection(self.storage,
                                               self.selected_disks)
        if self.disks_errors:
            # The disk selection has to make sense before we can proceed.
            self.set_error(
                _("There was a problem with your disk selection. "
                  "Click here for details."))
            self._back_clicked = False
            return

        if arch.isS390():
            # check for unformatted DASDs and launch dasdfmt if any discovered
            rc = self._check_dasd_formats()
            if rc == DASD_FORMAT_NO_CHANGE:
                pass
            elif rc == DASD_FORMAT_REFRESH:
                # User hit OK on the dialog
                self.refresh()
            elif rc == DASD_FORMAT_RETURN_TO_HUB:
                # User clicked uri to return to hub.
                NormalSpoke.on_back_clicked(self, button)
                return
            else:
                # User either hit cancel on the dialog or closed it via escape,
                # there was no formatting done.
                self._back_clicked = False
                return

        # even if they're not doing autopart, setting autopart.encrypted
        # establishes a default of encrypting new devices
        self.encrypted = self._encrypted.get_active()

        # We might first need to ask about an encryption passphrase.
        if self.encrypted and not self._setup_passphrase():
            self._back_clicked = False
            return

        # At this point there are three possible states:
        # 1) user chose custom part => just send them to the CustomPart spoke
        # 2) user wants to reclaim some more space => run the ResizeDialog
        # 3) we are just asked to do autopart => check free space and see if we need
        #                                        user to do anything more
        self.autopart = not self._customPart.get_active()
        disks = [d for d in self.disks if d.name in self.selected_disks]
        dialog = None
        if not self.autopart:
            self.skipTo = "CustomPartitioningSpoke"
        elif self._reclaim.get_active():
            # HINT: change the logic of this 'if' statement if we are asked to
            # support "reclaim before custom partitioning"

            # respect disk selection and other choices in the ReclaimDialog
            self.apply()
            dialog = ResizeDialog(self.data, self.storage, self.payload)
            dialog.refresh(disks)
        else:
            dialog = self._check_space_and_get_dialog(disks)

        if dialog:
            # more dialogs may need to be run based on user choices, but we are
            # only interested in the final result
            rc = self._run_dialogs(disks, start_with=dialog)

            if rc == RESPONSE_OK:
                # nothing special needed
                pass
            elif rc == RESPONSE_CANCEL:
                # A cancel button was clicked on one of the dialogs.  Stay on this
                # spoke.  Generally, this is because the user wants to add more disks.
                self._back_clicked = False
                return
            elif rc == RESPONSE_MODIFY_SW:
                # The "Fedora software selection" link was clicked on one of the
                # dialogs.  Send the user to the software spoke.
                self.skipTo = "SoftwareSelectionSpoke"
            elif rc == RESPONSE_QUIT:
                # Not enough space, and the user can't do anything about it so
                # they chose to quit.
                raise SystemExit("user-selected exit")
            else:
                # I don't know how we'd get here, but might as well have a
                # catch-all.  Just stay on this spoke.
                self._back_clicked = False
                return

        if self.autopart:
            refreshAutoSwapSize(self.storage)
        self.applyOnSkip = True
        NormalSpoke.on_back_clicked(self, button)
Пример #57
0
    def run_dasdfmt(self, to_format=None):
        """
        This generates the list of DASDs requiring dasdfmt and runs dasdfmt
        against them.

        to_format is an optional list of DASDs to format. This shouldn't be
        passed if run_dasdfmt is called during a ks installation, and if called
        during a manual installation, a list of DASDs needs to be passed.
        """
        if not to_format:
            # go ahead and initialize this
            to_format = []

        # if the storage thread is running, wait on it to complete before taking
        # any further actions on devices; most likely to occur if user has
        # zerombr in their ks file
        threadMgr.wait(THREAD_STORAGE)

        if flags.automatedInstall:
            # automated install case
            unformatted = []
            ldl = []

            if self.data.zerombr.zerombr:
                # unformatted DASDs
                unformatted += make_unformatted_dasd_list(
                    [d.name for d in getDisks(self.storage.devicetree)])
            if self.data.clearpart.cdl:
                # LDL DASDs
                ldl += [
                    d.name for d in self.storage.devicetree.dasd
                    if is_ldl_dasd(d.name)
                ]
            # combine into one nice list
            to_format = list(set(unformatted + ldl))
        else:
            # manual install; ask to verify they want to run dasdfmt
            # prepare our msg strings; copied directly from dasdfmt.glade
            summary = _(
                "The following unformatted or LDL DASDs have been "
                "detected on your system. You can choose to format them "
                "now with dasdfmt or cancel to leave them unformatted. "
                "Unformatted DASDs cannot be used during installation.\n\n")

            warntext = _(
                "Warning: All storage changes made using the installer will be lost when you choose to format.\n\nProceed to run dasdfmt?\n"
            )

            displaytext = summary + "\n".join(
                "/dev/" + d for d in to_format) + "\n" + warntext

            # now show actual prompt; note -- in cmdline mode, auto-answer for
            # this is 'no', so unformatted and ldl DASDs will remain so unless
            # zerombr or cdl are added to the ks file
            question_window = YesNoDialog(self._app, displaytext)
            self._app.switch_screen_modal(question_window)
            if not question_window.answer:
                # no? well fine then, back to the storage spoke with you;
                return None

        for disk in to_format:
            try:
                print(_("Formatting /dev/%s. This may take a moment.") % disk)
                format_dasd(disk)
            except DasdFormatError as err:
                # Log errors if formatting fails, but don't halt the installer
                log.error("dasdfmt /dev/%s failed: %s", disk, err)
                continue

        # need to make devicetree aware of disk changes
        self.storage.devicetree.populate()
        if not flags.automatedInstall:
            # reinit storage
            threadMgr.add(
                AnacondaThread(
                    name=THREAD_STORAGE,
                    target=storageInitialize,
                    args=(self.storage, self.data,
                          self.storage.devicetree.protectedDevNames)))
            # update the summary screen with the changes
            self._initialize()
Пример #58
0
    def on_info_bar_clicked(self, *args):
        if self.disks_errors:
            label = _(
                "The following errors were encountered when checking your disk "
                "selection. You can modify your selection or quit the "
                "installer.")

            dialog = DetailedErrorDialog(self.data,
                                         buttons=[
                                             C_("GUI|Storage|Error Dialog",
                                                "_Quit"),
                                             C_("GUI|Storage|Error Dialog",
                                                "_Modify Disk Selection")
                                         ],
                                         label=label)
            with self.main_window.enlightbox(dialog.window):
                errors = "\n".join(self.disks_errors)
                dialog.refresh(errors)
                rc = dialog.run()

            dialog.window.destroy()

            if rc == 0:
                # Quit.
                iutil.ipmi_report(constants.IPMI_ABORTED)
                sys.exit(0)

        elif self.errors:
            label = _(
                "The following errors were encountered when checking your storage "
                "configuration.  You can modify your storage layout or quit the "
                "installer.")

            dialog = DetailedErrorDialog(self.data,
                                         buttons=[
                                             C_("GUI|Storage|Error Dialog",
                                                "_Quit"),
                                             C_("GUI|Storage|Error Dialog",
                                                "_Modify Storage Layout")
                                         ],
                                         label=label)
            with self.main_window.enlightbox(dialog.window):
                errors = "\n".join(self.errors)
                dialog.refresh(errors)
                rc = dialog.run()

            dialog.window.destroy()

            if rc == 0:
                # Quit.
                iutil.ipmi_report(constants.IPMI_ABORTED)
                sys.exit(0)
        elif self.warnings:
            label = _(
                "The following warnings were encountered when checking your storage "
                "configuration.  These are not fatal, but you may wish to make "
                "changes to your storage layout.")

            dialog = DetailedErrorDialog(
                self.data,
                buttons=[C_("GUI|Storage|Warning Dialog", "_OK")],
                label=label)
            with self.main_window.enlightbox(dialog.window):
                warnings = "\n".join(self.warnings)
                dialog.refresh(warnings)
                rc = dialog.run()

            dialog.window.destroy()
Пример #59
0
    def _check_nfs_server(self, user_input, report_func):
        if ":" not in user_input or len(user_input.split(":")) != 2:
            report_func(_("Server must be specified as SERVER:/PATH"))
            return False

        return True
Пример #60
0
 def _get_tooltip(self, device):
     if device.protected:
         return _("This device contains the installation source.")
     else:
         return None