Пример #1
0
def test_create(release, hardened):
    prop = ("tag=test", )
    prop_short = ("tag=test_short", )

    if hardened:
        release = "{}-STABLE".format(release)

    IOCCreate(release, prop, 0).create_jail()
    IOCCreate(release, prop_short, 0, short=True).create_jail()

    assert True == True
Пример #2
0
    def create(self, job, options):
        """Creates a jail."""
        from iocage.lib.ioc_create import IOCCreate
        self.check_dataset_existence()

        release = options["release"]
        template = options["template"]
        pkglist = options["pkglist"]
        uuid = options["uuid"]
        basejail = options["basejail"]
        empty = options["empty"]
        short = options["short"]
        props = options["props"]
        pool = IOCJson().json_get_value("pool")
        iocroot = IOCJson(pool).json_get_value("iocroot")

        if template:
            release = template

        if not os.path.isdir(f"{iocroot}/releases/{release}") and not \
                template and not empty:
            self.middleware.call('jail.fetch', {"release": release}).wait()

        IOCCreate(release, props, 0, pkglist, template=template,
                  short=short, uuid=uuid, basejail=basejail,
                  empty=empty).create_jail()

        return True
Пример #3
0
    def create(self, options):
        """Creates a jail."""
        from iocage.lib.ioc_create import IOCCreate
        self.check_dataset_existence()

        release = options.get("release", None)
        template = options.get("template", None)
        pkglist = options.get("pkglist", None)
        # uuid = options.get("uuid", None)  Not in 0.9.7
        basejail = options.get("basejail", False)
        empty = options.get("empty", False)
        short = options.get("short", False)
        props = options.get("props", [])
        pool = IOCJson().json_get_value("pool")
        iocroot = IOCJson(pool).json_get_value("iocroot")

        if template:
            release = template

        if not os.path.isdir(f"{iocroot}/releases/{release}") and not \
                template and not empty:
            # FIXME: List index out of range
            # self.fetch(options={"release": release})
            pass

        IOCCreate(release, props, 0, pkglist, template=template,
                  short=short, basejail=basejail, empty=empty).create_jail()

        return True
Пример #4
0
def create_cmd(release, template, count, props, pkglist, basejail, empty,
               short, uuid):
    lgr = ioc_logger.Logger('ioc_cli_create').getLogger()

    if short and uuid:
        lgr.critical(
            "Can't use --short (-s) and --uuid (-u) at the same time!")
        exit(1)

    if not template and not release and not empty:
        lgr.critical("Must supply either --template (-t) or --release (-r)!")
        exit(1)

    if release and "=" in release:
        lgr.critical("Please supply a valid RELEASE!")
        exit(1)

    if template:
        # We don't really care it's not a RELEASE at this point.
        release = template

    if pkglist:
        _pkgformat = """
{
    "pkgs": [
    "foo",
    "bar"
    ]
}"""

        if not os.path.isfile(pkglist):
            lgr.critical("{} does not exist!\nPlease supply a JSON file "
                         "with the format:{}".format(pkglist, _pkgformat))
            exit(1)
        else:
            try:
                # Just try to open the JSON with the right key.
                with open(pkglist, "r") as p:
                    json.load(p)["pkgs"]  # noqa
            except JSONDecodeError:
                lgr.critical("Please supply a valid JSON file with the"
                             f" format:\n{_pkgformat}")
                exit(1)

    pool = IOCJson().json_get_value("pool")
    iocroot = IOCJson(pool).json_get_value("iocroot")

    if not os.path.isdir(
            f"{iocroot}/releases/{release}") and not template and not empty:
        freebsd_version = checkoutput(["freebsd-version"])

        if "HBSD" in freebsd_version:
            hardened = True
        else:
            hardened = False

        IOCFetch(release, hardened=hardened).fetch_release()

    if empty:
        release = "EMPTY"

    if count == 1:
        try:
            IOCCreate(release,
                      props,
                      0,
                      pkglist,
                      template=template,
                      short=short,
                      uuid=uuid,
                      basejail=basejail,
                      empty=empty).create_jail()
        except RuntimeError as err:
            lgr.error(err)
            if template:
                lgr.info("Created Templates:")
                templates = IOCList("template", hdr=False).list_datasets()
                for temp in templates:
                    lgr.info("  {}".format(temp[3]))
    else:
        for j in range(1, count + 1):
            try:
                IOCCreate(release,
                          props,
                          j,
                          pkglist,
                          template=template,
                          short=short,
                          basejail=basejail,
                          empty=empty).create_jail()
            except RuntimeError as err:
                lgr.error(err)
                if template:
                    lgr.info("Created Templates:")
                    templates = IOCList("template", hdr=False).list_datasets()
                    for temp in templates:
                        lgr.info("  {}".format(temp[3]))
                exit(1)
