Example #1
0
    def _mount_image(self, image_path, mount_point):
        # Work around inability to move shared filesystems.
        # Also, do not share the image mounts with /run bind-mounted to physical
        # target root during storage.mount_filesystems.
        rc = execWithRedirect("mount", ["--make-rprivate", "/"])
        if rc != 0:
            log.error("mount error (%s) making mount of '/' rprivate", rc)
            raise SourceSetupError("Mount error {}".format(rc))

        # 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 mount_point
        rc = mount(image_path, mount_point, fstype="auto", options="ro")
        if rc != 0:
            log.error("mount error (%s) with %s", rc, image_path)
            raise SourceSetupError("Mount error {}".format(rc))

        nested_image_files = glob.glob(mount_point + "/LiveOS/*.img")
        if nested_image_files:
            # Mount the first .img in the directory on mount_point
            nested_image = sorted(nested_image_files)[0]

            # move the mount to IMAGE_DIR
            os.makedirs(IMAGE_DIR, 0o755)
            rc = execWithRedirect("mount", ["--move", mount_point, IMAGE_DIR])
            if rc != 0:
                log.error("error %s moving mount", rc)
                raise SourceSetupError("Mount error {}".format(rc))

            nested_image_path = IMAGE_DIR + "/LiveOS/" + os.path.basename(nested_image)
            rc = mount(nested_image_path, mount_point, fstype="auto", options="ro")
            if rc != 0:
                log.error("mount error (%s) with %s", rc, nested_image_path)
                raise SourceSetupError("Mount error {} with {}".format(rc, nested_image_path))
Example #2
0
    def run(self):
        """Set up the installation source."""
        log.debug("Setting up NFS source: %s", self._url)

        for mount_point in [self._device_mount, self._iso_mount]:
            if os.path.ismount(mount_point):
                raise SourceSetupError(
                    "The mount point {} is already in use.".format(
                        mount_point))

        try:
            self._mount_nfs()
        except PayloadSetupError:
            raise SourceSetupError("Could not mount NFS url '{}'".format(
                self._url))

        iso_name = find_and_mount_iso_image(self._device_mount,
                                            self._iso_mount)

        if iso_name:
            log.debug("Using the ISO '%s' mounted at '%s'.", iso_name,
                      self._iso_mount)
            return self._iso_mount

        if verify_valid_installtree(self._device_mount):
            log.debug("Using the directory at '%s'.", self._device_mount)
            return self._device_mount

        # nothing found unmount the existing device
        unmount(self._device_mount)
        raise SourceSetupError(
            "Nothing useful found for NFS source at {}".format(self._url))
Example #3
0
    def _check_remote_image(self, url, proxy):
        """Check that the url is available and return required space."""
        size = 0
        # FIXME: validate earlier when setting?
        proxies = get_proxies_from_option(self._proxy)
        try:
            response = self._session.head(url,
                                          proxies=proxies,
                                          verify=True,
                                          timeout=NETWORK_CONNECTION_TIMEOUT)

            # At this point we know we can get the image and what its size is
            # Make a guess as to minimum size needed:
            # Enough space for image and image * 3
            if response.headers.get('content-length'):
                size = int(response.headers.get('content-length')) * 4
        except IOError as e:
            raise SourceSetupError(
                "Error opening liveimg: {}".format(e)) from e
        else:
            if response.status_code != 200:
                raise SourceSetupError("http request returned: {}".format(
                    response.status_code))

        return size
Example #4
0
    def run(self):
        """Set up the installation source."""
        log.debug("Setting up NFS source: %s", self._url)

        for mount_point in [self._device_mount, self._iso_mount]:
            if os.path.ismount(mount_point):
                raise SourceSetupError("The mount point {} is already in use.".format(
                    mount_point
                ))

        options, host, path = parse_nfs_url(self._url)
        path, image = self._split_iso_from_path(path)
        try:
            self._mount_nfs(host, options, path)
        except PayloadSetupError:
            raise SourceSetupError("Could not mount NFS url '{}'".format(self._url))

        iso_source_path = join_paths(self._device_mount, image) if image else self._device_mount

        iso_name = find_and_mount_iso_image(iso_source_path, self._iso_mount)

        if iso_name:
            log.debug("Using the ISO '%s' mounted at '%s'.", iso_name, self._iso_mount)
            return self._iso_mount

        if verify_valid_repository(self._device_mount):
            log.debug("Using the directory at '%s'.", self._device_mount)
            return self._device_mount

        # nothing found unmount the existing device
        unmount(self._device_mount)
        raise SourceSetupError(
            "Nothing useful found for NFS source at {}".format(self._url))
