Beispiel #1
0
    def setup(self):
        super().setup()
        # Mount the live device and copy from it instead of the overlay at /
        osimg_spec = self._get_live_os_image()

        if not osimg_spec:
            raise PayloadSetupError("No live image found!")

        osimg = payload_utils.resolve_device(osimg_spec)
        if not osimg:
            raise PayloadInstallError("Unable to find osimg for {}".format(osimg_spec))

        osimg_path = payload_utils.get_device_path(osimg)
        if not stat.S_ISBLK(os.stat(osimg_path)[stat.ST_MODE]):
            exn = PayloadSetupError("{} is not a valid block device".format(osimg_spec))
            if errorHandler.cb(exn) == ERROR_RAISE:
                raise exn

        rc = payload_utils.mount(osimg_path, INSTALL_TREE, fstype="auto", options="ro")
        if rc != 0:
            raise PayloadInstallError("Failed to mount the install tree")

        # Grab the kernel version list now so it's available after umount
        self._update_kernel_version_list()

        source = os.statvfs(INSTALL_TREE)
        self.source_size = source.f_frsize * (source.f_blocks - source.f_bfree)
Beispiel #2
0
    def _setup_hmc_device(self, method, iso_device_path, repo_device_path):
        # Check if /dev/hmcdrv is already mounted.
        if repo_device_path == "/dev/hmcdrv":
            log.debug("HMC is already mounted at %s.", DRACUT_REPODIR)
            url = "file://" + DRACUT_REPODIR
        else:
            log.debug("Trying to mount the content of HMC media drive.")

            # Test the SE/HMC file access.
            if util.execWithRedirect("/usr/sbin/lshmc", []):
                raise PayloadSetupError(
                    "The content of HMC media drive couldn't be accessed.")

            # Test if a path is a mount point.
            if os.path.ismount(INSTALL_TREE):
                log.debug("Don't mount the content of HMC media drive yet.")
            else:
                # Make sure that the directories exists.
                util.mkdirChain(INSTALL_TREE)

                # Mount the device.
                if util.execWithRedirect("/usr/bin/hmcdrvfs", [INSTALL_TREE]):
                    raise PayloadSetupError(
                        "The content of HMC media drive couldn't be mounted.")

            log.debug("We are ready to use the HMC at %s.", INSTALL_TREE)
            url = "file://" + INSTALL_TREE

        return url
Beispiel #3
0
    def _setup_harddrive_device(self, method, iso_device_path,
                                repo_device_path):
        url = None
        need_mount = False

        if method.biospart:
            log.warning("biospart support is not implemented")
            dev_spec = method.biospart
        else:
            dev_spec = method.partition
            need_mount = True
            # See if we used this method for stage2, thus dracut left it
            if iso_device_path and method.partition and \
               method.partition in iso_device_path and \
               DRACUT_ISODIR in repo_device_path:
                # Everything should be setup
                url = "file://" + DRACUT_REPODIR
                need_mount = False
                # We don't setup an install_device here
                # because we can't tear it down

        iso_device = payload_utils.resolve_device(self.storage, dev_spec)
        if need_mount:
            if not iso_device:
                raise PayloadSetupError(
                    "device for HDISO install %s does not exist" % dev_spec)

            self._setup_media(iso_device)
            url = "file://" + INSTALL_TREE
            self.install_device = iso_device

        return url
Beispiel #4
0
    def setup(self):
        super().setup()

        # Mount the live device and copy from it instead of the overlay at /
        osimg = payload_utils.resolve_device(self.storage,
                                             self.data.method.partition)
        if not osimg:
            raise PayloadInstallError("Unable to find osimg for %s" %
                                      self.data.method.partition)

        if not stat.S_ISBLK(os.stat(osimg.path)[stat.ST_MODE]):
            exn = PayloadSetupError("%s is not a valid block device" %
                                    (self.data.method.partition, ))
            if errorHandler.cb(exn) == ERROR_RAISE:
                raise exn
        rc = payload_utils.mount(osimg.path,
                                 INSTALL_TREE,
                                 fstype="auto",
                                 options="ro")
        if rc != 0:
            raise PayloadInstallError("Failed to mount the install tree")

        # Grab the kernel version list now so it's available after umount
        self._update_kernel_version_list()

        source = os.statvfs(INSTALL_TREE)
        self.source_size = source.f_frsize * (source.f_blocks - source.f_bfree)
