def clean(self, data): data = super().clean(data) if data is None: if self.null: return None return copy.deepcopy(self.default) if not isinstance(data, dict): raise Error(self.name, 'A dict was expected') verrors = ValidationErrors() for key, value in list(data.items()): if not self.additional_attrs: if key not in self.attrs: verrors.add(f'{self.name}.{key}', 'Field was not expected') continue attr = self.attrs.get(key) if not attr: continue data[key] = self._clean_attr(attr, value, verrors) # Do not make any field and required and not populate default values if not self.update: data.update(self.get_defaults(data, self.get_attrs_to_skip(data), verrors)) verrors.check() return data
def validate(self, value): super().validate(value) verrors = ValidationErrors() uri = urlparse(value) if not all(getattr(uri, k) for k in ('scheme', 'netloc')): verrors.add(self.name, 'Not a valid URI') verrors.check()
def _do_create(self, job, data): self.middleware.call_sync('jail.check_dataset_existence') verrors = ValidationErrors() branch = data.pop('branch') or self.get_version() install_notes = '' plugin_name = data.pop('plugin_name') jail_name = data.pop('jail_name') plugin_repository = data.pop('plugin_repository') post_install = False job.set_progress(0, f'Creating plugin: {plugin_name}') if jail_name in [ j['id'] for j in self.middleware.call_sync('jail.query') ]: verrors.add('plugin_create.jail_name', f'A jail with name {jail_name} already exists') else: verrors = common_validation(self.middleware, data, schema='plugin_create') verrors.check() job.set_progress(20, 'Initial validation complete') def progress_callback(content, exception): msg = content['message'].strip('\r\n') nonlocal install_notes, post_install if post_install and msg: install_notes += f'\n{msg}' if ' These pkgs will be installed:' in msg: job.set_progress(50, msg) elif 'Installing plugin packages:' in msg: job.set_progress(75, msg) elif 'Running post_install.sh' in msg: job.set_progress(90, msg) # Sets each message going forward as important to the user post_install = True else: job.set_progress(None, msg) ioc.IOCage(callback=progress_callback, silent=False).fetch( **{ 'accept': True, 'name': jail_name, 'plugin_name': plugin_name, 'git_repository': plugin_repository, 'props': data['props'], 'branch': branch, }) new_plugin = self.middleware.call_sync('plugin._get_instance', jail_name) new_plugin['install_notes'] = install_notes.strip() return new_plugin
def validate(self, value): if value is None: return verrors = ValidationErrors() if not dn.is_dn(value): verrors.add(self.name, "Invalid LDAP DN specified.") verrors.check() return super().validate(value)
def ping_remote(self, options): """ Method that will send an ICMP echo request to "hostname" and will wait up to "timeout" for a reply. """ ip = None ip_found = True verrors = ValidationErrors() try: ip = IpAddress() ip(options['hostname']) ip = options['hostname'] except ValueError: ip_found = False if not ip_found: try: if options['type'] == 'ICMP': ip = socket.getaddrinfo(options['hostname'], None)[0][4][0] elif options['type'] == 'ICMPV4': ip = socket.getaddrinfo(options['hostname'], None, socket.AF_INET)[0][4][0] elif options['type'] == 'ICMPV6': ip = socket.getaddrinfo(options['hostname'], None, socket.AF_INET6)[0][4][0] except socket.gaierror: verrors.add( 'options.hostname', f'{options["hostname"]} cannot be resolved to an IP address.' ) verrors.check() addr = ipaddress.ip_address(ip) if not addr.version == 4 and (options['type'] == 'ICMP' or options['type'] == 'ICMPV4'): verrors.add( 'options.type', f'Requested ICMPv4 protocol, but the address provided "{addr}" is not a valid IPv4 address.' ) if not addr.version == 6 and options['type'] == 'ICMPV6': verrors.add( 'options.type', f'Requested ICMPv6 protocol, but the address provided "{addr}" is not a valid IPv6 address.' ) verrors.check() ping_host = False if addr.version == 4: ping_host = self._ping_host(ip, options['timeout']) elif addr.version == 6: ping_host = self._ping6_host(ip, options['timeout']) return ping_host
def validate(self, value): if value is None: return value verrors = ValidationErrors() if value and len(str(value)) > self.max_length: verrors.add(self.name, f'Value greater than {self.max_length} not allowed') verrors.check() return super().validate(value)
async def validate(self, data, dev): verrors = ValidationErrors() unavail = [ i for i in data['capabilities'] if i not in dev.supported_capabilities ] if unavail: # gave us a capability that isn't supported on the device # or is "fixed" (meaning it can't be changed) verrors.add( f'capabilities_set.{data["action"]}', f'"{data["name"]}" does not support "{", ".join(unavail)}"') verrors.check()
def validate(self, value): if value is None: return verrors = ValidationErrors() if value: if not os.path.exists(value): verrors.add(self.name, "This path does not exist.", errno.ENOENT) self.validate_internal(verrors, value) verrors.check() return super().validate(value)
def validate_return_type(func, result, schemas): if not schemas and result is None: return elif not schemas: raise ValueError(f'Return schema missing for {func.__name__!r}') result = copy.deepcopy(result) if not isinstance(result, tuple): result = [result] verrors = ValidationErrors() for res_entry, schema in zip(result, schemas): clean_and_validate_arg(verrors, schema, res_entry) verrors.check()
def validate(self, value): verrors = ValidationErrors() attr_verrors = ValidationErrors() for attr in self.schemas: try: attr.validate(value) except TypeError: pass except ValidationErrors as e: attr_verrors.extend(e) else: break else: verrors.extend(attr_verrors) verrors.check()
def clone(self, job, source_jail, options): verrors = ValidationErrors() try: self.check_jail_existence(source_jail, skip=False) except CallError: verrors.add('source_jail', f'{source_jail} does not exist.', errno.ENOENT) else: try: self.check_jail_existence(options['uuid'], skip=False) except CallError: pass else: verrors.add( 'clone_jail.uuid', f'Jail with "{options["uuid"]}" uuid already exists.', errno.EEXIST) verrors.check() verrors = common_validation(self.middleware, options, schema='clone_jail') verrors.check() job.set_progress(25, 'Initial validation complete.') ioc.IOCage(jail=source_jail, skip_jails=True).create(source_jail, options['props'], _uuid=options['uuid'], thickjail=options['thickjail'], clone=True) job.set_progress(100, 'Jail has been successfully cloned.') return self.middleware.call_sync('jail._get_instance', options['uuid'])
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