Example #1
0
def pkg_cmd(command, jail):
    """Runs pkg with the command given inside the specified jail."""
    lgr = logging.getLogger('ioc_cli_pkg')

    jails, paths = IOCList("uuid").list_datasets()
    _jail = {
        tag: uuid
        for (tag, uuid) in jails.items()
        if uuid.startswith(jail) or tag == jail
    }

    if len(_jail) == 1:
        tag, uuid = next(iter(_jail.items()))
        path = paths[tag]
    elif len(_jail) > 1:
        lgr.error("Multiple jails found for" " {}:".format(jail))
        for t, u in sorted(_jail.items()):
            lgr.error("  {} ({})".format(u, t))
        raise RuntimeError()
    else:
        raise RuntimeError("{} not found!".format(jail))

    cmd = ("pkg", ) + command

    IOCExec(cmd, uuid, tag, path).exec_jail()
Example #2
0
def export_cmd(jail):
    """Make a recursive snapshot of the jail and export to a file."""
    jails, paths = IOCList("uuid").list_datasets()
    _jail = {
        tag: uuid
        for (tag, uuid) in jails.items()
        if uuid.startswith(jail) or tag == jail
    }

    if len(_jail) == 1:
        tag, uuid = next(iter(_jail.items()))
        path = paths[tag]
    elif len(_jail) > 1:
        lgr.error("Multiple jails found for" " {}:".format(jail))
        for t, u in sorted(_jail.items()):
            lgr.error("  {} ({})".format(u, t))
        raise RuntimeError()
    else:
        lgr.critical("{} not found!".format(jail))
        exit(1)

    status, _ = IOCList().list_get_jid(uuid)
    if status:
        lgr.critical("{} ({}) is runnning, stop the jail before "
                     "exporting!".format(uuid, tag))
        exit(1)

    IOCImage(callback=callback).export_jail(uuid, tag, path)
Example #3
0
def destroy_cmd(force, jails):
    """Destroys the jail's 2 datasets and the snapshot from the RELEASE."""
    lgr = logging.getLogger('ioc_cli_destroy')

    if jails:
        get_jid = IOCList().list_get_jid

        try:
            jail_list, paths = IOCList("uuid").list_datasets()
        except RuntimeError as err:
            err = str(err)

            if "Configuration is missing" in err:
                uuid = err.split()[6]
                pool = IOCJson().json_get_value("pool")
                path = f"{pool}/iocage/jails/{uuid}"

                IOCDestroy().__stop_jails__(path.replace(pool, ""))
                IOCDestroy().__destroy_datasets__(path)
                exit()
            else:
                raise RuntimeError(err)

        for jail in jails:
            _jail = {
                tag: uuid
                for (tag, uuid) in jail_list.items()
                if uuid.startswith(jail) or tag == jail
            }

            if len(_jail) == 1:
                tag, uuid = next(iter(_jail.items()))
                path = paths[tag]
            elif len(_jail) > 1:
                lgr.error("Multiple jails found for" " {}:".format(jail))
                for t, u in sorted(_jail.items()):
                    lgr.error("  {} ({})".format(u, t))
                raise RuntimeError()
            else:
                raise RuntimeError("{} not found!".format(jail))

            if not force:
                lgr.warning("\nWARNING: This will destroy"
                            " jail {} ({})".format(uuid, tag))

                if not click.confirm("\nAre you sure?"):
                    continue  # no, continue to next jail

            status, _ = get_jid(uuid)

            # If the jail is not running, let's do this thing.
            if status and not force:
                raise RuntimeError(f"{uuid} ({tag}) is running.\nPlease stop "
                                   "it first!")
            elif status and force:
                lgr.info("Stopping {} ({}).".format(uuid, tag))

            IOCDestroy().destroy_jail(path)
    else:
        raise RuntimeError("Please specify one or more jails!")
Example #4
0
def restart_cmd(jail, soft):
    """
    Looks for the jail supplied and passes the uuid, path and configuration
    location to stop_jail and start_jail.
    """
    jails, paths = IOCList("uuid").list_datasets()

    if jail == "ALL":
        for j in jails:
            uuid = jails[j]
            path = paths[j]

            check_type(uuid, j, path, True, soft)
    else:
        _jail = {
            tag: uuid
            for (tag, uuid) in jails.items()
            if uuid.startswith(jail) or tag == jail
        }

        if len(_jail) == 1:
            tag, uuid = next(iter(_jail.items()))
            path = paths[tag]

            check_type(uuid, tag, path, False, soft)
        elif len(_jail) > 1:
            lgr.error("Multiple jails found for" " {}:".format(jail))
            for t, u in sorted(_jail.items()):
                lgr.error("  {} ({})".format(u, t))
            raise RuntimeError()
        else:
            lgr.critical("{} not found!".format(jail))
            exit(1)
Example #5
0
def snapremove_cmd(jail, name):
    """Removes a snapshot from a user supplied jail."""
    lgr = ioc_logger.Logger('ioc_cli_snapremove').getLogger()

    jails, paths = IOCList("uuid").list_datasets()
    pool = IOCJson().json_get_value("pool")
    _jail = {tag: uuid for (tag, uuid) in jails.items() if
             uuid.startswith(jail) or tag == jail}

    if len(_jail) == 1:
        tag, uuid = next(iter(_jail.items()))
        path = paths[tag]
    elif len(_jail) > 1:
        lgr.error("Multiple jails found for"
                  " {}:".format(jail))
        for t, u in sorted(_jail.items()):
            lgr.critical("  {} ({})".format(u, t))
        exit(1)
    else:
        lgr.critical("{} not found!".format(jail))
        exit(1)

    # Looks like foo/iocage/jails/df0ef69a-57b6-4480-b1f8-88f7b6febbdf@BAR
    conf = IOCJson(path).json_load()

    if conf["template"] == "yes":
        target = "{}/iocage/templates/{}@{}".format(pool, tag, name)
    else:
        target = "{}/iocage/jails/{}@{}".format(pool, uuid, name)

    try:
        check_call(["zfs", "destroy", "-r", "-f", target])
        lgr.info("Snapshot: {} destroyed.".format(target))
    except CalledProcessError as err:
        lgr.error("{}".format(err))
