Пример #1
0
def properties(dataset, appended_properties: Optional[list]) -> list:
    dataset_properties = None
    try:
        dataset_properties = pyzfscmds.cmd.zfs_get(
            dataset,
            columns=["property", "value"],
            source=["local", "received"],
            properties=["all"])
    except RuntimeError:
        ZELogger.log(
            {
                "level": "EXCEPTION",
                "message": f"Failed to get properties of '{dataset}'"
            },
            exit_on_error=True)
    """
    Take each line of output containing properties and convert
    it to a list of property=value strings
    """
    dp = [line.split() for line in dataset_properties.splitlines()]
    remove_props = [rp[0] for rp in appended_properties]
    used_props = ["=".join(p) for p in dp if p[0] not in remove_props]

    used_props.extend(["=".join(pa) for pa in appended_properties])

    return used_props
Пример #2
0
def get_promote_snapshots(be_pool: str, destroy_dataset: str) -> list:
    """
    Look for clone we need to promote because they're dependent on snapshots
    """
    promote_snaps = None
    try:
        promote_snaps = pyzfscmds.cmd.zfs_list(
            be_pool,
            recursive=True,
            columns=['name', 'origin'],
            zfs_types=['filesystem', 'snapshot', 'volume'])
    except RuntimeError as e:
        ZELogger.log(
            {
                "level":
                "EXCEPTION",
                "message":
                f"Failed to list snapshots for promote in '{be_pool}'.\n{e}"
            },
            exit_on_error=True)

    split_promote_snaps = zedenv.lib.be.split_zfs_output(promote_snaps)

    target = re.compile(r'\b' + destroy_dataset + r'(@|/.*@).*' + r'\b')
    return [ds[0] for ds in split_promote_snaps if target.match(ds[1])]
Пример #3
0
    def __enter__(self):
        if os.path.exists(self.pidfile):
            pid = None
            with open(self.pidfile) as f:
                pid = self._check()
                if pid:
                    self.pidfd = None
                    raise ProcessRunningException(
                        f'process already running in {self.pidfile} as {pid}')
                else:
                    os.remove(self.pidfile)
                    self.pidfd = f

            if pid:
                ProcessRunningException(
                    f'process already running in {self.pidfile} as {pid}')

        try:
            with open(self.pidfile, 'w+') as f:
                f.write(str(os.getpid()))
        except OSError:
            ZELogger.log(
                {
                    "level": "EXCEPTION",
                    "message": f"Cannot write to pidfile {self.pidfile}"
                },
                exit_on_error=True)

        return self
Пример #4
0
def apply_settings_to_child_datasets(be_child_datasets_list, be_requested,
                                     verbose):

    canmount_setting = "canmount=noauto"
    for ds in be_child_datasets_list:
        if be_requested == ds:
            try:
                pyzfscmds.cmd.zfs_set(ds, canmount_setting)
            except RuntimeError:
                ZELogger.log(
                    {
                        "level":
                        "EXCEPTION",
                        "message":
                        f"Failed to set {canmount_setting} for {ds}\n{e}\n"
                    },
                    exit_on_error=True)

            if pyzfscmds.utility.is_clone(ds):
                try:
                    pyzfscmds.cmd.zfs_promote(ds)
                except RuntimeError:
                    ZELogger.log(
                        {
                            "level": "EXCEPTION",
                            "message": f"Failed to promote BE {ds}\n{e}\n"
                        },
                        exit_on_error=True)
                ZELogger.verbose_log(
                    {
                        "level": "INFO",
                        "message": f"Promoted {ds}.\n"
                    }, verbose)
Пример #5
0
 def plugin_property_error(self, prop):
     ZELogger.log({
         "level": "EXCEPTION",
         "message": (f"To use the {self.bootloader} plugin, use default{prop}, or set props\n"
                     f"To set it use the command (replacing with your pool and dataset)\n'"
                     f"zfs set org.zedenv:{prop}='<new mount>' zpool/ROOT/default\n")
     }, exit_on_error=True)
