Example #1
0
    def json_plugin_set_value(self, prop):
        from iocage.lib.ioc_exec import IOCExec
        from iocage.lib.ioc_list import IOCList

        pool, iocroot = _get_pool_and_iocroot()
        conf = self.json_load()
        uuid = conf["host_hostuuid"]
        tag = conf["tag"]
        _path = checkoutput([
            "zfs", "get", "-H", "-o", "value", "mountpoint",
            "{}/iocage/jails/{}".format(pool, uuid)
        ]).rstrip()
        status, _ = IOCList().list_get_jid(uuid)

        # Plugin variables
        settings = self.json_plugin_load()
        serviceset = settings["serviceset"]
        servicerestart = settings["servicerestart"].split()
        keys, _, value = ".".join(prop).partition("=")
        prop = keys.split(".")
        restart = False

        if "options" in prop:
            prop = keys.split(".")[1:]

        prop_cmd = "{},{},{}".format(serviceset, ",".join(prop),
                                     value).split(",")
        setting = settings["options"]

        try:
            while prop:
                current = prop[0]
                key = current
                prop.remove(current)

                if not prop:
                    if setting[current]:
                        try:
                            restart = setting[current]["requirerestart"]
                        except KeyError:
                            pass
                else:
                    setting = setting[current]

            if status:
                # IOCExec will not show this if it doesn't start the jail.
                self.lgr.info("Command output:")
            IOCExec(prop_cmd, uuid, tag, _path).exec_jail()

            if restart:
                self.lgr.info("\n-- Restarting service --")
                self.lgr.info("Command output:")
                IOCExec(servicerestart, uuid, tag, _path).exec_jail()

            self.lgr.info("\nKey: {} has been updated to {}".format(
                keys, value))
        except KeyError:
            raise RuntimeError("Key: \"{}\" does not exist!".format(key))
Example #2
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 #3
0
    def json_plugin_get_value(self, prop):
        from iocage.lib.ioc_exec import IOCExec

        pool, iocroot = _get_pool_and_iocroot()
        conf = self.json_load()
        uuid = conf["host_hostuuid"]
        tag = conf["tag"]
        _path = checkoutput([
            "zfs", "get", "-H", "-o", "value", "mountpoint",
            "{}/iocage/jails/{}".format(pool, uuid)
        ]).rstrip()
        # Plugin variables
        settings = self.json_plugin_load()
        serviceget = settings["serviceget"]
        prop_error = ".".join(prop)

        if "options" in prop:
            _prop = prop[1:]
        else:
            _prop = prop

        prop_cmd = "{},{}".format(serviceget, ",".join(_prop)).split(",")
        try:
            if prop[0] != "all":
                if len(_prop) > 1:
                    return get_nested_key(settings, prop)
                else:
                    return IOCExec(prop_cmd, uuid, tag, _path).exec_jail()
            else:
                return settings
        except KeyError:
            raise RuntimeError(
                "Key: \"{}\" does not exist!".format(prop_error))
Example #4
0
    def exec(self, jail, command, options):
        """Issues a command inside a jail."""
        from iocage.lib.ioc_exec import IOCExec

        tag, uuid, path = self.check_jail_existence(jail)
        host_user = options["host_user"]
        jail_user = options["jail_user"]

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

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

        return msg.decode("utf-8")
Example #5
0
    def exec(self, jail, command, options):
        """Issues a command inside a jail."""
        from iocage.lib.ioc_exec import IOCExec

        tag, uuid, path = self.check_jail_existence(jail)
        host_user = options["host_user"]
        jail_user = options["jail_user"]

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

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

        return msg.decode("utf-8")