Example #6
0
def chroot_cmd(jail, command):
    """Will chroot into a jail regardless if it's running."""
    lgr = logging.getLogger('ioc_cli_chroot')
    jails, paths = IOCList("uuid").list_datasets()
    command = list(command)

    # We may be getting ';', '&&' and so forth. Adding the shell for safety.
    if len(command) == 1:
        command = ["/bin/sh", "-c"] + command

    if jail.startswith("-"):
        raise RuntimeError("Please specify a jail first!")

    _jail = {
        tag: uuid
        for (tag, uuid) in jails.items()
        if uuid.startswith(jail) or tag == jail
    }

    if len(_jail) == 1:
        tag, uuid = next(iter(_jail.items()))
        path = paths[tag]

    elif len(_jail) > 1:
        lgr.error("Multiple jails found for" " {}:".format(jail))
        for t, u in sorted(_jail.items()):
            lgr.error("  {} ({})".format(u, t))
        raise RuntimeError()
    else:
        raise RuntimeError("{} not found!".format(jail))

    devfs_stderr = mount(f"{path}/root/dev", "devfs")

    if devfs_stderr:
        raise RuntimeError("ERROR: Mounting devfs failed!")

    fstab_stderr = mount(f"{path}/fstab", "fstab")

    if fstab_stderr:
        raise RuntimeError("ERROR: Mounting devfs failed!")

    chroot = Popen(["chroot", f"{path}/root"] + command)
    chroot.communicate()

    udevfs_stderr = umount(f"{path}/root/dev", "devfs")
    if udevfs_stderr:
        raise RuntimeError("ERROR: Unmounting devfs failed!")

    ufstab_stderr = umount(f"{path}/fstab", "fstab")
    if ufstab_stderr:
        if b"fstab reading failure\n" in ufstab_stderr:
            # By default our fstab is empty and will throw this error.
            pass
        else:
            raise RuntimeError("ERROR: Unmounting fstab failed!")

    if chroot.returncode:
        lgr.warning("WARNING: Chroot had a non-zero exit code!")
Example #7
0
def rollback_cmd(jail, name, force):
    """Get a list of jails and print the property."""
    lgr = ioc_logger.Logger('ioc_cli_rollback').getLogger()

    jails, paths = IOCList("uuid").list_datasets()
    pool = IOCJson().json_get_value("pool")

    _jail = {
        tag: uuid
        for (tag, uuid) in jails.items()
        if uuid.startswith(jail) or tag == jail
    }

    if len(_jail) == 1:
        tag, uuid = next(iter(_jail.items()))
        path = paths[tag]
    elif len(_jail) > 1:
        lgr.error("Multiple jails found for" f" {jail}:")
        for t, u in sorted(_jail.items()):
            lgr.error(f"  {u} ({t})")
        raise RuntimeError()
    else:
        lgr.critical(f"{jail} not found!")
        exit(1)

    # Looks like foo/iocage/jails/df0ef69a-57b6-4480-b1f8-88f7b6febbdf@BAR
    conf = IOCJson(path).json_load()

    if conf["template"] == "yes":
        target = f"{pool}/iocage/templates/{tag}"
    else:
        target = f"{pool}/iocage/jails/{uuid}"

    try:
        checkoutput(["zfs", "get", "-H", "creation", target], stderr=PIPE)
    except CalledProcessError:
        lgr.critical(f"Snapshot {target} does not exist!")
        exit(1)

    if not force:
        lgr.warning("\nThis will destroy ALL data created since"
                    f" {name} was taken.\nIncluding ALL snapshots taken after"
                    f" {name} for {uuid} ({tag})")
        if not click.confirm("\nAre you sure?"):
            exit()
    try:
        datasets = Popen(["zfs", "list", "-H", "-r", "-o", "name", target],
                         stdout=PIPE,
                         stderr=PIPE).communicate()[0].decode("utf-8").split()

        for dataset in datasets:
            check_call(["zfs", "rollback", "-r", f"{dataset}@{name}"])

        lgr.info(f"Rolled back to: {target}")
    except CalledProcessError as err:
        lgr.error(f"{err}")
        exit(1)
Example #8
0
def console_cmd(jail, force):
    """
    Runs jexec to login into the specified jail. Accepts a force flag that
    will attempt to start the jail if it is not already running.
    """
    lgr = ioc_logger.Logger('ioc_cli_console').getLogger()
    jails, paths = IOCList("uuid").list_datasets()

    _jail = {tag: uuid for (tag, uuid) in jails.items() if
             uuid.startswith(jail) or tag == jail}

    if len(_jail) == 1:
        tag, uuid = next(iter(_jail.items()))
        path = paths[tag]

        iocjson = IOCJson(path)
        conf = iocjson.json_load()
        login_flags = conf["login_flags"].split()
        exec_fib = conf["exec_fib"]
        status, _ = IOCList().list_get_jid(uuid)
    elif len(_jail) > 1:
        lgr.error("Multiple jails found for"
                  " {}:".format(jail))
        for t, u in sorted(_jail.items()):
            lgr.critical("  {} ({})".format(u, t))
        exit(1)
    else:
        lgr.critical("{} not found!".format(jail))
        exit(1)

    if not status and not force:
        lgr.critical("{} ({}) is not running!".format(uuid, tag))
        exit(1)

    if not status and force:
        lgr.info("{} ({}) is not running".format(uuid, tag) +
                 ", starting jail.")
        if conf["type"] == "jail":
            IOCStart(uuid, jail, path, conf, silent=True)
            status = True
        elif conf["type"] == "basejail":
            lgr.critical("Please run \"iocage migrate\" before trying"
                         " to start {} ({})".format(uuid, tag))
            exit(1)
        elif conf["type"] == "template":
            lgr.critical("Please convert back to a jail before trying"
                         " to start {} ({})".format(uuid, tag))
            exit(1)
        else:
            lgr.critical("{} is not a supported jail type.".format(
                conf["type"]
            ))
            exit(1)

    if status:
        Popen(["setfib", exec_fib, "jexec", f"ioc-{uuid}", "login"] +
              login_flags).communicate()
