Beispiel #1
0
    def updateNVRAMBootList(self):
        if not conf.target.is_hardware:
            return

        log.debug("updateNVRAMBootList: self.stage1_device.path = %s", self.stage1_device.path)

        buf = util.execWithCapture("nvram",
                                   ["--print-config=boot-device"])

        if len(buf) == 0:
            log.error("Failed to determine nvram boot device")
            return

        boot_list = buf.strip().replace("\"", "").split()
        log.debug("updateNVRAMBootList: boot_list = %s", boot_list)

        buf = util.execWithCapture("ofpathname",
                                   [self.stage1_device.path])

        if len(buf) > 0:
            boot_disk = buf.strip()
        else:
            log.error("Failed to translate boot path into device name")
            return

        # Place the disk containing the PReP partition first.
        # Remove all other occurances of it.
        boot_list = [boot_disk] + [x for x in boot_list if x != boot_disk]

        update_value = "boot-device=%s" % " ".join(boot_list)

        rc = util.execWithRedirect("nvram", ["--update-config", update_value])
        if rc:
            log.error("Failed to update new boot device order")
Beispiel #2
0
    def updateNVRAMBootList(self):
        if not conf.target.is_hardware:
            return

        log.debug("updateNVRAMBootList: self.stage1_device.path = %s", self.stage1_device.path)

        buf = util.execWithCapture("nvram",
                                   ["--print-config=boot-device"])

        if len(buf) == 0:
            log.error("Failed to determine nvram boot device")
            return

        boot_list = buf.strip().replace("\"", "").split()
        log.debug("updateNVRAMBootList: boot_list = %s", boot_list)

        buf = util.execWithCapture("ofpathname",
                                   [self.stage1_device.path])

        if len(buf) > 0:
            boot_disk = buf.strip()
        else:
            log.error("Failed to translate boot path into device name")
            return

        # Place the disk containing the PReP partition first.
        # Remove all other occurances of it.
        boot_list = [boot_disk] + [x for x in boot_list if x != boot_disk]

        update_value = "boot-device=%s" % " ".join(boot_list)

        rc = util.execWithRedirect("nvram", ["--update-config", update_value])
        if rc:
            log.error("Failed to update new boot device order")
Beispiel #3
0
    def exec_with_capture_test(self):
        """Test execWithCapture."""

        # check some output is returned
        self.assertGreater(len(util.execWithCapture('ls', ['--help'])), 0)

        # check no output is returned
        self.assertEqual(len(util.execWithCapture('true', [])), 0)
Beispiel #4
0
    def exec_with_capture_test(self):
        """Test execWithCapture."""

        # check some output is returned
        self.assertGreater(len(util.execWithCapture('ls', ['--help'])), 0)

        # check no output is returned
        self.assertEqual(len(util.execWithCapture('true', [])), 0)
Beispiel #5
0
    def test_exec_with_capture(self):
        """Test execWithCapture."""

        # check some output is returned
        assert len(util.execWithCapture('ls', ['--help'])) > 0

        # check no output is returned
        assert len(util.execWithCapture('true', [])) == 0
Beispiel #6
0
def shutdownServer():
    """Try to shutdown any running XVNC server

    Why is this function on the module level and not in the VncServer class ?

    As the server needs to be killed from the exit handler, it would have
    to somehow get to the VncServer instance. Like this, it can just kill
    it by calling a function of the vnc module.
    """
    try:
        util.execWithCapture("killall", [XVNC_BINARY_NAME])
        log.info("The XVNC server has been shut down.")
    except OSError as e:
        log.error("Shutdown of the XVNC server failed with exception:\n%s", e)
Beispiel #7
0
def shutdownServer():
    """Try to shutdown any running XVNC server

    Why is this function on the module level and not in the VncServer class ?

    As the server needs to be killed from the exit handler, it would have
    to somehow get to the VncServer instance. Like this, it can just kill
    it by calling a function of the vnc module.
    """
    try:
        util.execWithCapture("killall", [XVNC_BINARY_NAME])
        log.info("The XVNC server has been shut down.")
    except OSError as e:
        log.error("Shutdown of the XVNC server failed with exception:\n%s", e)