Пример #6
0
    def modify_bootloader(self, temp_boot: str):

        real_kernel_dir = os.path.join(self.zedenv_properties["boot"], "env")
        temp_kernel_dir = os.path.join(temp_boot, "env")

        real_old_dataset_kernel = os.path.join(real_kernel_dir, self.old_entry)
        temp_new_dataset_kernel = os.path.join(temp_kernel_dir, self.new_entry)

        if not os.path.isdir(real_old_dataset_kernel):
            ZELogger.log({
                "level":
                "INFO",
                "message":
                (f"No directory for Boot environments kernels found at "
                 f"'{real_old_dataset_kernel}', creating empty directory."
                 f"Don't forget to add your kernel to "
                 f"{real_kernel_dir}/zedenv-{self.boot_environment}.")
            })
            if not self.noop:
                try:
                    os.makedirs(temp_new_dataset_kernel)
                except PermissionError as e:
                    ZELogger.log(
                        {
                            "level":
                            "EXCEPTION",
                            "message":
                            f"Require Privileges to write to {temp_new_dataset_kernel}\n{e}"
                        },
                        exit_on_error=True)
                except OSError as os_err:
                    ZELogger.log({
                        "level": "EXCEPTION",
                        "message": os_err
                    },
                                 exit_on_error=True)
        else:
            if not self.noop:
                try:
                    shutil.copytree(real_old_dataset_kernel,
                                    temp_new_dataset_kernel)
                except PermissionError as e:
                    ZELogger.log(
                        {
                            "level":
                            "EXCEPTION",
                            "message":
                            f"Require Privileges to write to {temp_new_dataset_kernel}\n{e}"
                        },
                        exit_on_error=True)
                except IOError as e:
                    ZELogger.log(
                        {
                            "level":
                            "EXCEPTION",
                            "message":
                            f"IOError writing to {temp_new_dataset_kernel}\n{e}"
                        },
                        exit_on_error=True)
Пример #7
0
 def plugin_property_error(self, prop):
     ZELogger.log({
         "level": "EXCEPTION",
         "message": (f"To use the {self.bootloader} plugin, use the default setting '{prop}', "
                     f"or set a different value\n. To set it use the command (replacing with "
                     f"your pool and dataset)\n'zedenv set "
                     f"org.zedenv.{self.bootloader}:{prop}='<new mount>'\n")
     }, exit_on_error=True)
Пример #8
0
def cli(verbose: Optional[bool],
        zedenv_properties: Optional[list]):

    try:
        zedenv.lib.check.startup_check()
    except RuntimeError as err:
        ZELogger.log({"level": "EXCEPTION", "message": err}, exit_on_error=True)

    zedenv_set(verbose, zedenv_properties, zedenv.lib.be.root())
Пример #9
0
def properties(dataset, appended_properties: Optional[list]) -> list:
    dataset_properties = None
    try:
        dataset_properties = pyzfscmds.cmd.zfs_get(
            dataset,
            columns=["property", "value"],
            source=["local", "received"],
            properties=["all"])
    except RuntimeError:
        ZELogger.log(
            {
                "level": "EXCEPTION",
                "message": f"Failed to get properties of '{dataset}'"
            },
            exit_on_error=True)
    """
    Take each line of output containing properties and convert
    it to a list of property=value strings
    """
    dp = [line.split() for line in dataset_properties.splitlines()]
    remove_props = [rp[0] for rp in appended_properties]
    used_props = ["=".join(p) for p in dp if p[0] not in remove_props]

    used_props.extend(["=".join(pa) for pa in appended_properties])

    # Make sure that the mountpoint is correct even if we are in a chroot environment.
    # In this case, the ZFS pool is mounted with an alternative root (e.g. to `/mnt`).
    rpool = zedenv.lib.be.dataset_pool(dataset)
    altroot = None
    try:
        altroot = pyzfscmds.cmd.zpool_get(rpool,
                                          columns=["value"],
                                          properties=["altroot"])
    except RuntimeError:
        ZELogger.log(
            {
                "level": "EXCEPTION",
                "message": f"Failed to get properties of '{dataset}'"
            },
            exit_on_error=True)

    if altroot.strip() != '-':
        # Search and remove the alternative root at the beginning of the mountpoint
        for i, p in enumerate(used_props):
            prop, val = p.split("=")
            if prop != "mountpoint":
                continue

            alt_len, mp_len = len(altroot), len(val)
            if (mp_len >= alt_len) and (val[:alt_len] == altroot):
                mountpoint = "mountpoint=/"
                if mp_len != alt_len:
                    mountpoint = mountpoint + val[alt_len:]
                used_props[i] = mountpoint

    return used_props