Example #9
0
def rollback_cmd(jail, name, force):
    """Get a list of jails and print the property."""
    lgr = ioc_logger.Logger('ioc_cli_rollback').getLogger()

    jails, paths = IOCList("uuid").list_datasets()
    pool = IOCJson().json_get_value("pool")

    _jail = {
        tag: uuid
        for (tag, uuid) in jails.items()
        if uuid.startswith(jail) or tag == jail
    }

    if len(_jail) == 1:
        tag, uuid = next(iter(_jail.items()))
        path = paths[tag]
    elif len(_jail) > 1:
        lgr.error("Multiple jails found for" " {}:".format(jail))
        for t, u in sorted(_jail.items()):
            lgr.error("  {} ({})".format(u, t))
        raise RuntimeError()
    else:
        lgr.critical("{} not found!".format(jail))
        exit(1)

    # Looks like foo/iocage/jails/df0ef69a-57b6-4480-b1f8-88f7b6febbdf@BAR
    target = "{}{}@{}".format(pool, path, name)
    try:
        checkoutput(["zfs", "get", "-H", "creation", target], stderr=PIPE)
    except CalledProcessError:
        lgr.critical("Snapshot {} does not exist!".format(target))
        exit(1)

    if not force:
        lgr.warning("\nThis will destroy ALL data created since"
                    " {} was taken.".format(name) +
                    "\nIncluding ALL snapshots taken after"
                    " {} for {} ({}).".format(name, uuid, tag))
        if not click.confirm("\nAre you sure?"):
            exit()
    try:
        datasets = Popen([
            "zfs", "list", "-H", "-r", "-o", "name", "{}{}".format(pool, path)
        ],
                         stdout=PIPE,
                         stderr=PIPE).communicate()[0].decode("utf-8").split()

        for dataset in datasets:
            check_call(
                ["zfs", "rollback", "-r", "{}@{}".format(dataset, name)])

        lgr.info("Rolled back to: {}.".format(target))
    except CalledProcessError as err:
        lgr.error("{}".format(err))
        exit(1)
Example #10
0
def update_cmd(jail):
    """Runs update with the command given inside the specified jail."""
    lgr = ioc_logger.Logger('ioc_cli_update').getLogger()

    jails, paths = IOCList("uuid").list_datasets()
    _jail = {
        tag: uuid
        for (tag, uuid) in jails.items()
        if uuid.startswith(jail) or tag == jail
    }

    if len(_jail) == 1:
        tag, uuid = next(iter(_jail.items()))
        path = paths[tag]
    elif len(_jail) > 1:
        lgr.error("Multiple jails found for" " {}:".format(jail))
        for t, u in sorted(_jail.items()):
            lgr.critical("  {} ({})".format(u, t))
        exit(1)
    else:
        lgr.critical("{} not found!".format(jail))
        exit(1)

    freebsd_version = checkoutput(["freebsd-version"])
    status, jid = IOCList.list_get_jid(uuid)
    conf = IOCJson(path).json_load()
    started = False

    if conf["type"] == "jail":
        if not status:
            IOCStart(uuid, tag, path, conf, silent=True)
            status, jid = IOCList.list_get_jid(uuid)
            started = True
    elif conf["type"] == "basejail":
        lgr.critical("Please run \"iocage migrate\" before trying"
                     " to update {} ({})".format(uuid, tag))
        exit(1)
    elif conf["type"] == "template":
        lgr.critical("Please convert back to a jail before trying"
                     " to update {} ({})".format(uuid, tag))
        exit(1)
    else:
        lgr.critical("{} is not a supported jail type.".format(conf["type"]))
        exit(1)

    if "HBSD" in freebsd_version:
        Popen(["hbsd-update", "-j", jid]).communicate()

        if started:
            IOCStop(uuid, tag, path, conf, silent=True)
    else:
        IOCFetch(conf["cloned_release"]).fetch_update(True, uuid, tag)

        if started:
            IOCStop(uuid, tag, path, conf, silent=True)
Example #11
0
    def check_jail_existence(self, jail):
        self.check_dataset_existence()

        jails, paths = IOCList("uuid").list_datasets()
        _jail = {tag: uuid for (tag, uuid) in jails.items() if
                 uuid.startswith(jail) or tag == jail}

        if len(_jail) == 1:
            tag, uuid = next(iter(_jail.items()))
            path = paths[tag]

            return tag, uuid, path
        elif len(_jail) > 1:
            raise RuntimeError("Multiple jails found for {}:".format(jail))
        else:
            raise RuntimeError("{} not found!".format(jail))
Example #12
0
    def check_jail_existence(self, jail):
        self.check_dataset_existence()

        jails, paths = IOCList("uuid").list_datasets()
        _jail = {tag: uuid for (tag, uuid) in jails.items() if
                 uuid.startswith(jail) or tag == jail}

        if len(_jail) == 1:
            tag, uuid = next(iter(_jail.items()))
            path = paths[tag]

            return tag, uuid, path
        elif len(_jail) > 1:
            raise RuntimeError("Multiple jails found for {}:".format(jail))
        else:
            raise RuntimeError("{} not found!".format(jail))
Example #13
0
def set_cmd(prop, jail, plugin):
    """Get a list of jails and print the property."""
    lgr = ioc_logger.Logger('ioc_cli_set').getLogger()

    jails, paths = IOCList("uuid").list_datasets(set=True)
    _jail = {
        tag: uuid
        for (tag, uuid) in jails.items()
        if uuid.startswith(jail) or tag == jail
    }

    if len(_jail) == 1:
        tag, uuid = next(iter(_jail.items()))
        path = paths[tag]
        iocjson = IOCJson(path, cli=True)
    elif len(_jail) > 1:
        lgr.error("Multiple jails found for" " {}:".format(jail))
        for t, u in sorted(_jail.items()):
            lgr.error("  {} ({})".format(u, t))
        raise RuntimeError()
    else:
        lgr.critical("{} not found!".format(jail))
        exit(1)

    if "template" in prop.split("=")[0]:
        if "template" in path and prop != "template=no":
            lgr.critical("{} ({}) is already a template!".format(uuid, tag))
            exit(1)
        elif "template" not in path and prop != "template=yes":
            lgr.critical("{} ({}) is already a jail!".format(uuid, tag))
            exit(1)
    if plugin:
        _prop = prop.split(".")
        IOCJson(path, cli=True).json_plugin_set_value(_prop)
    else:
        try:
            # We use this to test if it's a valid property at all.
            _prop = prop.partition("=")[0]
            iocjson.json_get_value(_prop)

            # The actual setting of the property.
            iocjson.json_set_value(prop)
        except KeyError:
            _prop = prop.partition("=")[0]
            lgr.critical("{} is not a valid property!".format(_prop))
            exit(1)
