def validate_date(typedef, value): if (value == 'now' or value == 'current'): return value try: return str(int(value)) except (ValueError, TypeError): pass for f,pre in [('%Y-%m-%dT%H:%M:%S', None), ('%Y-%m-%d %H:%M:%S', None), ('%Y-%m-%dT%H:%M:%S%z', None), ('%Y-%m-%d %H:%M:%S%z', None), ('%Y-%m-%d', None), ('%m-%d', '%Y-'), ('%H:%M', '%Y-%m-%dT')]: try: t = value if pre: pref = datetime.datetime.now().strftime(pre) f = pre + f t = pref + t return value except: pass command._raise_argument_validation_exception(typedef, value, 'invalid date')
def validate_controller_node(typedef, value): """ Either the value must be a controller uuid, or the value must be a controller alias, and the underlying controller-node uuid for the alias must exist. """ try: validate_uuid(typedef, value) return value except error.ArgumentValidationError, e: uuid = convert_alias_to_object_key('controller-node', value) try: validate_uuid(typedef, uuid) try: _exists = bigsh.get_object_from_store('controller-node', uuid) return value except e: command._raise_argument_validation_exception(typedef, value, 'controller "%s" doesn\'t exist' % value) except error.ArgumentValidationError, e: nodes = bigsh.get_table_from_store('controller-node') aliases = dict([[x['controller'], x['alias']] for x in bigsh.get_table_from_store('controller-alias')]) choices = [aliases.get(x['id'], x['id']) for x in nodes] command._raise_argument_validation_exception(typedef, value, 'choices: ' + ', '.join(choices))
def validate_resolvable_ip_address(typedef, value): try: socket.gethostbyname(value) except: msg = 'unresolvable name' command._raise_argument_validation_exception(typedef, value, msg)
def validate_inverse_netmask(typedef, value): """ These look like 0.0.0.255, and are intended to only match when the there is one group of 1's and one group of zero's. """ if is_inverse_netmask(value): return value command._raise_argument_validation_exception(typedef, value, 'invalid netmask')
def validate_host(typedef, value): """ """ if _is_mac_address(value): return value # needs to be upgraded for bigdb. command._raise_argument_validation_exception(typedef, value, 'not host alias nor mac address')
def validate_existing_obj(typedef, value, data, path = None): """ Lookup the specific obj_type's primary key value for validation. """ filter = dict(data) # XXX test for path in search_keys, and the length of those keys. filter['|'.join(bigsh.bigdb.search_keys[path])] = value if not bigsh.bigdb.exists(path, filter, config = False): command._raise_argument_validation_exception(typedef, value, "doesn't exist ")
def validate_integer(typedef, value): # Check that the value is actually an integer try: value = int(value) except (ValueError, TypeError): command._raise_argument_validation_exception(typedef, value, 'value is not an integer') validate_integer_range(typedef, value, typedef.get('range')) return value
def validate_resolvable_ip_address(typedef, value): # see if this is an object we know about, for exameple a switch. dpid = convert_alias_to_object_key('switch-config', value) try: validate_dpid(typedef, dpid) except: try: socket.gethostbyname(value) except: msg = 'unresolvable name' command._raise_argument_validation_exception(typedef, value, msg)
def validate_existing_obj(typedef, value, obj_type): """ Lookup the specific obj_type's primary key value for validation. """ lookup_value = convert_alias_to_object_key(obj_type, value) try: sdnsh.get_object_from_store(obj_type, lookup_value) return value except Exception, _e: command._raise_argument_validation_exception(typedef, value, "doesn't exist ")
def validate_config(typedef, value): if value.startswith('config://'): return value elif utif.full_word_from_choices( value, ['running-config', 'upgrade-config', 'trash']): return value else: for prefixes in ['http://', 'ftp://', 'tftp://', 'file://']: if value.startswith(prefixes): return value data = sdnsh.store.get_user_data_table(value, 'latest') if len(data): return value msg = 'not a valid copy, must be (running-config, upgrade-config ' \ 'or must start with config://, http://, ftp://, or tftp://' command._raise_argument_validation_exception(typedef, value, msg)
def validate_string(typedef, value): """ Validate a string, check length. """ # Check to see if the typedef has any pattern restrictions. If it does, # then match against all of the patterns. If it matches any # of the patterns (i.e. not all of the patterns), then the argument # value is considered to be valid. patterns = typedef.get('pattern') if patterns: # If it's a single pattern convert it to a tuple, so we can handle # it in a common way below. Note that we don't use collection.Sequence # in the isinstance call because strings are sequences if command._is_string(patterns): patterns = (patterns,) for pattern in patterns: if re.match(pattern, str(value)): break else: command._raise_argument_validation_exception(typedef, value, 'invalid string pattern') # Check for any length restrictions. This can be a single scalar length or # a single length range or a sequence of either of those. For scalar lengths # the length must match it exactly. For length ranges the length of the argument # must be between the two values (inclusive). For a list of length specs, the # length must match any of the lengths (either scalar or range) in the list. lengths = typedef.get('length') if lengths: if command._is_single_range(lengths): lengths = (lengths,) for length in lengths: command._check_one_range(length) if isinstance(length, numbers.Integral): if len(value) == length: break if len(value) >= length[0] and len(value) <= length[1]: break else: command._raise_argument_validation_exception(typedef, value, 'invalid string length') return value
def validate_config(typedef, value): if value.startswith('config://'): return value elif utif.full_word_from_choices(value, ['running-config', 'upgrade-config', 'trash' ]): return value else: for prefixes in ['http://', 'ftp://', 'tftp://', 'file://']: if value.startswith(prefixes): return value data = sdnsh.store.get_user_data_table(value, 'latest') if len(data): return value msg = 'not a valid copy, must be (running-config, upgrade-config ' \ 'or must start with config://, http://, ftp://, or tftp://' command._raise_argument_validation_exception(typedef, value, msg)
def validate_hex_or_dec_integer(typedef, value): # Check that the value is actually an hex or decimal integer if HEX_RE.match(value): # if it matches, it ought to succeed conversion, below's really not needed try: _value = int(value, 16) except (ValueError, TypeError): command._raise_argument_validation_exception(typedef, value, 'value is not a hex integer') else: try: _value = int(value) except (ValueError, TypeError): command._raise_argument_validation_exception(typedef, value, 'value is not an integer') validate_integer_range(typedef, _value, typedef.get('range')) return value
def validate_integer_comma_ranges(typedef, value): for range in value.split(','): m = ICR_RANGE_RE.match(range); if (m): lower = int(m.group(1)) upper = int(m.group(2)) if (lower >= upper): msg = "Invalid range: %d-%d" % (lower, upper) command._raise_argument_validation_exception(typedef, value, msg) elif not ICR_SINGLE_RE.match(range): msg = "Must be a comma separated list of integers ranges" \ ", such as '10-15,25,1-3'" command._raise_argument_validation_exception(typedef, value, msg) return value
def validate_enum(typedef, value): # FIXME: Sort of a hack. The base enum class doesn't have a values # field, so there's nothing to check against. We really just use it # as a base type to indicate the validation function (i.e. this function) # to use. name = typedef.get('name') if name == 'enum': return enum_values = typedef.get('values') if not enum_values: raise error.CommandDescriptionError('Unspecified enum values') if not isinstance(enum_values, collections.Mapping): # If it's not a dictionary then it should be an array # or tuple where the (string) elements are both the key # and the value for the enum items. So here we convert # to a dictionary so we can use the same logic for both # cases below. if command._is_string(enum_values): enum_values = (enum_values,) if isinstance(enum_values, collections.Sequence): enum_values = dict((v,v) for v in enum_values) else: raise error.CommandDescriptionError( 'Enum values must be either a string, dict, tuple, or list') prefix_matches = [] lower_value = value.lower() for enum_value, return_value in enum_values.items(): lower_enum_value = enum_value.lower() if lower_enum_value == lower_value: return (return_value, enum_value) if lower_enum_value.startswith(lower_value): prefix_matches.append((return_value, enum_value)) if len(prefix_matches) == 0: command._raise_argument_validation_exception(typedef, value, 'unexpected value for enum', enum_values.keys()) return prefix_matches
def validate_host(typedef, value): """ """ if _is_mac_address(value): return value pk = mi.pk('host-config') key = convert_alias_to_object_key('host-config', value) key_dict = {pk: key} mi.split_compound_into_dict('host-config', pk, key_dict, is_prefix=True) if 'mac' in key_dict and _is_mac_address(key_dict['mac']): try: _exists = rest_to_model.get_model_from_url('host', key_dict) return value except: raise error.ArgumentValidationError('host "%s": doesn\'t exist' % value) command._raise_argument_validation_exception( typedef, value, 'not host alias nor mac address')
def validate_host(typedef, value): """ """ if _is_mac_address(value): return value pk = mi.pk('host-config') key = convert_alias_to_object_key('host-config', value) key_dict = { pk : key } mi.split_compound_into_dict('host-config', pk, key_dict, is_prefix = True) if 'mac' in key_dict and _is_mac_address(key_dict['mac']): try: _exists = rest_to_model.get_model_from_url('host', key_dict) return value except: raise error.ArgumentValidationError( 'host "%s": doesn\'t exist' % value) command._raise_argument_validation_exception(typedef, value, 'not host alias nor mac address')
def validate_switch_dpid(typedef, value): """ Either the value must be a syntactic dpid (eight-hex-bytes), Or the value must be a switch alias, and the underlying dpid must exist. """ try: validate_dpid(typedef, value) return value except error.ArgumentValidationError, e: if bigsh.bigdb.enabled(): # use a bigdb approach for the alias transformation. (schema, switches) = bigsh.bigdb.schema_and_result("core/switch", {}) alias_field = bigsh.bigdb.alias_field['core/switch'] for switch in switches.iter(): # BSC-2292, need to use alias field name here for switch if alias_field in switch and switch[alias_field] == value: return value command._raise_argument_validation_exception(typedef, value, 'switch "%s" doesn\'t exist' % value) return dpid = convert_alias_to_object_key('switch-config', value) try: validate_dpid(typedef, dpid) try: _exists = bigsh.get_object_from_store('switch-config', dpid) return value except e: command._raise_argument_validation_exception(typedef, value, 'switch "%s" doesn\'t exist' % value) except error.ArgumentValidationError, e: command._raise_argument_validation_exception(typedef, value, 'not switch alias nor dpid')
def validate_switch_dpid(typedef, value): """ Either the value must be a syntactic dpid (eight-hex-bytes), Or the value must be a switch alias, and the underlying dpid must exist. """ try: validate_dpid(typedef, value) return value except error.ArgumentValidationError, e: dpid = convert_alias_to_object_key('switch-config', value) try: validate_dpid(typedef, dpid) try: _exists = sdnsh.get_object_from_store('switch-config', dpid) return value except e: command._raise_argument_validation_exception( typedef, value, 'switch "%s" doesn\'t exist' % value) except error.ArgumentValidationError, e: command._raise_argument_validation_exception( typedef, value, 'not switch alias nor dpid')
def validate_integer_range(typedef, value, ranges): # Check for any range restrictions. This can be a single scalar value or # a single range or a list/tuple of a combination of those. For scalar ranges # the arg must match it exactly. For ranges the value of the argument # must be between the two values (inclusive). For a list of range specs, the # value must match any of the lengths (either scalar or range) in the list. if ranges: if command._is_single_range(ranges): ranges = (ranges,) for r in ranges: command._check_one_range(r) if isinstance(r, numbers.Integral): if value == r: break else: lower_boundary = command._convert_range_boundary(r[0], value) upper_boundary = command._convert_range_boundary(r[1], value) if value >= lower_boundary and value <= upper_boundary: break else: command._raise_argument_validation_exception(typedef, value, 'value is outside specified ' 'range: (%d-%d)' % (r[0], r[1]))
def validate_switch_dpid(typedef, value): """ Either the value must be a syntactic dpid (eight-hex-bytes), Or the value must be a switch alias, and the underlying dpid must exist. """ try: validate_dpid(typedef, value) return value except error.ArgumentValidationError, e: dpid = convert_alias_to_object_key('switch-config', value) try: validate_dpid(typedef, dpid) try: _exists = sdnsh.get_object_from_store('switch-config', dpid) return value except e: command._raise_argument_validation_exception(typedef, value, 'switch "%s" doesn\'t exist' % value) except error.ArgumentValidationError, e: command._raise_argument_validation_exception(typedef, value, 'not switch alias nor dpid')
def validate_cidr_range(typedef, value): match = CIDR_RE.match(value) if not match: command._raise_argument_validation_exception(typedef, value, 'not cidr syntax: ip/n') if int(match.group(3)) > 32: command._raise_argument_validation_exception(typedef, value, 'cidr range above 32') if len([x for x in match.group(1).split('.') if int(x) < 256]) != 4: command._raise_argument_validation_exception(typedef, value, 'cidr range above 32') return value
def validate_ip_address_not_netmask(typedef, value): """ For ip addresses associated with interfaces, the configured value must not be one of the many masks. """ # if its not an ip address, then its not a netmask, requiring # a test for ip address match. if not IP_ADDR_RE.match(value): command._raise_argument_validation_exception(typedef, value, 'not an ip-address') # must be four dotted quad's, validate each is within 2^8 range if len([x for x in value.split('.') if int(x) < 256]) != 4: command._raise_argument_validation_exception(typedef, value, 'not an ip-address') if (not is_inverse_netmask(value)) and (not is_netmask(value)): return value command._raise_argument_validation_exception(typedef, value, 'must not be a mask')
def validate_identifier(typedef, value, reserved = None): """ When identifier is used as a 'type' in the description, it will validate against the bigsh reserved_words. When identifier is used as a 'base-type' in the description, it will also use any 'reserved' attributes in the description. This allows some control over whether the 'reserved' attribute takes effect at the syntax-layer or at the action-layer """ if not re.match(r'^[a-zA-Z0-9_-]+$', str(value)): msg = 'Invalid characters in identifier' command._raise_argument_validation_exception(typedef, value, msg) if value in bsn_constants.reserved_words: msg = 'reserved word "%s" in "%s"' % (value, ', '.join(bsn_constants.reserved_words)) command._raise_argument_validation_exception(typedef, value, msg) if reserved and value in reserved: msg = 'reserved word "%s" in "%s"' % (value, ', '.join(reserved)) command._raise_argument_validation_exception(typedef, value, msg) return value
def validate_identifier(typedef, value, reserved = None): """ When identifier is used as a 'type' in the description, it will validate against the sdnsh reserved_words. When identifier is used as a 'base-type' in the description, it will also use any 'reserved' attributes in the description. This allows some control over whether the 'reserved' attribute takes effect at the syntax-layer or at the action-layer """ if not re.match(r'^[a-zA-Z0-9_-]+$', str(value)): msg = 'Invalid characters in identifier' command._raise_argument_validation_exception(typedef, value, msg) if value in sdnsh.reserved_words: msg = 'reserved word "%s" in "%s"' % (value, ', '.join(sdnsh.reserved_words)) command._raise_argument_validation_exception(typedef, value, msg) if reserved and value in reserved: msg = 'reserved word "%s" in "%s"' % (value, ', '.join(reserved)) command._raise_argument_validation_exception(typedef, value, msg) return value
def validate_not_reserved(typedef, value, reserved = None): if value in reserved: msg = 'reserved word "%s" in "%s"' % (value, ', '.join(reserved)) command._raise_argument_validation_exception(typedef, value, msg) return value
def validate_duration(typedef, value): for s in ['weeks', 'days', 'hours', 'mins', 'secs', 'ms']: if value.endswith(s): return value command._raise_argument_validation_exception(typedef, value, 'invalid duration')
def validate_mac_address(typedef, value): if _is_mac_address(value): return value command._raise_argument_validation_exception(typedef, value, 'mac address')
def validate_uuid(typedef, value): if not utif.COMMAND_UUID_RE.match(value): command._raise_argument_validation_exception(typedef, value, 'uuid') return value
def validate_dpid(typedef, value): if not utif.COMMAND_DPID_RE.match(value): command._raise_argument_validation_exception(typedef, value, 'switch dpid') return value
def validate_netmask(typedef, value): if not is_netmask(value): command._raise_argument_validation_exception(typedef, value, 'invalid netmask') return value