Beispiel #8
0
    def setup(self):
        security_proxy = SECURITY.get_proxy()
        realm = RealmData.from_structure(security_proxy.Realm)

        if not realm.name:
            return

        try:
            argv = ["discover", "--verbose"
                    ] + realm.discover_options + [realm.name]
            output = util.execWithCapture("realm", argv, filter_stderr=True)
        except OSError:
            # TODO: A lousy way of propagating what will usually be
            # 'no such realm'
            # The error message is logged by util
            return

        # Now parse the output for the required software. First line is the
        # realm name, and following lines are information as "name: value"
        self.packages = ["realmd"]
        self.discovered = ""

        lines = output.split("\n")
        if not lines:
            return
        self.discovered = lines.pop(0).strip()
        realm_log.info("Realm discovered: %s", self.discovered)
        for line in lines:
            parts = line.split(":", 1)
            if len(parts) == 2 and parts[0].strip() == "required-package":
                self.packages.append(parts[1].strip())

        realm_log.info("Realm %s needs packages %s", self.discovered,
                       ", ".join(self.packages))
Beispiel #9
0
    def setup(self):
        security_proxy = SECURITY.get_proxy()
        realm = RealmData.from_structure(security_proxy.Realm)

        if not realm.name:
            return

        try:
            argv = ["discover", "--verbose"] + realm.discover_options + [realm.name]
            output = util.execWithCapture("realm", argv, filter_stderr=True)
        except OSError:
            # TODO: A lousy way of propagating what will usually be
            # 'no such realm'
            # The error message is logged by util
            return

        # Now parse the output for the required software. First line is the
        # realm name, and following lines are information as "name: value"
        self.packages = ["realmd"]
        self.discovered = ""

        lines = output.split("\n")
        if not lines:
            return
        self.discovered = lines.pop(0).strip()
        realm_log.info("Realm discovered: %s", self.discovered)
        for line in lines:
            parts = line.split(":", 1)
            if len(parts) == 2 and parts[0].strip() == "required-package":
                self.packages.append(parts[1].strip())

        realm_log.info("Realm %s needs packages %s",
                       self.discovered, ", ".join(self.packages))
Beispiel #10
0
    def detect_live_os_image(self):
        """Detect live os image in the system."""
        log.debug("Trying to detect live os base image automatically")
        for block_device in [
                "/dev/mapper/live-base", "/dev/mapper/live-osimg-min"
        ]:
            try:
                if stat.S_ISBLK(os.stat(block_device)[stat.ST_MODE]):
                    log.debug("Detected live base image %s", block_device)
                    return block_device
            except FileNotFoundError:
                pass

        # Is it a squashfs+overlayfs base image?
        if os.path.exists("/run/rootfsbase"):
            try:
                block_device = execWithCapture(
                    "findmnt",
                    ["-n", "-o", "SOURCE", "/run/rootfsbase"]).strip()
                if block_device:
                    log.debug("Detected live base image %s", block_device)
                    return block_device
            except (OSError, FileNotFoundError):
                pass

        log.debug("No live base image detected")
        return ""
Beispiel #11
0
    def run(self):
        if not self._realm_data.name:
            log.debug("No realm name set, skipping realm discovery.")
            return self._realm_data

        output = ""

        try:
            argv = ["discover", "--verbose"] + self._realm_data.discover_options \
                + [self._realm_data.name]
            output = util.execWithCapture(REALM_TOOL_NAME,
                                          argv,
                                          filter_stderr=True)
        except OSError:
            # TODO: A lousy way of propagating what will usually be
            # 'no such realm'
            # The error message is logged by util
            return self._realm_data

        realm_discovered, required_packages = self._parse_realm_data(output)

        # set the result in the realm data holder and return it
        self._realm_data.discovered = realm_discovered
        self._realm_data.required_packages = required_packages
        return self._realm_data