Example #14
0
def exec_cmd(command, jail, host_user, jail_user):
    """Runs the command given inside the specified jail as the supplied
    user."""
    lgr = ioc_logger.Logger('ioc_cli_exec').getLogger()

    # We may be getting ';', '&&' and so forth. Adding the shell for safety.
    if len(command) == 1:
        command = ("/bin/sh", "-c") + command

    if jail.startswith("-"):
        lgr.critical("Please specify a jail first!")
        exit(1)

    if host_user and jail_user:
        lgr.critical("Please only specify either host_user or"
                     " jail_user, not both!")
        exit(1)

    jails, paths = IOCList("uuid").list_datasets()
    _jail = {
        tag: uuid
        for (tag, uuid) in jails.items()
        if uuid.startswith(jail) or tag == jail
    }

    if len(_jail) == 1:
        tag, uuid = next(iter(_jail.items()))
        path = paths[tag]
    elif len(_jail) > 1:
        lgr.error("Multiple jails found for" " {}:".format(jail))
        for t, u in sorted(_jail.items()):
            lgr.error("  {} ({})".format(u, t))
        raise RuntimeError()
    else:
        lgr.critical("{} not found!".format(jail))
        exit(1)

    msg, err = IOCExec(command, uuid, tag, path, host_user,
                       jail_user).exec_jail()

    if err:
        err = indent_lines(msg)
        lgr.error("{}".format(err))
    else:
        lgr.info(msg.decode("utf-8"))
Example #15
0
def snapshot_cmd(jail, name):
    """Get a list of jails and print the property."""
    lgr = ioc_logger.Logger('ioc_cli_snapshot').getLogger()

    jails, paths = IOCList("uuid").list_datasets()
    pool = IOCJson().json_get_value("pool")
    date = datetime.utcnow().strftime("%F_%T")

    _jail = {
        tag: uuid
        for (tag, uuid) in jails.items()
        if uuid.startswith(jail) or tag == jail
    }

    if len(_jail) == 1:
        tag, uuid = next(iter(_jail.items()))
        path = paths[tag]
    elif len(_jail) > 1:
        lgr.error("Multiple jails found for" " {}:".format(jail))
        for t, u in sorted(_jail.items()):
            lgr.error("  {} ({})".format(u, t))
        raise RuntimeError()
    else:
        lgr.critical("{} not found!".format(jail))
        exit(1)

    # If they don't supply a snapshot name, we will use the date.
    if not name:
        name = date

    # Looks like foo/iocage/jails/df0ef69a-57b6-4480-b1f8-88f7b6febbdf@BAR
    conf = IOCJson(path).json_load()

    if conf["template"] == "yes":
        target = "{}/iocage/templates/{}@{}".format(pool, tag, name)
    else:
        target = "{}/iocage/jails/{}@{}".format(pool, uuid, name)

    try:
        check_call(["zfs", "snapshot", "-r", target], stderr=PIPE)
        lgr.info("Snapshot: {} created.".format(target))
    except CalledProcessError:
        lgr.critical("Snapshot already exists!")
        exit(1)
Example #16
0
def destroy_cmd(force, release, download, jails):
    """Destroys the jail's 2 datasets and the snapshot from the RELEASE."""
    lgr = ioc_logger.Logger('ioc_cli_destroy').getLogger()

    if download and not release:
        exit("--release (-r) must be specified as well!")

    if jails and not release:
        get_jid = IOCList().list_get_jid

        try:
            jail_list, paths = IOCList("uuid").list_datasets()
        except RuntimeError as err:
            err = str(err)

            if "Configuration is missing" in err:
                uuid = err.split()[5]
                pool = IOCJson().json_get_value("pool")
                path = f"{pool}/iocage/jails/{uuid}"

                IOCDestroy().__stop_jails__(path.replace(pool, ""))
                IOCDestroy().__destroy_parse_datasets__(path)
                exit()
            else:
                lgr.critical(err)
                exit(1)

        for jail in jails:
            _jail = {
                tag: uuid
                for (tag, uuid) in jail_list.items()
                if uuid.startswith(jail) or tag == jail
            }

            if len(_jail) == 1:
                tag, uuid = next(iter(_jail.items()))
                path = paths[tag]
            elif len(_jail) > 1:
                lgr.error("Multiple jails found for" " {}:".format(jail))
                for t, u in sorted(_jail.items()):
                    lgr.critical("  {} ({})".format(u, t))
                exit(1)
            else:
                lgr.critical("{} not found!".format(jail))
                exit(1)

            if not force:
                lgr.warning("\nThis will destroy"
                            " jail {} ({})".format(uuid, tag))

                if not click.confirm("\nAre you sure?"):
                    continue  # no, continue to next jail

            status, _ = get_jid(uuid)

            # If the jail is not running, let's do this thing.
            if status and not force:
                lgr.critical(f"{uuid} ({tag}) is running.\nPlease stop "
                             "it first!")
                exit(1)
            elif status and force:
                lgr.info("Stopping {} ({}).".format(uuid, tag))

            IOCDestroy().destroy_jail(path)
    elif jails and release:
        pool = IOCJson().json_get_value("pool")

        for release in jails:
            path = f"{pool}/iocage/releases/{release}"

            if not force:
                lgr.warning(f"\nThis will destroy RELEASE: {release}")
                lgr.warning("       and any jail that was created with it.")

                if not click.confirm("\nAre you sure?"):
                    continue

            IOCDestroy().__destroy_parse_datasets__(path)

            if download:
                path = f"{pool}/iocage/download/{release}"
                IOCDestroy().__destroy_parse_datasets__(path)

    elif not jails and release:
        lgr.critical("Please specify one or more RELEASEs!")
        exit(1)
    else:
        lgr.critical("Please specify one or more jails!")
        exit(1)