Beispiel #5
0
    def _setup_cdrom_device(self, method, iso_device_path, repo_device_path):
        url = None

        # FIXME: We really should not talk about NFS here - regression from re-factorization?

        # Check for valid optical media if we didn't boot from one
        if not verifyMedia(DRACUT_REPODIR):
            self.install_device = find_optical_install_media(self.storage)

        # Only look at the dracut mount if we don't already have a cdrom
        if repo_device_path and not self.install_device:
            self.install_device = payload_utils.resolve_device(self.storage, repo_device_path)
            url = "file://" + DRACUT_REPODIR
            if not method.method:
                # See if this is a nfs mount
                if ':' in repo_device_path:
                    # prepend nfs: to the url as that's what the parser
                    # wants.  Note we don't get options from this, but
                    # that's OK for the UI at least.
                    _options, host, path = util.parseNfsUrl("nfs:%s" % repo_device_path)
                    method.method = "nfs"
                    method.server = host
                    method.dir = path
                else:
                    method.method = "cdrom"
        else:
            if self.install_device:
                if not method.method:
                    method.method = "cdrom"
                self._setup_media(self.install_device)
                url = "file://" + INSTALL_TREE
            elif method.method == "cdrom":
                raise PayloadSetupError("no usable optical media found")

        return url
Beispiel #6
0
    def _setup_install_tree(self, device, install_tree_path, device_mount_dir):
        self._setup_device(device, mountpoint=device_mount_dir)
        path = os.path.normpath("%s/%s" % (device_mount_dir, install_tree_path))

        if not verify_valid_installtree(path):
            payload_utils.teardown_device(device)
            raise PayloadSetupError("failed to find valid installation tree")
Beispiel #7
0
    def _setup_device(device, mountpoint):
        """Prepare an install CD/DVD for use as a package source."""
        log.info("setting up device %s and mounting on %s", device.name,
                 mountpoint)
        # Is there a symlink involved?  If so, let's get the actual path.
        # This is to catch /run/install/isodir vs. /mnt/install/isodir, for
        # instance.
        real_mountpoint = os.path.realpath(mountpoint)
        mount_device_path = payload_utils.get_mount_device_path(
            real_mountpoint)

        if mount_device_path:
            log.warning("%s is already mounted on %s", mount_device_path,
                        mountpoint)

            if mount_device_path == device.path:
                return
            else:
                payload_utils.unmount(real_mountpoint)

        try:
            payload_utils.setup_device(device)
            payload_utils.mount_device(device, mountpoint)
        except StorageError as e:
            log.error("mount failed: %s", e)
            payload_utils.teardown_device(device)
            raise PayloadSetupError(str(e))
Beispiel #8
0
def mount(url, mountpoint, fstype, options):
    try:
        return blivet.util.mount(url,
                                 mountpoint,
                                 fstype=fstype,
                                 options=options)
    except OSError as e:
        raise PayloadSetupError(str(e))