Пример #10
0
    def post_activate(self):
        canmount_setting = "canmount=noauto" if self.zfs_be else "canmount=on"

        try:
            pyzfscmds.cmd.zfs_set(f"{self.be_root}/{self.boot_environment}", canmount_setting)
        except RuntimeError:
            ZELogger.log({
                "level": "EXCEPTION",
                "message": f"Failed to set {canmount_setting} for {ds}\n{e}\n"
            }, exit_on_error=True)
Пример #11
0
def cli(boot_environment: str, mountpoint: Optional[list],
        verbose: Optional[bool]):
    try:
        zedenv.lib.check.startup_check()
    except RuntimeError as err:
        ZELogger.log({
            "level": "EXCEPTION",
            "message": err
        },
                     exit_on_error=True)

    be_root = zedenv.lib.be.root()
    dataset_mountpoint = pyzfscmds.system.agnostic.dataset_mountpoint(
        f"{be_root}/{boot_environment}")

    if not pyzfscmds.utility.dataset_exists(f"{be_root}/{boot_environment}"):
        ZELogger.log(
            {
                "level": "EXCEPTION",
                "message":
                f"Boot environment doesn't exist {boot_environment}.\n"
            },
            exit_on_error=True)

    if dataset_mountpoint:
        if dataset_mountpoint == "/":
            ZELogger.log(
                {
                    "level": "EXCEPTION",
                    "message": f"Cannot Mount root dataset.\n"
                },
                exit_on_error=True)
        ZELogger.log(
            {
                "level": "EXCEPTION",
                "message": f"Dataset already mounted to {dataset_mountpoint}\n"
            },
            exit_on_error=True)

    real_mountpoint = None
    if mountpoint:
        if len(mountpoint) > 1:
            ZELogger.log(
                {
                    "level":
                    "EXCEPTION",
                    "message":
                    f"Boot environments can only view mounted to one location at once.\n"
                },
                exit_on_error=True)
        real_mountpoint = mountpoint[0]

    zedenv_mount(boot_environment, real_mountpoint, verbose, be_root)
Пример #12
0
    def _loader_replace(self, configs: list):
        be_dataset = f"{self.be_root}/{self.boot_environment}"

        target = re.compile(r'^vfs.root.mountfrom=.*$')

        for c in configs:
            with open(c, "r") as loader_conf:
                conf_list = loader_conf.readlines()

            line_nums = [
                l for l, val in enumerate(conf_list) if target.search(val)
            ]

            for lnum in line_nums:
                conf_list[lnum] = f"vfs.root.mountfrom={be_dataset}\n"

            if not self.noop:
                if os.path.isfile(c):
                    ZELogger.verbose_log(
                        {
                            "level":
                            "INFO",
                            "message":
                            (f"File {c} already exists, backed up to "
                             f"'{c}.bak' and replaced.\n")
                        }, self.verbose)
                    if os.path.isfile(f"{c}.bak"):
                        try:
                            os.remove(f"{c}.bak")
                        except PermissionError:
                            ZELogger.log(
                                {
                                    "level":
                                    "EXCEPTION",
                                    "message":
                                    (f"Require Privileges to remove "
                                     f"'{c}.bak'\n")
                                },
                                exit_on_error=True)
                    try:
                        shutil.move(c, f"{c}.bak")
                    except PermissionError:
                        ZELogger.log(
                            {
                                "level":
                                "EXCEPTION",
                                "message": (f"Require Privileges to write to "
                                            f"'{c}.bak'\n")
                            },
                            exit_on_error=True)

                with open(c, "w") as loader_conf:
                    loader_conf.writelines(conf_list)