Example #6
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 #7
0
    def create_install_packages(self, jail_uuid, location, _tag, config):
        """
        Takes a list of pkg's to install into the target jail. The resolver
        property is required for pkg to have network access.
        """
        status, jid = IOCList().list_get_jid(jail_uuid)
        err = False
        if not status:
            IOCStart(jail_uuid, _tag, location, config, silent=True)
            resolver = config["resolver"]

            if resolver != "/etc/resolv.conf" and resolver != "none":
                with open("{}/etc/resolv.conf".format(location),
                          "w") as resolv_conf:
                    for line in resolver.split(";"):
                        resolv_conf.write(line + "\n")
            else:
                copy(resolver, "{}/root/etc/resolv.conf".format(location))

            status, jid = IOCList().list_get_jid(jail_uuid)

        if not self.plugin:
            with open(self.pkglist, "r") as j:
                self.pkglist = json.load(j)["pkgs"]

        self.lgr.info("\nInstalling pkg... ")
        # To avoid a user being prompted about pkg.
        Popen(["pkg-static", "-j", jid, "install", "-q", "-y", "pkg"],
              stderr=PIPE).communicate()

        # We will have mismatched ABI errors from earlier, this is to be safe.
        os.environ["ASSUME_ALWAYS_YES"] = "yes"
        cmd = ("pkg-static", "upgrade", "-f", "-q", "-y")
        pkg_upgrade = IOCExec(cmd,
                              jail_uuid,
                              _tag,
                              location,
                              plugin=self.plugin).exec_jail()

        if pkg_upgrade:
            self.lgr.error("ERROR: {}".format(pkg_upgrade.decode("utf-8")))
            err = True

        self.lgr.info("Installing supplied packages:")
        for pkg in self.pkglist:
            self.lgr.info("  - {}... ".format(pkg))
            cmd = ("pkg", "install", "-q", "-y", pkg)
            pkg_install = IOCExec(cmd,
                                  jail_uuid,
                                  _tag,
                                  location,
                                  plugin=self.plugin).exec_jail()

            if pkg_install:
                self.lgr.error("ERROR: {}".format(pkg_install))
                err = True

        os.remove("{}/root/etc/resolv.conf".format(location))

        if status:
            IOCStop(jail_uuid, _tag, location, config, silent=True)

        if self.plugin and err:
            return err
Example #8
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")
Example #9
0
    def create_install_packages(self, jail_uuid, location, _tag, config):
        """
        Takes a list of pkg's to install into the target jail. The resolver
        property is required for pkg to have network access.
        """
        status, jid = IOCList().list_get_jid(jail_uuid)
        err = False
        if not status:
            IOCStart(jail_uuid, _tag, location, config, silent=True)
            resolver = config["resolver"]

            if resolver != "/etc/resolv.conf" and resolver != "none":
                with open("{}/etc/resolv.conf".format(location),
                          "w") as resolv_conf:
                    for line in resolver.split(";"):
                        resolv_conf.write(line + "\n")
            else:
                copy(resolver, "{}/root/etc/resolv.conf".format(location))

            status, jid = IOCList().list_get_jid(jail_uuid)

        # Connectivity test courtesy David Cottlehuber off Google Group
        srv_connect_cmd = ["drill", "_http._tcp.pkg.freebsd.org", "SRV"]
        dnssec_connect_cmd = ["drill", "-D", "pkg.freebsd.org"]

        self.lgr.info("Testing SRV response to FreeBSD")
        srv_connection = IOCExec(srv_connect_cmd,
                                 jail_uuid,
                                 _tag,
                                 location,
                                 plugin=self.plugin).exec_jail()

        if srv_connection:
            raise RuntimeError(f"{srv_connection}\n"
                               f"Command run: {' '.join(srv_connect_cmd)}")

        self.lgr.info("Testing DNSSEC response to FreeBSD")
        dnssec_connection = IOCExec(dnssec_connect_cmd,
                                    jail_uuid,
                                    _tag,
                                    location,
                                    plugin=self.plugin).exec_jail()

        if dnssec_connection:
            raise RuntimeError(f"{dnssec_connection}\n"
                               f"Command run: {' '.join(dnssec_connect_cmd)}")

        if not self.plugin:
            with open(self.pkglist, "r") as j:
                self.pkglist = json.load(j)["pkgs"]

        self.lgr.info("\nInstalling pkg... ")
        # To avoid a user being prompted about pkg.
        Popen(["pkg-static", "-j", jid, "install", "-q", "-y", "pkg"],
              stderr=PIPE).communicate()

        # We will have mismatched ABI errors from earlier, this is to be safe.
        os.environ["ASSUME_ALWAYS_YES"] = "yes"
        cmd = ("pkg-static", "upgrade", "-f", "-q", "-y")
        pkg_upgrade = IOCExec(cmd,
                              jail_uuid,
                              _tag,
                              location,
                              plugin=self.plugin).exec_jail()

        if pkg_upgrade:
            self.lgr.error(f"{pkg_upgrade}")
            err = True

        self.lgr.info("Installing supplied packages:")
        for pkg in self.pkglist:
            self.lgr.info("  - {}... ".format(pkg))
            cmd = ("pkg", "install", "-q", "-y", pkg)
            pkg_install = IOCExec(cmd,
                                  jail_uuid,
                                  _tag,
                                  location,
                                  plugin=self.plugin).exec_jail()

            if pkg_install:
                self.lgr.error("{}".format(pkg_install))
                err = True

        os.remove("{}/root/etc/resolv.conf".format(location))

        if status:
            IOCStop(jail_uuid, _tag, location, config, silent=True)

        if self.plugin and err:
            return err