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 stop(self, jail): """Takes a jail and stops it.""" uuid, _, iocage = self.check_jail_existence(jail) status, _ = IOCList.list_get_jid(uuid) if status: iocage.stop() return True
def stop(self, job, jail, force): """Takes a jail and stops it.""" uuid, _, iocage = self.check_jail_existence(jail) status, _ = IOCList.list_get_jid(uuid) if status: try: iocage.stop(force=force) except Exception as e: raise CallError(str(e)) return True
def start(self, job, jail): """Takes a jail and starts it.""" uuid, _, iocage = self.check_jail_existence(jail) status, _ = IOCList.list_get_jid(uuid) if not status: try: iocage.start() except BaseException as e: raise CallError(str(e)) return True
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""" uuid, path, _ = self.check_jail_existence(jail) status, jid = IOCList.list_get_jid(uuid) started = False if status: self.middleware.call_sync('jail.stop', jail, job=True) started = True IOCImage().export_jail(uuid, path) if started: self.middleware.call_sync('jail.start', jail, job=True) 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 fstab(self, jail, options): """Adds an fstab mount to the jail""" uuid, _, iocage = self.check_jail_existence(jail, skip=False) status, jid = IOCList.list_get_jid(uuid) action = options['action'].lower() if status and action != 'list': raise CallError( f'{jail} should not be running when adding a mountpoint') verrors = ValidationErrors() source = options.get('source') if source: if not os.path.exists(source): verrors.add( 'options.source', 'Provided path for source does not exist' ) source = source.replace(' ', r'\040') # fstab hates spaces ;) destination = options.get('destination') if destination: destination = f'/{destination}' if destination[0] != '/' else destination dst = f'{self.get_iocroot()}/jails/{jail}/root' if dst not in destination: destination = f'{dst}{destination}' if os.path.exists(destination): if not os.path.isdir(destination): verrors.add( 'options.destination', 'Destination is not a directory, please provide a valid destination' ) elif os.listdir(destination): verrors.add( 'options.destination', 'Destination directory should be empty' ) else: os.makedirs(destination) # fstab hates spaces ;) destination = destination.replace(' ', r'\040') if action != 'list': for f in options: if not options.get(f) and f not in ('index',): verrors.add( f'options.{f}', 'This field is required' ) fstype = options.get('fstype') fsoptions = options.get('fsoptions') dump = options.get('dump') _pass = options.get('pass') index = options.get('index') if action == 'replace' and index is None: verrors.add( 'options.index', 'Index must not be None when replacing fstab entry' ) if verrors: raise verrors _list = iocage.fstab(action, source, destination, fstype, fsoptions, dump, _pass, index=index) if action == "list": split_list = {} system_mounts = ( '/root/bin', '/root/boot', '/root/lib', '/root/libexec', '/root/rescue', '/root/sbin', '/root/usr/bin', '/root/usr/include', '/root/usr/lib', '/root/usr/libexec', '/root/usr/sbin', '/root/usr/share', '/root/usr/libdata', '/root/usr/lib32' ) for i in _list: fstab_entry = i[1].split() _fstab_type = 'SYSTEM' if fstab_entry[0].endswith( system_mounts) else 'USER' split_list[i[0]] = {'entry': fstab_entry, 'type': _fstab_type} return split_list return True
def fstab(self, jail, options): """Manipulate a jails fstab""" uuid, _, iocage = self.check_jail_existence(jail, skip=False) status, jid = IOCList.list_get_jid(uuid) action = options['action'].lower() index = options.get('index') if status and action != 'list': raise CallError( f'{jail} should not be running when adding a mountpoint') verrors = ValidationErrors() if action in ('add', 'replace', 'remove'): if action != 'remove' or index is None: # For remove we allow removing by index or mount, so if index is not specified # we should validate that rest of the fields exist. for f in ('source', 'destination', 'fstype', 'fsoptions', 'dump', 'pass'): if not options.get(f): verrors.add( f'options.{f}', f'This field is required with "{action}" action.') if action == 'replace' and index is None: verrors.add( 'options.index', 'Index cannot be "None" when replacing an fstab entry.') verrors.check() source = options.get('source') if action in ('add', 'replace') and not os.path.exists(source): verrors.add('options.source', 'The provided path for the source does not exist.') destination = options.get('destination') if destination: destination = f'/{destination}' if destination[0] != '/' else \ destination dst = f'{self.get_iocroot()}/jails/{jail}/root' if dst not in destination: destination = f'{dst}{destination}' if os.path.exists(destination): if not os.path.isdir(destination): verrors.add( 'options.destination', 'Destination is not a directory. Please provide a ' 'empty directory for the destination.') elif os.listdir(destination): verrors.add('options.destination', 'Destination directory must be empty.') else: os.makedirs(destination) # Setup defaults for library source = source or '' destination = destination or '' fstype = options.get('fstype') fsoptions = options.get('fsoptions') dump = options.get('dump') _pass = options.get('pass') if verrors: raise verrors try: _list = iocage.fstab(action, source, destination, fstype, fsoptions, dump, _pass, index=index) except ioc_exceptions.ValidationFailed as e: # CallError uses strings, the exception message may not always be a # list. if not isinstance(e.message, str) and isinstance( e.message, Iterable): e.message = '\n'.join(e.message) self.logger.error(f'{e!r}') raise CallError(e.message) if action == "list": split_list = {} system_mounts = ('/root/bin', '/root/boot', '/root/lib', '/root/libexec', '/root/rescue', '/root/sbin', '/root/usr/bin', '/root/usr/include', '/root/usr/lib', '/root/usr/libexec', '/root/usr/sbin', '/root/usr/share', '/root/usr/libdata', '/root/usr/lib32') for i in _list: fstab_entry = i[1] _fstab_type = 'SYSTEM' if fstab_entry[0].endswith( system_mounts) else 'USER' split_list[i[0]] = {'entry': fstab_entry, 'type': _fstab_type} return split_list return True