Пример #1
0
    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)
Пример #2
0
    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
Пример #3
0
    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
Пример #4
0
    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()
Пример #5
0
    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)
Пример #6
0
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
Пример #7
0
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
Пример #8
0
    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)
Пример #9
0
    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)
Пример #10
0
    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)
Пример #11
0
    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()
Пример #13
0
    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
Пример #14
0
    def preInstall(self, packages=None, groups=None):
        """ Perform pre-installation tasks. """
        iutil.mkdirChain(iutil.getSysroot() + "/root")

        self._writeModuleBlacklist()
Пример #15
0
    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
Пример #16
0
 def preInstall(self, packages=None, groups=None):
     """ Perform pre-installation tasks. """
     iutil.mkdirChain(ROOT_PATH + "/root")
Пример #17
0
    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)
Пример #18
0
    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
Пример #19
0
 def create_return(path):
     iutil.mkdirChain(path)
     return path
Пример #20
0
    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)
Пример #21
0
    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)
Пример #22
0
    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
Пример #23
0
    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)
Пример #24
0
 def create_return(path):
     iutil.mkdirChain(path)
     return path
Пример #25
0
    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)
Пример #26
0
 def preInstall(self, packages=None, groups=None):
     """ Perform pre-installation tasks. """
     iutil.mkdirChain(ROOT_PATH + "/root")
Пример #27
0
    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)
Пример #28
0
    def preInstall(self, packages=None, groups=None):
        """ Perform pre-installation tasks. """
        iutil.mkdirChain(iutil.getSysroot() + "/root")

        self._writeModuleBlacklist()
Пример #29
0
    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
Пример #30
0
    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
Пример #31
0
    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)