Пример #1
0
    def _doFilesystemMangling(self, anaconda):
        log.info("doing post-install fs mangling")
        wait = anaconda.intf.waitWindow(
            _("Post-Installation"),
            _("Performing post-installation filesystem changes.  This may take several minutes."
              ))

        # resize rootfs first, since it is 100% full due to genMinInstDelta
        self._resizeRootfs(anaconda, wait)

        # remount filesystems
        anaconda.id.storage.mountFilesystems()

        # restore the label of / to what we think it is
        rootDevice = anaconda.id.storage.rootDevice
        rootDevice.setup()
        # ensure we have a random UUID on the rootfs
        # FIXME: this should be abstracted per filesystem type
        iutil.execWithRedirect("tune2fs", ["-U", "random", rootDevice.path],
                               stdout="/dev/tty5",
                               stderr="/dev/tty5")
        # and now set the uuid in the storage layer
        rootDevice.updateSysfsPath()
        iutil.notify_kernel("/sys%s" % rootDevice.sysfsPath)
        storage.udev.udev_settle()
        rootDevice.updateSysfsPath()
        info = storage.udev.udev_get_block_device(rootDevice.sysfsPath)
        rootDevice.format.uuid = storage.udev.udev_device_get_uuid(info)
        log.info("reset the rootdev (%s) to have a uuid of %s" %
                 (rootDevice.sysfsPath, rootDevice.format.uuid))

        # for any filesystem that's _not_ on the root, we need to handle
        # moving the bits from the livecd -> the real filesystems.
        # this is pretty distasteful, but should work with things like
        # having a separate /usr/local

        def _setupFilesystems(mounts, chroot="", teardown=False):
            """ Setup or teardown all filesystems except for "/" """
            mountpoints = sorted(mounts.keys(), reverse=teardown is True)
            if teardown:
                method = "teardown"
                kwargs = {}
            else:
                method = "setup"
                kwargs = {"chroot": chroot}

            mountpoints.remove("/")
            for mountpoint in mountpoints:
                device = mounts[mountpoint]
                getattr(device.format, method)(**kwargs)

        # Start by sorting the mountpoints in decreasing-depth order.
        mountpoints = sorted(anaconda.id.storage.mountpoints.keys(),
                             reverse=True)
        # We don't want to copy the root filesystem.
        mountpoints.remove("/")
        stats = {}  # mountpoint: posix.stat_result

        # unmount the filesystems, except for /
        _setupFilesystems(anaconda.id.storage.mountpoints, teardown=True)

        # mount all of the filesystems under /mnt so we can copy in content
        _setupFilesystems(anaconda.id.storage.mountpoints,
                          chroot=anaconda.rootPath + "/mnt")

        # And now let's do the real copies
        for tocopy in mountpoints:
            device = anaconda.id.storage.mountpoints[tocopy]

            # FIXME: all calls to wait.refresh() are kind of a hack... we
            # should do better about not doing blocking things in the
            # main thread.  but threading anaconda is a job for another
            # time.
            wait.refresh()

            if not os.path.exists("%s/%s" % (anaconda.rootPath, tocopy)):
                # the directory does not exist in the live image, so there's
                # nothing to move
                continue

            iutil.copytree("%s/%s" % (anaconda.rootPath, tocopy),
                           "%s/mnt/%s" % (anaconda.rootPath, tocopy), True,
                           True, flags.selinux)
            wait.refresh()
            shutil.rmtree("%s/%s" % (anaconda.rootPath, tocopy))
            wait.refresh()

        # now unmount each fs, collect stat info for the mountpoint, then
        # remove the entire tree containing the mountpoint
        for tocopy in mountpoints:
            device = anaconda.id.storage.mountpoints[tocopy]
            device.format.teardown()
            if not os.path.exists("%s/%s" % (anaconda.rootPath, tocopy)):
                continue

            try:
                stats[tocopy] = os.stat("%s/mnt/%s" %
                                        (anaconda.rootPath, tocopy))
            except Exception as e:
                log.info("failed to get stat info for mountpoint %s: %s" %
                         (tocopy, e))

            shutil.rmtree("%s/mnt/%s" %
                          (anaconda.rootPath, tocopy.split("/")[1]))
            wait.refresh()

        # now mount all of the filesystems so that post-install writes end
        # up where they're supposed to end up
        _setupFilesystems(anaconda.id.storage.mountpoints,
                          chroot=anaconda.rootPath)

        # restore stat info for each mountpoint
        for mountpoint in reversed(mountpoints):
            if mountpoint not in stats:
                # there's no info to restore since the mountpoint did not
                # exist in the live image
                continue

            dest = "%s/%s" % (anaconda.rootPath, mountpoint)
            st = stats[mountpoint]

            # restore the correct stat info for this mountpoint
            os.utime(dest, (st.st_atime, st.st_mtime))
            os.chown(dest, st.st_uid, st.st_gid)
            os.chmod(dest, stat.S_IMODE(st.st_mode))

        # ensure that non-fstab filesystems are mounted in the chroot
        if flags.selinux:
            try:
                isys.mount("/selinux", anaconda.rootPath + "/selinux",
                           "selinuxfs")
            except Exception, e:
                log.error("error mounting selinuxfs: %s" % (e, ))
