Exemple #1
0
def UnmountFilesystems(mountpoint):
    """
    This attempts to unmount all of the filesystems.
    Note that it unmounts /var
    """
    try:
        for directory in ["boot/grub", "dev", "var"]:
            try:
                path = os.path.join(mountpoint, directory)
                LogIt("Attempting to unmount {}".format(path))
                bsd.unmount(path)
            except BaseException as e:
                LogIt("Unable to unmount {}: {}".format(path, str(e)))
                raise
        try:
            bsd.unmount(mountpoint)
        except BaseException as e:
            LogIt("Unable to unmount BE: {}".format(str(e)))
            raise
        try:
            os.rmdir(mountpoint)
        except BaseException as e:
            LogIt("Could not remove {}: {}".format(mountpoint, str(e)))
    except:
        raise InstallationError("Unable to unmount filesystems in new Boot Environment")
Exemple #2
0
def MountFilesystems(bename, mountpoint, **kwargs):
    """
    Mount the necessary filesystems, and clean up on error.
    The filesystems are bename -> mountpoint, freenas-boot/grub -> mountpoint/boot/grub,
    devfs -> mountpoint/dev, tmpfs mountpoint/var
    We also create mountpoint/boot/grub
    """
    mounted = []
    try:
        LogIt("Mounting {} on {}".format(bename, mountpoint))
        bsd.nmount(source=bename,
                   fspath=mountpoint,
                   fstype="zfs")
        mounted = [mountpoint]
        
        grub_path = "{}/boot/grub".format(mountpoint)
        LogIt("Mounting grub on {}".format(grub_path))
        os.makedirs(grub_path, 0o755)
        bsd.nmount(source="freenas-boot/grub",
                   fspath=grub_path,
                   fstype="zfs")
        mounted.append(grub_path)
        
        dev_path = os.path.join(mountpoint, "dev")
        LogIt("Mounting dev on {}".format(dev_path))
        os.makedirs(dev_path, 0o755)
        bsd.nmount(source="devfs",
                   fspath=dev_path,
                   fstype="devfs")
        mounted.append(dev_path)
        
    except os.error as e:
        LogIt("Got exception {} while mounting; have mounted {}".format(str(e), mounted))
        for path in mounted:
            try:
                bsd.unmount(path)
            except:
                raise InstallationError("Unable to mount filesystems")
    except BaseException as e:
        LogIt("Got base exception {}; have mounted {}".format(str(e), mounted))
        raise InstallationError("Error while mounting filesystems")
Exemple #3
0
    def run(self, src, dest_path, fstype=None):
        if not fstype:
            try:
                fstype, _ = system('/usr/sbin/fstyp', src)
            except SubprocessException:
                raise TaskException(errno.EINVAL, 'Cannot figure out filesystem type')

        if fstype == 'ntfs':
            try:
                bsd.kld.kldload('/boot/kernel/fuse.ko')
            except OSError as err:
                raise TaskException(err.errno, str(err))

        src_mount = tempfile.mkdtemp()

        try:
            bsd.nmount(source=src, fspath=src_mount, fstype=fstype)
        except OSError as err:
            raise TaskException(err.errno, "Cannot mount disk: {0}".format(str(err)))

        def callback(srcfile, dstfile):
            self.set_progress(self.copied / self.nfiles * 100, "Copying {0}".format(os.path.basename(srcfile)))

        self.set_progress(0, "Counting files...")
        self.nfiles = count_files(src_mount)
        self.copied = 0
        failures = []

        try:
            copytree(src_mount, dest_path, progress_callback=callback)
        except shutil.Error as err:
            failures = list(err)

        try:
            bsd.unmount(src_mount, bsd.MountFlags.FORCE)
        except OSError:
            pass

        bsd.kld.kldunload('fuse')
        os.rmdir(src_mount)
        return failures