Example #5
0
    def run(self):
        """Set up the installation source."""
        log.debug("Trying to mount the content of HMC media drive.")

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

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

        log.debug("We are ready to use the HMC at %s.", self._target_mount)
Example #6
0
    def set_sources(self, sources):
        """Set a new list of sources to this payload.

        Before setting the sources, please make sure the sources are not initialized otherwise
        the SourceSetupError exception will be raised. Payload have to cleanup after itself.

        ..NOTE:
        The SourceSetupError is a reasonable effort to solve the race condition. However,
        there is still a possibility that the task to initialize sources (`SetupSourcesWithTask()`)
        was created with the old list but not run yet. In that case this check will not work and
        the initialization task will run with the old list.

        :param sources: set a new sources
        :type sources: instance of pyanaconda.modules.payloads.source.source_base.PayloadSourceBase
        :raise: IncompatibleSourceError when source is not a supported type
                SourceSetupError when attached sources are initialized
        """
        for source in sources:
            if source.type not in self.supported_source_types:
                raise IncompatibleSourceError(
                    "Source type {} is not supported by this payload.".format(
                        source.type.value))

        if any(source.get_state() == SourceState.READY
               for source in self.sources):
            raise SourceSetupError(
                "Can't change list of sources if there is at least one source "
                "initialized! Please tear down the sources first.")

        self._sources = sources
        log.debug("New sources %s were added.", sources)
        self.sources_changed.emit()
Example #7
0
    def run(self):
        """Run live installation source setup."""
        # Mount the live device and copy from it instead of the overlay at /
        device_tree = STORAGE.get_proxy(DEVICE_TREE)
        device_name = device_tree.ResolveDevice(self._live_partition)
        if not device_name:
            raise SourceSetupError("Failed to find liveOS image!")

        device_data = DeviceData.from_structure(device_tree.GetDeviceData(device_name))

        if not stat.S_ISBLK(os.stat(device_data.path)[stat.ST_MODE]):
            raise SourceSetupError("{} is not a valid block device".format(
                self._live_partition))
        rc = mount(device_data.path, self._target_mount, fstype="auto", options="ro")
        if rc != 0:
            raise SourceSetupError("Failed to mount the install tree")
Example #8
0
    def run(self):
        """Collect and call tear down tasks for all the sources."""
        if not self._sources:
            raise SourceSetupError("No sources specified for tear down!")

        errors = []

        for source in self._sources:
            tasks = source.tear_down_with_tasks()
            log.debug("Collected %s tasks from %s source",
                      [task.name for task in tasks],
                      source.type)

            for task in tasks:
                log.debug("Running task %s", task.name)
                try:
                    task.run()
                except SourceTearDownError as e:
                    message = "Task '{}' from source '{}' has failed, reason: {}".format(
                        task.name, source.type, str(e))
                    errors.append(message)
                    log.error("%s\n%s", message, traceback.format_exc())

        if errors:
            raise SourceTearDownError("Sources tear down have failed", errors)
Example #9
0
    def _do_mount(self):
        """Run CD-ROM installation source setup."""
        log.debug("Trying to detect CD-ROM automatically")

        device_tree = STORAGE.get_proxy(DEVICE_TREE)
        device_name = ""

        for dev_name in device_tree.FindOpticalMedia():
            try:
                device_data = DeviceData.from_structure(
                    device_tree.GetDeviceData(dev_name))
                mount(device_data.path, self._target_mount, "iso9660", "ro")
            except PayloadSetupError:
                continue

            if is_valid_install_disk(self._target_mount):
                device_name = dev_name
                log.info("using CD-ROM device %s mounted at %s", dev_name,
                         self._target_mount)
                break
            else:
                unmount(self._target_mount)

        if not device_name:
            raise SourceSetupError("Found no CD-ROM")
    def _mount_device(self, device_path):
        """Mount the specified device."""
        log.debug("Mounting %s at %s.", device_path, self._target_mount)

        try:
            rc = blivet.util.mount(
                device_path,
                self._target_mount,
                fstype="auto",
                options="ro"
            )
        except OSError as e:
            raise SourceSetupError(str(e)) from e

        if rc != 0:
            raise SourceSetupError("Failed to mount the Live OS image.")