Пример #2
0
    def _doFilesystemMangling(self, anaconda):
        log.info("doing post-install fs mangling")
        wait = anaconda.intf.waitWindow(_("Post-Installation"),
                                        _("Performing post-installation filesystem changes.  This may take several minutes."))

        # resize rootfs first, since it is 100% full due to genMinInstDelta
        rootDevice = anaconda.storage.rootDevice
        rootDevice.setup()

        # This is a workaround to make sure the m_time it set to current time so that
        # the e2fsck before resizing doesn't get confused by times in the future
        rootDevice.format.testMount()

        rootDevice.format.targetSize = rootDevice.size
        rootDevice.format.doResize(intf=anaconda.intf)

        # ensure we have a random UUID on the rootfs
        rootDevice.format.writeRandomUUID()

        # remount filesystems
        anaconda.storage.mountFilesystems()

        # and now set the uuid in the storage layer
        rootDevice.updateSysfsPath()
        iutil.notify_kernel("/sys%s" %rootDevice.sysfsPath)
        storage.udev.udev_settle()
        rootDevice.updateSysfsPath()
        info = storage.udev.udev_get_block_device(rootDevice.sysfsPath)
        rootDevice.format.uuid = storage.udev.udev_device_get_uuid(info)
        log.info("reset the rootdev (%s) to have a uuid of %s" %(rootDevice.sysfsPath, rootDevice.format.uuid))

        # for any filesystem that's _not_ on the root, we need to handle
        # moving the bits from the livecd -> the real filesystems.
        # this is pretty distasteful, but should work with things like
        # having a separate /usr/local

        def _setupFilesystems(mounts, chroot="", teardown=False):
            """ Setup or teardown all filesystems except for "/" """
            mountpoints = sorted(mounts.keys(),
                                 reverse=teardown is True)
            if teardown:
                method = "teardown"
                kwargs = {}
            else:
                method = "setup"
                kwargs = {"chroot": chroot}

            mountpoints.remove("/")
            for mountpoint in mountpoints:
                device = mounts[mountpoint]
                getattr(device.format, method)(**kwargs)

        # Start by sorting the mountpoints in decreasing-depth order.
        # Only include ones that exist on the original livecd filesystem
        mountpoints = filter(os.path.exists,
                             sorted(anaconda.storage.mountpoints.keys(),
                             reverse=True))
        # We don't want to copy the root filesystem.
        mountpoints.remove("/")
        stats = {} # mountpoint: posix.stat_result

        # unmount the filesystems, except for /
        _setupFilesystems(anaconda.storage.mountpoints, teardown=True)

        # mount all of the filesystems under /mnt so we can copy in content
        _setupFilesystems(anaconda.storage.mountpoints,
                          chroot="/mnt")

        # And now let's do the real copies
        for tocopy in mountpoints:
            device = anaconda.storage.mountpoints[tocopy]
            source = "%s/%s" % (ROOT_PATH, tocopy)
            dest   = "/mnt/%s" % (tocopy,)

            # FIXME: all calls to wait.refresh() are kind of a hack... we
            # should do better about not doing blocking things in the
            # main thread.  but threading anaconda is a job for another
            # time.
            wait.refresh()

            try:
                log.info("Gathering stats on %s" % (source,))
                stats[tocopy]= os.stat(source)
            except Exception as e:
                log.info("failed to get stat info for mountpoint %s: %s"
                            % (source, e))

            log.info("Copying %s to %s" % (source, dest))
            copytree(source, dest, True, True, flags.selinux)
            wait.refresh()

            log.info("Removing %s" % (source,))
            shutil.rmtree(source)
            wait.refresh()

        # unmount the target filesystems and remount in their final locations
        # so that post-install writes end up where they're supposed to end up
        _setupFilesystems(anaconda.storage.mountpoints, teardown=True)
        _setupFilesystems(anaconda.storage.mountpoints,
                          chroot=ROOT_PATH)

        # restore stat info for each mountpoint
        for mountpoint in reversed(mountpoints):
            dest = "%s/%s" % (ROOT_PATH, mountpoint)
            log.info("Restoring stats on %s" % (dest,))
            st = stats[mountpoint]

            # restore the correct stat info for this mountpoint
            os.utime(dest, (st.st_atime, st.st_mtime))
            os.chown(dest, st.st_uid, st.st_gid)
            os.chmod(dest, stat.S_IMODE(st.st_mode))

        wait.pop()
    def _doFilesystemMangling(self, anaconda):
        log.info("doing post-install fs mangling")
        wait = anaconda.intf.waitWindow(_("Post-Installation"),
                                        _("Performing post-installation filesystem changes.  This may take several minutes."))

        # resize rootfs first, since it is 100% full due to genMinInstDelta
        rootDevice = anaconda.storage.rootDevice
        rootDevice.setup()
        rootDevice.format.targetSize = rootDevice.size
        rootDevice.format.doResize(intf=anaconda.intf)

        # ensure we have a random UUID on the rootfs
        rootDevice.format.writeRandomUUID()

        # remount filesystems
        anaconda.storage.mountFilesystems()

        # and now set the uuid in the storage layer
        rootDevice.updateSysfsPath()
        iutil.notify_kernel("/sys%s" %rootDevice.sysfsPath)
        storage.udev.udev_settle()
        rootDevice.updateSysfsPath()
        info = storage.udev.udev_get_block_device(rootDevice.sysfsPath)
        rootDevice.format.uuid = storage.udev.udev_device_get_uuid(info)
        log.info("reset the rootdev (%s) to have a uuid of %s" %(rootDevice.sysfsPath, rootDevice.format.uuid))

        # for any filesystem that's _not_ on the root, we need to handle
        # moving the bits from the livecd -> the real filesystems.
        # this is pretty distasteful, but should work with things like
        # having a separate /usr/local

        def _setupFilesystems(mounts, chroot="", teardown=False):
            """ Setup or teardown all filesystems except for "/" """
            mountpoints = sorted(mounts.keys(),
                                 reverse=teardown is True)
            if teardown:
                method = "teardown"
                kwargs = {}
            else:
                method = "setup"
                kwargs = {"chroot": chroot}

            mountpoints.remove("/")
            for mountpoint in mountpoints:
                device = mounts[mountpoint]
                getattr(device.format, method)(**kwargs)

        # Start by sorting the mountpoints in decreasing-depth order.
        mountpoints = sorted(anaconda.storage.mountpoints.keys(),
                             reverse=True)
        # We don't want to copy the root filesystem.
        mountpoints.remove("/")
        stats = {} # mountpoint: posix.stat_result

        # unmount the filesystems, except for /
        _setupFilesystems(anaconda.storage.mountpoints, teardown=True)

        # mount all of the filesystems under /mnt so we can copy in content
        _setupFilesystems(anaconda.storage.mountpoints,
                          chroot=anaconda.rootPath + "/mnt")

        # And now let's do the real copies
        for tocopy in mountpoints:
            device = anaconda.storage.mountpoints[tocopy]

            # FIXME: all calls to wait.refresh() are kind of a hack... we
            # should do better about not doing blocking things in the
            # main thread.  but threading anaconda is a job for another
            # time.
            wait.refresh()

            if not os.path.exists("%s/%s" % (anaconda.rootPath, tocopy)):
                # the directory does not exist in the live image, so there's
                # nothing to move
                continue

            copytree("%s/%s" % (anaconda.rootPath, tocopy),
                     "%s/mnt/%s" % (anaconda.rootPath, tocopy),
                     True, True, flags.selinux)
            wait.refresh()
            shutil.rmtree("%s/%s" % (anaconda.rootPath, tocopy))
            wait.refresh()

        # now unmount each fs, collect stat info for the mountpoint, then
        # remove the entire tree containing the mountpoint
        for tocopy in mountpoints:
            device = anaconda.storage.mountpoints[tocopy]
            device.format.teardown()
            if not os.path.exists("%s/%s" % (anaconda.rootPath, tocopy)):
                continue

            try:
                stats[tocopy]= os.stat("%s/mnt/%s" % (anaconda.rootPath,
                                                      tocopy))
            except Exception as e:
                log.info("failed to get stat info for mountpoint %s: %s"
                            % (tocopy, e))

            shutil.rmtree("%s/mnt/%s" % (anaconda.rootPath,
                                         tocopy.split("/")[1]))
            wait.refresh()

        # now mount all of the filesystems so that post-install writes end
        # up where they're supposed to end up
        _setupFilesystems(anaconda.storage.mountpoints,
                          chroot=anaconda.rootPath)

        # restore stat info for each mountpoint
        for mountpoint in reversed(mountpoints):
            if mountpoint not in stats:
                # there's no info to restore since the mountpoint did not
                # exist in the live image
                continue

            dest = "%s/%s" % (anaconda.rootPath, mountpoint)
            st = stats[mountpoint]

            # restore the correct stat info for this mountpoint
            os.utime(dest, (st.st_atime, st.st_mtime))
            os.chown(dest, st.st_uid, st.st_gid)
            os.chmod(dest, stat.S_IMODE(st.st_mode))

        wait.pop()