Пример #13
0
def cli(boot_environment: str, verbose: Optional[bool]):
    try:
        zedenv.lib.check.startup_check()
    except RuntimeError as err:
        ZELogger.log({"level": "EXCEPTION", "message": err}, exit_on_error=True)

    be_root = zedenv.lib.be.root()
    dataset_mountpoint = pyzfscmds.system.agnostic.dataset_mountpoint(
        f"{be_root}/{boot_environment}")

    if not pyzfscmds.utility.dataset_exists(f"{be_root}/{boot_environment}"):
        ZELogger.log({
            "level": "EXCEPTION",
            "message": f"Boot environment doesn't exist {boot_environment}.\n"
        }, exit_on_error=True)

    if dataset_mountpoint == "/":
        ZELogger.log({
            "level": "EXCEPTION",
            "message": f"Cannot Unmount root dataset.\n"
        }, exit_on_error=True)

    if not dataset_mountpoint:
        ZELogger.log({
            "level": "EXCEPTION",
            "message": f"Boot environment already un-mounted\n"
        }, exit_on_error=True)

    zedenv_umount(boot_environment, verbose, be_root)
Пример #14
0
    def check_zedenv_properties(self):
        """
        Get zedenv properties in format:
            {"property": <property val>}
        If prop unset, leave default
        """
        for prop in self.zedenv_properties:
            prop_val = zedenv.lib.be.get_property(
                    "/".join([self.be_root, self.boot_environment]),
                    f"org.zedenv:{prop}")

            if prop_val is not None and prop_val != "-":
                self.zedenv_properties[prop] = prop_val

            ZELogger.log({"level": "INFO", "message": f"Found: {prop}"})
Пример #15
0
def cli(boot_environment: str, verbose: Optional[bool],
        bootloader: Optional[str], noconfirm: Optional[bool],
        noop: Optional[bool]):

    try:
        zedenv.lib.check.startup_check()
    except RuntimeError as err:
        ZELogger.log({
            "level": "EXCEPTION",
            "message": err
        },
                     exit_on_error=True)

    try:
        with zedenv.lib.check.Pidfile():

            boot_environment_root = zedenv.lib.be.root()

            bootloader_set = zedenv.lib.be.get_property(
                boot_environment_root, "org.zedenv:bootloader")
            if not bootloader and bootloader_set:
                if bootloader_set != '-':
                    bootloader = bootloader_set

            if not bootloader:
                ZELogger.log({
                    "level":
                    "WARNING",
                    "message":
                    ("WARNING: Running activate without a bootloader. "
                     "Re-run with a default bootloader, or with the "
                     "'--bootloader/-b' flag. If you plan to manually edit your "
                     "bootloader config this message can safely be ignored.\n")
                })

                if noconfirm:
                    sys.exit(
                        "The '--noconfirm/-y' flag requires the bootloader option "
                        "'--bootloader/-b'.")

            zedenv_activate(boot_environment, boot_environment_root, verbose,
                            bootloader, noconfirm, noop)

    except IOError as e:
        if e[0] == errno.EPERM:
            ZELogger.log(
                {
                    "level": "EXCEPTION",
                    "message": "You need root permissions to activate"
                },
                exit_on_error=True)
    except zedenv.lib.check.ProcessRunningException as pr:
        ZELogger.log(
            {
                "level": "EXCEPTION",
                "message": f"Already running activate.\n {pr}"
            },
            exit_on_error=True)
Пример #16
0
def zedenv_set(verbose: Optional[bool], zedenv_properties: Optional[list], be_root: str):

    for prop in zedenv_properties:
        try:
            pyzfscmds.cmd.zfs_set(be_root, prop)
        except RuntimeError:
            ZELogger.log({
                "level": "EXCEPTION",
                "message": f"Failed to set zedenv property '{prop}'\n"
            }, exit_on_error=True)

        if verbose:
            ZELogger.verbose_log({
                "level": "INFO",
                "message": f"Set '{prop}' successfully"
            }, verbose)