Example #11
0
 def run(self):
     """Run Repo files installation source setup."""
     log.debug("Trying to detect repo files automatically")
     for repo_dir in self._repo_dirs:
         if len(glob.glob(os.path.join(repo_dir, "*.repo"))) > 0:
             return
     raise SourceSetupError("repo files not found")
Example #12
0
 def _download_image(self, url, image_path, session):
     """Download the image using Requests with progress reporting"""
     error = None
     try:
         log.info("Starting image download")
         with open(image_path, "wb") as f:
             ssl_verify = not self._noverifyssl
             proxies = get_proxies_from_option(self._proxy)
             response = session.get(url,
                                    proxies=proxies,
                                    verify=ssl_verify,
                                    stream=True,
                                    timeout=NETWORK_CONNECTION_TIMEOUT)
             total_length = response.headers.get('content-length')
             if total_length is None:
                 # just download the file in one go and fake the progress reporting once done
                 log.warning(
                     "content-length header is missing for the installation image, "
                     "download progress reporting will not be available")
                 f.write(response.content)
                 size = f.tell()
                 progress = DownloadProgress(self._url, size,
                                             self.report_progress)
                 progress.end()
             else:
                 # requests return headers as strings, so convert total_length to int
                 progress = DownloadProgress(self._url, int(total_length),
                                             self.report_progress)
                 bytes_read = 0
                 for buf in response.iter_content(1024 * 1024):
                     if buf:
                         f.write(buf)
                         f.flush()
                         bytes_read += len(buf)
                         progress.update(bytes_read)
                 progress.end()
             log.info("Image download finished")
     except RequestException as e:
         error = "Error downloading liveimg: {}".format(e)
         log.error(error)
         raise SourceSetupError(error)
     else:
         if not os.path.exists(image_path):
             error = "Failed to download {}, file doesn't exist".format(
                 self._url)
             log.error(error)
             raise SourceSetupError(error)
Example #13
0
    def run(self):
        """Run Hard drive installation source setup.

        Always sets up two mount points: First for the device, and second for the ISO image or a
        bind for unpacked ISO. These depend on each other, and must be destroyed in the correct
        order again.

        :raise: SourceSetupError
        :return: named tuple with path to the install tree and name of ISO if set or empty string
        :rtype: SetupHardDriveResult instance
        """
        log.debug("Setting up Hard drive source")

        for mount_point in [self._device_mount, self._iso_mount]:
            if os.path.ismount(mount_point):
                raise SourceSetupError(
                    "The mount point {} is already in use.".format(
                        mount_point))

        if not find_and_mount_device(self._partition, self._device_mount):
            raise SourceSetupError(
                "Could not mount device specified as {}".format(
                    self._partition))

        full_path_on_mounted_device = os.path.normpath("{}/{}".format(
            self._device_mount, self._directory))

        iso_name = find_first_iso_image(full_path_on_mounted_device)

        if iso_name:
            full_path_to_iso = self._create_iso_path(
                full_path_on_mounted_device, iso_name)

            if mount_iso_image(full_path_to_iso, self._iso_mount):
                log.debug("Using the ISO '%s' mounted at '%s'.", iso_name,
                          self._iso_mount)
                return SetupHardDriveResult(self._iso_mount, iso_name)

        if verify_valid_installtree(full_path_on_mounted_device):
            log.debug("Using the directory at '%s'.",
                      full_path_on_mounted_device)
            return SetupHardDriveResult(full_path_on_mounted_device, "")

        raise SourceSetupError(
            "Nothing useful found for Hard drive ISO source at partition={} directory={}"
            .format(self._partition, self._directory))
Example #14
0
    def update_kernel_version_list(self):
        """Update list of kernel versions."""
        if url_target_is_tarfile(self._url):
            if not os.path.exists(self.image_path):
                raise SourceSetupError("Failed to find tarfile image")
            kernel_version_list = get_kernel_version_list_from_tar(self.image_path)
        else:
            kernel_version_list = get_kernel_version_list(INSTALL_TREE)

        self.set_kernel_version_list(kernel_version_list)
    def _get_device_path(self):
        """Get a device path of the block device."""
        log.debug("Resolving %s.", self._image_path)
        device_tree = STORAGE.get_proxy(DEVICE_TREE)

        # Get the device name.
        device_name = device_tree.ResolveDevice(self._image_path)

        if not device_name:
            raise SourceSetupError("Failed to resolve the Live OS image.")

        # Get the device path.
        device_data = DeviceData.from_structure(
            device_tree.GetDeviceData(device_name)
        )
        device_path = device_data.path

        if not stat.S_ISBLK(os.stat(device_path)[stat.ST_MODE]):
            raise SourceSetupError("{} is not a valid block device.".format(device_path))

        return device_path
