def check_power_manage(power_manage): """Check power manage format is correct.""" if not power_manage: return if not isinstance(power_manage, dict): raise exception.InvalidParameter( 'invalid power manage %s' % power_manage ) for key in power_manage: if key not in ['ip', 'username', 'password']: raise exception.InvalidParameter( 'unrecognized field %s in power manage %s' % ( key, power_manage ) ) for key in ['ip', 'username', 'password']: if key not in power_manage: raise exception.InvalidParameter( 'no field %s in power manage %s' % ( key, power_manage ) ) check_power_manage_field = '_check_power_manage_%s' % key this_module = globals() if check_power_manage_field in this_module: this_module[check_power_manage_field]( power_manage[key] ) else: logging.debug( 'function %s is not defined', check_power_manage_field )
def validate_host(host): """Validate host. Makesure hostname is not empty, there is only one mgmt network, The mgmt network is not in promiscuous mode. """ if not host.hostname: raise exception.Invalidparameter('host %s does not set hostname' % host.name) if not host.host_networks: raise exception.InvalidParameter('host %s does not have any network' % host.name) mgmt_interface_set = False for host_network in host.host_networks: if host_network.is_mgmt: if mgmt_interface_set: raise exception.InvalidParameter( 'host %s multi interfaces set mgmt ' % host.name) if host_network.is_promiscuous: raise exception.InvalidParameter( 'host %s interface %s is mgmt but promiscuous' % (host.name, host_network.interface)) mgmt_interface_set = True if not mgmt_interface_set: raise exception.InvalidParameter('host %s has no mgmt interface' % host.name)
def check_switch_credentials(credentials): """Check switch credentials format is correct.""" if not credentials: return if not isinstance(credentials, dict): raise exception.InvalidParameter( 'credentials %s is not dict' % credentials ) for key in credentials: if key not in ['version', 'community']: raise exception.InvalidParameter( 'unrecognized key %s in credentials %s' % (key, credentials) ) for key in ['version', 'community']: if key not in credentials: raise exception.InvalidParameter( 'there is no %s field in credentials %s' % (key, credentials) ) key_check_func_name = '_check_switch_credentials_%s' % key this_module = globals() if key_check_func_name in this_module: this_module[key_check_func_name]( credentials[key] ) else: logging.debug( 'function %s is not defined', key_check_func_name )
def wrapper(*args, **filters): wrapped_func = get_wrapped_func(func) argspec = inspect.getargspec(wrapped_func) wrapped_args = argspec.args args_defaults = argspec.defaults # wrapped_must_args are positional args caller must pass in. if args_defaults: wrapped_must_args = wrapped_args[:-len(args_defaults)] else: wrapped_must_args = wrapped_args[:] # make sure any positional args without default value in # decorated function should appear in args or filters. if len(args) < len(wrapped_must_args): remain_args = wrapped_must_args[len(args):] for remain_arg in remain_args: if remain_arg not in filters: raise exception.InvalidParameter( 'function missing declared arg %s ' 'while caller sends args %s' % (remain_arg, args)) # make sure args should be no more than positional args # declared in decorated function. if len(args) > len(wrapped_args): raise exception.InvalidParameter( 'function definition args %s while the caller ' 'sends args %s' % (wrapped_args, args)) # exist_args are positional args caller has given. exist_args = dict(zip(wrapped_args, args)).keys() must_support_keys = set(support_keys) all_support_keys = must_support_keys | set(optional_support_keys) wrapped_supported_keys = set(filters) | set(exist_args) unsupported_keys = (set(filters) - set(wrapped_args) - all_support_keys - set(ignore_support_keys)) # unsupported_keys are the keys that are not in support_keys, # optional_support_keys, ignore_support_keys and are not passed in # by positional args. It means the decorated function may # not understand these parameters. if unsupported_keys: raise exception.InvalidParameter( 'filter keys %s are not supported for %s' % (list(unsupported_keys), wrapped_func)) # missing_keys are the keys that must exist but missing in # both positional args or kwargs. missing_keys = must_support_keys - wrapped_supported_keys if missing_keys: raise exception.InvalidParameter( 'filter keys %s not found for %s' % (list(missing_keys), wrapped_func)) # We filter kwargs to eliminate ignore_support_keys in kwargs # passed to decorated function. filtered_filters = dict([(key, value) for key, value in filters.items() if key not in ignore_support_keys]) return func(*args, **filtered_filters)
def _check_vlans(vlans): """Check vlans format is acceptable.""" for vlan in vlans: if not isinstance(vlan, int): raise exception.InvalidParameter( 'vlan %s is not int' % vlan )
def check_ip(ip): """Check ip is ip address formatted.""" try: netaddr.IPAddress(ip) except Exception as error: logging.exception(error) raise exception.InvalidParameter('ip address %s format uncorrect' % ip)
def check_mac(mac): """Check mac is mac address formatted.""" try: netaddr.EUI(mac) except Exception as error: logging.exception(error) raise exception.InvalidParameter('invalid mac address %s' % mac)
def autofill_os_config(config, os_id, **kwargs): load_metadatas() if os_id not in OS_METADATA_MAPPING: raise exception.InvalidParameter( 'os %s is not found in os metadata mapping' % os_id) return _autofill_config('', config, OS_METADATA_MAPPING[os_id], **kwargs)
def _get_host(host_id, session=None, **kwargs): """Get host by id.""" if isinstance(host_id, (int, long)): return utils.get_db_object(session, models.Host, id=host_id, **kwargs) else: raise exception.InvalidParameter( 'host id %s type is not int compatible' % host_id)
def check_name(name): """Check name meeting name format requirement.""" if not NAME_PATTERN.match(name): raise exception.InvalidParameter( 'name %s does not match the pattern %s' % ( name, NAME_PATTERN.pattern ) )
def autofill_package_config(config, adapter_id, **kwargs): load_metadatas() if adapter_id not in PACKAGE_METADATA_MAPPING: raise exception.InvalidParameter( 'adapter %s is not found in package metadata mapping' % adapter_id) return _autofill_config('', config, PACKAGE_METADATA_MAPPING[adapter_id], **kwargs)
def _validate_self(config_path, config_key, config, metadata, whole_check, **kwargs): """validate config by metadata self section.""" logging.debug('validate config self %s', config_path) if '_self' not in metadata: if isinstance(config, dict): _validate_config(config_path, config, metadata, whole_check, **kwargs) return field_type = metadata['_self'].get('field_type', basestring) if not isinstance(config, field_type): raise exception.InvalidParameter('%s config type is not %s: %s' % (config_path, field_type, config)) is_required = metadata['_self'].get('is_required', False) required_in_whole_config = metadata['_self'].get( 'required_in_whole_config', False) if isinstance(config, basestring): if config == '' and not is_required and not required_in_whole_config: # ignore empty config when it is optional return required_in_options = metadata['_self'].get('required_in_options', False) options = metadata['_self'].get('options', None) if required_in_options: if field_type in [int, basestring, float, bool]: if options and config not in options: raise exception.InvalidParameter( '%s config is not in %s: %s' % (config_path, options, config)) elif field_type in [list, tuple]: if options and not set(config).issubset(set(options)): raise exception.InvalidParameter( '%s config is not in %s: %s' % (config_path, options, config)) elif field_type == dict: if options and not set(config.keys()).issubset(set(options)): raise exception.InvalidParameter( '%s config is not in %s: %s' % (config_path, options, config)) validator = metadata['_self'].get('validator', None) logging.debug('validate by validator %s', validator) if validator: if not validator(config_key, config, **kwargs): raise exception.InvalidParameter('%s config is invalid' % config_path) if isinstance(config, dict): _validate_config(config_path, config, metadata, whole_check, **kwargs)
def _check_subnet(subnet): """Check subnet format is correct.""" try: netaddr.IPNetwork(subnet) except Exception as error: logging.exception(error) raise exception.InvalidParameter('subnet %s format unrecognized' % subnet)
def validate_package_config(config, adapter_id, whole_check=False, **kwargs): """Validate package config.""" load_metadatas() if adapter_id not in PACKAGE_METADATA_MAPPING: raise exception.InvalidParameter( 'adapter %s is not found in package metedata mapping' % adapter_id) _validate_config('', config, PACKAGE_METADATA_MAPPING[adapter_id], whole_check, **kwargs)
def validate_os_config(config, os_id, whole_check=False, **kwargs): """Validate os config.""" load_metadatas() if os_id not in OS_METADATA_MAPPING: raise exception.InvalidParameter( 'os %s is not found in os metadata mapping' % os_id) _validate_config('', config, OS_METADATA_MAPPING[os_id], whole_check, **kwargs)
def _get_machine(machine_id, session=None, **kwargs): """Get machine by id.""" if isinstance(machine_id, (int, long)): return utils.get_db_object(session, models.Machine, id=machine_id, **kwargs) raise exception.InvalidParameter( 'machine id %s type is not int compatible' % machine_id)
def _get_permission(permission_id, session=None, **kwargs): """Get permission object by the unique key of Permission table.""" if isinstance(permission_id, (int, long)): return utils.get_db_object(session, models.Permission, id=permission_id, **kwargs) raise exception.InvalidParameter( 'permission id %s type is not int compatible' % permission_id)
def _get_switch(switch_id, session=None, **kwargs): """Get Switch object switch id.""" if isinstance(switch_id, (int, long)): return utils.get_db_object(session, models.Switch, id=switch_id, **kwargs) raise exception.InvalidParameter( 'switch id %s type is not int compatible' % switch_id)
def _get_subnet(subnet_id, session=None, **kwargs): """Get subnet by subnet id.""" if isinstance(subnet_id, (int, long)): return utils.get_db_object(session, models.Subnet, id=subnet_id, **kwargs) raise exception.InvalidParameter( 'subnet id %s type is not int compatible' % subnet_id)
def add_db_object(session, table, exception_when_existing=True, *args, **kwargs): """Create db object. If not exception_when_existing and the db object exists, Instead of raising exception, updating the existing db object. """ if not session: raise exception.DatabaseException('session param is None') with session.begin(subtransactions=True): logging.debug( 'session %s add object %s atributes %s to table %s', id(session), args, kwargs, table.__name__) argspec = inspect.getargspec(table.__init__) arg_names = argspec.args[1:] arg_defaults = argspec.defaults if not arg_defaults: arg_defaults = [] if not ( len(arg_names) - len(arg_defaults) <= len(args) <= len(arg_names) ): raise exception.InvalidParameter( 'arg names %s does not match arg values %s' % ( arg_names, args) ) db_keys = dict(zip(arg_names, args)) if db_keys: db_object = session.query(table).filter_by(**db_keys).first() else: db_object = None new_object = False if db_object: logging.debug( 'got db object %s: %s', db_keys, db_object ) if exception_when_existing: raise exception.DuplicatedRecord( '%s exists in table %s' % (db_keys, table.__name__) ) else: db_object = table(**db_keys) new_object = True for key, value in kwargs.items(): setattr(db_object, key, value) if new_object: session.add(db_object) session.flush() db_object.initialize() db_object.validate() logging.debug( 'session %s db object %s added', id(session), db_object ) return db_object
def _get_switchmachine(switch_machine_id, session=None, **kwargs): """Get switch machine by switch_machine_id.""" if not isinstance(switch_machine_id, (int, long)): raise exception.InvalidParameter( 'switch machine id %s type is not int compatible' % (switch_machine_id)) return utils.get_db_object(session, models.SwitchMachine, switch_machine_id=switch_machine_id, **kwargs)
def autofill_flavor_config(config, flavor_id, **kwargs): load_metadatas() if not flavor_id: logging.info('There is no flavor, skipping...') elif flavor_id not in FLAVOR_METADATA_MAPPING: raise exception.InvalidParameter( 'flavor %s is not found in flavor metadata mapping' % flavor_id) else: return _autofill_config('', config, FLAVOR_METADATA_MAPPING[flavor_id], **kwargs)
def _add_machine(mac, owner_id=None, session=None, **kwargs): """Add a machine.""" if isinstance(owner_id, (int, long)): return utils.add_db_object(session, models.Machine, True, mac, owner_id=owner_id, **kwargs) raise exception.InvalidParameter('owner id %s type is not int compatible' % owner_id)
def validate_flavor_config(config, flavor_id, whole_check=False, **kwargs): """Validate flavor config.""" load_metadatas() if not flavor_id: logging.info('There is no flavor, skipping flavor validation...') elif flavor_id not in FLAVOR_METADATA_MAPPING: raise exception.InvalidParameter( 'flavor %s is not found in flavor metedata mapping' % flavor_id) else: _validate_config('', config, FLAVOR_METADATA_MAPPING[flavor_id], whole_check, **kwargs)
def _check_ip_range(ip_ranges): """Check if the ip range is valid. The valid range can be a range or individual ips. Range should be two ips jointed with "-", different ip ranges and ips should be separated by "," e.g. "10.1.0.0-10.1.0.50, 10.1.0.60" """ for ip_range in ip_ranges.split(','): ip_ends = ip_range.split('-') try: ipaddress.IPv4Address(ip_ends[0].decode()) if len(ip_ends) == 2: ipaddress.IPv4Address(ip_ends[1].decode()) except Exception as error: logging.exception(error) raise exception.InvalidParameter( 'ip range %s format unrecognized' % ip_ranges) finally: if len(ip_ends) > 2: raise exception.InvalidParameter( 'ip range %s format unrecognized' % ip_ranges)
def _validate_config(config_path, config, metadata, whole_check, **kwargs): """validate config by metadata.""" logging.debug('validate config %s', config_path) generals = {} specified = {} for key, value in metadata.items(): if key.startswith('$'): generals[key] = value elif key.startswith('_'): pass else: specified[key] = value config_keys = set(config.keys()) specified_keys = set(specified.keys()) intersect_keys = config_keys & specified_keys not_found_keys = config_keys - specified_keys redundant_keys = specified_keys - config_keys for key in redundant_keys: if '_self' not in specified[key]: continue if specified[key]['_self'].get('is_required', False): raise exception.InvalidParameter( '%s/%s does not find but it is required' % (config_path, key)) if (whole_check and specified[key]['_self'].get( 'required_in_whole_config', False)): raise exception.InvalidParameter( '%s/%s does not find but it is required in whole config' % (config_path, key)) for key in intersect_keys: _validate_self('%s/%s' % (config_path, key), key, config[key], specified[key], whole_check, **kwargs) for key in not_found_keys: if not generals: raise exception.InvalidParameter('key %s missing in metadata %s' % (key, config_path)) for general_key, general_value in generals.items(): _validate_self('%s/%s' % (config_path, key), key, config[key], general_value, whole_check, **kwargs)
def check_ipmi_credentials(ipmi_credentials): """Check ipmi credentials format is correct.""" if not ipmi_credentials: return if not isinstance(ipmi_credentials, dict): raise exception.InvalidParameter('invalid ipmi credentials %s' % ipmi_credentials) for key in ipmi_credentials: if key not in ['ip', 'username', 'password']: raise exception.InvalidParameter( 'unrecognized field %s in ipmi credentials %s' % (key, ipmi_credentials)) for key in ['ip', 'username', 'password']: if key not in ipmi_credentials: raise exception.InvalidParameter( 'no field %s in ipmi credentials %s' % (key, ipmi_credentials)) check_ipmi_credential_field = '_check_ipmi_credentials_%s' % key this_module = globals() if check_ipmi_credential_field in this_module: this_module[check_ipmi_credential_field](ipmi_credentials[key]) else: logging.debug('function %s is not defined', check_ipmi_credential_field)
def autofill_network_mapping(name, config, **kwargs): logging.debug('autofill %s config %s by params %s', name, config, kwargs) if not config: return config if isinstance(config, basestring): config = {'interface': config, 'subnet': None} if not isinstance(config, dict): return config if 'interface' not in config: return config subnet = None interface = config['interface'] if 'cluster' in kwargs: cluster = kwargs['cluster'] for clusterhost in cluster.clusterhosts: host = clusterhost.host for host_network in host.host_networks: if host_network.interface == interface: subnet = host_network.subnet.subnet elif 'clusterhost' in kwargs: clusterhost = kwargs['clusterhost'] host = clusterhost.host for host_network in host.host_networks: if host_network.interface == interface: subnet = host_network.subnet.subnet if not subnet: raise exception.InvalidParameter('interface %s not found in host(s)' % interface) if 'subnet' not in config or not config['subnet']: config['subnet'] = subnet else: if config['subnet'] != subnet: raise exception.InvalidParameter( 'subnet %s in config is not equal to subnet %s in hosts' % (config['subnet'], subnet)) return config
def _get_field_from_configuration(configs): """Get fields from configurations.""" fields = {} for config in configs: if not isinstance(config, dict): raise exception.InvalidParameter('config %s is not dict' % config) field_name = config['NAME'] fields[field_name] = { 'name': field_name, 'id': field_name, 'field_type': config.get('FIELD_TYPE', basestring), 'display_type': config.get('DISPLAY_TYPE', 'text'), 'validator': config.get('VALIDATOR', None), 'js_validator': config.get('JS_VALIDATOR', None), 'description': config.get('DESCRIPTION', field_name) } return fields
def get_package_os_metadata(adapter_id, os_id, user=None, session=None, **kwargs): """Get metadata by adapter and os.""" adapter = adapter_holder_api.get_adapter(adapter_id, user=user, session=session) os_ids = [os['id'] for os in adapter['supported_oses']] if os_id not in os_ids: raise exception.InvalidParameter( 'os %s is not in the supported os list of adapter %s' % (os_id, adapter_id)) metadatas = {} metadatas['os_config'] = _get_os_metadata(os_id) metadatas['package_config'] = _get_package_metadata(adapter_id) return metadatas