Пример #17
0
def cli(boot_environment: str, verbose: Optional[bool],
        existing: Optional[str]):
    try:
        zedenv.lib.check.startup_check()
    except RuntimeError as err:
        ZELogger.log({
            "level": "EXCEPTION",
            "message": err
        },
                     exit_on_error=True)

    parent_dataset = zedenv.lib.be.root()
    root_dataset = pyzfscmds.system.agnostic.mountpoint_dataset("/")

    zedenv_create(parent_dataset, root_dataset, boot_environment, verbose,
                  existing)
Пример #18
0
    def __init__(self, zedenv_data: dict):

        for k in zedenv_data:
            if k not in plugin_config.allowed_keys:
                raise ValueError(f"Type {k} is not in allowed keys")

        self.boot_environment = zedenv_data['boot_environment']
        self.old_boot_environment = zedenv_data['old_boot_environment']
        self.bootloader = zedenv_data['bootloader']
        self.verbose = zedenv_data['verbose']
        self.noconfirm = zedenv_data['noconfirm']
        self.noop = zedenv_data['noop']
        self.be_root = zedenv_data['boot_environment_root']

        self.env_dir = "env"
        self.boot_mountpoint = "/boot"

        self.entry_prefix = "zedenv"

        self.old_entry = f"{self.entry_prefix}-{self.old_boot_environment}"
        self.new_entry = f"{self.entry_prefix}-{self.boot_environment}"

        esp = zedenv.lib.be.get_property(
            "/".join([self.be_root, self.boot_environment]), "org.zedenv:esp")
        if esp is None or esp == "-":
            self.esp = "/mnt/efi"
        else:
            self.esp = esp
        ZELogger.verbose_log(
            {
                "level": "INFO",
                "message": f"esp set to {esp}\n"
            }, self.verbose)

        if not os.path.isdir(self.esp):
            ZELogger.log(
                {
                    "level":
                    "EXCEPTION",
                    "message":
                    ("To use the systemdboot plugin, an 'esp' must be mounted at the "
                     "default location of `/mnt/esp`, or at another location, with the "
                     "property 'org.zedenv:esp' set on the dataset. To set it use the "
                     "command (replacing with your pool and dataset)\n'"
                     "zfs set org.zedenv:esp='/mnt/efi' zpool/ROOT/default\n")
                },
                exit_on_error=True)
Пример #19
0
def zedenv_umount(boot_environment: str, verbose: bool, be_root: str):
    boot_environment_dataset = f"{be_root}/{boot_environment}"
    child_datasets_unformatted = None
    try:
        child_datasets_unformatted = pyzfscmds.cmd.zfs_list(
            boot_environment_dataset,
            sort_properties_descending=['name'],
            recursive=True,
            columns=['name'])
    except RuntimeError:
        ZELogger.log(
            {
                "level":
                "EXCEPTION",
                "message":
                f"Failed to get list of datasets for '{boot_environment}'.\n{e}"
            },
            exit_on_error=True)

    for d in zedenv.lib.be.split_zfs_output(child_datasets_unformatted):
        mountpoint = pyzfscmds.system.agnostic.dataset_mountpoint(d[0])
        if mountpoint:
            try:
                zedenv.lib.system.umount(mountpoint)
            except RuntimeError as e:
                ZELogger.log(
                    {
                        "level":
                        "EXCEPTION",
                        "message":
                        f"Failed Un-mounting child dataset from '{mountpoint}'.\n{e}"
                    },
                    exit_on_error=True)
            ZELogger.verbose_log(
                {
                    "level": "INFO",
                    "message": f"Unmounted {d[0]} from {mountpoint}.\n"
                }, verbose)
        else:
            ZELogger.verbose_log(
                {
                    "level":
                    "INFO",
                    "message":
                    f"Child dataset {d[0]} wasn't mounted, won't unmount.\n"
                }, verbose)
