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")