Beispiel #9
0
    def _write_dnf_repo(self, repo, repo_path):
        """Write a repo object to a DNF repo.conf file.

        :param repo: DNF repository object
        :param string repo_path: Path to write the repo to
        :raises: PayloadSetupError if the repo doesn't have a url
        """
        with open(repo_path, "w") as f:
            f.write("[%s]\n" % repo.id)
            f.write("name=%s\n" % repo.id)
            if self.is_repo_enabled(repo.id):
                f.write("enabled=1\n")
            else:
                f.write("enabled=0\n")

            if repo.mirrorlist:
                f.write("mirrorlist=%s\n" % repo.mirrorlist)
            elif repo.metalink:
                f.write("metalink=%s\n" % repo.metalink)
            elif repo.baseurl:
                f.write("baseurl=%s\n" % repo.baseurl[0])
            else:
                f.close()
                os.unlink(repo_path)
                raise PayloadSetupError(
                    "The repo {} has no baseurl, mirrorlist or "
                    "metalink".format(repo.id))

            # kickstart repo modifiers
            ks_repo = self.get_addon_repo(repo.id)
            if not ks_repo:
                return

            if ks_repo.noverifyssl:
                f.write("sslverify=0\n")

            if ks_repo.proxy:
                try:
                    proxy = ProxyString(ks_repo.proxy)
                    f.write("proxy=%s\n" % proxy.url)
                except ProxyStringError as e:
                    log.error(
                        "Failed to parse proxy for _writeInstallConfig %s: %s",
                        ks_repo.proxy, e)

            if ks_repo.cost:
                f.write("cost=%d\n" % ks_repo.cost)

            if ks_repo.includepkgs:
                f.write("include=%s\n" % ",".join(ks_repo.includepkgs))

            if ks_repo.excludepkgs:
                f.write("exclude=%s\n" % ",".join(ks_repo.excludepkgs))
Beispiel #10
0
def mount(device_path, mount_point, fstype, options):
    """Mount a filesystem.

    :param str device_path: a device path
    :param str mount_point: a mount point
    :param str fstype: a filesystem type
    :param str options: mount options
    """
    try:
        return blivet.util.mount(device_path, mount_point, fstype=fstype, options=options)
    except OSError as e:
        raise PayloadSetupError(str(e)) from e
Beispiel #11
0
    def setup(self):
        """ Check the availability and size of the image.
        """
        super().setup()

        if self.data.liveimg.url.startswith("file://"):
            error = self._setup_file_image()
        else:
            error = self._setup_url_image()

        if error:
            raise PayloadSetupError(str(error))

        log.debug("liveimg size is %s", self._min_size)
Beispiel #12
0
    def _setup_harddrive_addon_repo(self, ksrepo):
        iso_device = payload_utils.resolve_device(ksrepo.partition)
        if not iso_device:
            raise PayloadSetupError("device for HDISO addon repo install %s does not exist" %
                                    ksrepo.partition)

        ksrepo.generate_mount_dir()

        device_mount_dir = ISO_DIR + "-" + ksrepo.mount_dir_suffix
        install_root_dir = INSTALL_TREE + "-" + ksrepo.mount_dir_suffix

        self._find_and_mount_iso(iso_device, device_mount_dir, ksrepo.iso_path, install_root_dir)
        url = "file://" + install_root_dir

        return url
Beispiel #13
0
    def _setup_media(self, device):
        method = self.data.method
        if method.method == "harddrive":
            try:
                method.dir = self._find_and_mount_iso(device, ISO_DIR,
                                                      method.dir, INSTALL_TREE)
            except PayloadSetupError as ex:
                log.warning(str(ex))

                try:
                    self._setup_install_tree(device, method.dir, INSTALL_TREE)
                except PayloadSetupError as ex:
                    log.error(str(ex))
                    raise PayloadSetupError(
                        "failed to setup installation tree or ISO from HDD")
        elif not (method.method == "cdrom"
                  and self._device_is_mounted_as_source(device)):
            payload_utils.mount_device(device, INSTALL_TREE)