Example #17
0
def upgrade_cmd(jail, release):
    """Runs upgrade with the command given inside the specified jail."""
    lgr = logging.getLogger('ioc_cli_upgrade')

    jails, paths = IOCList("uuid").list_datasets()
    _jail = {
        tag: uuid
        for (tag, uuid) in jails.items()
        if uuid.startswith(jail) or tag == jail
    }

    if len(_jail) == 1:
        tag, uuid = next(iter(_jail.items()))
        path = paths[tag]
        root_path = "{}/root".format(path)
    elif len(_jail) > 1:
        lgr.error("Multiple jails found for" " {}:".format(jail))
        for t, u in sorted(_jail.items()):
            lgr.error("  {} ({})".format(u, t))
        raise RuntimeError()
    else:
        raise RuntimeError("{} not found!".format(jail))

    pool = IOCJson().json_get_value("pool")
    iocroot = IOCJson(pool).json_get_value("iocroot")
    freebsd_version = checkoutput(["freebsd-version"])
    status, jid = IOCList.list_get_jid(uuid)
    conf = IOCJson(path).json_load()
    host_release = os.uname()[2]
    jail_release = conf["release"]
    started = False

    if conf["release"] == "EMPTY":
        raise RuntimeError("Upgrading is not supported for empty jails.")

    if conf["type"] == "jail":
        if not status:
            IOCStart(uuid, tag, path, conf, silent=True)
            status, jid = IOCList.list_get_jid(uuid)
            started = True
    elif conf["type"] == "basejail":
        raise RuntimeError("Please run \"iocage migrate\" before trying"
                           " to upgrade {} ({})".format(uuid, tag))
    elif conf["type"] == "template":
        raise RuntimeError("Please convert back to a jail before trying"
                           " to upgrade {} ({})".format(uuid, tag))
    else:
        raise RuntimeError("{} is not a supported jail type.".format(
            conf["type"]))

    _freebsd_version = "{}/releases/{}/root/bin/freebsd-version".format(
        iocroot, release)

    if "HBSD" in freebsd_version:
        Popen(["hbsd-upgrade", "-j", jid]).communicate()
    else:
        if os.path.isfile("{}/etc/freebsd-update.conf".format(root_path)):
            # 10.3-RELEASE and under lack this flag
            if float(host_release.partition("-")[0][:5]) <= 10.3:
                raise RuntimeError(
                    "Host: {} is too old, please upgrade to "
                    "10.3-RELEASE or above".format(host_release))

            os.environ["PAGER"] = "/bin/cat"
            fetch = Popen([
                "freebsd-update", "-b", root_path, "-d",
                "{}/var/db/freebsd-update/".format(root_path), "-f",
                "{}/etc/freebsd-update.conf".format(root_path),
                "--currently-running {}".format(jail_release), "-r", release,
                "upgrade"
            ],
                          stdin=PIPE)
            fetch.communicate(b"y")

            while not __upgrade_install__(root_path, release):
                pass

            if release[:4].endswith("-"):
                # 9.3-RELEASE and under don't actually have this binary.
                new_release = release
            else:
                with open(_freebsd_version, "r") as r:
                    for line in r:
                        if line.startswith("USERLAND_VERSION"):
                            new_release = line.rstrip().partition(
                                "=")[2].strip('"')

            IOCJson(path, silent=True).json_set_value(
                "release={}".format(new_release))

            if started:
                IOCStop(uuid, tag, path, conf, silent=True)

            lgr.info("\n{} ({}) successfully upgraded from {} to {}!".format(
                uuid, tag, jail_release, new_release))
Example #18
0
def export_cmd(jail):
    """Make a recursive snapshot of the jail and export to a file."""
    lgr = logging.getLogger('ioc_cli_export')

    pool = IOCJson().json_get_value("pool")
    iocroot = IOCJson(pool).json_get_value("iocroot")
    date = datetime.utcnow().strftime("%F")
    jails, paths = IOCList("uuid").list_datasets()
    _jail = {
        tag: uuid
        for (tag, uuid) in jails.items()
        if uuid.startswith(jail) or tag == jail
    }

    if len(_jail) == 1:
        tag, uuid = next(iter(_jail.items()))
        path = paths[tag]
    elif len(_jail) > 1:
        lgr.error("Multiple jails found for" " {}:".format(jail))
        for t, u in sorted(_jail.items()):
            lgr.error("  {} ({})".format(u, t))
        raise RuntimeError()
    else:
        raise RuntimeError("{} not found!".format(jail))

    status, _ = IOCList().list_get_jid(uuid)
    if status:
        raise RuntimeError("{} ({}) is runnning, stop the jail before "
                           "exporting!".format(uuid, tag))

    images = "{}/images".format(iocroot)
    name = "{}_{}".format(uuid, date)
    image = "{}/{}_{}".format(images, name, tag)
    image_path = "{}{}".format(pool, path)
    jail_list = []

    # Looks like foo/iocage/jails/df0ef69a-57b6-4480-b1f8-88f7b6febbdf@BAR
    target = "{}@ioc-export-{}".format(image_path, date)

    try:
        checkoutput(["zfs", "snapshot", "-r", target], stderr=STDOUT)
    except CalledProcessError as err:
        raise RuntimeError("ERROR: {}".format(
            err.output.decode("utf-8").rstrip()))

    datasets = Popen(
        ["zfs", "list", "-H", "-r", "-o", "name", "{}{}".format(pool, path)],
        stdout=PIPE,
        stderr=PIPE).communicate()[0].decode("utf-8").split()

    for dataset in datasets:
        if len(dataset) == 54:
            _image = image
            jail_list.append(_image)
        elif len(dataset) > 54:
            image_name = dataset.partition("{}{}".format(pool, path))[2]
            name = image_name.replace("/", "_")
            _image = image + name
            jail_list.append(_image)
            target = "{}@ioc-export-{}".format(dataset, date)

        # Sending each individually as sending them recursively to a file does
        # not work how one expects.
        try:
            with open(_image, "wb") as export:
                lgr.info("Exporting dataset: {}".format(dataset))
                check_call(["zfs", "send", target], stdout=export)
        except CalledProcessError as err:
            raise RuntimeError("ERROR: {}".format(err))

    lgr.info("\nPreparing zip file: {}.zip.".format(image))
    with zipfile.ZipFile("{}.zip".format(image),
                         "w",
                         compression=zipfile.ZIP_DEFLATED,
                         allowZip64=True) as final:
        os.chdir(images)

        for jail in jail_list:
            final.write(jail)

    # Cleanup our mess.
    try:
        checkoutput(["zfs", "destroy", "-r", target], stderr=STDOUT)

        for jail in jail_list:
            os.remove(jail)

    except CalledProcessError as err:
        raise RuntimeError("ERROR: {}".format(
            err.output.decode("utf-8").rstrip()))

    lgr.info("\nExported: {}.zip".format(image))
