Пример #1
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("\nAn 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("pkg error, refusing to fetch artifact and "
                           "run post_install.sh!\n")