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)
def update_to_latest_patch(self, job, jail): """Updates specified jail to latest patch level.""" uuid, path, _ = self.check_jail_existence(jail) status, jid = IOCList.list_get_jid(uuid) conf = IOCJson(path).json_load() # Sometimes if they don't have an existing patch level, this # becomes 11.1 instead of 11.1-RELEASE _release = conf["release"].rsplit("-", 1)[0] release = _release if "-RELEASE" in _release else conf["release"] started = False if conf["type"] == "jail": if not status: self.start(jail) started = True else: return False if conf["basejail"] != "yes": IOCFetch(release).fetch_update(True, uuid) else: # Basejails only need their base RELEASE updated IOCFetch(release).fetch_update() if started: self.stop(jail) return True
def update(self, job, jail): # FIXME: No-op until I change iocage behavior with freebsd-update # not existing. # TODO: upgrade needs to be broken out of cli. """Updates specified jail to latest patch level.""" from iocage.lib.ioc_fetch import IOCFetch tag, uuid, path = self.check_jail_existence(jail) status, jid = IOCList.list_get_jid(uuid) conf = IOCJson(path).json_load() started = False if conf["type"] == "jail": if not status: self.start(jail) started = True else: return False IOCFetch(conf["cloned_release"]).fetch_update(True, uuid, tag) if started: self.stop(jail) return True
def get(self, jail, options): """Gets a jail property.""" prop = options["prop"] plugin = options["plugin"] tag, uuid, path = self.check_jail_existence(jail) if "template" in prop.split("=")[0]: if "template" in path and prop != "template=no": raise RuntimeError(f"{uuid} ({tag}) is already a template!") elif "template" not in path and prop != "template=yes": raise RuntimeError(f"{uuid} ({tag}) is already a jail!") if plugin: _prop = prop.split(".") return IOCJson(path).json_plugin_set_value(_prop) if prop == "all": return IOCJson(path).json_get_value(prop) elif prop == "state": status, _ = IOCList.list_get_jid(path.split("/")[3]) if status: return "UP" else: return "DOWN" return IOCJson(path).json_get_value(prop)
def __init__(self, conf, new_release, path): self.lgr = logging.getLogger("ioc_upgrade") self.pool = IOCJson().json_get_value("pool") self.iocroot = IOCJson(self.pool).json_get_value("iocroot") self.freebsd_version = checkoutput(["freebsd-version"]) self.conf = conf self.uuid = conf["host_hostuuid"] self.host_release = os.uname()[2] self.jail_release = conf["cloned_release"] self.new_release = new_release self.path = path self.status, self.jid = IOCList.list_get_jid(self.uuid) self._freebsd_version = f"{self.iocroot}/releases/" \ f"{new_release}/root/bin/freebsd-version"
def export(self, job, jail): """Exports jail to zip file""" uuid, path, _ = self.check_jail_existence(jail) status, jid = IOCList.list_get_jid(uuid) started = False if status: self.stop(jail) started = True IOCImage().export_jail(uuid, path) if started: self.start(jail) return True
def export(self, job, jail): """Exports jail to zip file""" from iocage.lib.ioc_image import IOCImage tag, uuid, path = self.check_jail_existence(jail) status, jid = IOCList.list_get_jid(uuid) started = False if status: self.stop(jail) started = True IOCImage().export_jail(uuid, tag, path) if started: self.start(jail) return True
def upgrade(self, job, jail, release): """Upgrades specified jail to specified RELEASE.""" uuid, path, _ = self.check_jail_existence(jail) status, jid = IOCList.list_get_jid(uuid) conf = IOCJson(path).json_load() root_path = f"{path}/root" started = False if conf["type"] == "jail": if not status: self.start(jail) started = True else: return False IOCUpgrade(conf, release, root_path).upgrade_jail() if started: self.stop(jail) return True
def update(self, job, jail): """Updates specified jail to latest patch level.""" from iocage.lib.ioc_fetch import IOCFetch tag, uuid, path = self.check_jail_existence(jail) status, jid = IOCList.list_get_jid(uuid) conf = IOCJson(path).json_load() started = False if conf["type"] == "jail": if not status: self.start(jail) started = True else: return False IOCFetch(conf["cloned_release"]).fetch_update(True, uuid, tag) if started: self.stop(jail) return True
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))
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()))