Пример #4
0
        log_method_call(self, device=self.device, type=self.type)
        if not self.device:
            return

        if self.device.startswith("/dev/mapper/"):
            try:
                name = dm_node_from_name(os.path.basename(self.device))
            except Exception, e:
                log.warning("failed to get dm node for %s" % self.device)
                return
        else:
            name = self.device

        path = get_sysfs_path_by_name(name)
        try:
            notify_kernel(path, action="change")
        except Exception, e:
            log.warning("failed to notify kernel of change: %s" % e)

    def create(self, *args, **kwargs):
        log_method_call(self,
                        device=self.device,
                        type=self.type,
                        status=self.status)
        # allow late specification of device path
        device = kwargs.get("device")
        if device:
            self.device = device

        if not os.path.exists(self.device):
            raise FormatCreateError("invalid device specification",
Пример #5
0
                        type=self.type)
        if not self.device:
            return

        if self.device.startswith("/dev/mapper/"):
            try:
                name = dm_node_from_name(os.path.basename(self.device))
            except Exception, e:
                log.warning("failed to get dm node for %s" % self.device)
                return
        else:
            name = self.device

        path = get_sysfs_path_by_name(name)
        try:
            notify_kernel(path, action="change")
        except Exception, e:
            log.warning("failed to notify kernel of change: %s" % e)

    def cacheMajorminor(self):
        """ Cache the value of self.majorminor.

            Once a device node of this format's device disappears (for instance
            after a teardown), it is no longer possible to figure out the value
            of self.majorminor pseudo-unique string. Call this method before
            that happens for caching this.
        """
        self._majorminor = None
        try:
            self.majorminor # this does the caching
        except StorageError:
Пример #6
0
    def _doFilesystemMangling(self, anaconda):
        # FIXME: this whole method is a big f*****g mess
        log.info("doing post-install fs mangling")
        wait = anaconda.intf.waitWindow(_("Post-Installation"),
                                        _("Performing post-installation filesystem changes.  This may take several minutes."))

        # resize rootfs first, since it is 100% full due to genMinInstDelta
        self._resizeRootfs(anaconda, wait)

        # remount filesystems
        anaconda.storage.mountFilesystems()

        # restore the label of / to what we think it is
        rootDevice = anaconda.storage.rootDevice
        rootDevice.setup()
        # ensure we have a random UUID on the rootfs
        # FIXME: this should be abstracted per filesystem type
        iutil.execWithRedirect("tune2fs",
                               ["-U",
                                "random",
                                rootDevice.path],
                               stdout="/dev/tty5",
                               stderr="/dev/tty5")
        # and now set the uuid in the storage layer
        rootDevice.updateSysfsPath()
        iutil.notify_kernel("/sys%s" %rootDevice.sysfsPath)
        storage.udev.udev_settle()
        rootDevice.updateSysfsPath()
        info = storage.udev.udev_get_block_device(rootDevice.sysfsPath)
        rootDevice.format.uuid = storage.udev.udev_device_get_uuid(info)
        log.info("reset the rootdev (%s) to have a uuid of %s" %(rootDevice.sysfsPath, rootDevice.format.uuid))

        # for any filesystem that's _not_ on the root, we need to handle
        # moving the bits from the livecd -> the real filesystems.
        # this is pretty distasteful, but should work with things like
        # having a separate /usr/local

        # now create a tree so that we know what's mounted under where
        fsdict = {"/": []}
        for mount in sorted(anaconda.storage.mountpoints.keys()):
            entry = anaconda.storage.mountpoints[mount]
            tocopy = entry.format.mountpoint
            if tocopy.startswith("/mnt") or tocopy == "swap":
                continue
            keys = sorted(fsdict.keys(), reverse = True)
            for key in keys:
                if tocopy.startswith(key):
                    fsdict[key].append(entry)
                    break
            fsdict[tocopy] = []
        log.debug("mangling dict looks like %s" %(fsdict,))

        # and now let's do the real copies; and we don't want to copy /!
        copied = ["/"]
        for tocopy in sorted(fsdict.keys()):
            if tocopy in copied:
                continue
            copied.append(tocopy)
            copied.extend(map(lambda x: x.format.mountpoint, fsdict[tocopy]))
            entry = anaconda.storage.mountpoints[tocopy]

            # FIXME: all calls to wait.refresh() are kind of a hack... we
            # should do better about not doing blocking things in the
            # main thread.  but threading anaconda is a job for another
            # time.
            wait.refresh()

            # unmount subdirs + this one and then remount under /mnt
            for e in fsdict[tocopy] + [entry]:
                e.format.teardown()
            for e in [entry] + fsdict[tocopy]:
                e.format.setup(chroot=anaconda.rootPath + "/mnt")

            copytree("%s/%s" %(anaconda.rootPath, tocopy),
                     "%s/mnt/%s" %(anaconda.rootPath, tocopy), True, True,
                     flags.selinux)
            shutil.rmtree("%s/%s" %(anaconda.rootPath, tocopy))
            wait.refresh()

            # mount it back in the correct place
            for e in fsdict[tocopy] + [entry]:
                e.format.teardown()
                try:
                    os.rmdir("%s/mnt/%s" %(anaconda.rootPath,
                                           e.format.mountpoint))
                except OSError as e:
                    log.debug("error removing %s" %(tocopy,))
            for e in [entry] + fsdict[tocopy]:                
                e.format.setup(chroot=anaconda.rootPath)

            wait.refresh()

        # ensure that non-fstab filesystems are mounted in the chroot
        if flags.selinux:
            try:
                isys.mount("/selinux", anaconda.rootPath + "/selinux", "selinuxfs")
            except Exception, e:
                log.error("error mounting selinuxfs: %s" %(e,))