Example #16
0
    def _handle_system_repository(self, data):
        """Handle a system repository.

        The user is trying to do "repo --name=updates" in a kickstart file.
        We can only enable or disable the already existing on-disk repo config.

        :raise: SourceSetupError if the system repository is not available
        """
        try:
            self._dnf_manager.set_repository_enabled(data.name, data.enabled)
        except UnknownRepositoryError:
            msg = "The '{}' repository is not one of the pre-defined repositories."
            raise SourceSetupError(msg.format(data.name)) from None
Example #17
0
    def run(self):
        """Collect and call set up tasks for all the sources."""
        if not self._sources:
            raise SourceSetupError("No sources specified for set up!")

        for source in self._sources:
            tasks = source.set_up_with_tasks()
            log.debug("Collected %s tasks from %s source",
                      [task.name for task in tasks], source.type)

            for task in tasks:
                log.debug("Running task %s", task.name)
                task.run()
Example #18
0
    def run(self):
        """Run installation source image check.

        :return: a tuple with the required space
        :rtype: an instance of SetupImageResult
        :raise: SourceSetupError on failure
        """
        path = get_local_image_path_from_url(self._url)

        if not os.path.exists(path):
            raise SourceSetupError("File {} does not exist.".format(path))

        size = self._get_required_space(path)
        return SetupImageResult(required_space=size)
Example #19
0
    def _send_request(self, session):
        """Send a HEAD request to the image URL."""
        # Send a request.
        proxies = get_proxies_from_option(self._proxy)
        response = session.head(url=self._url,
                                proxies=proxies,
                                verify=True,
                                timeout=NETWORK_CONNECTION_TIMEOUT)

        # Check the response.
        if response.status_code != 200:
            msg = "The request has failed: {}".format(response.status_code)
            raise SourceSetupError(msg)

        return response
Example #20
0
    def run(self):
        """Run Hard drive installation source setup.

        Always sets up two mount points: First for the device, and second for the ISO image or a
        bind for unpacked ISO. These depend on each other, and must be destroyed in the correct
        order again.

        :raise: SourceSetupError
        :return: path to the install tree
        :rtype: str
        """
        log.debug("Setting up Hard drive source")

        for mount_point in [self._device_mount, self._iso_mount]:
            if os.path.ismount(mount_point):
                raise SourceSetupError(
                    "The mount point {} is already in use.".format(
                        mount_point))

        if not find_and_mount_device(self._partition, self._device_mount):
            raise SourceSetupError(
                "Could not mount device specified as {}".format(
                    self._partition))

        full_path_on_mounted_device = os.path.normpath("{}/{}".format(
            self._device_mount, self._directory))

        if find_and_mount_iso_image(full_path_on_mounted_device,
                                    self._iso_mount):
            return self._iso_mount, True
        elif verify_valid_installtree(full_path_on_mounted_device):
            return full_path_on_mounted_device, False

        raise SourceSetupError(
            "Nothing useful found for Hard drive ISO source at partition={} directory={}"
            .format(self._partition, self._directory))