Exemple #4
0
def UpgradePossible():
    """
    An upgrade is possible if there is one (and only one) freenas-boot pool,
    and if that pool has an installation for the same project as us.  We'll
    determine the project by importing the pool, checking for a bootfs dataset,
    and mounting it to look at etc/version, which should startwith the same
    name as our project.  If any of those actions fail, return false.
    """
    global found_bootpool
    if not found_bootpool:
        LogIt("Boot pool has not been found, so no upgrade is possible")
        return False

    status = Dialog.MessageBox(
        Title(),
        "Checking for upgradable {} installation".format(Project()),
        width=45,
        height=10,
        wait=False)
    status.clear()
    status.run()
    try:
        try:
            zfs.import_pool(found_bootpool, "freenas-boot", {})
        except:
            LogIt("Could not import freenas-boot")
            return False
        boot_pool = None
        try:
            boot_pool = zfs.get("freenas-boot")
            try:
                bootfs = boot_pool.properties["bootfs"].value
                LogIt("bootfs = {}".format(bootfs))
                # Next we try to mount it
                try:
                    bsd.nmount(
                        source=bootfs,
                        fspath="/mnt",
                        fstype="zfs",
                        flags=bsd.MountFlags.RDONLY,
                    )
                except BaseException as e:
                    LogIt("Couldn't mount, got exception {}".format(e))
                    raise
                try:
                    with open("/mnt/etc/version") as f:
                        version = f.read().rstrip()
                    if version.startswith(Project()):
                        return True
                    LogIt("{} does not start with {}".format(
                        version, Project()))
                except:
                    LogIt("Could not open version file")
                    pass
                finally:
                    bsd.unmount("/mnt")
            except:
                LogIt("Could not get bootfs property, or mount dataset")

        except:
            LogIt("Could not get freenas-boot pool")
        finally:
            if boot_pool:
                zfs.export_pool(boot_pool)
    except:
        LogIt("Could not find unimported freenas-boot pool")
    LogIt("Returning false")
    return False
def umount(name):
    with contextlib.suppress(OSError):
        bsd.unmount(os.path.join('/nfs', name))
def umount(name):
    bsd.unmount(os.path.join('/nfs', name))
def umount(name):
    try:
        bsd.unmount(os.path.join('/nfs', name))
    except OSError as err:
        logger.warning('Cannot unmount {0}: {1}'.format(name, err))
Exemple #8
0
        def callback(srcfile, dstfile):
            self.set_progress(self.copied / self.nfiles * 100, "Copying {0}".format(os.path.basename(srcfile)))

        self.set_progress(0, "Counting files...")
        self.nfiles = count_files(src_mount)
        self.copied = 0
        failures = []

        try:
            copytree(src_mount, dest_path, progress_callback=callback)
        except shutil.Error, err:
            failures = err.message

        try:
            bsd.unmount(src_mount, bsd.MountFlags.FORCE)
        except OSError:
            pass

        bsd.kld.kldunload('fuse')
        os.rmdir(src_mount)
        return failures


@description("Exports active volume")
@accepts(str)
class VolumeDetachTask(Task):
    def verify(self, name):
        if not self.datastore.exists('volumes', ('name', '=', name)):
            raise VerifyException(errno.ENOENT, 'Volume {0} not found'.format(name))
Exemple #9
0
        def callback(srcfile, dstfile):
            self.set_progress(self.copied / self.nfiles * 100,
                              "Copying {0}".format(os.path.basename(srcfile)))

        self.set_progress(0, "Counting files...")
        self.nfiles = count_files(src_mount)
        self.copied = 0
        failures = []

        try:
            copytree(src_mount, dest_path, progress_callback=callback)
        except shutil.Error, err:
            failures = err.message

        try:
            bsd.unmount(src_mount, bsd.MountFlags.FORCE)
        except OSError:
            pass

        bsd.kld.kldunload('fuse')
        os.rmdir(src_mount)
        return failures