Beispiel #12
0
    def run(self):
        """Run the task"""
        if not self._gpg_keys:
            log.debug("No GPG keys to import.")
            return

        if not os.path.exists(self._sysroot + "/usr/bin/rpm"):
            log.error(
                "Can not import GPG keys to RPM database because "
                "the 'rpm' executable is missing on the target "
                "system. The following keys were not imported:\n%s",
                "\n".join(self._gpg_keys)
            )
            return

        # Get substitutions for variables.
        # TODO: replace the interpolation with DNF once possible
        basearch = util.execWithCapture("uname", ["-i"]).strip().replace("'", "")
        releasever = util.get_os_release_value("VERSION_ID", sysroot=self._sysroot) or ""

        # Import GPG keys to RPM database.
        for key in self._gpg_keys:
            key = key.replace("$releasever", releasever).replace("$basearch", basearch)

            log.info("Importing GPG key to RPM database: %s", key)
            rc = util.execWithRedirect("rpm", ["--import", key], root=self._sysroot)

            if rc:
                log.error("Failed to import the GPG key.")
Beispiel #13
0
def _get_current_free_space_map():
    """Get the available file system disk space of the current system.

    :return: a dictionary of mount points and their available space
    """
    mapping = {}

    # Generate the dictionary of mount points and sizes.
    output = execWithCapture('df', ['--output=target,avail'])
    lines = output.rstrip().splitlines()

    for line in lines:
        key, val = line.rsplit(maxsplit=1)

        if not key.startswith('/'):
            continue

        mapping[key] = Size(int(val) * 1024)

    # Add /var/tmp/ if this is a directory or image installation.
    if not conf.target.is_hardware:
        var_tmp = os.statvfs("/var/tmp")
        mapping["/var/tmp"] = Size(var_tmp.f_frsize * var_tmp.f_bfree)

    return mapping
Beispiel #14
0
    def test_exec_with_capture_no_stderr(self):
        """Test execWithCapture with no stderr"""

        with tempfile.NamedTemporaryFile(mode="w+t") as testscript:
            testscript.write("""#!/bin/sh
echo "output"
echo "error" >&2
""")
            testscript.flush()

            # check that only the output is captured
            assert util.execWithCapture("/bin/sh", [testscript.name], filter_stderr=True) == \
                    "output\n"

            # check that both output and error are captured
            assert util.execWithCapture("/bin/sh",
                                        [testscript.name]) == "output\nerror\n"
Beispiel #15
0
 def test_resolve_date_format(self):
     """All locales' date formats should be properly resolved."""
     locales = (line.strip() for line in execWithCapture("locale", ["-a"]).splitlines())
     for locale in locales:
         locale_mod.setlocale(locale_mod.LC_ALL, locale)
         order = localization.resolve_date_format(1, 2, 3, fail_safe=False)[0]
         for i in (1, 2, 3):
             self.assertIn(i, order)
Beispiel #16
0
    def exec_with_capture_no_stderr_test(self):
        """Test execWithCapture with no stderr"""

        with tempfile.NamedTemporaryFile(mode="w+t") as testscript:
            testscript.write("""#!/bin/sh
echo "output"
echo "error" >&2
""")
            testscript.flush()

            # check that only the output is captured
            self.assertEqual(
                    util.execWithCapture("/bin/sh", [testscript.name], filter_stderr=True),
                    "output\n")

            # check that both output and error are captured
            self.assertEqual(util.execWithCapture("/bin/sh", [testscript.name]), "output\nerror\n")
Beispiel #17
0
    def updateNVRAMBootList(self):
        if not conf.target.is_hardware:
            return

        log.debug("updateNVRAMBootList: self.stage1_device.path = %s",
                  self.stage1_device.path)

        buf = util.execWithCapture("nvram", ["--print-config=boot-device"],
                                   filter_stderr=True)

        if len(buf) == 0:
            log.error("Failed to determine nvram boot device")
            return

        boot_list = buf.strip().replace("\"", "").split()
        log.debug("updateNVRAMBootList: boot_list = %s", boot_list)

        buf = util.execWithCapture("ofpathname", [self.stage1_device.path],
                                   filter_stderr=True)

        if len(buf) > 0:
            boot_disk = buf.strip()
        else:
            log.error("Failed to translate boot path into device name")
            return

        # Place the disk containing the PReP partition first.
        # Remove all other occurances of it.
        boot_list = [boot_disk] + [x for x in boot_list if x != boot_disk]

        # The boot-device NVRAM variable has a maximum number of devices allowed,
        # don't add more than the limit in the ibm,max-boot-devices OF property.
        max_dev_path = "/sys/firmware/devicetree/base/ibm,max-boot-devices"
        if os.access(max_dev_path, os.F_OK):
            with open(max_dev_path, "rb") as f:
                limit = int.from_bytes(f.read(4), byteorder='big')
                boot_list = boot_list[:limit]

        update_value = "boot-device=%s" % " ".join(boot_list)

        rc = util.execWithRedirect("nvram", ["--update-config", update_value])
        if rc:
            log.error("Failed to update new boot device order")