Example #19
0
def snaplist_cmd(header, jail):
    """Allows a user to show resource usage of all jails."""
    lgr = ioc_logger.Logger('ioc_cli_snaplist').getLogger()

    jails, paths = IOCList("uuid").list_datasets()
    pool = IOCJson().json_get_value("pool")
    snap_list = []
    table = Texttable(max_width=0)

    _jail = {
        tag: uuid
        for (tag, uuid) in jails.items()
        if uuid.startswith(jail) or tag == jail
    }

    if len(_jail) == 1:
        tag, uuid = next(iter(_jail.items()))
        path = paths[tag]
    elif len(_jail) > 1:
        lgr.error("Multiple jails found for" " {}:".format(jail))
        for t, u in sorted(_jail.items()):
            lgr.critical("  {} ({})".format(u, t))
        exit(1)
    else:
        lgr.critical("{} not found!".format(jail))
        exit(1)

    conf = IOCJson(path).json_load()

    if conf["template"] == "yes":
        full_path = "{}/iocage/templates/{}".format(pool, tag)
    else:
        full_path = "{}/iocage/jails/{}".format(pool, uuid)

    zconf = ["zfs", "get", "-H", "-o", "value"]
    snapshots = Popen(["zfs", "list", "-r", "-H", "-t", "snapshot", full_path],
                      stdout=PIPE,
                      stderr=PIPE).communicate()[0].decode("utf-8").split("\n")

    for snap in snapshots:
        # We get an empty list at the end.
        if snap:
            snap = snap.split()
            snapname = snap[0].rsplit("@")[1]
            root_snapname = snap[0].rsplit("@")[0].split("/")[-1]

            if root_snapname == "root":
                snapname += "/root"
            elif root_snapname != uuid and root_snapname != tag:
                # basejail datasets.
                continue

            creation = Popen(
                zconf + ["creation", snap[0]],
                stdout=PIPE).communicate()[0].decode("utf-8").strip()
            used = snap[1]
            referenced = Popen(
                zconf + ["referenced", snap[0]],
                stdout=PIPE).communicate()[0].decode("utf-8").strip()

            snap_list.append([snapname, creation, referenced, used])

    if header:
        snap_list.insert(0, ["NAME", "CREATED", "RSIZE", "USED"])
        # We get an infinite float otherwise.
        table.set_cols_dtype(["t", "t", "t", "t"])
        table.add_rows(snap_list)
        lgr.info(table.draw())
    else:
        for snap in snap_list:
            lgr.info("\t".join(snap))
Example #20
0
def migrate_cmd(force, delete):
    """Migrates all the iocage_legacy develop basejails to clone jails."""
    lgr = ioc_logger.Logger('ioc_cli_migrate').getLogger()

    jails, paths = IOCList("uuid").list_datasets()

    if not force:
        lgr.warning("\nThis will migrate ALL basejails to "
                    "clonejails, it can take a long time!")

        if not click.confirm("\nAre you sure?"):
            exit()

    for tag, uuid in jails.items():
        pool = IOCJson().json_get_value("pool")
        iocroot = IOCJson(pool).json_get_value("iocroot")
        jail = "{}/iocage/jails/{}".format(pool, uuid)
        jail_old = "{}/iocage/jails_old/{}".format(pool, uuid)
        path = paths[tag]
        conf = IOCJson(path).json_load()
        release = conf["release"]

        if conf["type"] == "basejail":
            try:
                checkoutput(["zfs", "rename", "-p", jail, jail_old],
                            stderr=STDOUT)
            except CalledProcessError as err:
                lgr.critical("{}".format(err.output.decode("utf-8").strip()))
                exit(1)

            try:
                os.remove("{}/tags/{}".format(iocroot, tag))
            except OSError:
                pass

            new_uuid = IOCCreate(release, "", 0, None, migrate=True,
                                 config=conf,
                                 silent=True).create_jail()
            new_prop = IOCJson("{}/jails/{}".format(iocroot, new_uuid),
                               silent=True).json_set_value
            new_prop("host_hostname={}".format(new_uuid))
            new_prop("host_hostuuid={}".format(new_uuid))
            new_prop("type=jail")
            new_prop(
                "jail_zfs_dataset={}/jails/{}/data".format(iocroot,
                                                           new_uuid))

            lgr.info("Copying files for {} ({}), please wait...".format(
                uuid, tag
            ))

            copytree("{}/jails_old/{}/root".format(iocroot, uuid),
                     "{}/jails/{}/root".format(iocroot, new_uuid),
                     symlinks=True)

            copy("{}/jails_old/{}/fstab".format(iocroot, uuid),
                 "{}/jails/{}/fstab".format(iocroot, new_uuid))
            for line in fileinput.input("{}/jails/{}/root/etc/rc.conf".format(
                    iocroot, new_uuid), inplace=1):
                lgr.info(line.replace(f'hostname="{uuid}"',
                                      f'hostname="{new_uuid}"').rstrip())

            if delete:
                try:
                    checkoutput(["zfs", "destroy", "-r", "-f", jail_old],
                                stderr=STDOUT)
                except CalledProcessError as err:
                    raise RuntimeError("{}".format(
                        err.output.decode("utf-8").rstrip()))

                try:
                    check_call(["zfs", "destroy", "-r", "-f",
                                "{}/iocage/jails_old".format(pool)])
                except CalledProcessError:
                    # We just want the top level dataset gone, no big deal.
                    pass

            lgr.info("{} ({}) migrated to {} ({})!\n".format(uuid, tag,
                                                             new_uuid, tag))