Пример #20
0
def cli(
        boot_environment: str,
        verbose: Optional[bool],
        # unmount: Optional[bool],
        noconfirm: Optional[bool],
        noop: Optional[bool]):
    try:
        zedenv.lib.check.startup_check()
    except RuntimeError as err:
        ZELogger.log({
            "level": "EXCEPTION",
            "message": err
        },
                     exit_on_error=True)

    zedenv_destroy(boot_environment, zedenv.lib.be.root(),
                   pyzfscmds.system.agnostic.mountpoint_dataset("/"), verbose,
                   noconfirm, noop)
Пример #21
0
def cli(zedenv_properties: Optional[list],
        scripting: Optional[bool],
        recursive: Optional[bool],
        defaults: Optional[bool]):

    try:
        zedenv.lib.check.startup_check()
    except RuntimeError as err:
        ZELogger.log({"level": "EXCEPTION", "message": err}, exit_on_error=True)

    formatted_list_entries = zedenv_get(zedenv_properties,
                                        scripting,
                                        recursive,
                                        defaults,
                                        zedenv.lib.be.root())

    for k in formatted_list_entries:
        ZELogger.log({"level": "INFO", "message": k})
Пример #22
0
def snapshot(boot_environment_name,
             boot_environment_root,
             snap_prefix: Optional[str] = None,
             snap_suffix_time_format: str = "%Y-%m-%d-%H-%f") -> str:
    """
    Recursively Snapshot BE
    :param boot_environment_name: Name of BE to snapshot.
    :param boot_environment_root: Root dataset for BEs.
    :param snap_prefix: Prefix on snapshot names.
    :param snap_suffix_time_format: Suffix on snapshot names.
    :return: Name of snapshot without dataset.
    """
    if "/" in boot_environment_name:
        ZELogger.log(
            {
                "level":
                "EXCEPTION",
                "message": ("Failed to get snapshot.\n",
                            "Existing boot environment name ",
                            f"{boot_environment_name} should not contain '/'")
            },
            exit_on_error=True)

    dataset_name = f"{boot_environment_root}/{boot_environment_name}"

    with zedenv.lib.system.setlocale():
        suffix_time = datetime.datetime.now().strftime(snap_suffix_time_format)
    full_snap_suffix = f"{snap_prefix}-{suffix_time}" if snap_prefix else suffix_time

    try:
        pyzfscmds.cmd.zfs_snapshot(dataset_name,
                                   full_snap_suffix,
                                   recursive=True)
    except RuntimeError:
        ZELogger.log(
            {
                "level":
                "EXCEPTION",
                "message":
                f"Failed to create snapshot: '{dataset_name}@{full_snap_suffix}'"
            },
            exit_on_error=True)

    return full_snap_suffix
Пример #23
0
def activate_boot_environment(be_requested: str,
                              dataset_mountpoint: Optional[str],
                              verbose: Optional[bool], noop: Optional[bool],
                              bootloader_plugin):

    if dataset_mountpoint != "/":
        if dataset_mountpoint:
            ZELogger.verbose_log(
                {
                    "level": "INFO",
                    "message": f"Unmounting {dataset_mountpoint}.\n"
                }, verbose)

            if not noop:
                try:
                    zedenv.lib.system.umount(dataset_mountpoint)
                except RuntimeError as e:
                    ZELogger.log(
                        {
                            "level":
                            "EXCEPTION",
                            "message":
                            f"Failed unmounting dataset {be_requested}\n{e}\n"
                        },
                        exit_on_error=True)

        mount_and_modify_dataset(be_requested,
                                 pre_mount_properties=["canmount=noauto"],
                                 post_mount_properties=["mountpoint=/"],
                                 verbose=verbose,
                                 noop=noop,
                                 plugin=bootloader_plugin)

    if not noop:
        try:
            pyzfscmds.cmd.zpool_set(zedenv.lib.be.dataset_pool(be_requested),
                                    f"bootfs={be_requested}")
        except RuntimeError as e:
            ZELogger.log(
                {
                    "level": "EXCEPTION",
                    "message": f"Failed to set bootfs to {be_requested}\n{e}\n"
                },
                exit_on_error=True)