Example #21
0
    def _check_image_sum(self, image_path, checksum):
        self.report_progress("Checking image checksum")
        sha256 = hashlib.sha256()
        with open(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", image_path, filesum)

        if lowerASCII(checksum) != filesum:
            log.error("%s does not match checksum of %s.", checksum, image_path)
            raise SourceSetupError("Checksum of image {} does not match".format(image_path))
    def run(self):
        """Run the task.

        Check /run/rootfsbase to detect a squashfs+overlayfs base image.

        :return: a path of a block device or None
        """
        block_device = \
            self._check_block_device("/dev/mapper/live-base") or \
            self._check_block_device("/dev/mapper/live-osimg-min") or \
            self._check_mount_point("/run/rootfsbase")

        if not block_device:
            raise SourceSetupError("No Live OS image found!")

        log.debug("Detected the Live OS image '%s'.", block_device)
        return block_device
Example #23
0
    def _do_mount(self):
        """Run CD-ROM installation source setup.

        Try to discover installation media and mount that. Device used for booting (inst.stage2)
        has a priority.
        """
        log.debug("Trying to detect CD-ROM automatically")
        device_tree = STORAGE.get_proxy(DEVICE_TREE)

        device_candidates = self._get_device_candidate_list(device_tree)
        device_name = self._choose_installation_device(device_tree,
                                                       device_candidates)

        if not device_name:
            raise SourceSetupError("Found no CD-ROM")

        return device_name
Example #24
0
    def run(self):
        """Run installation source image check.

        :return: a tuple with the required space
        :rtype: an instance of SetupImageResult
        :raise: SourceSetupError on failure
        """
        with requests_session() as session:
            try:
                # Send a HEAD request to the image URL.
                response = self._send_request(session)

                # Calculate the required space for the image.
                size = self._get_required_space(response)

            except RequestException as e:
                msg = "Error while handling a request: {}".format(e)
                raise SourceSetupError(msg) from e

        return SetupImageResult(required_space=size)
Example #25
0
    def run(self):
        """Set up the installation source."""
        log.debug("Trying to mount NFS: %s", self._url)

        if ismount(self._target_mount):
            raise SourceSetupError(
                "Something is already mounted at the target {}".format(
                    self._target_mount))

        options, host, path = parse_nfs_url(self._url)
        if not options:
            options = "nolock"
        elif "nolock" not in options:
            options += ",nolock"

        mount("{}:{}".format(host, path),
              self._target_mount,
              fstype="nfs",
              options=options)

        log.debug("We are ready to use NFS at %s.", self._target_mount)
Example #26
0
    def set_up_sources_task_with_exception_test(self):
        """Test task to set up installation sources which raise exception."""
        set_up_task1 = create_autospec(Task)
        set_up_task2 = create_autospec(Task)
        set_up_task3 = create_autospec(Task)

        set_up_task2.run_with_signals.side_effect = SourceSetupError("task2 error")

        source1 = create_autospec(PayloadSourceBase)
        source2 = create_autospec(PayloadSourceBase)

        source1.set_up_with_tasks.return_value = [set_up_task1, set_up_task2]
        source2.set_up_with_tasks.return_value = [set_up_task3]

        task = SetUpSourcesTask([source1, source2])

        with self.assertRaises(SourceSetupError):
            task.run()

        set_up_task1.run_with_signals.assert_called_once()
        set_up_task2.run_with_signals.assert_called_once()
        set_up_task3.run_with_signals.assert_not_called()
Example #27
0
    def _set_up_additional_repository(self, data):
        """Set up sources for the additional repository."""
        # Check the validity of the repository.
        if not data.url:
            msg = "The '{}' repository has no mirror, baseurl or metalink set."
            raise SourceSetupError(msg.format(data.name)) from None

        # Set up the NFS source with a substituted URL.
        elif data.url.startswith("nfs://"):
            device_mount = self._create_mount_point(constants.MOUNT_DIR,
                                                    data.name + "-nfs-device")
            iso_mount = self._create_mount_point(constants.MOUNT_DIR,
                                                 data.name + "-nfs-iso")
            task = SetUpNFSSourceTask(device_mount=device_mount,
                                      iso_mount=iso_mount,
                                      url=self._dnf_manager.substitute(
                                          data.url))
            mount_point = task.run()
            data.url = "file://" + mount_point

        # Set up the HDD source.
        elif data.url.startswith("hd:"):
            device_mount = self._create_mount_point(ISO_DIR + "-" + data.name +
                                                    "-hdd-device")
            iso_mount = self._create_mount_point(INSTALL_TREE + "-" +
                                                 data.name + "-hdd-iso")

            partition, directory = parse_hdd_url(data.url)

            task = SetUpHardDriveSourceTask(
                device_mount=device_mount,
                iso_mount=iso_mount,
                partition=partition,
                directory=directory,
            )
            result = task.run()
            data.url = "file://" + result.install_tree_path
Example #28
0
 def _check_mount(self):
     if os.path.ismount(self._target_mount):
         raise SourceSetupError("The mount point {} is already in use.".format(
             self._target_mount
         ))
Example #29
0
 def _check_local_image(self, file_path):
     """Check that the file exists and return required space."""
     if not os.path.exists(file_path):
         raise SourceSetupError("File {} does not exist".format(file_path))
     size = os.stat(file_path)[stat.ST_SIZE] * 3
     return size
Example #30
0
 def _check_mount(self):
     """Check if the source is unmounted."""
     if os.path.ismount(self._target_mount):
         raise SourceSetupError(
             "The mount point {} is already in use.".format(
                 self._target_mount))