Beispiel #18
0
def ifaceForHostIP(host):
    route = util.execWithCapture("ip", ["route", "get", "to", host])
    if not route:
        log.error("Could not get interface for route to %s", host)
        return ""

    routeInfo = route.split()
    if routeInfo[0] != host or len(routeInfo) < 5 or \
       "dev" not in routeInfo or routeInfo.index("dev") > 3:
        log.error('Unexpected "ip route get to %s" reply: %s', host, routeInfo)
        return ""

    return routeInfo[routeInfo.index("dev") + 1]
    def _check_mount_point(self, mount_point):
        """Check a block device at the specified mount point."""
        log.debug("Checking the %s mount point.", mount_point)

        if not os.path.exists(mount_point):
            return None

        try:
            block_device = execWithCapture("findmnt", ["-n", "-o", "SOURCE", mount_point]).strip()
            return block_device or None
        except (OSError, FileNotFoundError):
            pass

        return None
Beispiel #20
0
def iface_for_host_ip(host_ip):
    """Get interface used to access given host IP."""
    route = util.execWithCapture("ip", ["route", "get", "to", host_ip])
    if not route:
        log.error("Could not get interface for route to %s", host_ip)
        return ""

    route_info = route.split()
    if route_info[0] != host_ip or len(route_info) < 5 or \
       "dev" not in route_info or route_info.index("dev") > 3:
        log.error('Unexpected "ip route get to %s" reply: %s', host_ip, route_info)
        return ""

    return route_info[route_info.index("dev") + 1]
Beispiel #21
0
def iface_for_host_ip(host_ip):
    """Get interface used to access given host IP."""
    route = util.execWithCapture("ip", ["route", "get", "to", host_ip])
    if not route:
        log.error("Could not get interface for route to %s", host_ip)
        return ""

    route_info = route.split()
    if route_info[0] != host_ip or len(route_info) < 5 or \
       "dev" not in route_info or route_info.index("dev") > 3:
        log.error('Unexpected "ip route get to %s" reply: %s', host_ip, route_info)
        return ""

    return route_info[route_info.index("dev") + 1]
Beispiel #22
0
def get_df_map():
    """Return (mountpoint -> size available) mapping."""
    output = util.execWithCapture('df', ['--output=target,avail'])
    output = output.rstrip()
    lines = output.splitlines()
    structured = {}
    for line in lines:
        key, val = line.rsplit(maxsplit=1)
        if not key.startswith('/'):
            continue
        structured[key] = Size(int(val) * 1024)

    # Add /var/tmp/ if this is a directory or image installation
    if not conf.target.is_hardware:
        var_tmp = os.statvfs("/var/tmp")
        structured["/var/tmp"] = Size(var_tmp.f_frsize * var_tmp.f_bfree)
    return structured
Beispiel #23
0
    def write_config(self):
        config_path = "%s%s" % (conf.target.system_root, self.efi_config_file)

        with open(config_path, "w") as fd:
            grub_dir = self.config_dir
            fs_uuid = self.stage2_device.format.uuid

            grub_dir = util.execWithCapture("grub2-mkrelpath", [grub_dir],
                                            root=conf.target.system_root)
            if not grub_dir:
                raise BootLoaderError("Could not get GRUB directory path")

            fd.write("search --no-floppy --fs-uuid --set=dev %s\n" % fs_uuid)
            fd.write("set prefix=($dev)%s\n" % grub_dir)
            fd.write("export $prefix\n")
            fd.write("configfile $prefix/grub.cfg\n")

        super().write_config()