Пример #24
0
def cli(boot_environment: str, verbose: Optional[bool],
        bootloader: Optional[str], noconfirm: Optional[bool],
        noop: Optional[bool]):

    if noconfirm and not bootloader:
        sys.exit(
            "The '--noconfirm/-y' flag requires the bootloader option '--bootloader/-b'."
        )

    try:
        zedenv.lib.check.startup_check()
    except RuntimeError as err:
        ZELogger.log({
            "level": "EXCEPTION",
            "message": err
        },
                     exit_on_error=True)

    zedenv_activate(boot_environment, zedenv.lib.be.root(), verbose,
                    bootloader, noconfirm, noop)
Пример #25
0
def get_origin_snapshots(destroy_dataset: str) -> list:
    origin_all_snaps = None
    try:
        origin_all_snaps = pyzfscmds.cmd.zfs_list(
            destroy_dataset,
            recursive=True,
            columns=['origin'],
            zfs_types=['filesystem', 'snapshot', 'volume'])
    except RuntimeError as e:
        ZELogger.log(
            {
                "level":
                "EXCEPTION",
                "message":
                f"Failed to list origin snapshots for '{destroy_dataset}'.\n{e}"
            },
            exit_on_error=True)

    split_snaps = zedenv.lib.be.split_zfs_output(origin_all_snaps)
    return [ds[0].rstrip() for ds in split_snaps if ds[0].rstrip() != '-']
Пример #26
0
def zedenv_list(
        verbose: Optional[bool],
        # alldatasets: Optional[bool],
        spaceused: Optional[bool],
        scripting: Optional[bool],
        # snapshots: Optional[bool],
        origin: Optional[bool],
        be_root: str):
    """
    Main list command. Separate for testing.
    """
    ZELogger.verbose_log(
        {
            "level": "INFO",
            "message": "Listing Boot Environments:\n"
        }, verbose)

    columns = ["name"]

    # TODO: Complete
    # if spaceused:
    #     columns.extend(["used", "usedds", "usedbysnapshots", "usedrefreserv", "refer"])
    """
    TODO:
    if all_datasets:

    if snapshots:
    """

    if origin:
        columns.append("origin")

    columns.append("creation")

    boot_environments = configure_boot_environment_list(
        be_root, columns, scripting)

    for list_output in boot_environments:
        ZELogger.log({"level": "INFO", "message": list_output})
Пример #27
0
def mount_children(child_datasets: list, mountpoint: str, verbose: bool):
    for cd in child_datasets:
        if cd['mountpoint'] == "none" or cd['mountpoint'] == "legacy":
            ZELogger.verbose_log(
                {
                    "level":
                    "INFO",
                    "message": (f"Skipped mounting dataset {cd['name']} "
                                f"since mountpoint is {cd['mountpoint']}.\n")
                }, verbose)
        else:
            if cd['source'] == 'local':
                child = pyzfscmds.utility.dataset_child_name(
                    cd['name'], check_exists=False)
                new_mount = os.path.join(mountpoint, child.lstrip('/'))
            else:
                new_mount = os.path.join(mountpoint,
                                         cd['mountpoint'].lstrip('/'))

            if not os.path.exists(new_mount):
                os.makedirs(new_mount)

            try:
                zedenv.lib.system.zfs_manual_mount(cd['name'], new_mount)
            except RuntimeError as e:
                ZELogger.log(
                    {
                        "level":
                        "EXCEPTION",
                        "message":
                        f"Failed mounting child dataset to '{new_mount}'.\n{e}"
                    },
                    exit_on_error=True)
            ZELogger.verbose_log(
                {
                    "level": "INFO",
                    "message":
                    f"Mounted dataset {cd['name']} to '{new_mount}'.\n"
                }, verbose)