Beispiel #14
0
    def _find_and_mount_iso(self, device, device_mount_dir, iso_path,
                            iso_mount_dir):
        """Find and mount installation source from ISO on device.

        Return changed path to the iso to save looking for iso in the future call.
        """
        self._setup_device(device, mountpoint=device_mount_dir)

        # check for ISO images in the newly mounted dir
        path = device_mount_dir
        if iso_path:
            path = os.path.normpath("%s/%s" % (path, iso_path))

        # XXX it would be nice to streamline this when we're just setting
        #     things back up after storage activation instead of having to
        #     pretend we don't already know which ISO image we're going to
        #     use
        image = find_first_iso_image(path)
        if not image:
            payload_utils.teardown_device(device)
            raise PayloadSetupError("failed to find valid iso image")

        if path.endswith(".iso"):
            path = os.path.dirname(path)

        # this could already be set up the first time through
        if not os.path.ismount(iso_mount_dir):
            # mount the ISO on a loop
            image = os.path.normpath("%s/%s" % (path, image))
            payload_utils.mount(image,
                                iso_mount_dir,
                                fstype='iso9660',
                                options="ro")

        if not iso_path.endswith(".iso"):
            result_path = os.path.normpath("%s/%s" %
                                           (iso_path, os.path.basename(image)))
            while result_path.startswith("/"):
                # ridiculous
                result_path = result_path[1:]

            return result_path

        return iso_path
Beispiel #15
0
    def _setup_media(self, device):
        method = self.data.method
        if method.method == "harddrive":
            try:
                method.dir = self._find_and_mount_iso(device, ISO_DIR, method.dir, INSTALL_TREE)
            except PayloadSetupError as ex:
                log.warning(str(ex))

                try:
                    self._setup_install_tree(device, method.dir, INSTALL_TREE)
                except PayloadSetupError as ex:
                    log.error(str(ex))
                    raise PayloadSetupError("failed to setup installation tree or ISO from HDD")

        # Check to see if the device is already mounted, in which case
        # we don't need to mount it again
        elif method.method == "cdrom" and payload_utils.get_mount_paths(device.path):
            return
        else:
            payload_utils.mount_device(device, INSTALL_TREE)
Beispiel #16
0
    def _setup_nfs_device(self, method, iso_device_path, repo_device_path):
        # There are several possible scenarios here:
        # 1. dracut could have mounted both the nfs repo and an iso and used
        #    the stage2 from inside the iso to boot from.
        #    iso_device_path and repo_device_path will be set in this case.
        # 2. dracut could have mounted the nfs repo and used a stage2 from
        #    the NFS mount w/o mounting the iso.
        #    iso_device_path will be None and repo_device_path will be the nfs: path
        # 3. dracut did not mount the nfs (eg. stage2 came from elsewhere)
        #    iso_device_path and/or repo_device_path are None
        # 4. The repo may not contain an iso, in that case use it as is
        url = None
        path = None

        if iso_device_path and repo_device_path:
            path = util.parseNfsUrl('nfs:%s' % iso_device_path)[2]
            # See if the dir holding the iso is what we want
            # and also if we have an iso mounted to /run/install/repo
            if path and path in iso_device_path and DRACUT_ISODIR in repo_device_path:
                # Everything should be setup
                url = "file://" + DRACUT_REPODIR
        else:
            # see if the nfs dir is mounted
            need_mount = True
            if repo_device_path:
                _options, host, path = util.parseNfsUrl('nfs:%s' %
                                                        repo_device_path)
                if method.server and method.server == host and \
                   method.dir and method.dir == path:
                    need_mount = False
                    path = DRACUT_REPODIR
            elif iso_device_path:
                # iso_device_path with no repo_device_path can happen when options on an existing
                # nfs mount have changed. It is already mounted, but on INSTALL_TREE
                # which is the same as DRACUT_ISODIR, making it hard for _setup_NFS
                # to detect that it is already mounted.
                _options, host, path = util.parseNfsUrl('nfs:%s' %
                                                        iso_device_path)
                if path and path in iso_device_path:
                    need_mount = False
                    path = DRACUT_ISODIR

            if need_mount:
                # Mount the NFS share on INSTALL_TREE. If it ends up
                # being nfsiso we will move the mountpoint to ISO_DIR.
                if method.dir.endswith(".iso"):
                    nfs_dir = os.path.dirname(method.dir)
                else:
                    nfs_dir = method.dir

                self._setup_NFS(INSTALL_TREE, method.server, nfs_dir,
                                method.opts)
                path = INSTALL_TREE

            # check for ISO images in the newly mounted dir
            if method.dir.endswith(".iso"):
                # if the given URL includes a specific ISO image file, use it
                image_file = os.path.basename(method.dir)
                path = os.path.normpath("%s/%s" % (path, image_file))

            image = findFirstIsoImage(path)

            # An image was found, mount it on INSTALL_TREE
            if image:
                if path.startswith(INSTALL_TREE):
                    # move the INSTALL_TREE mount to ISO_DIR so we can
                    # mount the contents of the iso there.
                    # work around inability to move shared filesystems
                    util.execWithRedirect("mount", ["--make-rprivate", "/"])
                    util.execWithRedirect("mount",
                                          ["--move", INSTALL_TREE, ISO_DIR])
                    # The iso is now under ISO_DIR
                    path = ISO_DIR
                elif path.endswith(".iso"):
                    path = os.path.dirname(path)

                # mount the ISO on a loop
                image = os.path.normpath("%s/%s" % (path, image))
                mountImage(image, INSTALL_TREE)

                url = "file://" + INSTALL_TREE
            elif os.path.isdir(path):
                # Fall back to the mount path instead of a mounted iso
                url = "file://" + path
            else:
                # Do not try to use iso as source if it is not valid source
                raise PayloadSetupError("Not a valid ISO image!")

        return url