Beispiel #24
0
    def _encrypt_password(self):
        """Make sure self.encrypted_password is set up properly."""
        if self.encrypted_password:
            return

        if not self.password:
            raise RuntimeError("cannot encrypt empty password")

        (pread, pwrite) = os.pipe()
        passwords = "%s\n%s\n" % (self.password, self.password)
        os.write(pwrite, passwords.encode("utf-8"))
        os.close(pwrite)
        buf = util.execWithCapture("grub2-mkpasswd-pbkdf2", [],
                                   stdin=pread,
                                   root=util.getSysroot())
        os.close(pread)
        self.encrypted_password = buf.split()[-1].strip()
        if not self.encrypted_password.startswith("grub.pbkdf2."):
            raise BootLoaderError("failed to encrypt boot loader password")
Beispiel #25
0
def is_service_installed(service, root="/"):
    """Is a systemd service installed?

    Runs 'systemctl list-unit-files' to determine if the service exists.

    :param str service: name of the service to check
    :param str root: path to the sysroot, defaults to installation environment
    """
    if not service.endswith(".service"):
        service += ".service"

    args = ["list-unit-files", service, "--no-legend"]

    if root != "/":
        args += ["--root", root]

    unit_file = execWithCapture("systemctl", args)

    return bool(unit_file)
    def _is_language_support_installed(self, lang):
        """Is the support for the specified language installed?

        The language is considered to be supported if we are not
        able to determine the supported locales due to missing tools.

        :param lang: a value for the LANG locale variable
        :return: False if the locale is known to be not supported, otherwise True
        """
        try:
            output = execWithCapture("locale", ["-a"], root=self._sysroot)
        except OSError as e:
            log.warning("Couldn't get supported locales: %s", e)
            return True

        match = find_best_locale_match(lang, output.splitlines())

        log.debug("The '%s' locale matched '%s'.", lang, match)
        return bool(match)
Beispiel #27
0
def _df_map():
    """Return (mountpoint -> size available) mapping."""
    output = util.execWithCapture('df', ['--output=target,avail'])
    output = output.rstrip()
    lines = output.splitlines()
    structured = {}
    for line in lines:
        items = line.split()
        key = items[0]
        val = items[1]
        if not key.startswith('/'):
            continue
        structured[key] = Size(int(val) * 1024)

    # Add /var/tmp/ if this is a directory or image installation
    if flags.dirInstall or flags.imageInstall:
        var_tmp = os.statvfs("/var/tmp")
        structured["/var/tmp"] = Size(var_tmp.f_frsize * var_tmp.f_bfree)
    return structured
Beispiel #28
0
    def _encrypt_password(self):
        """Make sure self.encrypted_password is set up properly."""
        if self.encrypted_password:
            return

        if not self.password:
            raise RuntimeError("cannot encrypt empty password")

        (pread, pwrite) = os.pipe()
        passwords = "%s\n%s\n" % (self.password, self.password)
        os.write(pwrite, passwords.encode("utf-8"))
        os.close(pwrite)
        buf = util.execWithCapture("grub2-mkpasswd-pbkdf2", [],
                                   stdin=pread,
                                   root=conf.target.system_root)
        os.close(pread)
        self.encrypted_password = buf.split()[-1].strip()
        if not self.encrypted_password.startswith("grub.pbkdf2."):
            raise BootLoaderError("failed to encrypt boot loader password")
Beispiel #29
0
def get_default_route_iface(family="inet"):
    """Get the device having default route.

    :return: the name of the network device having default route
    """
    routes = util.execWithCapture("ip", ["-f", family, "route", "show"])
    if not routes:
        log.debug("Could not get default %s route device", family)
        return None

    for line in routes.split("\n"):
        if line.startswith("default"):
            parts = line.split()
            if len(parts) >= 5 and parts[3] == "dev":
                return parts[4]
            else:
                log.debug("Could not parse default %s route device", family)
                return None

    return None