@description("Exports active volume")
@accepts(str)
class VolumeDetachTask(Task):
    def verify(self, name):
        if not self.datastore.exists('volumes', ('name', '=', name)):
            raise VerifyException(errno.ENOENT,
                                  'Volume {0} not found'.format(name))
def umount(name):
    try:
        bsd.unmount(os.path.join('/nfs', name))
    except OSError as err:
        logger.warning('Cannot unmount {0}: {1}'.format(name, err))
Exemple #11
0
def InstallGrub(chroot, disks, bename, efi=False):
    # Tell beadm to activate the dataset, and make the grub
    # configuration.
    # To do that, we need to change some file.
    os.environ["PATH"] = os.environ["PATH"] + ":/usr/local/bin:/usr/local/sbin"
    grub_files = ["{}/usr/local/sbin/beadm".format(chroot),
                  "{}/conf/base/etc/local/grub.d/10_ktrueos".format(chroot)]
    backup_data = {}
    for data_file in grub_files:
        LogIt("Backing up {}".format(data_file))
        with open(data_file, "r") as f:
            backup_data[data_file] = [x.rstrip() for x in f]
        with open(data_file, "w") as f:
            for line in backup_data[data_file]:
                if line.startswith("ROOTFS="):
                    LogIt("Setting {} -> {}".format(line, "ROOTFS={}".format(bename)))
                    print("ROOTFS={}".format(bename), file=f)
                else:
                    print(line, file=f)
    x = "{}/etc/local".format(chroot)
    cleanit = None
    if os.path.islink(x):
        # If /usr/local/etc is a symlink to /etc/local, we need to chagne it
        try:
            cleanit = os.readlink("{}/etc/local".format(chroot))
            LogIt("Getting rid of {}/etc/local".format(chroot))
            os.remove("{}/etc/local".format(chroot))
        except:
            pass
    if not os.path.exists(x):
        try:
            os.symlink("/conf/base/etc/local", x)
        except:
            pass

    os.environ["GRUB_TERMINAL_OUTPUT"] = "console serial"
    if efi:
        with open("{}/conf/base/etc/local/default/grub".format(chroot), "r") as f:
            lines = [x.rstrip() for x in f]
        with open("{}/conf/base/etc/local/default/grub".format(chroot), "w") as f:
            LogIt("Editing default/grub")
            for line in lines:
                LogIt("\t{}".format(line))
                if "GRUB_TERMINAL_OUTPUT=console" in line:
                    line = line.replace("GRUB_TERMINAL_OUTPUT=console", "GRUB_TERMINAL_OUTPUT=gfxterm")
                    LogIt("\t\t-> {}".format(line))
                print(line, file=f)
        
    for disk_name in disks:
        LogIt("InstallGrub:  disk={}".format(disk_name))
        disk = Utils.Disk(disk_name)
        if disk is None:
            LogIt("Cannot find disk info for {}".format(disk_name))
            raise InstallationError("Cannot find information for {}".format(disk_name))
        if efi:
            sysctl.sysctlbyname("kern.geom.debugflags", old=False, new=16)
            sysctl.sysctlbyname("kern.geom.label.disk_ident.enable", old=False, new=0)
            try:
                RunCommand("/sbin/glabel", "label", "efibsd", "/dev/{}p1".format(disk.name))
            except RunCommandException as e:
                LogIt("glabel got {}".format(str(e)))
                
            try:
                os.makedirs("{}/boot/efi".format(chroot), 0o755)
            except:
                pass
            LogIt("Attempting to mount /dev/{}p1 on {}/boot/efi".format(disk.name, chroot))
            bsd.nmount(source="/dev/{}p1".format(disk.name),
                       fspath="{}/boot/efi".format(chroot),
                       fstype="msdosfs")
            LogIt("Attempting to run grub-install in chrooted environment")
            RunCommand("/usr/local/sbin/grub-install",
                       "--efi-directory=/boot/efi",
                       "--removable",
                       "--target=x86_64-efi",
                       "/dev/{}".format(disk.name),
                       chroot=chroot)
            LogIt("Attempting to unmount {}/boot/efi".format(chroot))
            bsd.unmount("{}/boot/efi".format(chroot))
        else:
            RunCommand("/usr/local/sbin/grub-install",
                       "--modules=zfs part_gpt",
                       "/dev/{}".format(disk.name),
                       chroot=chroot)
    RunCommand("/usr/local/sbin/beadm", "activate",
               os.path.basename(bename),
               chroot=chroot)
    RunCommand("/usr/local/sbin/grub-mkconfig",
               "-o", "/boot/grub/grub.cfg",
               chroot=chroot)
    # Now put the grub files back to what they should be
    for name, data in backup_data.items():
        LogIt("Restoring {}".format(name))
        with open(name, "w") as f:
            for line in data:
                print(line, file=f)
                
    if cleanit:
        try:
            p = "{}/etc/local".format(chroot)
            os.remove(p)
            os.symlink(cleanit, p)
        except BaseException as e:
            LogIt("Got exception {} while trying to clean /etc/local fixup".format(str(e)))