Beispiel #17
0
    def update_base_repo(self, fallback=True, checkmount=True):
        """Update the base repository from the DBus source."""
        log.info("Configuring the base repo")
        self._reset_configuration()

        disabled_treeinfo_repo_names = self._cleanup_old_treeinfo_repositories()

        # Find the source and its type.
        source_proxy = self.get_source_proxy()
        source_type = source_proxy.Type

        # Change the default source to CDROM if there is a valid install media.
        # FIXME: Set up the default source earlier.
        if checkmount and self._is_source_default() and find_optical_install_media():
            source_type = SOURCE_TYPE_CDROM
            source_proxy = create_source(source_type)
            set_source(self.proxy, source_proxy)

        # Set up the source.
        set_up_sources(self.proxy)

        # Read in all the repos from the installation environment, make a note of which
        # are enabled, and then disable them all.  If the user gave us a method, we want
        # to use that instead of the default repos.
        self._base.read_all_repos()

        # Enable or disable updates.
        self.set_updates_enabled(self._updates_enabled)

        # Repo files are always loaded from the system.
        # When reloaded their state needs to be synchronized with the user configuration.
        # So we disable them now and enable them later if required.
        enabled = []
        with self._repos_lock:
            for repo in self._base.repos.iter_enabled():
                enabled.append(repo.id)
                repo.disable()

        # Add a new repo.
        if source_type not in SOURCE_REPO_FILE_TYPES:
            # Get the repo configuration of the first source.
            data = RepoConfigurationData.from_structure(
                self.proxy.GetRepoConfigurations()[0]
            )

            log.debug("Using the repo configuration: %s", data)

            # Get the URL.
            install_tree_url = data.url if data.type == URL_TYPE_BASEURL else ""
            mirrorlist = data.url if data.type == URL_TYPE_MIRRORLIST else ""
            metalink = data.url if data.type == URL_TYPE_METALINK else ""

            # Fallback to the installation root.
            base_repo_url = install_tree_url

            try:
                self._refresh_install_tree(data)
                self._base.conf.releasever = self._get_release_version(install_tree_url)
                base_repo_url = self._get_base_repo_location(install_tree_url)
                log.debug("releasever from %s is %s", base_repo_url, self._base.conf.releasever)

                self._load_treeinfo_repositories(base_repo_url, disabled_treeinfo_repo_names, data)
            except configparser.MissingSectionHeaderError as e:
                log.error("couldn't set releasever from base repo (%s): %s", source_type, e)

            try:
                base_ksrepo = self.data.RepoData(
                    name=constants.BASE_REPO_NAME,
                    baseurl=base_repo_url,
                    mirrorlist=mirrorlist,
                    metalink=metalink,
                    noverifyssl=not data.ssl_verification_enabled,
                    proxy=data.proxy,
                    sslcacert=data.ssl_configuration.ca_cert_path,
                    sslclientcert=data.ssl_configuration.client_cert_path,
                    sslclientkey=data.ssl_configuration.client_key_path
                )
                self._add_repo_to_dnf(base_ksrepo)
                self._fetch_md(base_ksrepo.name)
            except (MetadataError, PayloadError) as e:
                log.error("base repo (%s/%s) not valid -- removing it",
                          source_type, base_repo_url)
                log.error("reason for repo removal: %s", e)
                with self._repos_lock:
                    self._base.repos.pop(constants.BASE_REPO_NAME, None)
                if not fallback:
                    with self._repos_lock:
                        for repo in self._base.repos.iter_enabled():
                            self._disable_repo(repo.id)
                    return

                # Fallback to the default source
                #
                # This is at the moment CDN on RHEL
                # and closest mirror everywhere else.
                tear_down_sources(self.proxy)

                source_type = conf.payload.default_source
                source_proxy = create_source(source_type)
                set_source(self.proxy, source_proxy)

                set_up_sources(self.proxy)

        # We need to check this again separately in case REPO_FILES were set above.
        if source_type in SOURCE_REPO_FILE_TYPES:

            # If this is a kickstart install, just return now as we normally do not
            # want to read the on media repo files in such a case. On the other hand,
            # the local repo files are a valid use case if the system is subscribed
            # and the CDN is selected as the installation source.
            if self.source_type == SOURCE_TYPE_CDN and is_module_available(SUBSCRIPTION):
                # only check if the Subscription module is available & CDN is the
                # installation source
                subscription_proxy = SUBSCRIPTION.get_proxy()
                load_cdn_repos = subscription_proxy.IsSubscriptionAttached
            else:
                # if the Subscription module is not available, we simply can't use
                # the CDN repos, making our decision here simple
                load_cdn_repos = False
            if flags.automatedInstall and not load_cdn_repos:
                return

            # Otherwise, fall back to the default repos that we disabled above
            with self._repos_lock:
                for (id_, repo) in self._base.repos.items():
                    if id_ in enabled:
                        log.debug("repo %s: fall back enabled from default repos", id_)
                        repo.enable()

        for repo in self.addons:
            ksrepo = self.get_addon_repo(repo)

            if ksrepo.is_harddrive_based():
                ksrepo.baseurl = self._setup_harddrive_addon_repo(ksrepo)

            log.debug("repo %s: mirrorlist %s, baseurl %s, metalink %s",
                      ksrepo.name, ksrepo.mirrorlist, ksrepo.baseurl, ksrepo.metalink)
            # one of these must be set to create new repo
            if not (ksrepo.mirrorlist or ksrepo.baseurl or ksrepo.metalink or
                    ksrepo.name in self._base.repos):
                raise PayloadSetupError("Repository %s has no mirror, baseurl or "
                                        "metalink set and is not one of "
                                        "the pre-defined repositories" %
                                        ksrepo.name)

            self._add_repo_to_dnf(ksrepo)

        with self._repos_lock:

            # disable unnecessary repos
            for repo in self._base.repos.iter_enabled():
                id_ = repo.id
                if 'source' in id_ or 'debuginfo' in id_:
                    self._disable_repo(id_)
                elif constants.isFinal and 'rawhide' in id_:
                    self._disable_repo(id_)

            # fetch md for enabled repos
            enabled_repos = self._enabled_repos
            for repo_name in self.addons:
                if repo_name in enabled_repos:
                    self._fetch_md(repo_name)