Beispiel #30
0
def get_default_route_iface(family="inet"):
    """Get the device having default route.

    :return: the name of the network device having default route
    """
    routes = util.execWithCapture("ip", ["-f", family, "route", "show"])
    if not routes:
        log.debug("Could not get default %s route device", family)
        return None

    for line in routes.split("\n"):
        if line.startswith("default"):
            parts = line.split()
            if len(parts) >= 5 and parts[3] == "dev":
                return parts[4]
            else:
                log.debug("Could not parse default %s route device", family)
                return None

    return None
Beispiel #31
0
    def install(self, args=None):
        buf = util.execWithCapture("zipl", [], root=util.getSysroot())
        for line in buf.splitlines():
            if line.startswith("Preparing boot device: "):
                # Output here may look like:
                #     Preparing boot device: dasdb (0200).
                #     Preparing boot device: dasdl.
                # We want to extract the device name and pass that.
                name = re.sub(r".+?: ", "", line)
                self.stage1_name = re.sub(r"(\s\(.+\))?\.$", "", name)
            # a limitation of s390x is that the kernel parameter list must not
            # exceed 896 bytes; there is nothing we can do about this, so just
            # catch the error and show it to the user instead of crashing
            elif line.startswith("Error: The length of the parameters "):
                errorHandler.cb(ZIPLError(line))

        if not self.stage1_name:
            raise BootLoaderError("could not find IPL device")

        # do the reipl
        util.reIPL(self.stage1_name)
Beispiel #32
0
    def install(self, args=None):
        buf = util.execWithCapture("zipl", [], root=conf.target.system_root)
        for line in buf.splitlines():
            if line.startswith("Preparing boot device: "):
                # Output here may look like:
                #     Preparing boot device: dasdb (0200).
                #     Preparing boot device: dasdl.
                # We want to extract the device name and pass that.
                name = re.sub(r".+?: ", "", line)
                self.stage1_name = re.sub(r"(\s\(.+\))?\.$", "", name)
            # a limitation of s390x is that the kernel parameter list must not
            # exceed 896 bytes; there is nothing we can do about this, so just
            # catch the error and show it to the user instead of crashing
            elif line.startswith("Error: The length of the parameters "):
                raise BootLoaderError(line)

        if not self.stage1_name:
            raise BootLoaderError("could not find IPL device")

        # do the reipl
        util.reIPL(self.stage1_name)
Beispiel #33
0
    def test_exec_with_capture_empty(self):
        """Test execWithCapture with no output"""

        # check that the output is an empty string
        assert util.execWithCapture("/bin/sh", ["-c", "exit 0"]) == ""
Beispiel #34
0
    def exec_with_capture_empty_test(self):
        """Test execWithCapture with no output"""

        # check that the output is an empty string
        self.assertEqual(util.execWithCapture("/bin/sh", ["-c", "exit 0"]), "")
Beispiel #35
0
    def exec_with_capture_empty_test(self):
        """Test execWithCapture with no output"""

        # check that the output is an empty string
        self.assertEqual(util.execWithCapture("/bin/sh", ["-c", "exit 0"]), "")
Beispiel #36
0
def lsblk_callback():
    """Callback to get info about block devices."""

    options = "NAME,SIZE,OWNER,GROUP,MODE,FSTYPE,LABEL,UUID,PARTUUID,FSAVAIL,FSUSE%,MOUNTPOINT"

    return util.execWithCapture("lsblk", ["--bytes", "-o", options])
Beispiel #37
0
def lsblk_callback():
    """Callback to get info about block devices."""

    return util.execWithCapture("lsblk", ["--perms", "--fs", "--bytes"])
Beispiel #38
0
def nmcli_dev_list_callback():
    """Callback to get info about network devices."""

    return util.execWithCapture("nmcli", ["device", "show"])
Beispiel #39
0
def lsblk_callback():
    """Callback to get info about block devices."""

    return util.execWithCapture("lsblk", ["--perms", "--fs", "--bytes"])
Beispiel #40
0
def nmcli_dev_list_callback():
    """Callback to get info about network devices."""

    return util.execWithCapture("nmcli", ["device", "show"])