def prepare_mount_targets(self, storage): """ Prepare the ostree root """ ostreesetup = self.data.ostreesetup # Currently, blivet sets up mounts in the physical root. # We used to unmount them and remount them in the sysroot, but # since 664ef7b43f9102aa9332d0db5b7d13f8ece436f0 we now just set up # bind mounts. # Make /usr readonly like ostree does at runtime normally self._setup_internal_bindmount('/usr', bind_ro=True, src_physical=False) # Explicitly do API mounts; some of these may be tracked by blivet, but # we'll skip them below. api_mounts = ["/dev", "/proc", "/run", "/sys"] for path in api_mounts: self._setup_internal_bindmount(path) # Handle /var; if the admin didn't specify a mount for /var, we need # to do the default ostree one. # https://github.com/ostreedev/ostree/issues/855 var_root = '/ostree/deploy/' + ostreesetup.osname + '/var' if storage.mountpoints.get("/var") is None: self._setup_internal_bindmount(var_root, dest='/var', recurse=False) else: # Otherwise, bind it self._setup_internal_bindmount('/var', recurse=False) # Now that we have /var, start filling in any directories that may be # required later there. We explicitly make /var/lib, since # systemd-tmpfiles doesn't have a --prefix-only=/var/lib. We rely on # 80-setfilecons.ks to set the label correctly. util.mkdirChain(util.getSysroot() + '/var/lib') # Next, run tmpfiles to make subdirectories of /var. We need this for # both mounts like /home (really /var/home) and %post scripts might # want to write to e.g. `/srv`, `/root`, `/usr/local`, etc. The # /var/lib/rpm symlink is also critical for having e.g. `rpm -qa` work # in %post. We don't iterate *all* tmpfiles because we don't have the # matching NSS configuration inside Anaconda, and we can't "chroot" to # get it because that would require mounting the API filesystems in the # target. for varsubdir in ('home', 'roothome', 'lib/rpm', 'opt', 'srv', 'usrlocal', 'mnt', 'media', 'spool', 'spool/mail'): self._safe_exec_with_redirect("systemd-tmpfiles", ["--create", "--boot", "--root=" + util.getSysroot(), "--prefix=/var/" + varsubdir]) # Handle mounts like /boot (except avoid /boot/efi; we just need the # toplevel), and any admin-specified points like /home (really # /var/home). Note we already handled /var above. Avoid recursion since # sub-mounts will be in the list too. We sort by length as a crude # hack to try to simulate the tree relationship; it looks like this # is handled in blivet in a different way. for mount in sorted(storage.mountpoints, key=len): if mount in ('/', '/var') or mount in api_mounts: continue self._setup_internal_bindmount(mount, recurse=False) # And finally, do a nonrecursive bind for the sysroot self._setup_internal_bindmount("/", dest="/sysroot", recurse=False)
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 _copy_file(self, file_path, target_file_path): if not os.path.isfile(file_path): return False # make sure the output folder exists util.mkdirChain(os.path.dirname(target_file_path)) shutil.copy(file_path, target_file_path) return True
def _setup_hmc_device(self, storage, method, isodev, device): # Check if /dev/hmcdrv is already mounted. if device == "/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 prepareMountTargets(self, storage): """ Prepare the ostree root """ ostreesetup = self.data.ostreesetup # Currently, blivet sets up mounts in the physical root. # We used to unmount them and remount them in the sysroot, but # since 664ef7b43f9102aa9332d0db5b7d13f8ece436f0 we now just set up # bind mounts. # Make /usr readonly like ostree does at runtime normally self._setupInternalBindmount('/usr', bind_ro=True, src_physical=False) # Explicitly do API mounts; some of these may be tracked by blivet, but # we'll skip them below. api_mounts = ["/dev", "/proc", "/run", "/sys"] for path in api_mounts: self._setupInternalBindmount(path) # Handle /var; if the admin didn't specify a mount for /var, we need # to do the default ostree one. # https://github.com/ostreedev/ostree/issues/855 varroot = '/ostree/deploy/' + ostreesetup.osname + '/var' if storage.mountpoints.get("/var") is None: self._setupInternalBindmount(varroot, dest='/var', recurse=False) else: # Otherwise, bind it self._setupInternalBindmount('/var', recurse=False) # Now that we have /var, start filling in any directories that may be # required later there. We explicitly make /var/lib, since # systemd-tmpfiles doesn't have a --prefix-only=/var/lib. We rely on # 80-setfilecons.ks to set the label correctly. util.mkdirChain(util.getSysroot() + '/var/lib') # Next, run tmpfiles to make subdirectories of /var. We need this for # both mounts like /home (really /var/home) and %post scripts might # want to write to e.g. `/srv`, `/root`, `/usr/local`, etc. The # /var/lib/rpm symlink is also critical for having e.g. `rpm -qa` work # in %post. We don't iterate *all* tmpfiles because we don't have the # matching NSS configuration inside Anaconda, and we can't "chroot" to # get it because that would require mounting the API filesystems in the # target. for varsubdir in ('home', 'roothome', 'lib/rpm', 'opt', 'srv', 'usrlocal', 'mnt', 'media', 'spool', 'spool/mail'): self._safeExecWithRedirect("systemd-tmpfiles", ["--create", "--boot", "--root=" + util.getSysroot(), "--prefix=/var/" + varsubdir]) # Handle mounts like /boot (except avoid /boot/efi; we just need the # toplevel), and any admin-specified points like /home (really # /var/home). Note we already handled /var above. Avoid recursion since # sub-mounts will be in the list too. We sort by length as a crude # hack to try to simulate the tree relationship; it looks like this # is handled in blivet in a different way. for mount in sorted(storage.mountpoints, key=len): if mount in ('/', '/var') or mount in api_mounts: continue self._setupInternalBindmount(mount, recurse=False) # And finally, do a nonrecursive bind for the sysroot self._setupInternalBindmount("/", dest="/sysroot", recurse=False)
def take_screenshot(self, name=None): """Take a screenshot of the whole screen (works even with multiple displays). :param name: optional name for the screenshot that will be appended to the filename, after the standard prefix & screenshot number :type name: str or NoneType """ # Make sure the screenshot directory exists. util.mkdirChain(constants.SCREENSHOTS_DIRECTORY) if name is None: screenshot_filename = "screenshot-%04d.png" % self._screenshot_index else: screenshot_filename = "screenshot-%04d-%s.png" % ( self._screenshot_index, name) fn = os.path.join(constants.SCREENSHOTS_DIRECTORY, screenshot_filename) root_window = self.current_window.get_window() pixbuf = Gdk.pixbuf_get_from_window(root_window, 0, 0, root_window.get_width(), root_window.get_height()) pixbuf.savev(fn, 'png', [], []) log.info("%s taken", screenshot_filename) self._screenshot_index += 1
def get_os_version_test(self): """Test get_os_version.""" with tempfile.TemporaryDirectory() as root: # prepare paths util.mkdirChain(root + "/usr/lib") util.mkdirChain(root + "/etc") # backup file only with open(root + "/usr/lib/os-release", "w") as f: f.write( "# blah\nVERSION_ID=foo256bar \n VERSION_ID = wrong\n\n") version = util.get_os_version(root) self.assertEqual(version, "foo256bar") # main file and backup too with open(root + "/etc/os-release", "w") as f: f.write("# blah\nVERSION_ID=more-important\n") version = util.get_os_version(root) self.assertEqual(version, "more-important") # both, main file twice with open(root + "/etc/os-release", "w") as f: f.write( "# blah\nVERSION_ID=more-important\nVERSION_ID=not-reached\n \n" ) version = util.get_os_version(root) self.assertEqual(version, "more-important") # no files os.remove(root + "/usr/lib/os-release") os.remove(root + "/etc/os-release") version = util.get_os_version(root) self.assertEqual(version, None)
def _write_interface_rename_config(self, root, ifname_option_values, overwrite): """Write systemd configuration .link file for interface renaming. :param root: path to the root of the target system :type root: str :param ifname_option_values: list of ifname boot option values :type ifname_option_values: list(str) :param overwrite: overwrite existing configuration file :type overwrite: bool """ if ifname_option_values: target_system_dir = util.join_paths( root, self.SYSTEMD_NETWORK_CONFIG_DIR) util.mkdirChain(target_system_dir) for ifname_value in ifname_option_values: iface, mac = ifname_value.split(":", 1) content = self.INTERFACE_RENAME_FILE_CONTENT_TEMPLATE.format( mac, iface) config_file = self.INTERFACE_RENAME_FILE_TEMPLATE.format(iface) config_file_path = util.join_paths(self.SYSTEMD_NETWORK_CONFIG_DIR, config_file) _write_config_file( root, config_file_path, content, "Cannot write {} configuration file for ifname={} option.". format(config_file_path, ifname_value), overwrite)
def _copy_pem_files(self, input_folder, output_folder, not_empty=True): """Copy all pem files from input_folder to output_folder. Files with the pem extension are generally encryption keys and certificates. If output_folder does not exist, it & any parts of its path will be created. :param str input_folder: input folder for the pem files :param str output_folder: output folder where to copy the pem files :return: False if the input directory does not exists or is empty, True after all pem files have be successfully copied :rtype: bool """ # check the input folder exists if not os.path.isdir(input_folder): return False # optionally check the input folder is not empty if not_empty and not os.listdir(input_folder): return False # make sure the output folder exist util.mkdirChain(output_folder) # transfer all the pem files in the input folder for pem_file_path in glob.glob(os.path.join(input_folder, "*.pem")): shutil.copy(pem_file_path, output_folder) # if we got this far the pem copy operation was a success return True
def _fill_var_subdirectories(self): """Add subdirectories to /var Once we have /var, start filling in any directories that may be required later there. We explicitly make /var/lib, since systemd-tmpfiles doesn't have a --prefix-only=/var/lib. We rely on 80-setfilecons.ks to set the label correctly. Next, run tmpfiles to make subdirectories of /var. We need this for both mounts like /home (really /var/home) and %post scripts might want to write to e.g. `/srv`, `/root`, `/usr/local`, etc. The /var/lib/rpm symlink is also critical for having e.g. `rpm -qa` work in %post. We don't iterate *all* tmpfiles because we don't have the matching NSS configuration inside Anaconda, and we can't "chroot" to get it because that would require mounting the API filesystems in the target. """ mkdirChain(self._sysroot + '/var/lib') self._create_tmpfiles('/var/home') self._create_tmpfiles('/var/roothome') self._create_tmpfiles('/var/lib/rpm') self._create_tmpfiles('/var/opt') self._create_tmpfiles('/var/srv') self._create_tmpfiles('/var/usrlocal') self._create_tmpfiles('/var/mnt') self._create_tmpfiles('/var/media') self._create_tmpfiles('/var/spool') self._create_tmpfiles('/var/spool/mail')
def copyFileToPath(fileName, destPath='', overwrite=False): if not os.path.isfile(fileName): return False destfile = os.path.join(destPath, fileName.lstrip('/')) if (os.path.isfile(destfile) and not overwrite): return False if not os.path.isdir(os.path.dirname(destfile)): util.mkdirChain(os.path.dirname(destfile)) shutil.copy(fileName, destfile) return True
def test_get_os_relase_value(self): """Test the get_release_value function.""" with tempfile.TemporaryDirectory() as root: # prepare paths util.mkdirChain(root + "/usr/lib") util.mkdirChain(root + "/etc") # no file with self.assertLogs(level="DEBUG") as cm: version = util.get_os_release_value("VERSION_ID", root) msg = "VERSION_ID not found in os-release files" self.assertTrue(any(map(lambda x: msg in x, cm.output))) self.assertEqual(version, None) # backup file only with open(root + "/usr/lib/os-release", "w") as f: f.write( "# blah\nVERSION_ID=foo256bar \n VERSION_ID = wrong\n\n") version = util.get_os_release_value("VERSION_ID", root) self.assertEqual(version, "foo256bar") self.assertEqual(util.get_os_release_value("PLATFORM_ID", root), None) # main file and backup too with open(root + "/etc/os-release", "w") as f: f.write("# blah\nVERSION_ID=more-important\n") version = util.get_os_release_value("VERSION_ID", root) self.assertEqual(version, "more-important") # both, main file twice with open(root + "/etc/os-release", "w") as f: f.write( "# blah\nVERSION_ID=more-important\nVERSION_ID=not-reached\n \n" ) version = util.get_os_release_value("VERSION_ID", root) self.assertEqual(version, "more-important") # quoted values with open(root + "/etc/os-release", "w") as f: f.write( "PRETTY_NAME=\"Fedora 32\"\nPLATFORM_ID='platform:f32'\n") self.assertEqual(util.get_os_release_value("PRETTY_NAME", root), "Fedora 32") self.assertEqual(util.get_os_release_value("PLATFORM_ID", root), "platform:f32") # no files os.remove(root + "/usr/lib/os-release") os.remove(root + "/etc/os-release") version = util.get_os_release_value("VERSION_ID", root) self.assertEqual(version, None)
def _write_module_blacklist(self): """Copy modules from modprobe.blacklist=<module> on cmdline to /etc/modprobe.d/anaconda-blacklist.conf so that modules will continue to be blacklisted when the system boots. """ if "modprobe.blacklist" not in flags.cmdline: return util.mkdirChain(util.getSysroot() + "/etc/modprobe.d") with open(util.getSysroot() + "/etc/modprobe.d/anaconda-blacklist.conf", "w") as f: f.write("# Module blacklists written by anaconda\n") for module in flags.cmdline["modprobe.blacklist"].split(): f.write("blacklist %s\n" % module)
def _setup_internal_bindmount(self, src, dest=None, src_physical=True, bind_ro=False, recurse=True): """Internal API for setting up bind mounts between the physical root and sysroot Also ensures we track them in self._internal_mounts so we can cleanly unmount them. Currently, blivet sets up mounts in the physical root. We used to unmount them and remount them in the sysroot, but since 664ef7b43f9102aa9332d0db5b7d13f8ece436f0 we now just set up bind mounts. :param src: Source path, will be prefixed with physical or sysroot :param dest: Destination, will be prefixed with sysroot (defaults to same as src) :param src_physical: Prefix src with physical root :param bind_ro: Make mount read-only :param recurse: Use --rbind to recurse, otherwise plain --bind """ # Default to the same basename if dest is None: dest = src # Almost all of our mounts go from physical to sysroot if src_physical: src = self._physroot + src else: src = self._sysroot + src # Canonicalize dest to the full path dest = self._sysroot + dest if bind_ro: safe_exec_with_redirect("mount", ["--bind", src, src]) safe_exec_with_redirect("mount", ["--bind", "-o", "remount,ro", src, src]) else: # Create missing directories for user defined mount points if not os.path.exists(dest): mkdirChain(dest) # Recurse for non-ro binds so we pick up sub-mounts # like /sys/firmware/efi/efivars. if recurse: bindopt = '--rbind' else: bindopt = '--bind' safe_exec_with_redirect("mount", [bindopt, src, dest]) self._internal_mounts.append(src if bind_ro else dest)
def copy_resolv_conf_to_root(root=""): """Copy resolv.conf to a system root.""" src = "/etc/resolv.conf" dst = os.path.join(root, src.lstrip('/')) if not os.path.isfile(src): log.debug("%s does not exist", src) return if os.path.isfile(dst): log.debug("%s already exists", dst) return dst_dir = os.path.dirname(dst) if not os.path.isdir(dst_dir): util.mkdirChain(dst_dir) shutil.copyfile(src, dst)
def get_locale_map_from_ostree(repo, ref): """Get a map of languages and locales from the given OSTree. For example: {"en": ["en_US"]} :param repo: the OSTree repository url :param ref: the name of branch inside the repository :return: a map of languages and locales """ # Fallback to just en_US in case of errors. locale_map = {"en": ["en_US"]} # Let's only handle local embedded repos for now. Anyway, it'd probably # not be very common to only override ostreesetup through kickstart and # still want the interactive installer. Though to be nice, let's handle # that case. if not repo.startswith("file://"): log.info("ostree repo is not local; defaulting to en_US") return # Convert to regular UNIX path. repo = repo[len("file://"):] util.mkdirChain(os.path.join(repo, "tmp/usr/lib")) rc = util.execWithRedirect("/usr/bin/ostree", [ "checkout", "--repo", repo, ref, "--subpath", "/usr/lib/locale/locale-archive", "%s/tmp/usr/lib/locale" % repo ]) if rc != 0: log.error("failed to check out locale-archive; check program.log") return for line in util.execReadlines( "/usr/bin/localedef", ["--prefix", os.path.join(repo, "tmp"), "--list-archive"]): line = strip_codeset_and_modifier(line) if '_' in line: (lang, _territory) = line.split('_', 1) else: lang = line if lang not in locale_map: locale_map[lang] = [line] else: locale_map[lang].append(line) # Nuke the checkout for good measure. shutil.rmtree(os.path.join(repo, "tmp/usr")) return locale_map
def _write_module_blacklist(self): """Copy modules from modprobe.blacklist=<module> on cmdline to /etc/modprobe.d/anaconda-blacklist.conf so that modules will continue to be blacklisted when the system boots. """ if "modprobe.blacklist" not in flags.cmdline: return util.mkdirChain(util.getSysroot() + "/etc/modprobe.d") with open( util.getSysroot() + "/etc/modprobe.d/anaconda-blacklist.conf", "w") as f: f.write("# Module blacklists written by anaconda\n") for module in flags.cmdline["modprobe.blacklist"].split(): f.write("blacklist %s\n" % module)
def write_module_blacklist(sysroot): """Create module blacklist based on the user preference. Copy modules from modprobe.blacklist=<module> on cmdline to /etc/modprobe.d/anaconda-blacklist.conf so that modules will continue to be blacklisted when the system boots. """ if "modprobe.blacklist" not in kernel_arguments: return mkdirChain(os.path.join(sysroot, "etc/modprobe.d")) with open(os.path.join(sysroot, "etc/modprobe.d/anaconda-blacklist.conf"), "w") as f: f.write("# Module blacklists written by anaconda\n") for module in kernel_arguments.get("modprobe.blacklist").split(): f.write("blacklist %s\n" % module)
def get_locale_map_from_ostree(repo, ref): """Get a map of languages and locales from the given OSTree. For example: {"en": ["en_US"]} :param repo: the OSTree repository url :param ref: the name of branch inside the repository :return: a map of languages and locales """ # Fallback to just en_US in case of errors. locale_map = {"en": ["en_US"]} # Let's only handle local embedded repos for now. Anyway, it'd probably # not be very common to only override ostreesetup through kickstart and # still want the interactive installer. Though to be nice, let's handle # that case. if not repo.startswith("file://"): log.info("ostree repo is not local; defaulting to en_US") return # Convert to regular UNIX path. repo = repo[len("file://"):] util.mkdirChain(os.path.join(repo, "tmp/usr/lib")) rc = util.execWithRedirect("/usr/bin/ostree", ["checkout", "--repo", repo, ref, "--subpath", "/usr/lib/locale/locale-archive", "%s/tmp/usr/lib/locale" % repo]) if rc != 0: log.error("failed to check out locale-archive; check program.log") return for line in util.execReadlines("/usr/bin/localedef", ["--prefix", os.path.join(repo, "tmp"), "--list-archive"]): line = strip_codeset_and_modifier(line) if '_' in line: (lang, _territory) = line.split('_', 1) else: lang = line if lang not in locale_map: locale_map[lang] = [line] else: locale_map[lang].append(line) # Nuke the checkout for good measure. shutil.rmtree(os.path.join(repo, "tmp/usr")) return locale_map
def _initialize_localemap(self, ref, repo): if self.localemap: return # fallback to just en_US in case of errors self.localemap = {"en": ["en_US"]} # Let's only handle local embedded repos for now. Anyway, it'd probably # not be very common to only override ostreesetup through kickstart and # still want the interactive installer. Though to be nice, let's handle # that case. if not repo.startswith("file://"): log.info("ostree repo is not local; defaulting to en_US") return # convert to regular UNIX path repo = repo[len("file://"):] util.mkdirChain(os.path.join(repo, "tmp/usr/lib")) rc = util.execWithRedirect("/usr/bin/ostree", [ "checkout", "--repo", repo, ref, "--subpath", "/usr/lib/locale/locale-archive", "%s/tmp/usr/lib/locale" % repo ]) if rc != 0: log.error("failed to check out locale-archive; check program.log") return for line in util.execReadlines( "/usr/bin/localedef", ["--prefix", os.path.join(repo, "tmp"), "--list-archive"]): line = self._strip_codeset_and_modifier(line) if '_' in line: (lang, _territory) = line.split('_', 1) else: lang = line if lang not in self.localemap: self.localemap[lang] = [line] else: self.localemap[lang].append(line) # nuke the checkout for good measure shutil.rmtree(os.path.join(repo, "tmp/usr"))
def _copy_file_to_root(self, root, config_file, overwrite=False): """Copy the file to target system. :param root: path to the root of the target system :type root: str :param config_file: path of the file :type config_file: str :param overwrite: overwrite existing configuration file :type overwrite: bool """ if not os.path.isfile(config_file): return fpath = os.path.normpath(root + config_file) if os.path.isfile(fpath) and not overwrite: return if not os.path.isdir(os.path.dirname(fpath)): util.mkdirChain(os.path.dirname(fpath)) shutil.copy(config_file, fpath)
def _do_mount(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.") # Make sure that the directories exists. mkdirChain(self._target_mount) # 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)
def test_mkdir_chain(self): """Test mkdirChain.""" # don't fail if directory path already exists util.mkdirChain('/') util.mkdirChain('/tmp') # create a path and test it exists test_folder = "test_mkdir_chain" test_paths = [ "foo", "foo/bar/baz", "", "čřščščřščř", "asdasd asdasd", "! spam" ] # join with the toplevel test folder and the folder for this # test test_paths = [ os.path.join(ANACONDA_TEST_DIR, test_folder, p) for p in test_paths ] def create_return(path): util.mkdirChain(path) return path # create the folders and check that they exist for p in test_paths: assert os.path.exists(create_return(p)) # try to create them again - all the paths should already exist # and the mkdirChain function needs to handle that # without a traceback for p in test_paths: util.mkdirChain(p)
def take_screenshot(self, name=None): """Take a screenshot of the whole screen (works even with multiple displays). :param name: optional name for the screenshot that will be appended to the filename, after the standard prefix & screenshot number :type name: str or NoneType """ # Make sure the screenshot directory exists. util.mkdirChain(constants.SCREENSHOTS_DIRECTORY) if name is None: screenshot_filename = "screenshot-%04d.png" % self._screenshot_index else: screenshot_filename = "screenshot-%04d-%s.png" % (self._screenshot_index, name) fn = os.path.join(constants.SCREENSHOTS_DIRECTORY, screenshot_filename) root_window = self.current_window.get_window() pixbuf = Gdk.pixbuf_get_from_window(root_window, 0, 0, root_window.get_width(), root_window.get_height()) pixbuf.savev(fn, 'png', [], []) log.info("%s taken", screenshot_filename) self._screenshot_index += 1
def _set_up_fips(self): """Set up FIPS in the target system.""" log.debug("Copying the crypto policy.") # Create /etc/crypto-policies. src = "/etc/crypto-policies/" dst = join_paths(self._sysroot, src) util.mkdirChain(dst) # Copy the config file. src = "/etc/crypto-policies/config" dst = join_paths(self._sysroot, src) shutil.copyfile(src, dst) # Log the file content on the target system. util.execWithRedirect("/bin/cat", [dst]) # Copy the back-ends. src = "/etc/crypto-policies/back-ends/" dst = join_paths(self._sysroot, src) shutil.copytree(src, dst, symlinks=True) # Log the directory content on the target system. util.execWithRedirect("/bin/ls", ["-l", dst])
def mkdir_chain_test(self): """Test mkdirChain.""" # don't fail if directory path already exists util.mkdirChain('/') util.mkdirChain('/tmp') # create a path and test it exists test_folder = "test_mkdir_chain" test_paths = [ "foo", "foo/bar/baz", u"foo/bar/baz", "", "čřščščřščř", u"čřščščřščř", "asdasd asdasd", "! spam" ] # join with the toplevel test folder and the folder for this # test test_paths = [os.path.join(ANACONDA_TEST_DIR, test_folder, p) for p in test_paths] def create_return(path): util.mkdirChain(path) return path # create the folders and check that they exist for p in test_paths: self.assertTrue(os.path.exists(create_return(p))) # try to create them again - all the paths should already exist # and the mkdirChain function needs to handle that # without a traceback for p in test_paths: util.mkdirChain(p)
def create_return(path): util.mkdirChain(path) return path
def createUser(self, user_name, *args, **kwargs): """Create a new user on the system with the given name. Optional kwargs: :keyword str algo: The password algorithm to use in case isCrypted=True. If none is given, the cryptPassword default is used. :keyword str gecos: The GECOS information (full name, office, phone, etc.). Defaults to "". :keyword groups: A list of group names the user should be added to. Each group name can contain an optional GID in parenthesis, such as "groupName(5000)". Defaults to []. :type groups: list of str :keyword str homedir: The home directory for the new user. Defaults to /home/<name>. :keyword bool isCrypted: Is the password kwargs already encrypted? Defaults to False. :keyword bool lock: Is the new account locked by default? Defaults to False. :keyword str password: The password. See isCrypted for how this is interpreted. If the password is "" then the account is created with a blank password. If None or False the account will be left in its initial state (locked) :keyword str root: The directory of the system to create the new user in. homedir will be interpreted relative to this. Defaults to util.getSysroot(). :keyword str shell: The shell for the new user. If none is given, the login.defs default is used. :keyword int uid: The UID for the new user. If none is given, the next available one is used. :keyword int gid: The GID for the new user. If none is given, the next available one is used. """ root = kwargs.get("root", util.getSysroot()) if self.checkUserExists(user_name, root): raise ValueError("User %s already exists" % user_name) args = ["-R", root] # Split the groups argument into a list of (username, gid or None) tuples # the gid, if any, is a string since that makes things simpler group_gids = [ GROUPLIST_FANCY_PARSE.match(group).groups() for group in kwargs.get("groups", []) ] # If a specific gid is requested: # - check if a group already exists with that GID. i.e., the user's # GID should refer to a system group, such as users. If so, just set # the GID. # - check if a new group is requested with that GID. If so, set the GID # and let the block below create the actual group. # - if neither of those are true, create a new user group with the requested # GID # otherwise use -U to create a new user group with the next available GID. if kwargs.get("gid", None): if not self._getgrgid(kwargs['gid'], root) and \ not any(gid[1] == str(kwargs['gid']) for gid in group_gids): self.createGroup(user_name, gid=kwargs['gid'], root=root) args.extend(['-g', str(kwargs['gid'])]) else: args.append('-U') # If any requested groups do not exist, create them. group_list = [] for group_name, gid in group_gids: existing_group = self._getgrnam(group_name, root) # Check for a bad GID request if gid and existing_group and gid != existing_group[2]: raise ValueError("Group %s already exists with GID %s" % (group_name, gid)) # Otherwise, create the group if it does not already exist if not existing_group: self.createGroup(group_name, gid=gid, root=root) group_list.append(group_name) if group_list: args.extend(['-G', ",".join(group_list)]) if kwargs.get("homedir"): homedir = kwargs["homedir"] else: homedir = "/home/" + user_name # useradd expects the parent directory tree to exist. parent_dir = util.parent_dir(root + homedir) # If root + homedir came out to "/", such as if we're creating the sshpw user, # parent_dir will be empty. Don't create that. if parent_dir: util.mkdirChain(parent_dir) args.extend(["-d", homedir]) # Check whether the directory exists or if useradd should create it mk_homedir = not os.path.exists(root + homedir) if mk_homedir: args.append("-m") else: args.append("-M") if kwargs.get("shell"): args.extend(["-s", kwargs["shell"]]) if kwargs.get("uid"): args.extend(["-u", str(kwargs["uid"])]) if kwargs.get("gecos"): args.extend(["-c", kwargs["gecos"]]) args.append(user_name) with self._ensureLoginDefs(root): status = util.execWithRedirect("useradd", args) if status == 4: raise ValueError("UID %s already exists" % kwargs.get("uid")) elif status == 6: raise ValueError("Invalid groups %s" % kwargs.get("groups", [])) elif status == 9: raise ValueError("User %s already exists" % user_name) elif status != 0: raise OSError("Unable to create user %s: status=%s" % (user_name, status)) if not mk_homedir: try: stats = os.stat(root + homedir) orig_uid = stats.st_uid orig_gid = stats.st_gid # Gett the UID and GID of the created user pwent = self._getpwnam(user_name, root) log.info( "Home directory for the user %s already existed, " "fixing the owner and SELinux context.", user_name) # home directory already existed, change owner of it properly util.chown_dir_tree(root + homedir, int(pwent[2]), int(pwent[3]), orig_uid, orig_gid) util.execWithRedirect("restorecon", ["-r", root + homedir]) except OSError as e: log.critical( "Unable to change owner of existing home directory: %s", e.strerror) raise pw = kwargs.get("password", False) crypted = kwargs.get("isCrypted", False) algo = kwargs.get("algo", None) lock = kwargs.get("lock", False) self.setUserPassword(user_name, pw, crypted, lock, algo, root)
def pre_install(self): """Perform pre-installation tasks.""" util.mkdirChain(util.getSysroot() + "/root") self._write_module_blacklist()
anaconda = Anaconda() util.setup_translations() # reset python's default SIGINT handler signal.signal(signal.SIGINT, signal.SIG_IGN) signal.signal(signal.SIGTERM, lambda num, frame: sys.exit(1)) # synchronously-delivered signals such as SIGSEGV and SIGILL cannot be # handled properly from python, so install signal handlers from the C # function in isys. isys.installSyncSignalHandlers() setup_environment() # make sure we have /var/log soon, some programs fail to start without it util.mkdirChain("/var/log") # Create a PID file. The exit handler, installed later, will clean it up. pidfile = pid.PidFile(pidname='anaconda', register_term_signal_handler=False) try: pidfile.create() except pid.PidFileError as e: log.error("Unable to create %s, exiting", pidfile.filename) # If we had a $DISPLAY at start and zenity is available, we may be # running in a live environment and we can display an error dialog. # Otherwise just print an error. if flags.preexisting_x11 and os.access("/usr/bin/zenity", os.X_OK): # The module-level _() calls are ok here because the language may # be set from the live environment in this case, and anaconda's
def createUser(self, user_name, *args, **kwargs): """Create a new user on the system with the given name. Optional kwargs: :keyword str algo: The password algorithm to use in case isCrypted=True. If none is given, the cryptPassword default is used. :keyword str gecos: The GECOS information (full name, office, phone, etc.). Defaults to "". :keyword groups: A list of group names the user should be added to. Each group name can contain an optional GID in parenthesis, such as "groupName(5000)". Defaults to []. :type groups: list of str :keyword str homedir: The home directory for the new user. Defaults to /home/<name>. :keyword bool isCrypted: Is the password kwargs already encrypted? Defaults to False. :keyword bool lock: Is the new account locked by default? Defaults to False. :keyword str password: The password. See isCrypted for how this is interpreted. If the password is "" then the account is created with a blank password. If None or False the account will be left in its initial state (locked) :keyword str root: The directory of the system to create the new user in. homedir will be interpreted relative to this. Defaults to util.getSysroot(). :keyword str shell: The shell for the new user. If none is given, the login.defs default is used. :keyword int uid: The UID for the new user. If none is given, the next available one is used. :keyword int gid: The GID for the new user. If none is given, the next available one is used. """ root = kwargs.get("root", util.getSysroot()) if self.checkUserExists(user_name, root): raise ValueError("User %s already exists" % user_name) args = ["-R", root] # Split the groups argument into a list of (username, gid or None) tuples # the gid, if any, is a string since that makes things simpler group_gids = [GROUPLIST_FANCY_PARSE.match(group).groups() for group in kwargs.get("groups", [])] # If a specific gid is requested: # - check if a group already exists with that GID. i.e., the user's # GID should refer to a system group, such as users. If so, just set # the GID. # - check if a new group is requested with that GID. If so, set the GID # and let the block below create the actual group. # - if neither of those are true, create a new user group with the requested # GID # otherwise use -U to create a new user group with the next available GID. if kwargs.get("gid", None): if not self._getgrgid(kwargs['gid'], root) and \ not any(gid[1] == str(kwargs['gid']) for gid in group_gids): self.createGroup(user_name, gid=kwargs['gid'], root=root) args.extend(['-g', str(kwargs['gid'])]) else: args.append('-U') # If any requested groups do not exist, create them. group_list = [] for group_name, gid in group_gids: existing_group = self._getgrnam(group_name, root) # Check for a bad GID request if gid and existing_group and gid != existing_group[2]: raise ValueError("Group %s already exists with GID %s" % (group_name, gid)) # Otherwise, create the group if it does not already exist if not existing_group: self.createGroup(group_name, gid=gid, root=root) group_list.append(group_name) if group_list: args.extend(['-G', ",".join(group_list)]) if kwargs.get("homedir"): homedir = kwargs["homedir"] else: homedir = "/home/" + user_name # useradd expects the parent directory tree to exist. parent_dir = util.parent_dir(root + homedir) # If root + homedir came out to "/", such as if we're creating the sshpw user, # parent_dir will be empty. Don't create that. if parent_dir: util.mkdirChain(parent_dir) args.extend(["-d", homedir]) # Check whether the directory exists or if useradd should create it mk_homedir = not os.path.exists(root + homedir) if mk_homedir: args.append("-m") else: args.append("-M") if kwargs.get("shell"): args.extend(["-s", kwargs["shell"]]) if kwargs.get("uid"): args.extend(["-u", str(kwargs["uid"])]) if kwargs.get("gecos"): args.extend(["-c", kwargs["gecos"]]) args.append(user_name) with self._ensureLoginDefs(root): status = util.execWithRedirect("useradd", args) if status == 4: raise ValueError("UID %s already exists" % kwargs.get("uid")) elif status == 6: raise ValueError("Invalid groups %s" % kwargs.get("groups", [])) elif status == 9: raise ValueError("User %s already exists" % user_name) elif status != 0: raise OSError("Unable to create user %s: status=%s" % (user_name, status)) if not mk_homedir: try: stats = os.stat(root + homedir) orig_uid = stats.st_uid orig_gid = stats.st_gid # Gett the UID and GID of the created user pwent = self._getpwnam(user_name, root) log.info("Home directory for the user %s already existed, " "fixing the owner and SELinux context.", user_name) # home directory already existed, change owner of it properly util.chown_dir_tree(root + homedir, int(pwent[2]), int(pwent[3]), orig_uid, orig_gid) util.execWithRedirect("restorecon", ["-r", root + homedir]) except OSError as e: log.critical("Unable to change owner of existing home directory: %s", e.strerror) raise pw = kwargs.get("password", False) crypted = kwargs.get("isCrypted", False) algo = kwargs.get("algo", None) lock = kwargs.get("lock", False) self.setUserPassword(user_name, pw, crypted, lock, algo, root)
anaconda = Anaconda() util.setup_translations() # reset python's default SIGINT handler signal.signal(signal.SIGINT, signal.SIG_IGN) signal.signal(signal.SIGTERM, lambda num, frame: sys.exit(1)) # synchronously-delivered signals such as SIGSEGV and SIGILL cannot be # handled properly from python, so install signal handlers from the C # function in isys. isys.installSyncSignalHandlers() setup_environment() # make sure we have /var/log soon, some programs fail to start without it util.mkdirChain("/var/log") # Create a PID file. The exit handler, installed later, will clean it up. pidfile = pid.PidFile(pidname='anaconda', register_term_signal_handler=False) try: pidfile.create() except pid.PidFileError as e: log.error("Unable to create %s, exiting", pidfile.filename) # If we had a $DISPLAY at start and zenity is available, we may be # running in a live environment and we can display an error dialog. # Otherwise just print an error. if flags.preexisting_x11 and os.access("/usr/bin/zenity", os.X_OK): # The module-level _() calls are ok here because the language may
def _create_logs_directory(self): """Create directory for Anaconda logs on the install target""" mkdirChain(join_paths(self._sysroot, ANACONDA_LOG_DIR))
def create_user(username, password=False, is_crypted=False, lock=False, homedir=None, uid=None, gid=None, groups=None, shell=None, gecos="", root=None): """Create a new user on the system with the given name. :param str username: The username for the new user to be created. :param str password: The password. See is_crypted for how this is interpreted. If the password is "" then the account is created with a blank password. If None or False the account will be left in its initial state (locked) :param bool is_crypted: Is the password already encrypted? Defaults to False. :param bool lock: Is the new account locked by default? Defaults to False. :param str homedir: The home directory for the new user. Defaults to /home/<name>. :param int uid: The UID for the new user. If none is given, the next available one is used. :param int gid: The GID for the new user. If none is given, the next available one is used. :param groups: A list of group names the user should be added to. Each group name can contain an optional GID in parenthesis, such as "groupName(5000)". Defaults to []. :type groups: list of str :param str shell: The shell for the new user. If none is given, the login.defs default is used. :param str gecos: The GECOS information (full name, office, phone, etc.). Defaults to "". :param str root: The directory of the system to create the new user in. The homedir option will be interpreted relative to this. Defaults to util.getSysroot(). """ # resolve the optional arguments that need a default that can't be # reasonably set in the function signature if homedir: homedir = homedir else: homedir = "/home/" + username if groups is None: groups = [] if root is None: root = util.getSysroot() if check_user_exists(username, root): raise ValueError("User %s already exists" % username) args = ["-R", root] # Split the groups argument into a list of (username, gid or None) tuples # the gid, if any, is a string since that makes things simpler group_gids = [ GROUPLIST_FANCY_PARSE.match(group).groups() for group in groups ] # If a specific gid is requested: # - check if a group already exists with that GID. i.e., the user's # GID should refer to a system group, such as users. If so, just set # the GID. # - check if a new group is requested with that GID. If so, set the GID # and let the block below create the actual group. # - if neither of those are true, create a new user group with the requested # GID # otherwise use -U to create a new user group with the next available GID. if gid: if not _getgrgid(gid, root) and not any(one_gid[1] == str(gid) for one_gid in group_gids): create_group(username, gid=gid, root=root) args.extend(['-g', str(gid)]) else: args.append('-U') # If any requested groups do not exist, create them. group_list = [] for group_name, gid in group_gids: existing_group = _getgrnam(group_name, root) # Check for a bad GID request if gid and existing_group and gid != existing_group[2]: raise ValueError("Group %s already exists with GID %s" % (group_name, gid)) # Otherwise, create the group if it does not already exist if not existing_group: create_group(group_name, gid=gid, root=root) group_list.append(group_name) if group_list: args.extend(['-G', ",".join(group_list)]) # useradd expects the parent directory tree to exist. parent_dir = util.parent_dir(root + homedir) # If root + homedir came out to "/", such as if we're creating the sshpw user, # parent_dir will be empty. Don't create that. if parent_dir: util.mkdirChain(parent_dir) args.extend(["-d", homedir]) # Check whether the directory exists or if useradd should create it mk_homedir = not os.path.exists(root + homedir) if mk_homedir: args.append("-m") else: args.append("-M") if shell: args.extend(["-s", shell]) if uid: args.extend(["-u", str(uid)]) if gecos: args.extend(["-c", gecos]) args.append(username) with _ensure_login_defs(root): status = util.execWithRedirect("useradd", args) if status == 4: raise ValueError("UID %s already exists" % uid) elif status == 6: raise ValueError("Invalid groups %s" % groups) elif status == 9: raise ValueError("User %s already exists" % username) elif status != 0: raise OSError("Unable to create user %s: status=%s" % (username, status)) if not mk_homedir: try: stats = os.stat(root + homedir) orig_uid = stats.st_uid orig_gid = stats.st_gid # Get the UID and GID of the created user pwent = _getpwnam(username, root) log.info( "Home directory for the user %s already existed, " "fixing the owner and SELinux context.", username) # home directory already existed, change owner of it properly util.chown_dir_tree(root + homedir, int(pwent[2]), int(pwent[3]), orig_uid, orig_gid) util.execWithRedirect("restorecon", ["-r", root + homedir]) except OSError as e: log.critical( "Unable to change owner of existing home directory: %s", e.strerror) raise set_user_password(username, password, is_crypted, lock, root)
def create_root_dir(sysroot): """Create root directory on the installed system.""" mkdirChain(os.path.join(sysroot, "root"))