Пример #5
0
    def fetch_plugin(self, _json, props, num):
        """Expects an JSON object."""
        with open(_json, "r") as j:
            conf = json.load(j)
        self.release = conf["release"]
        pkg_repos = conf["fingerprints"]
        freebsd_version = f"{self.iocroot}/releases/{conf['release']}" \
                          "/root/bin/freebsd-version"

        if num <= 1:
            self.lgr.info("Plugin: {}".format(conf["name"]))
            self.lgr.info("  Using RELEASE: {}".format(self.release))
            self.lgr.info(
                "  Post-install Artifact: {}".format(conf["artifact"]))
            self.lgr.info("  These pkgs will be installed:")

            for pkg in conf["pkgs"]:
                self.lgr.info("    - {}".format(pkg))

            if not os.path.isdir("{}/releases/{}".format(self.iocroot,
                                                         self.release)):
                self.fetch_release()

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

        # We set our properties that we need, and then iterate over the user
        #  supplied properties replacing ours. Finally we add _1, _2 etc to
        # the tag with the final iteration if the user supplied count.
        create_props = [f"cloned_release={self.release}",
                        f"release={release}", "type=plugin"]

        # If the user supplied a tag, we shouldn't add ours.
        if "tag" not in [p.split("=")[0] for p in props]:
            _tag = f"tag={conf['name']}"
            create_props += [_tag]
        else:
            for p in props:
                _p = p.split("=")[0]
                _tag = p if _p == "tag" else ""

        create_props = [f"{k}={v}" for k, v in
                        (p.split("=") for p in props)] + create_props
        create_props = [f"{k}_{num}" if k == f"{_tag}"
                        and num != 0 else k for k in create_props]

        uuid = IOCCreate(self.release, create_props, 0).create_jail()
        jaildir = "{}/jails/{}".format(self.iocroot, uuid)
        repo_dir = "{}/root/usr/local/etc/pkg/repos".format(jaildir)
        _conf = IOCJson(jaildir).json_load()
        tag = _conf["tag"]

        # We do this test again as the user could supply a malformed IP to
        # fetch that bypasses the more naive check in cli/fetch
        if _conf["ip4_addr"] == "none" and _conf["ip6_addr"] == "none":
            self.lgr.error("\nERROR: An IP address is needed to fetch a "
                           "plugin!\n")
            self.lgr.error("Destroying partial plugin.")
            IOCDestroy(uuid, tag, jaildir).destroy_jail()
            raise RuntimeError()

        IOCStart(uuid, tag, jaildir, _conf, silent=True)

        try:
            os.makedirs(repo_dir, 0o755)
        except OSError:
            # It exists, that's fine.
            pass

        for repo in pkg_repos:
            repo_name = repo
            repo = pkg_repos[repo]
            f_dir = "{}/root/usr/local/etc/pkg/fingerprints/{}/trusted".format(
                jaildir, repo_name)
            repo_conf = """\
{reponame}: {{
            url: "{packagesite}",
            signature_type: "fingerprints",
            fingerprints: "/usr/local/etc/pkg/fingerprints/{reponame}",
            enabled: true
            }}
"""

            try:
                os.makedirs(f_dir, 0o755)
            except OSError:
                self.lgr.error("Repo: {} already exists, skipping!".format(
                    repo_name))

            r_file = "{}/{}.conf".format(repo_dir, repo_name)

            with open(r_file, "w") as r_conf:
                r_conf.write(repo_conf.format(reponame=repo_name,
                                              packagesite=conf["packagesite"]))

            f_file = "{}/{}".format(f_dir, repo_name)

            for r in repo:
                finger_conf = """\
function: {function}
fingerprint: {fingerprint}
"""
                with open(f_file, "w") as f_conf:
                    f_conf.write(finger_conf.format(function=r["function"],
                                                    fingerprint=r[
                                                        "fingerprint"]))
        err = IOCCreate(self.release, create_props, 0, plugin=True,
                        pkglist=conf["pkgs"]).create_install_packages(uuid,
                                                                      jaildir,
                                                                      tag,
                                                                      _conf)
        if not err:
            # We need to pipe from tar to the root of the jail.
            if conf["artifact"]:
                # TODO: Fancier.
                self.lgr.info("Fetching artifact... ")

                Popen(["git", "clone", conf["artifact"],
                       "{}/plugin".format(jaildir)],
                      stdout=PIPE, stderr=PIPE).communicate()
                tar_in = Popen(["tar", "cvf", "-", "-C",
                                "{}/plugin/overlay/".format(jaildir), "."],
                               stdout=PIPE, stderr=PIPE).communicate()
                Popen(["tar", "xf", "-", "-C", "{}/root".format(jaildir)],
                      stdin=PIPE).communicate(input=tar_in[0])

                try:
                    copy("{}/plugin/post_install.sh".format(jaildir),
                         "{}/root/root".format(jaildir))

                    self.lgr.info("Running post_install.sh")
                    command = ["sh", "/root/post_install.sh"]
                    IOCExec(command, uuid, conf["name"], jaildir,
                            skip=True).exec_jail()
                except (IOError, OSError):
                    pass
        else:
            self.lgr.error("ERROR: pkg error, refusing to fetch artifact and "
                           "run post_install.sh!\n")
