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)
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
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
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)
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
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")
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))
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))
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))
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
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)
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
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)
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
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)
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
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)