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. iutil.mkdirChain(iutil.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=" + iutil.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 """ global _screenshotIndex # Make sure the screenshot directory exists. iutil.mkdirChain(constants.SCREENSHOTS_DIRECTORY) if name is None: screenshot_filename = "screenshot-%04d.png" % _screenshotIndex else: screenshot_filename = "screenshot-%04d-%s.png" % (_screenshotIndex, name) fn = os.path.join(constants.SCREENSHOTS_DIRECTORY, screenshot_filename) root_window = self.main_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) _screenshotIndex += 1
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. iutil.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 _initTargetRPM(self): self.etcrpm_dir = iutil.getSysroot() + "/etc/rpm" self.librpm_dir = iutil.getSysroot() + "/var/lib/rpm" # Configure /etc/rpm iutil.mkdirChain(self.etcrpm_dir) # For rpm-extra-macros._tmppath iutil.mkdirChain(iutil.getSysroot() + "/install/tmp") # Setup /etc/rpm/platform shutil.copy("/etc/rpm/platform", self.etcrpm_dir) # Setup /etc/rpm/sysinfo/Dirnames iutil.mkdirChain(self.etcrpm_dir + "/sysinfo") fd = open(self.etcrpm_dir + "/sysinfo/Dirnames", "w") fd.write("/\n") fd.close() # Setup provides if needed # Setup /var/lib/rpm iutil.mkdirChain(self.librpm_dir) iutil.mkdirChain(self.librpm_dir + "/log") # Touch the log file fd = open(self.librpm_dir + "/log/log.0000000001", "w") fd.close() # Configure the DB_CONFIG buf = """ # ================ Environment set_data_dir . set_create_dir . set_lg_dir ./log set_tmp_dir ./tmp set_flags db_log_autoremove on # -- thread_count must be >= 8 set_thread_count 64 # ================ Logging # ================ Memory Pool set_cachesize 0 1048576 0 set_mp_mmapsize 268435456 # ================ Locking set_lk_max_locks 16384 set_lk_max_lockers 16384 set_lk_max_objects 16384 mutex_set_max 163840 # ================ Replication """ fd = open(self.librpm_dir + "/DB_CONFIG", "w") fd.write(buf) fd.close()
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. iutil.mkdirChain(iutil.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=" + iutil.getSysroot(), "--prefix=/var/" + varsubdir ]) # Handle mounts like /boot, and any admin-specified points like # /home (really /var/home). Note we already handled /var above. for mount in storage.mountpoints: if mount in ('/', '/var') or mount in api_mounts: continue self._setupInternalBindmount(mount) # And finally, do a nonrecursive bind for the sysroot self._setupInternalBindmount("/", dest="/sysroot", recurse=False)
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)): iutil.mkdirChain(os.path.dirname(destfile)) shutil.copy(fileName, destfile) return True
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)): iutil.mkdirChain(os.path.dirname(destfile)) shutil.copy(fileName, destfile) return True
def _writeModuleBlacklist(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 iutil.mkdirChain(ROOT_PATH + "/etc/modprobe.d") with open(ROOT_PATH + "/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 _writeModuleBlacklist(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 iutil.mkdirChain(iutil.getSysroot() + "/etc/modprobe.d") with open(iutil.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 mkdir_chain_test(self): """Test mkdirChain.""" # don't fail if directory path already exists iutil.mkdirChain('/dev/null') iutil.mkdirChain('/') iutil.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): iutil.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: iutil.mkdirChain(p)
def mkdir_chain_test(self): """Test mkdirChain.""" # don't fail if directory path already exists iutil.mkdirChain("/") iutil.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): iutil.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: iutil.mkdirChain(p)
def save_layouts_to_udev(self, layouts, variants): """ Sets layouts to udev, so it will also apply to newly connected keyboards (or existing after udevadm trigger). Otherwise Xorg setup them based on xorg.conf with a fallback to hardcoded values. :param layouts: list of layouts :param variants: list of layout variants, matching *layouts* """ udev_rules_dir = '/run/udev/rules.d' udev_rules_path = udev_rules_dir + '/90-keyboard-layout.rules' try: iutil.mkdirChain(udev_rules_dir) except FileExistsError: pass with open(udev_rules_path, 'w') as rules: rules.write('ENV{{ID_INPUT_KEYBOARD}}=="1", ' 'ENV{{xkblayout}}="{layouts}", ' 'ENV{{xkbvariant}}="{variants}"\n'.format( layouts=','.join(layouts), variants=','.join(variants))) iutil.startProgram(['udevadm', 'control', '-R']).communicate()
def createUser (self, user_name, *args, **kwargs): """Create a new user on the system with the given name. Optional kwargs: algo -- The password algorithm to use in case isCrypted=True. If none is given, the cryptPassword default is used. gecos -- The GECOS information (full name, office, phone, etc.). Defaults to "". groups -- A list of existing group names the user should be added to. Defaults to []. homedir -- The home directory for the new user. Defaults to /home/<name>. isCrypted -- Is the password kwargs already encrypted? Defaults to False. lock -- Is the new account locked by default? Defaults to False. 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) root -- The directory of the system to create the new user in. homedir will be interpreted relative to this. Defaults to /mnt/sysimage. shell -- The shell for the new user. If none is given, the libuser default is used. uid -- The UID for the new user. If none is given, the next available one is used. gid -- The GID for the new user. If none is given, the next available one is used. """ childpid = os.fork() root = kwargs.get("root", "/mnt/sysimage") if not childpid: if not root in ["","/"]: os.chroot(root) os.chdir("/") del(os.environ["LIBUSER_CONF"]) self.admin = libuser.admin() if self.admin.lookupUserByName(user_name): log.error("User %s already exists, not creating.", user_name) os._exit(1) userEnt = self.admin.initUser(user_name) groupEnt = self.admin.initGroup(user_name) if kwargs.get("gid", -1) >= 0: groupEnt.set(libuser.GIDNUMBER, kwargs["gid"]) grpLst = filter(lambda grp: grp, map(self.admin.lookupGroupByName, kwargs.get("groups", []))) userEnt.set(libuser.GIDNUMBER, [groupEnt.get(libuser.GIDNUMBER)[0]] + map(lambda grp: grp.get(libuser.GIDNUMBER)[0], grpLst)) if kwargs.get("homedir", False): userEnt.set(libuser.HOMEDIRECTORY, kwargs["homedir"]) else: iutil.mkdirChain('/home') userEnt.set(libuser.HOMEDIRECTORY, "/home/" + user_name) if kwargs.get("shell", False): userEnt.set(libuser.LOGINSHELL, kwargs["shell"]) if kwargs.get("uid", -1) >= 0: userEnt.set(libuser.UIDNUMBER, kwargs["uid"]) if kwargs.get("gecos", False): userEnt.set(libuser.GECOS, kwargs["gecos"]) # need to create home directory for the user or does it already exist? # userEnt.get returns lists (usually with a single item) mk_homedir = not os.path.exists(userEnt.get(libuser.HOMEDIRECTORY)[0]) try: self.admin.addUser(userEnt, mkmailspool=kwargs.get("mkmailspool", True), mkhomedir=mk_homedir) except RuntimeError as e: log.critical("Error when creating new user: %s", e) os._exit(1) try: self.admin.addGroup(groupEnt) except RuntimeError as e: log.critical("Error when creating new group: %s", e) os._exit(1) if not mk_homedir: try: stats = os.stat(userEnt.get(libuser.HOMEDIRECTORY)[0]) orig_uid = stats.st_uid orig_gid = stats.st_gid log.info("Home directory for the user %s already existed, " "fixing the owner.", user_name) # home directory already existed, change owner of it properly iutil.chown_dir_tree(userEnt.get(libuser.HOMEDIRECTORY)[0], userEnt.get(libuser.UIDNUMBER)[0], groupEnt.get(libuser.GIDNUMBER)[0], orig_uid, orig_gid) except OSError as e: log.critical("Unable to change owner of existing home directory: %s", os.strerror) os._exit(1) pw = kwargs.get("password", False) try: if pw: if kwargs.get("isCrypted", False): password = kwargs["password"] else: password = cryptPassword(kwargs["password"], algo=kwargs.get("algo", None)) self.admin.setpassUser(userEnt, password, True) userEnt.set(libuser.SHADOWLASTCHANGE, "") self.admin.modifyUser(userEnt) elif pw == "": # Setup the account with *NO* password self.admin.unlockUser(userEnt) log.info("user account %s setup with no password", user_name) if kwargs.get("lock", False): self.admin.lockUser(userEnt) log.info("user account %s locked", user_name) # setpassUser raises SystemError on failure, while unlockUser and lockUser # raise RuntimeError except (RuntimeError, SystemError) as e: log.critical("Unable to set password for new user: %s", e) os._exit(1) # Add the user to all the groups they should be part of. grpLst.append(self.admin.lookupGroupByName(user_name)) try: for grp in grpLst: grp.add(libuser.MEMBERNAME, user_name) self.admin.modifyGroup(grp) except RuntimeError as e: log.critical("Unable to add user to groups: %s", e) os._exit(1) os._exit(0) try: status = os.waitpid(childpid, 0)[1] except OSError as e: log.critical("exception from waitpid while creating a user: %s %s", e.errno, e.strerror) return False if os.WIFEXITED(status) and (os.WEXITSTATUS(status) == 0): return True else: return False
def preInstall(self, packages=None, groups=None): """ Perform pre-installation tasks. """ iutil.mkdirChain(iutil.getSysroot() + "/root") self._writeModuleBlacklist()
def mount(self, *args, **kwargs): """ Mount this filesystem. Arguments: None Keyword Arguments: options -- mount options (overrides all other option strings) chroot -- prefix to apply to mountpoint mountpoint -- mountpoint (overrides self.mountpoint) """ options = kwargs.get("options", "") chroot = kwargs.get("chroot", "/") mountpoint = kwargs.get("mountpoint") if not self.exists: raise FSError("filesystem has not been created") if not mountpoint: mountpoint = self.mountpoint if not mountpoint: raise FSError("no mountpoint given") if self.status: return if not isinstance(self, NoDevFS) and not os.path.exists(self.device): raise FSError("device %s does not exist" % self.device) # XXX os.path.join is FUBAR: # # os.path.join("/mnt/foo", "/") -> "/" # #mountpoint = os.path.join(chroot, mountpoint) chrootedMountpoint = os.path.normpath("%s/%s" % (chroot, mountpoint)) iutil.mkdirChain(chrootedMountpoint) if flags.selinux: ret = isys.resetFileContext(mountpoint, chroot) log.info("set SELinux context for mountpoint %s to %s" \ % (mountpoint, ret)) # passed in options override default options if not options or not isinstance(options, str): options = self.options try: rc = isys.mount(self.device, chrootedMountpoint, fstype=self.mountType, options=options, bindMount=isinstance(self, BindFS)) except Exception as e: raise FSError("mount failed: %s" % e) if rc: raise FSError("mount failed: %s" % rc) if flags.selinux and "ro" not in options.split(","): ret = isys.resetFileContext(mountpoint, chroot) log.info("set SELinux context for newly mounted filesystem " "root at %s to %s" %(mountpoint, ret)) isys.setFileContext("%s/lost+found" % mountpoint, lost_and_found_context, chroot) self._mountpoint = chrootedMountpoint
def preInstall(self, packages=None, groups=None): """ Perform pre-installation tasks. """ iutil.mkdirChain(ROOT_PATH + "/root")
def createUser(self, user_name, *args, **kwargs): """Create a new user on the system with the given name. Optional kwargs: algo -- The password algorithm to use in case isCrypted=True. If none is given, the cryptPassword default is used. gecos -- The GECOS information (full name, office, phone, etc.). Defaults to "". groups -- A list of existing group names the user should be added to. Defaults to []. homedir -- The home directory for the new user. Defaults to /home/<name>. isCrypted -- Is the password kwargs already encrypted? Defaults to False. lock -- Is the new account locked by default? Defaults to False. 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) root -- The directory of the system to create the new user in. homedir will be interpreted relative to this. Defaults to /mnt/sysimage. shell -- The shell for the new user. If none is given, the libuser default is used. uid -- The UID for the new user. If none is given, the next available one is used. gid -- The GID for the new user. If none is given, the next available one is used. """ childpid = self._prepareChroot(kwargs.get("root", iutil.getSysroot())) if childpid == 0: if self.admin.lookupUserByName(user_name): log.error("User %s already exists, not creating.", user_name) os._exit(1) userEnt = self.admin.initUser(user_name) groupEnt = self.admin.initGroup(user_name) gid = kwargs.get("gid") or -1 if gid >= 0: groupEnt.set(libuser.GIDNUMBER, kwargs["gid"]) grpLst = [ grp for grp in map(self.admin.lookupGroupByName, kwargs.get("groups", [])) if grp ] userEnt.set(libuser.GIDNUMBER, [groupEnt.get(libuser.GIDNUMBER)[0]] + [grp.get(libuser.GIDNUMBER)[0] for grp in grpLst]) homedir = kwargs.get("homedir", None) if not homedir: homedir = "/home/" + user_name # libuser expects the parent directory tree to exist. parent_dir = iutil.parent_dir(homedir) if parent_dir: iutil.mkdirChain(parent_dir) userEnt.set(libuser.HOMEDIRECTORY, homedir) if kwargs.get("shell", False): userEnt.set(libuser.LOGINSHELL, kwargs["shell"]) uid = kwargs.get("uid") or -1 if uid >= 0: userEnt.set(libuser.UIDNUMBER, kwargs["uid"]) if kwargs.get("gecos", False): userEnt.set(libuser.GECOS, kwargs["gecos"]) # need to create home directory for the user or does it already exist? # userEnt.get returns lists (usually with a single item) mk_homedir = not os.path.exists( userEnt.get(libuser.HOMEDIRECTORY)[0]) try: self.admin.addUser(userEnt, mkmailspool=kwargs.get("mkmailspool", True), mkhomedir=mk_homedir) except RuntimeError as e: log.critical("Error when creating new user: %s", e) os._exit(1) try: self.admin.addGroup(groupEnt) except RuntimeError as e: log.critical("Error when creating new group: %s", e) os._exit(1) if not mk_homedir: try: stats = os.stat(userEnt.get(libuser.HOMEDIRECTORY)[0]) orig_uid = stats.st_uid orig_gid = stats.st_gid 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 iutil.chown_dir_tree( userEnt.get(libuser.HOMEDIRECTORY)[0], userEnt.get(libuser.UIDNUMBER)[0], groupEnt.get(libuser.GIDNUMBER)[0], orig_uid, orig_gid) iutil.execWithRedirect( "restorecon", ["-r", userEnt.get(libuser.HOMEDIRECTORY)[0]]) except OSError as e: log.critical( "Unable to change owner of existing home directory: %s", os.strerror) os._exit(1) pw = kwargs.get("password", False) try: if pw: if kwargs.get("isCrypted", False): password = kwargs["password"] else: password = cryptPassword(kwargs["password"], algo=kwargs.get("algo", None)) self.admin.setpassUser(userEnt, password, True) userEnt.set(libuser.SHADOWLASTCHANGE, "") self.admin.modifyUser(userEnt) elif pw == "": # Setup the account with *NO* password self.admin.unlockUser(userEnt) log.info("user account %s setup with no password", user_name) if kwargs.get("lock", False): self.admin.lockUser(userEnt) log.info("user account %s locked", user_name) # setpassUser raises SystemError on failure, while unlockUser and lockUser # raise RuntimeError except (RuntimeError, SystemError) as e: log.critical("Unable to set password for new user: %s", e) os._exit(1) # Add the user to all the groups they should be part of. grpLst.append(self.admin.lookupGroupByName(user_name)) try: for grp in grpLst: grp.add(libuser.MEMBERNAME, user_name) self.admin.modifyGroup(grp) except RuntimeError as e: log.critical("Unable to add user to groups: %s", e) os._exit(1) os._exit(0) else: return self._finishChroot(childpid)
def create_return(path): iutil.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 existing group names the user should be added to. 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 iutil.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", iutil.getSysroot()) if self.checkUserExists(user_name, root): raise ValueError("User %s already exists" % user_name) args = ["-R", root] # If a specific gid is requested, create the user group with that GID. # Otherwise let useradd do it automatically. if kwargs.get("gid", None): self.createGroup(user_name, gid=kwargs['gid'], root=root) args.extend(['-g', str(kwargs['gid'])]) else: args.append('-U') if kwargs.get("groups"): args.extend(['-G', ",".join(kwargs["groups"])]) if kwargs.get("homedir"): homedir = kwargs["homedir"] else: homedir = "/home/" + user_name # useradd expects the parent directory tree to exist. parent_dir = iutil.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: iutil.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 = iutil.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 iutil.chown_dir_tree(root + homedir, int(pwent[2]), int(pwent[3]), orig_uid, orig_gid) iutil.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 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 iutil.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", iutil.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 = iutil.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: iutil.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 = iutil.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 iutil.chown_dir_tree(root + homedir, int(pwent[2]), int(pwent[3]), orig_uid, orig_gid) iutil.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 mount(self, *args, **kwargs): """ Mount this filesystem. Arguments: None Keyword Arguments: options -- mount options (overrides all other option strings) chroot -- prefix to apply to mountpoint mountpoint -- mountpoint (overrides self.mountpoint) """ options = kwargs.get("options", "") chroot = kwargs.get("chroot", "/") mountpoint = kwargs.get("mountpoint") if not self.exists: raise FSError("filesystem has not been created") if not mountpoint: mountpoint = self.mountpoint if not mountpoint: raise FSError("no mountpoint given") if self.status: return if not isinstance(self, NoDevFS) and not os.path.exists(self.device): raise FSError("device %s does not exist" % self.device) # XXX os.path.join is FUBAR: # # os.path.join("/mnt/foo", "/") -> "/" # #mountpoint = os.path.join(chroot, mountpoint) chrootedMountpoint = os.path.normpath("%s/%s" % (chroot, mountpoint)) iutil.mkdirChain(chrootedMountpoint) if flags.selinux: ret = isys.resetFileContext(mountpoint, chroot) log.info("set SELinux context for mountpoint %s to %s" \ % (mountpoint, ret)) # passed in options override default options if not options or not isinstance(options, str): options = self.options try: rc = isys.mount(self.device, chrootedMountpoint, fstype=self.mountType, options=options, bindMount=isinstance(self, BindFS)) except Exception as e: raise FSError("mount failed: %s" % e) if rc: raise FSError("mount failed: %s" % rc) if flags.selinux and "ro" not in options.split(","): ret = isys.resetFileContext(mountpoint, chroot) log.info("set SELinux context for newly mounted filesystem " "root at %s to %s" % (mountpoint, ret)) isys.setFileContext("%s/lost+found" % mountpoint, lost_and_found_context, chroot) self._mountpoint = chrootedMountpoint
def _initSmart(self, command=None, argv=None): iutil.mkdirChain(self.smart_dir) iutil.mkdirChain(self.wrapper_dir) buf = """#!/bin/bash export PATH="${PATH}" export D="%s" export OFFLINE_ROOT="$D" export IPKG_OFFLINE_ROOT="$D" export OPKG_OFFLINE_ROOT="$D" export INTERCEPT_DIR="/" export NATIVE_ROOT="/" exec 1>>/tmp/scriptlet.log 2>&1 echo $2 $1/$3 $4 if [ $2 = "/bin/sh" ]; then $2 -x $1/$3 $4 else $2 $1/$3 $4 fi if [ $? -ne 0 ]; then if [ $4 -eq 1 ]; then mkdir -p $1/etc/rpm-postinsts num=100 while [ -e $1/etc/rpm-postinsts/${num}-* ]; do num=$((num + 1)); done name=`head -1 $1/$3 | cut -d' ' -f 2` echo "#!$2" > $1/etc/rpm-postinsts/${num}-${name} echo "# Arg: $4" >> $1/etc/rpm-postinsts/${num}-${name} cat $1/$3 >> $1/etc/rpm-postinsts/${num}-${name} chmod +x $1/etc/rpm-postinsts/${num}-${name} else echo "Error: pre/post remove scriptlet failed" fi fi """ % (self.sysroot) fd = open(self.wrapper_dir + "/scriptlet_wrapper", "w") fd.write(buf) fd.close() os.chmod(self.wrapper_dir + "/scriptlet_wrapper", 0755) self.smart_ctrl = init(command, argv=argv, datadir=self.smart_dir, configfile=None, gui=False, shell=False, quiet=True, interface=None, forcelocks=False, loglevel=None) # Override the dummy interface with the locally defined one iface.object = AnacondaInterface(self.smart_ctrl) initDistro(self.smart_ctrl) initPlugins() initPycurl() initPsyco() sysconf.set("rpm-root", self.sysroot, soft=True) sysconf.set("rpm-extra-macros._tmppath", "/install/tmp", soft=True) sysconf.set("rpm-extra-macros._cross_scriptlet_wrapper", self.wrapper_dir + "/scriptlet_wrapper", soft=True) sysconf.set("rpm-nolinktos", "1") sysconf.set("rpm-noparentdirs", "1") sysconf.remove("channels") self.repo_manager = SmartRepoManager(self.runSmart)
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 iutil.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", iutil.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 = iutil.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: iutil.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 = iutil.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 iutil.chown_dir_tree(root + homedir, int(pwent[2]), int(pwent[3]), orig_uid, orig_gid) iutil.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 createUser(self, user_name, *args, **kwargs): """Create a new user on the system with the given name. Optional kwargs: algo -- The password algorithm to use in case isCrypted=True. If none is given, the cryptPassword default is used. gecos -- The GECOS information (full name, office, phone, etc.). Defaults to "". groups -- A list of existing group names the user should be added to. Defaults to []. homedir -- The home directory for the new user. Defaults to /home/<name>. isCrypted -- Is the password kwargs already encrypted? Defaults to False. lock -- Is the new account locked by default? Defaults to False. 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) root -- The directory of the system to create the new user in. homedir will be interpreted relative to this. Defaults to /mnt/sysimage. shell -- The shell for the new user. If none is given, the libuser default is used. uid -- The UID for the new user. If none is given, the next available one is used. gid -- The GID for the new user. If none is given, the next available one is used. """ childpid = self._prepareChroot(kwargs.get("root", iutil.getSysroot())) if childpid == 0: if self.admin.lookupUserByName(user_name): log.error("User %s already exists, not creating.", user_name) os._exit(1) userEnt = self.admin.initUser(user_name) groupEnt = self.admin.initGroup(user_name) gid = kwargs.get("gid") or -1 if gid >= 0: groupEnt.set(libuser.GIDNUMBER, kwargs["gid"]) grpLst = [grp for grp in map(self.admin.lookupGroupByName, kwargs.get("groups", [])) if grp] userEnt.set(libuser.GIDNUMBER, [groupEnt.get(libuser.GIDNUMBER)[0]] + [grp.get(libuser.GIDNUMBER)[0] for grp in grpLst]) homedir = kwargs.get("homedir", None) if not homedir: homedir = "/home/" + user_name # libuser expects the parent directory tree to exist. parent_dir = iutil.parent_dir(homedir) if parent_dir: iutil.mkdirChain(parent_dir) userEnt.set(libuser.HOMEDIRECTORY, homedir) if kwargs.get("shell", False): userEnt.set(libuser.LOGINSHELL, kwargs["shell"]) uid = kwargs.get("uid") or -1 if uid >= 0: userEnt.set(libuser.UIDNUMBER, kwargs["uid"]) if kwargs.get("gecos", False): userEnt.set(libuser.GECOS, kwargs["gecos"]) # need to create home directory for the user or does it already exist? # userEnt.get returns lists (usually with a single item) mk_homedir = not os.path.exists(userEnt.get(libuser.HOMEDIRECTORY)[0]) try: self.admin.addUser(userEnt, mkmailspool=kwargs.get("mkmailspool", True), mkhomedir=mk_homedir) except RuntimeError as e: log.critical("Error when creating new user: %s", e) os._exit(1) try: self.admin.addGroup(groupEnt) except RuntimeError as e: log.critical("Error when creating new group: %s", e) os._exit(1) if not mk_homedir: try: stats = os.stat(userEnt.get(libuser.HOMEDIRECTORY)[0]) orig_uid = stats.st_uid orig_gid = stats.st_gid 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 iutil.chown_dir_tree(userEnt.get(libuser.HOMEDIRECTORY)[0], userEnt.get(libuser.UIDNUMBER)[0], groupEnt.get(libuser.GIDNUMBER)[0], orig_uid, orig_gid) iutil.execWithRedirect("restorecon", ["-r", userEnt.get(libuser.HOMEDIRECTORY)[0]]) except OSError as e: log.critical("Unable to change owner of existing home directory: %s", os.strerror) os._exit(1) pw = kwargs.get("password", False) try: if pw: if kwargs.get("isCrypted", False): password = kwargs["password"] else: password = cryptPassword(kwargs["password"], algo=kwargs.get("algo", None)) self.admin.setpassUser(userEnt, password, True) userEnt.set(libuser.SHADOWLASTCHANGE, "") self.admin.modifyUser(userEnt) elif pw == "": # Setup the account with *NO* password self.admin.unlockUser(userEnt) log.info("user account %s setup with no password", user_name) if kwargs.get("lock", False): self.admin.lockUser(userEnt) log.info("user account %s locked", user_name) # setpassUser raises SystemError on failure, while unlockUser and lockUser # raise RuntimeError except (RuntimeError, SystemError) as e: log.critical("Unable to set password for new user: %s", e) os._exit(1) # Add the user to all the groups they should be part of. grpLst.append(self.admin.lookupGroupByName(user_name)) try: for grp in grpLst: grp.add(libuser.MEMBERNAME, user_name) self.admin.modifyGroup(grp) except RuntimeError as e: log.critical("Unable to add user to groups: %s", e) os._exit(1) os._exit(0) else: return self._finishChroot(childpid)
anaconda = Anaconda() iutil.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() setupEnvironment() # make sure we have /var/log soon, some programs fail to start without it iutil.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
anaconda = Anaconda() iutil.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 iutil.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 existing group names the user should be added to. 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 iutil.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", iutil.getSysroot()) if self.checkUserExists(user_name, root): raise ValueError("User %s already exists" % user_name) args = ["-R", root] # If a specific gid is requested, create the user group with that GID. # Otherwise let useradd do it automatically. if kwargs.get("gid", None): self.createGroup(user_name, gid=kwargs['gid'], root=root) args.extend(['-g', str(kwargs['gid'])]) else: args.append('-U') if kwargs.get("groups"): args.extend(['-G', ",".join(kwargs["groups"])]) if kwargs.get("homedir"): homedir = kwargs["homedir"] else: homedir = "/home/" + user_name # useradd expects the parent directory tree to exist. parent_dir = iutil.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: iutil.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 = iutil.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 iutil.chown_dir_tree(root + homedir, int(pwent[2]), int(pwent[3]), orig_uid, orig_gid) iutil.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)