def build_add_fault_command(shell, params): if not params.has_key('type') or params['type'] not in FAULT_TYPES.keys(): message = 'must be present and one of ' + str(alphabetical_keys(FAULT_TYPES)) exception=MultipleInvalid() exception.add(Invalid(message, ['type'], message)) raise exception return FAULT_TYPES[params['type']](shell, params)
def build_add_fault_command(shell, params): if not params.has_key('type') or params['type'] not in FAULT_TYPES.keys(): message = 'must be present and one of ' + str( alphabetical_keys(FAULT_TYPES)) exception = MultipleInvalid() exception.add(Invalid(message, ['type'], message)) raise exception return FAULT_TYPES[params['type']](shell, params)
def read_config(self): """Reads the configuration properties from the ini file and links the section to comply with the cluster config dictionary format. :return: dictionary containing all configuration properties from the ini file in compliance to the cluster config format :raises: :py:class:`voluptuous.MultipleInvalid` if not all sections present or broken links between secitons """ clusters = dict((key, value) for key, value in self.conf.iteritems() if re.search(ConfigReader.cluster_section + "/(.*)", key) and key.count("/") == 1) conf_values = dict() errors = MultipleInvalid() # FIXME: to be refactored: # we should check independently each one of the sections, and raise errors accordingly. for cluster in clusters: # Get the name of the cluster name = re.search(ConfigReader.cluster_section + "/(.*)", cluster).groups()[0] if not name: errors.add("Invalid section name `%s`" % cluster) continue cluster_conf = dict(self.conf[cluster]) try: self.schemas['cluster'](cluster_conf) except MultipleInvalid as ex: for error in ex.errors: errors.add("Section `%s`: %s" % (cluster, error)) continue cloud_name = ConfigReader.cloud_section + "/" + cluster_conf[ 'cloud'] login_name = ConfigReader.login_section + "/" + cluster_conf[ 'login'] setup_name = ConfigReader.setup_section + "/" + cluster_conf[ 'setup_provider'] values = dict() values['cluster'] = cluster_conf try: values['setup'] = dict(self.conf[setup_name]) self.schemas['setup'](values['setup']) except KeyError, ex: errors.add( "cluster `%s` setup section `%s` does not exists" % ( cluster, setup_name)) except MultipleInvalid, ex: for error in ex.errors: errors.add(error)
def check_assertion_consumer_service(attrs): keys = attrs.keys() if ('AssertionConsumerServiceURL' in keys and 'ProtocolBinding' in keys and 'AssertionConsumerServiceIndex' not in keys): _errors = [] if attrs['ProtocolBinding'] != BINDING_HTTP_POST: _errors.append( Invalid(DEFAULT_VALUE_ERROR.format(BINDING_HTTP_POST), path=['ProtocolBinding'])) if attrs[ 'AssertionConsumerServiceURL'] not in assertion_consumer_service_urls: _errors.append( Invalid(DEFAULT_VALUE_ERROR.format( assertion_consumer_service_urls), path=['AssertionConsumerServiceURL'])) if _errors: raise MultipleInvalid(errors=_errors) return attrs elif ('AssertionConsumerServiceURL' not in keys and 'ProtocolBinding' not in keys and 'AssertionConsumerServiceIndex' in keys): if attrs[ 'AssertionConsumerServiceIndex'] not in assertion_consumer_service_indexes: raise Invalid(DEFAULT_LIST_VALUE_ERROR.format( ', '.join(assertion_consumer_service_indexes)), path=['AssertionConsumerServiceIndex']) return attrs else: raise Invalid( 'Uno e uno solo uno tra gli attributi o gruppi di attributi devono essere presenti: ' '[AssertionConsumerServiceIndex, [AssertionConsumerServiceUrl, ProtocolBinding]]' )
def __call__(self, v): if not isinstance(v, (list, tuple)): raise Invalid(self.msg or 'Value {} is not sequence!'.format(v)) if len(v) != len(self._schemas): raise Invalid(self.msg or 'List lengths differ, value:{} != target:{}'.format(len(v), len(self._schemas))) consumed = set() missing = [] for index, value in enumerate(v): found = False for i, s in enumerate(self._schemas): if i in consumed: continue try: s(value) except Invalid: pass else: found = True consumed.add(i) break if not found: missing.append((index, value)) if len(missing) == 1: el = missing[0] raise Invalid(self.msg or 'Element #{} ({}) is not valid against any validator'.format(el[0], el[1])) elif missing: raise MultipleInvalid([ Invalid(self.msg or 'Element #{} ({}) is not valid against any validator'.format(el[0], el[1])) for el in missing ]) return v
def __init__(self, **kargs): super(EntityBase, self).__init__(kargs) self.validate() try: raise getattr(self, 'error') except AttributeError: pass except Invalid as e: raise MultipleInvalid([e])
def __call__(self, data): """Validate data against this schema.""" try: values = self._compiled([], data) if hasattr(self, 'after_validate'): return self.after_validate(values) return values except MultipleInvalid: raise except Invalid as e: raise MultipleInvalid([e])
def after_validate(self, values): errors = [] for key in values.keys(): method_name = key + '_validator' if hasattr(self, method_name): try: getattr(self, method_name)(values) except Invalid as e: errors.append(ExclusiveInvalid(e.msg, [key])) if errors: raise MultipleInvalid(errors) return values
def test__validate_owncakeydata_exception(mock_Schema): mocked_schema = mock.MagicMock() mocked_schema.side_effect = MultipleInvalid("x") mock_Schema.return_value = mocked_schema with pytest.raises(OnwCAInvalidDataStructure) as err: _validate_owncakeydata( { "key": "key", "key_bytes": "key_bytes", "public_key": "public_key", "public_key_bytes": "public_key_bytes", } ) assert "OnwcaKeyData: " in err.value
def _check_certificate(cert): _errors = [] cert = load_certificate(cert) is_expired = verify_certificate_expiration(cert) has_supported_alg = verify_certificate_algorithm(cert) no_sha1 = verify_bad_certificate_algorithm(cert) if is_expired: _errors.append(Invalid('Il certificato è scaduto.')) if not has_supported_alg: _errors.append( Invalid( 'Il certificato deve essere firmato con un algoritmo valido.')) if not no_sha1: _errors.append( Invalid( 'Il certificato non deve essere firmato tramite algoritmo SHA1 (deprecato).' )) if _errors: raise MultipleInvalid(errors=_errors) return cert
def read_config(self): """Reads the configuration properties from the ini file and links the section to comply with the cluster config dictionary format. :return: tuple of dictionaries (clusters, storage) containing all configuration properties from the ini file in compliance to the cluster config format, and global configuration options for the storage. :raises: :py:class:`voluptuous.MultipleInvalid` if not all sections present or broken links between secitons """ storage_section = self.conf.get('storage', { 'storage_path': Configurator.default_storage_path, 'storage_type': Configurator.default_storage_type}) clusters = dict((key, value) for key, value in self.conf.iteritems() if re.search(ConfigReader.cluster_section + "/(.*)", key) and key.count("/") == 1) conf_values = dict() errors = MultipleInvalid() # FIXME: to be refactored: # we should check independently each one of the sections, and raise errors accordingly. for cluster in clusters: # Get the name of the cluster name = re.search(ConfigReader.cluster_section + "/(.*)", cluster).groups()[0] if not name: errors.add("Invalid section name `%s`" % cluster) continue cluster_conf = dict(self.conf[cluster]) try: self.schemas['cluster'](cluster_conf) except MultipleInvalid as ex: for error in ex.errors: errors.add("Section `%s`: %s" % (cluster, error)) continue cloud_name = ConfigReader.cloud_section + "/" + cluster_conf[ 'cloud'] login_name = ConfigReader.login_section + "/" + cluster_conf[ 'login'] setup_name = ConfigReader.setup_section + "/" + cluster_conf[ 'setup_provider'] values = dict() values['cluster'] = cluster_conf try: values['setup'] = dict(self.conf[setup_name]) self.schemas['setup'](values['setup']) except KeyError as ex: errors.add( "cluster `%s` setup section `%s` does not exists" % ( cluster, setup_name)) except MultipleInvalid as ex: for error in ex.errors: errors.add(error) try: values['login'] = dict(self.conf[login_name]) self.schemas['login'](values['login']) except KeyError as ex: errors.add( "cluster `%s` login section `%s` does not exists" % ( cluster, login_name)) except MultipleInvalid as ex: errors.add(Invalid("Error in login section `%s`: %s" % ( login_name, str.join(', ', [str(e) for e in ex.errors])))) try: values['cloud'] = dict(self.conf[cloud_name]) self.schemas['cloud'](values['cloud']) except KeyError as ex: errors.add( "cluster `%s` cloud section `%s` does not exists" % ( cluster, cloud_name)) except MultipleInvalid as ex: for error in ex.errors: errors.add(Invalid("section %s: %s" % (cloud_name, error))) try: # nodes can inherit the properties of cluster or overwrite them nodes = dict((key, value) for key, value in values['cluster'].items() if key.endswith('_nodes')) values['nodes'] = dict() for node in nodes.iterkeys(): node_name = re.search("(.*)_nodes", node).groups()[0] property_name = "%s/%s/%s" % (ConfigReader.cluster_section, name, node_name) if property_name in self.conf: node_values = dict( (key, value.strip("'").strip('"')) for key, value in self.conf[property_name].iteritems()) node_values = dict( values['cluster'].items() + node_values.items()) values['nodes'][node_name] = node_values else: values['nodes'][node_name] = values['cluster'] if errors.errors: log.error("Ignoring cluster `%s`: %s" % ( name, str.join(", ", [str(e) for e in errors.errors]))) else: conf_values[name] = values except KeyError as ex: errors.add("Error in section `%s`" % cluster) # FIXME: do we really need to raise an exception if we cannot # parse *part* of the configuration files? We should just # ignore those with errors and return both the parsed # configuration values _and_ a list of errors if errors.errors: raise errors return (conf_values, storage_section)
def read_config(self): """Reads the configuration properties from the ini file and links the section to comply with the cluster config dictionary format. :return: tuple of dictionaries (clusters, storage) containing all configuration properties from the ini file in compliance to the cluster config format, and global configuration options for the storage. :raises: :py:class:`voluptuous.MultipleInvalid` if not all sections present or broken links between secitons """ storage_section = self.conf.get( 'storage', { 'storage_path': Configurator.default_storage_path, 'storage_type': Configurator.default_storage_type }) clusters = dict((key, value) for key, value in self.conf.items() if re.search(ConfigReader.cluster_section + "/(.*)", key) and key.count("/") == 1) conf_values = dict() errors = MultipleInvalid() # FIXME: to be refactored: # we should check independently each one of the sections, and raise errors accordingly. for cluster in clusters: # Get the name of the cluster name = re.search(ConfigReader.cluster_section + "/(.*)", cluster).groups()[0] if not name: errors.add("Invalid section name `%s`" % cluster) continue cluster_conf = dict(self.conf[cluster]) try: self.schemas['cluster'](cluster_conf) except MultipleInvalid as ex: for error in ex.errors: errors.add("Section `%s`: %s" % (cluster, error)) continue cloud_name = ConfigReader.cloud_section + "/" + cluster_conf[ 'cloud'] login_name = ConfigReader.login_section + "/" + cluster_conf[ 'login'] setup_name = ConfigReader.setup_section + "/" + cluster_conf[ 'setup_provider'] values = dict() values['cluster'] = cluster_conf try: values['setup'] = dict(self.conf[setup_name]) self.schemas['setup'](values['setup']) except KeyError as ex: errors.add("cluster `%s` setup section `%s` does not exists" % (cluster, setup_name)) except MultipleInvalid as ex: for error in ex.errors: errors.add(error) try: values['login'] = dict(self.conf[login_name]) self.schemas['login'](values['login']) except KeyError as ex: errors.add("cluster `%s` login section `%s` does not exists" % (cluster, login_name)) except MultipleInvalid as ex: errors.add( Invalid("Error in login section `%s`: %s" % (login_name, str.join(', ', [str(e) for e in ex.errors])))) try: values['cloud'] = dict(self.conf[cloud_name]) self.schemas['cloud'](values['cloud']) except KeyError as ex: errors.add("cluster `%s` cloud section `%s` does not exists" % (cluster, cloud_name)) except MultipleInvalid as ex: for error in ex.errors: errors.add(Invalid("section %s: %s" % (cloud_name, error))) try: # nodes can inherit the properties of cluster or overwrite them nodes = dict((key, value) for key, value in values['cluster'].items() if key.endswith('_nodes')) values['nodes'] = dict() for node in nodes.keys(): node_name = re.search("(.*)_nodes", node).groups()[0] property_name = "%s/%s/%s" % (ConfigReader.cluster_section, name, node_name) if property_name in self.conf: node_values = dict( (key, value.strip("'").strip('"')) for key, value in self.conf[property_name].items()) node_values = dict(values['cluster'].items() + node_values.items()) values['nodes'][node_name] = node_values else: values['nodes'][node_name] = values['cluster'] if errors.errors: log.error( "Ignoring cluster `%s`: %s" % (name, str.join(", ", [str(e) for e in errors.errors]))) else: conf_values[name] = values except KeyError as ex: errors.add("Error in section `%s`" % cluster) # FIXME: do we really need to raise an exception if we cannot # parse *part* of the configuration files? We should just # ignore those with errors and return both the parsed # configuration values _and_ a list of errors if errors.errors: raise errors return (conf_values, storage_section)
def server_file_structure(data: dict) -> ServerFileData: """"Transform read data into the elegant form, validating extra things""" errs = [] # Deal with servers servers = data['servers'] server_ids = servers.values() # Deal with servers # NB: this is a dict input; server names are definitely unique servers_output: Dict[str, Server] = { k: Server(k, v) for k, v in servers.items() } # Deal with switches # NB: this is a dict input; switchnames are definitely unique switches = data['switches'] switch_ids = switches.values() switches_output: Dict[str, Switch] = { k: Switch(k, v) for k, v in switches.items() } # Make device set from servers and switches devices_output: Dict[str, Device] = dict(servers_output) devices_output.update(switches_output) if len(servers) + len(switches) != len(devices_output.keys()): errs.append(Invalid("Server shares a name with a switch")) all_ids = list(server_ids) all_ids.extend(switch_ids) if len(server_ids) + len(switch_ids) != len(set(all_ids)): errs.append(Invalid( f"Server [{str(sorted(server_ids))}] " f"and switch [{str(sorted(switch_ids))}] " f"serial numbers are not unique")) try: # Construct racks racks = data['racks'] racks_output: Dict[str, Rack] = {} for rack_name, elems in racks.items(): rack_elems: Dict[int, Device] = {} for loc, dev_name in elems.items(): dev_obj = devices_output.get(dev_name) if dev_obj is None: errs.append( Invalid( f"Rack {rack_name} location {loc}: " f"{dev_name} is an unknown device")) else: rack_elems[loc] = dev_obj racks_output[rack_name] = Rack(dev_name, rack_elems) connections = data['connections'] connections_output: Set[Connection] = set() # Confirm we're connecting devices that we know about. # Transform connections to device references. for rack_name, wires in connections.items(): rack = racks_output.get(rack_name) if rack is None: errs.append(Invalid(f'In connections, {rack_name} ' f'has not been defined')) else: # Sort: gets consistent error ordering. for f in sorted(wires): rack_slot1, port1, rack_slot2, port2 = f def get_dev(loc: int) -> Optional[Device]: assert rack is not None # for typechecking dev = rack.devices.get(loc) if dev is None: errs.append( Invalid( f'In connections, RU #{loc} ' f'in {rack_name} has no device')) return dev rack_dev1 = get_dev(rack_slot1) rack_dev2 = get_dev(rack_slot2) if rack_dev1 is not None and rack_dev2 is not None: conn = Connection(rack_dev1, port1, rack_dev2, port2) if conn in connections_output: errs.append( Invalid( f"Duplicate connection: " f"slot#{rack_slot1}:port#{port1} " f"-> slot#{rack_slot2}:port#{port2} " f"results in {conn.text()} - " "do you have the reverse " "connection listed?")) else: connections_output.add(conn) except Exception as e: import traceback traceback.print_exc() raise if errs: raise MultipleInvalid(errs) return ServerFileData( servers_output, switches_output, devices_output, racks_output, connections_output)