Пример #6
0
    def json_set_value(self, prop, create_func=False):
        """Set a property for the specified jail."""
        # Circular dep! Meh.
        from iocage.lib.ioc_list import IOCList
        from iocage.lib.ioc_create import IOCCreate
        key, _, value = prop.partition("=")

        conf = self.json_load()
        old_tag = conf["tag"]
        uuid = conf["host_hostuuid"]
        status, jid = IOCList.list_get_jid(uuid)
        conf[key] = value
        sysctls_cmd = ["sysctl", "-d", "security.jail.param"]
        jail_param_regex = re.compile("security.jail.param.")
        sysctls_list = Popen(
            sysctls_cmd, stdout=PIPE).communicate()[0].decode("utf-8").split()
        jail_params = [
            p.replace("security.jail.param.", "").replace(":", "")
            for p in sysctls_list if re.match(jail_param_regex, p)
        ]
        single_period = [
            "allow_raw_sockets", "allow_socket_af", "allow_set_hostname"
        ]

        if not create_func:
            if key == "tag":
                conf["tag"] = IOCCreate("", prop,
                                        0).create_link(conf["host_hostuuid"],
                                                       value,
                                                       old_tag=old_tag)
                tag = conf["tag"]

        if key == "template":
            pool, iocroot = _get_pool_and_iocroot()
            old_location = "{}/iocage/jails/{}".format(pool, uuid)
            new_location = "{}/iocage/templates/{}".format(pool, old_tag)

            if status:
                raise RuntimeError(f"{uuid} ({old_tag}) is running.\nPlease"
                                   "stop it first!")

            jails, paths = IOCList("uuid").list_datasets()
            for j in jails:
                _uuid = jails[j]
                _path = f"{paths[j]}/root"
                t_old_path = f"{old_location}/root@{_uuid}"
                t_path = f"{new_location}/root@{_uuid}"

                if _uuid == uuid:
                    continue

                origin = checkoutput(
                    ["zfs", "get", "-H", "-o", "value", "origin",
                     _path]).rstrip()

                if origin == t_old_path or origin == t_path:
                    _status, _ = IOCList.list_get_jid(_uuid)

                    if _status:
                        raise RuntimeError(f"CHILD: {_uuid} ({j}) is"
                                           f" running.\nPlease stop it first!")
            if value == "yes":
                try:
                    checkoutput(
                        ["zfs", "rename", "-p", old_location, new_location],
                        stderr=STDOUT)
                    conf["type"] = "template"

                    self.location = new_location.lstrip(pool).replace(
                        "/iocage", iocroot)
                except CalledProcessError as err:
                    raise RuntimeError("{}".format(
                        err.output.decode("utf-8").rstrip()))

                self.lgr.info("{} ({}) converted to a template.".format(
                    uuid, old_tag))
                self.lgr.disabled = True
            elif value == "no":
                try:
                    checkoutput(
                        ["zfs", "rename", "-p", new_location, old_location],
                        stderr=STDOUT)
                    conf["type"] = "jail"

                    self.location = old_location.lstrip(pool).replace(
                        "/iocage", iocroot)
                except CalledProcessError as err:
                    raise RuntimeError("{}".format(
                        err.output.decode("utf-8").rstrip()))

                self.lgr.info("{} ({}) converted to a jail.".format(
                    uuid, old_tag))
                self.lgr.disabled = True

        self.json_check_prop(key, value, conf)
        self.json_write(conf)
        self.lgr.info("Property: {} has been updated to {}".format(key, value))

        # Used for import
        if not create_func:
            if key == "tag":
                return tag

        # We can attempt to set a property in realtime to jail.
        if status:
            if key in single_period:
                key = key.replace("_", ".", 1)
            else:
                key = key.replace("_", ".")

            if key in jail_params:
                try:
                    checkoutput([
                        "jail", "-m", "jid={}".format(jid), "{}={}".format(
                            key, value)
                    ],
                                stderr=STDOUT)
                except CalledProcessError as err:
                    raise RuntimeError("{}".format(
                        err.output.decode("utf-8").rstrip()))