Пример #28
0
def destroy_origin_snapshots(destroy_dataset, be_pool, origin_snaps, noop,
                             verbose):
    # destroy origin snapshots used by destroy_dataset
    snapshots = None
    try:
        snapshots = pyzfscmds.cmd.zfs_list(be_pool,
                                           recursive=True,
                                           columns=['name'],
                                           zfs_types=['snapshot'])
    except RuntimeError:
        ZELogger.log(
            {
                "level":
                "EXCEPTION",
                "message":
                f"Failed to list origins snapshots of '{destroy_dataset}'.\n"
            },
            exit_on_error=True)
    snapshots_list = zedenv.lib.be.split_zfs_output(snapshots)

    for ors in origin_snaps:
        for ol in snapshots_list:
            snap = ol[0].rstrip()
            if ors == snap:
                if not noop:
                    try:
                        pyzfscmds.cmd.zfs_destroy_snapshot(snap)
                    except RuntimeError:
                        ZELogger.log(
                            {
                                "level": "EXCEPTION",
                                "message": f"Failed to destroy {snap}\n"
                            },
                            exit_on_error=True)
                ZELogger.verbose_log(
                    {
                        "level": "INFO",
                        "message": f"Destroyed {snap}.\n"
                    }, verbose)
Пример #29
0
def disable_children_automount(be_child_datasets: List[str], be_requested: str,
                               boot_environment_root: str,
                               verbose: Optional[bool]):
    """
    Dont run if noop
    """
    for ds in be_child_datasets:
        if not (be_requested in ds) and not (boot_environment_root == ds):
            try:
                pyzfscmds.cmd.zfs_set(ds, "canmount=noauto")
            except RuntimeError as e:
                ZELogger.log(
                    {
                        "level": "EXCEPTION",
                        "message":
                        f"Failed to set canmount=noauto on {ds}\n{e}\n"
                    },
                    exit_on_error=True)
            ZELogger.verbose_log(
                {
                    "level": "INFO",
                    "message": f"Disabled automount for {ds}\n"
                }, verbose)
Пример #30
0
    def recurse_move(self, source, dest, overwrite=False):
        for tf in os.listdir(source):
            tf_path_src = os.path.join(source, tf)
            tf_path_dst = os.path.join(dest, tf)

            if os.path.isfile(tf_path_src):
                if os.path.isfile(tf_path_dst) and not overwrite:
                    ZELogger.verbose_log({
                        "level": "INFO",
                        "message": f"File {tf_path_dst} already exists, will not modify.\n"
                    }, self.verbose)
                else:
                    try:
                        shutil.copy(tf_path_src, tf_path_dst)
                    except PermissionError:
                        ZELogger.log({
                            "level": "EXCEPTION",
                            "message": f"Require Privileges to write to '{tf_path_dst}.'\n"
                        }, exit_on_error=True)
                    ZELogger.verbose_log({
                        "level": "INFO",
                        "message": f"Copied file {tf_path_src} -> {tf_path_dst}\n"
                    }, self.verbose)
            elif os.path.isdir(tf_path_src):
                if os.path.isdir(tf_path_dst) and not overwrite:
                    ZELogger.verbose_log({
                        "level": "INFO",
                        "message": f"Directory {tf_path_dst} already exists, will not modify.\n"
                    }, self.verbose)

                    # Call again, may be empty
                    self.recurse_move(tf_path_src, tf_path_dst, overwrite=overwrite)

                else:
                    if os.path.isdir(tf_path_dst):
                        shutil.move(tf_path_dst, f"{tf_path_dst}.bak")
                        ZELogger.verbose_log({
                            "level": "INFO",
                            "message": (f"Directory {tf_path_dst} already exists, "
                                        f"creating backup {tf_path_dst}.bak.\n")
                        }, self.verbose)
                    try:
                        shutil.copytree(tf_path_src, tf_path_dst)
                    except PermissionError as e:
                        ZELogger.log({
                            "level": "EXCEPTION",
                            "message": f"Require Privileges to write to {tf_path_dst}\n{e}"
                        }, exit_on_error=True)
                    except IOError as e:
                        ZELogger.log({
                            "level": "EXCEPTION",
                            "message": f"IOError writing to {tf_path_dst}\n{e}"
                        }, exit_on_error=True)
                    ZELogger.verbose_log({
                        "level": "INFO",
                        "message": f"Copied dir {tf_path_src} -> {tf_path_dst}\n"
                    }, self.verbose)