Example #21
0
def start_cmd(rc, jails):
    """
    Looks for the jail supplied and passes the uuid, path and configuration
    location to start_jail.
    """
    lgr = logging.getLogger('ioc_cli_start')

    _jails, paths = IOCList("uuid").list_datasets()

    if rc:
        boot_order = {}
        for j in _jails:
            path = paths[j]
            conf = IOCJson(path).json_load()
            boot = conf["boot"]
            priority = conf["priority"]

            if boot == "on":
                boot_order[j] = int(priority)

        boot_order = OrderedDict(sorted(boot_order.items(),
                                        key=itemgetter(1)))
        for j in boot_order.keys():
            uuid = _jails[j]
            path = paths[j]
            conf = IOCJson(path).json_load()
            status, _ = IOCList().list_get_jid(uuid)

            if not status:
                lgr.info("  Starting {} ({})".format(uuid, j))
                IOCStart(uuid, j, path, conf, silent=True)
            else:
                lgr.info("{} ({}) is already running!".format(uuid, j))
        exit()

    if len(jails) >= 1 and jails[0] == "ALL":
        if len(_jails) < 1:
            raise RuntimeError("No jails exist to start!")

        for j in _jails:
            uuid = _jails[j]
            path = paths[j]

            conf = IOCJson(path).json_load()
            IOCStart(uuid, j, path, conf)
    else:
        if len(jails) < 1:
            raise RuntimeError("Please specify either one or more jails or "
                               "ALL!")

        for jail in jails:
            _jail = {tag: uuid for (tag, uuid) in _jails.items() if
                     uuid.startswith(jail) or tag == jail}

            if len(_jail) == 1:
                tag, uuid = next(iter(_jail.items()))
                path = paths[tag]
            elif len(_jail) > 1:
                lgr.error("Multiple jails found for"
                          " {}:".format(jail))
                for t, u in sorted(_jail.items()):
                    lgr.error("  {} ({})".format(u, t))
                raise RuntimeError()
            else:
                raise RuntimeError("{} not found!".format(jail))

            conf = IOCJson(path).json_load()

            if conf["type"] in ("jail", "plugin"):
                IOCStart(uuid, tag, path, conf)
            elif conf["type"] == "basejail":
                raise RuntimeError(
                    "Please run \"iocage migrate\" before trying"
                    " to start {} ({})".format(uuid, tag))
            elif conf["type"] == "template":
                raise RuntimeError(
                    "Please convert back to a jail before trying"
                    " to start {} ({})".format(uuid, tag))
            else:
                raise RuntimeError("{} is not a supported jail type.".format(
                    conf["type"]
                ))
Example #22
0
def get_cmd(prop, _all, _pool, jail, recursive, header, plugin):
    """Get a list of jails and print the property."""
    lgr = logging.getLogger('ioc_cli_get')

    get_jid = IOCList.list_get_jid
    jails, paths = IOCList("uuid").list_datasets()
    jail_list = []
    table = Texttable(max_width=0)

    if _all:
        # Confusing I know.
        jail = prop
        prop = "all"

    if _pool:
        pool = IOCJson().json_get_value("pool")

        lgr.info(pool)
        exit()

    if recursive is None:
        if jail == "":
            lgr.info("Usage: iocage get [OPTIONS] PROP JAIL\n")
            raise RuntimeError("Error: Missing argument \"jail\".")

        _jail = {
            tag: uuid
            for (tag, uuid) in jails.items()
            if uuid.startswith(jail) or tag == jail
        }

        if len(_jail) == 1:
            tag, uuid = next(iter(_jail.items()))
            path = paths[tag]
        elif len(_jail) > 1:
            lgr.error("Multiple jails found for" " {}:".format(jail))
            for t, u in sorted(_jail.items()):
                lgr.error("  {} ({})".format(u, t))
            raise RuntimeError()
        else:
            raise RuntimeError("{} not found!".format(jail))

        if prop == "state":
            status, _ = get_jid(path.split("/")[3])

            if status:
                state = "up"
            else:
                state = "down"

            lgr.info(state)
        elif plugin:
            _prop = prop.split(".")
            props = IOCJson(path).json_plugin_get_value(_prop)

            if isinstance(props, dict):
                lgr.info(json.dumps(props, indent=4))
            else:
                pass
        elif prop == "all":
            props = IOCJson(path).json_get_value(prop)

            for p, v in props.items():
                lgr.info("{}:{}".format(p, v))
        elif prop == "fstab":
            pool = IOCJson().json_get_value("pool")
            iocroot = IOCJson(pool).json_get_value("iocroot")
            index = 0

            with open("{}/jails/{}/fstab".format(iocroot, uuid), "r") as \
                    fstab:
                for line in fstab.readlines():
                    line = line.rsplit("#")[0].rstrip()
                    jail_list.append([index, line.replace("\t", " ")])
                    index += 1

            if header:
                jail_list.insert(0, ["INDEX", "FSTAB ENTRY"])
                # We get an infinite float otherwise.
                table.set_cols_dtype(["t", "t"])
                table.add_rows(jail_list)
                lgr.info(table.draw())
            else:
                for fstab in jail_list:
                    lgr.info("{}\t{}".format(fstab[0], fstab[1]))
        else:
            try:
                lgr.info(IOCJson(path).json_get_value(prop))
            except:
                raise RuntimeError("{} is not a valid property!".format(prop))
    else:
        for j in jails:
            uuid = jails[j]
            path = paths[j]
            try:
                if prop == "state":
                    status, _ = get_jid(path.split("/")[3])

                    if status:
                        state = "up"
                    else:
                        state = "down"

                    jail_list.append([uuid, j, state])
                elif prop == "all":
                    props = IOCJson(path).json_get_value(prop)

                    for p, v in props.items():
                        jail_list.append([uuid, j, "{}:{}".format(p, v)])
                else:
                    jail_list.append(
                        [uuid, j, IOCJson(path).json_get_value(prop)])
            except:
                raise RuntimeError("{} is not a valid property!".format(prop))

        # Prints the table
        if header:
            jail_list.insert(0, ["UUID", "TAG", "PROP - {}".format(prop)])
            # We get an infinite float otherwise.
            table.set_cols_dtype(["t", "t", "t"])
            table.add_rows(jail_list)
            lgr.info(table.draw())
        else:
            for jail in jail_list:
                lgr.info("\t".join(jail))