Пример #7
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))
Пример #8
0
def create_cmd(release, template, count, props, pkglist, basejail, short):
    lgr = logging.getLogger('ioc_cli_create')

    if not template and not release:
        raise RuntimeError(
            "Must supply either --template (-t) or --release (-r)!")

    if release and "=" in release:
        raise RuntimeError("Please supply a valid RELEASE!")

    if template:
        # We don't really care it's not a RELEASE at this point.
        release = template

    if pkglist:
        if not os.path.isfile(pkglist):
            _pkgformat = """
{
    "pkgs": [
    "foo",
    "bar",
    ]
}"""
            raise RuntimeError("{} does not exist!\nPlease supply a JSON file "
                               "with the format:{}".format(
                                   pkglist, _pkgformat))

    pool = IOCJson().json_get_value("pool")
    iocroot = IOCJson(pool).json_get_value("iocroot")

    if not os.path.isdir("{}/releases/{}".format(iocroot,
                                                 release)) and not template:
        IOCFetch(release).fetch_release()

    if count == 1:
        try:
            IOCCreate(release,
                      props,
                      0,
                      pkglist,
                      template=template,
                      short=short,
                      basejail=basejail).create_jail()
        except RuntimeError as err:
            lgr.error(err)
            if template:
                lgr.info("Created Templates:")
                templates = IOCList("template", hdr=False,
                                    rtrn_object=True).list_datasets()
                for temp in templates:
                    lgr.info("  {}".format(temp))
    else:
        for j in range(1, count + 1):
            try:
                IOCCreate(release,
                          props,
                          j,
                          pkglist,
                          template=template,
                          short=short,
                          basejail=basejail).create_jail()
            except RuntimeError as err:
                lgr.error(err)
                if template:
                    lgr.info("Created Templates:")
                    templates = IOCList("template",
                                        hdr=False,
                                        rtrn_object=True).list_datasets()
                    for temp in templates:
                        lgr.info("  {}".format(temp))
                exit(1)