Exemple #12
0
def SaveConfiguration(**kwargs):
    interactive = kwargs.get("interactive", False)
    upgrade_pool = kwargs.get("pool", None)
    if interactive:
        status = Dialog.MessageBox(Title(),
                                   "Mounting boot pool for upgrade_pool",
                                   height=7, width=35, wait=False)
        status.clear()
        status.run()
    upgrade_dir = tempfile.mkdtemp()
    try:
        mount_point = tempfile.mkdtemp()
        zfs.import_pool(upgrade_pool,
                        "freenas-boot",
                        {})
        LogIt("Imported old freenas-boot")
        freenas_boot = zfs.get("freenas-boot")
        try:
            LogIt("Looking for bootable dataset")
            bootfs = freenas_boot.properties["bootfs"].value
            if bootfs is None:
                if interactive:
                    try:
                        Dialog.MessageBox(Title(),
                                          "No active boot environment for upgrade",
                                          height=7, width=35).run()
                    except:
                        pass
                raise InstallerError("No active boot environment for upgrade")
            
            LogIt("Found dataset {}".format(bootfs))
            bsd.nmount(source=bootfs,
                       fspath=mount_point,
                       fstype="zfs",
                       flags=bsd.MountFlags.RDONLY,
            )
            LogIt("Mounted pool")
            if interactive:
                status = Dialog.MessageBox(Title(),
                                           "Copying configuration files for update",
                                           height=7, width=36, wait=False)
                status.clear()
                status.run()
            try:
                # Copy files now.
                for path in upgrade_paths:
                    src = os.path.join(mount_point, path)
                    dst = os.path.join(upgrade_dir, path)
                    if os.path.exists(src):
                        try:
                            os.makedirs(os.path.dirname(dst))
                        except:
                            pass
                        LogIt("Copying {} -> {}".format(src, dst))
                        copytree(src, dst,
                                 progress_callback=lambda s, d: LogIt("\t{} -> {}".format(s, d)))
                return upgrade_dir
            except BaseException as e:
                LogIt("While copying, got exception {}".format(str(e)))
                raise
            finally:
                LogIt("Unmounting pool")
                bsd.unmount(mount_point)

        except BaseException as e:
            LogIt("But got an excetion {}".format(str(e)))
        finally:
            LogIt("Exporting old freenas-boot pool")
            zfs.export_pool(freenas_boot)
    except InstallationError:
        raise
    except:
        if interactive:
            Dialog.MessageBox(Title(),
                              "Saving configuration files for upgrade_pool has failed",
                              height=10, width=45).run()
        raise
    finally:
        try:
            os.rmdir(mount_point)
        except:
            pass