Example #23
0
def fstab_cmd(action, fstab_string, jail):
    """
    Looks for the jail supplied and passes the uuid, path and configuration
    location to manipulate the fstab.
    """
    lgr = ioc_logger.Logger('ioc_cli_fstab').getLogger()
    pool = IOCJson().json_get_value("pool")
    iocroot = IOCJson(pool).json_get_value("iocroot")
    index = None
    _index = False
    fstab_string = list(fstab_string)

    _jails, paths = IOCList("uuid").list_datasets()

    if not fstab_string and action != "edit":
        lgr.critical("Please supply a fstab entry!")
        exit(1)

    _jail = {
        tag: uuid
        for (tag, uuid) in _jails.items()
        if uuid.startswith(jail) or tag == jail
    }

    if len(_jail) == 1:
        tag, uuid = next(iter(_jail.items()))
    elif len(_jail) > 1:
        lgr.error("Multiple jails found for" " {}:".format(jail))
        for t, u in sorted(_jail.items()):
            lgr.error("  {} ({})".format(u, t))
        raise RuntimeError()
    else:
        lgr.critical("{} not found!".format(jail))
        exit(1)

    # The user will expect to supply a string, the API would prefer these
    # separate. If the user supplies a quoted string, we will split it,
    # otherwise the format is acceptable to be imported directly.
    if len(fstab_string) == 1:
        try:
            source, destination, fstype, options, dump, _pass = fstab_string[
                0].split()
        except ValueError:
            # We're going to assume this is an index number.
            try:
                index = int(fstab_string[0])
            except TypeError:
                lgr.critical("Please specify either a valid fstab "
                             "entry or an index number.")
                exit(1)
            _index = True
            source, destination, fstype, options, dump, _pass = "", "", "", \
                                                                "", "", ""
    else:
        if action != "edit":
            try:
                source, destination, fstype, options, dump, _pass = \
                    fstab_string
            except ValueError:
                lgr.critical("Please specify a valid fstab entry!\n\n"
                             "Example:\n  /the/source /dest FSTYPE "
                             "FSOPTIONS FSDUMP FSPASS")
                exit(1)
        else:
            source, destination, fstype, options, dump, _pass = "", "", \
                                                                "", "", \
                                                                "", ""

    if not _index and action == "add":
        destination = "{}/jails/{}/root".format(iocroot, uuid) + destination

    IOCFstab(uuid,
             tag,
             action,
             source,
             destination,
             fstype,
             options,
             dump,
             _pass,
             index=index)
Example #24
0
def stop_cmd(rc, jails):
    """
    Looks for the jail supplied and passes the uuid, path and configuration
    location to stop_jail.
    """
    lgr = logging.getLogger('ioc_cli_stop')

    _jails, paths = IOCList("uuid").list_datasets()
    jail_order = {}
    boot_order = {}

    for j in _jails:
        path = paths[j]
        conf = IOCJson(path).json_load()
        boot = conf["boot"]
        priority = conf["priority"]

        jail_order[j] = int(priority)

        # This removes having to grab all the JSON again later.
        if boot == "on":
            boot_order[j] = int(priority)

    jail_order = OrderedDict(
        sorted(jail_order.items(), key=itemgetter(1), reverse=True))
    boot_order = OrderedDict(
        sorted(boot_order.items(), key=itemgetter(1), reverse=True))
    if rc:
        for j in boot_order.keys():
            uuid = _jails[j]
            path = paths[j]
            conf = IOCJson(path).json_load()
            status, _ = IOCList().list_get_jid(uuid)

            if status:
                lgr.info("  Stopping {} ({})".format(uuid, j))
                IOCStop(uuid, j, path, conf, silent=True)
            else:
                lgr.info("{} ({}) is not running!".format(uuid, j))
        exit()

    if len(jails) >= 1 and jails[0] == "ALL":
        if len(_jails) < 1:
            raise RuntimeError("No jails exist to stop!")

        for j in jail_order:
            uuid = _jails[j]
            path = paths[j]

            conf = IOCJson(path).json_load()
            IOCStop(uuid, j, path, conf)
    else:
        if len(jails) < 1:
            raise RuntimeError("Please specify either one or more jails or "
                               "ALL!")

        for jail in jails:
            _jail = {
                tag: uuid
                for (tag, uuid) in _jails.items()
                if uuid.startswith(jail) or tag == jail
            }

            if len(_jail) == 1:
                tag, uuid = next(iter(_jail.items()))
                path = paths[tag]
            elif len(_jail) > 1:
                lgr.error("Multiple jails found for" " {}:".format(jail))
                for t, u in sorted(_jail.items()):
                    lgr.error("  {} ({})".format(u, t))
                raise RuntimeError()
            else:
                raise RuntimeError("{} not found!".format(jail))

            conf = IOCJson(path).json_load()
            IOCStop(uuid, tag, path, conf)
Example #25
0
def restart_cmd(jail, soft):
    """
    Looks for the jail supplied and passes the uuid, path and configuration
    location to stop_jail and start_jail.
    """
    lgr = logging.getLogger('ioc_cli_restart')

    jails, paths = IOCList("uuid").list_datasets()
    if jail == "ALL":
        for j in jails:
            uuid = jails[j]
            path = paths[j]

            conf = IOCJson(path).json_load()

            if conf["type"] in ("jail", "plugin"):
                try:
                    if not soft:
                        __hard_restart__(uuid, j, path, conf)
                    else:
                        __soft_restart__(uuid, j, path, conf)
                except RuntimeError as err:
                    lgr.error(err)
            elif conf["type"] == "basejail":
                lgr.error("Please run \"iocage migrate\" before trying"
                          " to restart {} ({})".format(uuid, j))
            elif conf["type"] == "template":
                raise RuntimeError(
                    "Please convert back to a jail before trying"
                    " to restart {} ({})".format(uuid, j))
            else:
                lgr.error("{} is not a supported jail type.".format(
                    conf["type"]))
    else:
        _jail = {
            tag: uuid
            for (tag, uuid) in jails.items()
            if uuid.startswith(jail) or tag == jail
        }

        if len(_jail) == 1:
            tag, uuid = next(iter(_jail.items()))
            path = paths[tag]
        elif len(_jail) > 1:
            lgr.error("Multiple jails found for" " {}:".format(jail))
            for t, u in sorted(_jail.items()):
                lgr.error("  {} ({})".format(u, t))
            raise RuntimeError()
        else:
            raise RuntimeError("{} not found!".format(jail))

        conf = IOCJson(path).json_load()

        if conf["type"] in ("jail", "plugin"):
            if not soft:
                __hard_restart__(uuid, tag, path, conf)
            else:
                __soft_restart__(uuid, tag, path, conf)
        elif conf["type"] == "basejail":
            raise RuntimeError("Please run \"iocage migrate\" before trying"
                               " to restart {} ({})".format(uuid, tag))
        elif conf["type"] == "template":
            raise RuntimeError("Please convert back to a jail before trying"
                               " to restart {} ({})".format(uuid, tag))
        else:
            raise RuntimeError("{} is not a supported jail type.".format(
                conf["type"]))