def cli(force, delete): """Migrates all the iocage_legacy develop basejails to clone jails.""" # TODO: Move to API jails = ioc_list.IOCList("uuid").list_datasets() if not force: ioc_common.logit({ "level": "WARNING", "message": "\nThis will migrate ALL iocage-legacy develop" " basejails to clonejails, it can take a long" " time!\nPlease make sure you are not running" " this on iocage-legacy 1.7.6 basejails." }) if not click.confirm("\nAre you sure?"): exit() for uuid, path in jails.items(): pool = ioc_json.IOCJson().json_get_value("pool") iocroot = ioc_json.IOCJson(pool).json_get_value("iocroot") jail = f"{pool}/iocage/jails/{uuid}" jail_old = f"{pool}/iocage/jails_old/{uuid}" conf = ioc_json.IOCJson(path).json_load() try: tag = conf["tag"] except KeyError: # These are actually NEW jails. continue release = conf["cloned_release"] if conf["type"] == "basejail": try: ioc_common.checkoutput(["zfs", "rename", "-p", jail, jail_old], stderr=su.STDOUT) except su.CalledProcessError as err: ioc_common.logit( { "level": "EXCEPTION", "message": f"{err.output.decode('utf-8').strip()}" }, exit_on_error=True) try: os.remove(f"{iocroot}/tags/{tag}") except OSError: pass date_fmt_legacy = "%Y-%m-%d@%H:%M:%S" # We don't want to rename datasets to a bunch of dates. try: datetime.datetime.strptime(tag, date_fmt_legacy) _name = str(uuid.uuid4()) except ValueError: # They already named this jail, making it like our new ones. _name = tag new_uuid = ioc_create.IOCCreate(release, "", 0, None, migrate=True, config=conf, silent=True, uuid=_name, exit_on_error=True).create_jail() new_prop = ioc_json.IOCJson(f"{iocroot}/jails/{new_uuid}", silent=True).json_set_value new_prop(f"host_hostname={new_uuid}") new_prop(f"host_hostuuid={new_uuid}") new_prop("type=jail") new_prop(f"jail_zfs_dataset={iocroot}/jails/{new_uuid}/data") ioc_common.logit({ "level": "INFO", "message": f"Copying files for {new_uuid}, please wait..." }) ioc_common.copytree(f"{iocroot}/jails_old/{uuid}/root", f"{iocroot}/jails/{new_uuid}/root", symlinks=True) shutil.copy(f"{iocroot}/jails_old/{uuid}/fstab", f"{iocroot}/jails/{new_uuid}/fstab") for line in fileinput.input( f"{iocroot}/jails/{new_uuid}/root/etc/" "rc.conf", inplace=1): print( line.replace(f'hostname="{uuid}"', f'hostname="{new_uuid}"').rstrip()) if delete: try: ioc_common.checkoutput( ["zfs", "destroy", "-r", "-f", jail_old], stderr=su.STDOUT) except su.CalledProcessError as err: raise RuntimeError( f"{err.output.decode('utf-8').rstrip()}") try: su.check_call([ "zfs", "destroy", "-r", "-f", f"{pool}/iocage/jails_old" ]) except su.CalledProcessError: # We just want the top level dataset gone, no big deal. pass ioc_common.logit({ "level": "INFO", "message": f"{uuid} ({tag}) migrated to {new_uuid}!\n" })
def create(self, release, props, count=0, pkglist=None, template=False, short=False, _uuid=None, basejail=False, empty=False, clone=None, skip_batch=False): """Creates the jail dataset""" count = 0 if count == 1 and not skip_batch else count if short and _uuid: _uuid = _uuid[:8] if len(_uuid) != 8: ioc_common.logit( { "level": "EXCEPTION", "message": "Need a minimum of 8 characters to use --short" " (-s) and --uuid (-u) together!" }, _callback=self.callback, silent=self.silent) if not template and not release and not empty and not clone: ioc_common.logit( { "level": "EXCEPTION", "message": "Must supply either --template (-t) or" " --release (-r)!" }, _callback=self.callback, silent=self.silent) if not os.path.isdir( f"{self.iocroot}/releases/{release}") and not template and \ not empty and not clone: freebsd_version = ioc_common.checkoutput(["freebsd-version"]) if "HBSD" in freebsd_version: hardened = True else: hardened = False ioc_fetch.IOCFetch(release, hardened=hardened, silent=self.silent).fetch_release() if clone: clone_uuid, _ = self.__check_jail_existence__() status, _ = self.list("jid", uuid=clone_uuid) if status: ioc_common.logit( { "level": "EXCEPTION", "message": f"Jail: {self.jail} must not be running to be" " cloned!" }, _callback=self.callback, silent=self.silent) release = clone_uuid clone = self.jail try: if count > 1 and not skip_batch: for j in range(1, count + 1): try: if _uuid is not None: uuid.UUID(_uuid, version=4) count_uuid = _uuid # Is a UUID except ValueError: # This will allow named jails to use count # This can probably be smarter count_uuid = f"{_uuid}_{j}" self.create(release, props, j, pkglist=pkglist, template=template, short=short, _uuid=count_uuid, basejail=basejail, empty=empty, clone=clone, skip_batch=True) else: ioc_create.IOCCreate(release, props, count, pkglist, template=template, short=short, uuid=_uuid, basejail=basejail, empty=empty, clone=clone, silent=self.silent).create_jail() except RuntimeError: raise return False, None
def create(self, release, props, count=0, pkglist=None, template=False, short=False, uuid=None, basejail=False, empty=False, clone=None): if short and uuid: uuid = uuid[:8] if len(uuid) != 8: ioc_common.logit( { "level": "EXCEPTION", "message": "Need a minimum of 8 characters to use --short" " (-s) and --uuid (-u) together!" }, _callback=self.callback, silent=self.silent) if not template and not release and not empty and not clone: ioc_common.logit( { "level": "EXCEPTION", "message": "Must supply either --template (-t) or" " --release (-r)!" }, _callback=self.callback, silent=self.silent) if not os.path.isdir( f"{self.iocroot}/releases/{release}") and not template and \ not empty and not clone: freebsd_version = ioc_common.checkoutput(["freebsd-version"]) if "HBSD" in freebsd_version: hardened = True else: hardened = False ioc_fetch.IOCFetch(release, hardened=hardened).fetch_release() if clone: _, clone_uuid, _ = self.__check_jail_existence__() status, _ = self.list("jid", uuid=clone_uuid) if status: ioc_common.logit( { "level": "EXCEPTION", "message": f"Jail: {self.jail} must not be running to be" " cloned!" }, _callback=self.callback, silent=self.silent) release = clone_uuid clone = self.jail try: ioc_create.IOCCreate(release, props, count, pkglist, template=template, short=short, uuid=uuid, basejail=basejail, empty=empty, clone=clone).create_jail() except RuntimeError as err: return True, err return False, None
def cli(force, delete): """Migrates all the iocage_legacy develop basejails to clone jails.""" jails, paths = ioc_list.IOCList("uuid").list_datasets() if not force: ioc_common.logit({ "level": "WARNING", "message": "\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 = ioc_json.IOCJson().json_get_value("pool") iocroot = ioc_json.IOCJson(pool).json_get_value("iocroot") jail = f"{pool}/iocage/jails/{uuid}" jail_old = f"{pool}/iocage/jails_old/{uuid}" path = paths[tag] conf = ioc_json.IOCJson(path).json_load() release = conf["release"] if conf["type"] == "basejail": try: ioc_common.checkoutput(["zfs", "rename", "-p", jail, jail_old], stderr=su.STDOUT) except su.CalledProcessError as err: ioc_common.logit({ "level": "ERROR", "message": f"{err.output.decode('utf-8').strip()}" }) exit(1) try: os.remove(f"{iocroot}/tags/{tag}") except OSError: pass new_uuid = ioc_create.IOCCreate(release, "", 0, None, migrate=True, config=conf, silent=True).create_jail() new_prop = ioc_json.IOCJson(f"{iocroot}/jails/{new_uuid}", silent=True).json_set_value new_prop(f"host_hostname={new_uuid}") new_prop(f"host_hostuuid={new_uuid}") new_prop("type=jail") new_prop(f"jail_zfs_dataset={iocroot}/jails/{new_uuid}/data") ioc_common.logit({ "level": "INFO", "message": "Copying files for {uuid} ({tag}), please wait..." }) ioc_common.copytree(f"{iocroot}/jails_old/{uuid}/root", f"{iocroot}/jails/{new_uuid}/root", symlinks=True) shutil.copy(f"{iocroot}/jails_old/{uuid}/fstab", f"{iocroot}/jails/{new_uuid}/fstab") for line in fileinput.input( f"{iocroot}/jails/{new_uuid}/root/etc/" "rc.conf", inplace=1): ioc_common.logit({ "level": "INFO", "message": line.replace(f'hostname="{uuid}"', f'hostname="{new_uuid}"').rstrip() }) if delete: try: ioc_common.checkoutput( ["zfs", "destroy", "-r", "-f", jail_old], stderr=su.STDOUT) except su.CalledProcessError as err: raise RuntimeError( f"{err.output.decode('utf-8').rstrip()}") try: su.check_call([ "zfs", "destroy", "-r", "-f", f"{pool}/iocage/jails_old" ]) except su.CalledProcessError: # We just want the top level dataset gone, no big deal. pass ioc_common.logit({ "level": "INFO", "message": f"{uuid} ({tag}) migrated to {new_uuid}" f" ({tag})!\n" })