def test_get_parent_type(self): # todo: consider unusual parent situations (?) rfo = rfSchema.getSchemaObject( 'Example.Example', '/redfish/v1/$metadata#Example.Example') assert rfo self.assertTrue(rfo.getParentType('Example.v1_0_0.Example')) self.assertTrue(rfo.getParentType('Example.Example'))
def test_get_from_reference(self): # todo: consider no schema, consider service rfo = rfSchema.getSchemaObject( 'Example.Example', '/redfish/v1/$metadata#Example.Example') assert rfo self.assertTrue( rfo.getSchemaFromReference('ExampleResource') is not None) self.assertTrue( rfo.getSchemaFromReference('ExampleResource.v1_0_0') is not None) self.assertTrue( rfo.getSchemaFromReference('ExampleResource.v1_0_1') is not None) self.assertFalse( rfo.getSchemaFromReference('Resource.v1_0_1') is not None)
def test_get_type_tag(self): rfo = rfSchema.getSchemaObject( 'Example.Example', '/redfish/v1/$metadata#Example.Example') assert rfo self.assertTrue( rfo.getTypeTagInSchema('Example.v1_0_0.Example') is not None) self.assertFalse( rfo.getTypeTagInSchema('Example.v1_0_9.Example') is not None) self.assertTrue(rfo.getTypeTagInSchema('Example.Example') is not None) self.assertFalse( rfo.getTypeTagInSchema('Example.v1_0_0.ExampleEnum') is not None) self.assertTrue( rfo.getTypeTagInSchema('Example.v1_0_0.ExampleEnum', 'EnumType') is not None) self.assertTrue(rfo.getTypeTagInSchema('Example') is not None)
def test_highest_type(self): rfo = rfSchema.getSchemaObject( 'Example.Example', '/redfish/v1/$metadata#Example.Example') assert rfo self.assertTrue( rfo.getHighestType('Example.Example') == 'Example.v1_7_0.Example') self.assertTrue( rfo.getHighestType('Example.Example', 'Newark.v1_2_1') == 'Example.v1_2_1.Example') self.assertTrue( rfo.getHighestType('Example.Example', 'Newark.v0_0_0') == 'Example.Example') self.assertTrue( rfo.getHighestType('Example.Example', 'Newark') == 'Example.v1_7_0.Example') self.assertTrue( rfo.getHighestType('Example.Links') == 'Example.v1_7_0.Links') self.assertTrue( rfo.getHighestType('Example.Links', 'Example.v1_1_1') == 'Example.v1_0_0.Links')
def __init__(self, name: str, uri: str, jsondata: dict, typename: str, context: str, parent=None, isComplex=False, forceType=False): self.initiated = False self.parent = parent self.uri, self.name = uri, name self.rtime = 0 self.status = -1 self.isRegistry = False self.errorIndex = {} oem = config.get('oemcheck', True) # Check if this is a Registry resource parent_type = parent.typename if parent is not None and parent is not None else None if parent_type is not None and getType( parent_type) == 'MessageRegistryFile': traverseLogger.debug('{} is a Registry resource'.format(self.uri)) self.isRegistry = True self.context = None context = None # Check if we provide a valid json self.jsondata = jsondata traverseLogger.debug("payload: {}".format( json.dumps(self.jsondata, indent=4, sort_keys=True))) if not isinstance(self.jsondata, dict): traverseLogger.error("Resource no longer a dictionary...") raise ValueError('This Resource is no longer a Dictionary') # Check for @odata.id (todo: regex) odata_id = self.jsondata.get('@odata.id') if odata_id is None and not isComplex: if self.isRegistry: traverseLogger.debug( '{}: @odata.id missing, but not required for Registry resource' .format(self.uri)) else: traverseLogger.log( 'SERVICE', '{}: Json does not contain @odata.id'.format(self.uri)) # Get our real type (check for version) acquiredtype = typename if forceType else jsondata.get( '@odata.type', typename) if acquiredtype is None: traverseLogger.error( '{}: Json does not contain @odata.type or NavType'.format( uri)) raise ValueError if acquiredtype is not typename and isComplex: context = None if typename is not None: if not oem and 'OemObject' in typename: acquiredtype = typename if currentService: if not oem and 'OemObject' in acquiredtype: pass else: if jsondata.get('@odata.type') is not None: currentService.metadata.add_service_namespace( getNamespace(jsondata.get('@odata.type'))) if jsondata.get('@odata.context') is not None: # add the namespace to the set of namespaces referenced by this service ns = getNamespace( jsondata.get('@odata.context').split('#')[-1]) if '/' not in ns and not ns.endswith('$entity'): currentService.metadata.add_service_namespace(ns) # Provide a context for this (todo: regex) if context is None: context = self.jsondata.get('@odata.context') if context is None: context = createContext(acquiredtype) if self.isRegistry: # If this is a Registry resource, @odata.context is not required; do our best to construct one traverseLogger.debug( '{}: @odata.context missing from Registry resource; constructed context {}' .format(acquiredtype, context)) elif isComplex: pass else: traverseLogger.debug( '{}: Json does not contain @odata.context'.format( uri)) self.context = context # Get Schema object self.schemaObj = rfSchema.getSchemaObject(acquiredtype, self.context) if self.schemaObj is None: traverseLogger.error( "ResourceObject creation: No schema XML for {} {} {}".format( typename, acquiredtype, self.context)) raise ValueError # Use string comprehension to get highest type if acquiredtype is typename and not forceType: acquiredtype = self.schemaObj.getHighestType(typename, parent_type) if not isComplex: traverseLogger.debug( 'No @odata.type present, assuming highest type {} {}'. format(typename, acquiredtype)) # Check if we provide a valid type (todo: regex) self.typename = acquiredtype typename = self.typename self.initiated = True # get our metadata metadata = currentService.metadata if currentService else None self.typeobj = rfSchema.getTypeObject(typename, self.schemaObj) self.propertyList = self.typeobj.getProperties( self.jsondata, topVersion=getNamespace(typename)) propertyList = [prop.payloadName for prop in self.propertyList] # get additional self.additionalList = [] propTypeObj = self.typeobj if propTypeObj.propPattern is not None and len( propTypeObj.propPattern) > 0: prop_pattern = propTypeObj.propPattern.get('Pattern', '.*') prop_type = propTypeObj.propPattern.get('Type', 'Resource.OemObject') regex = re.compile(prop_pattern) for key in [ k for k in self.jsondata if k not in propertyList and regex.fullmatch(k) ]: val = self.jsondata.get(key) value_obj = rfSchema.PropItem(propTypeObj.schemaObj, propTypeObj.fulltype, key, val, customType=prop_type) self.additionalList.append(value_obj) if config['uricheck'] and self.typeobj.expectedURI is not None: my_id = self.jsondata.get('Id') self.errorIndex[ 'bad_uri_schema_uri'] = not self.typeobj.compareURI( uri, my_id) self.errorIndex[ 'bad_uri_schema_odata'] = not self.typeobj.compareURI( odata_id, my_id) if self.errorIndex['bad_uri_schema_uri']: traverseLogger.error('{}: URI not in Redfish.Uris: {}'.format( uri, self.typename)) if my_id != uri.rsplit('/', 1)[-1]: traverseLogger.error( 'Id {} in payload doesn\'t seem to match URI'.format( my_id)) else: traverseLogger.debug('{} in Redfish.Uris: {}'.format( uri, self.typename)) if self.errorIndex['bad_uri_schema_odata']: traverseLogger.error( '{}: odata_id not in Redfish.Uris: {}'.format( odata_id, self.typename)) if my_id != uri.rsplit('/', 1)[-1]: traverseLogger.error( 'Id {} in payload doesn\'t seem to match URI'.format( my_id)) else: traverseLogger.debug('{} in Redfish.Uris: {}'.format( odata_id, self.typename)) # get annotation successService, annotationProps = getAnnotations( metadata, self.jsondata) if successService: self.additionalList.extend(annotationProps) # list illegitimate properties together self.unknownProperties = [ k for k in self.jsondata if k not in propertyList + [prop.payloadName for prop in self.additionalList] and '@odata' not in k ] self.links = OrderedDict() sample = config.get('sample') linklimits = config.get('linklimits', {}) self.links.update( self.typeobj.getLinksFromType(self.jsondata, self.context, self.propertyList, oem, linklimits, sample)) self.links.update( getAllLinks(self.jsondata, self.additionalList, self.schemaObj, context=context, linklimits=linklimits, sample_size=sample, oemCheck=oem))
def createResourceObject(name, uri, jsondata=None, typename=None, context=None, parent=None, isComplex=False): """ Factory for resource object, move certain work here """ traverseLogger.debug('Creating ResourceObject {} {} {}'.format( name, uri, typename)) oem = config.get('oemcheck', True) # Create json from service or from given original_jsondata = jsondata if jsondata is None and not isComplex: success, jsondata, status, rtime = callResourceURI(uri) traverseLogger.debug('{}, {}, {}'.format(success, jsondata, status)) if not success: traverseLogger.error('{}: URI could not be acquired: {}'.format( uri, status)) return None else: success, jsondata, status, rtime = True, jsondata, -1, 0 if not isinstance(jsondata, dict): if not isComplex: traverseLogger.error("Resource no longer a dictionary...") else: traverseLogger.debug("ComplexType does not have val") return success, None, status return None acquiredtype = jsondata.get('@odata.type', typename) if acquiredtype is None: traverseLogger.error( '{}: Json does not contain @odata.type or NavType'.format(uri)) return None if typename is not None: if not oem and 'OemObject' in typename: acquiredtype = typename original_context = context if context is None: context = jsondata.get('@odata.context') if context is None: context = createContext(acquiredtype) # Get Schema object schemaObj = rfSchema.getSchemaObject(acquiredtype, context) if schemaObj is None: traverseLogger.warn( "ResourceObject creation: No schema XML for {} {}".format( acquiredtype, context)) return None forceType = False # Check if this is a Registry resource parent_type = parent.typename if parent is not None and parent.typeobj is not None else None # get highest type if type is invalid if schemaObj.getTypeTagInSchema(acquiredtype) is None: if schemaObj.getTypeTagInSchema( getNamespaceUnversioned(acquiredtype)) is not None: traverseLogger.warn( "Namespace version of type appears missing from SchemaXML, attempting highest type: {}" .format(acquiredtype)) acquiredtype = schemaObj.getHighestType(acquiredtype, parent_type) typename = acquiredtype traverseLogger.warn("New namespace: {}".format(typename)) forceType = True else: traverseLogger.warn( "getResourceObject: Namespace appears nonexistent in SchemaXML: {} {}" .format(acquiredtype, context)) return None # check odata.id if it corresponds odata_id = jsondata.get('@odata.id', '') currentType = acquiredtype baseObj = schemaObj success = True allTypes = [] while currentType not in allTypes and success: allTypes.append(currentType) success, baseObj, currentType = baseObj.getParentType( currentType, 'EntityType') traverseLogger.debug('success = {}, currentType = {}'.format( success, currentType)) uri_item = uri scheme, netloc, path, params, query, fragment = urlparse(uri_item) scheme, netloc, path, params, query, fragment_odata = urlparse(odata_id) if 'Resource.Resource' in allTypes: if fragment is '': if original_jsondata is None: traverseLogger.debug( 'Acquired resource OK {}'.format(uri_item)) else: traverseLogger.debug( 'Acquired resource thru AutoExpanded means {}'.format( uri_item)) traverseLogger.info( 'Regetting resource from URI {}'.format(uri_item)) new_payload = createResourceObject(name, uri_item, None, typename, context, parent, isComplex) if new_payload is None: traverseLogger.warn( 'Could not acquire resource, reverting to original payload...' ) else: if original_jsondata is None: traverseLogger.warn( 'Acquired Resource.Resource type with fragment, could cause issues {}' .format(uri_item)) else: traverseLogger.warn( 'Found uri with fragment, which Resource.Resource types do not use {}' .format(uri_item)) if fragment_odata is '': pass else: traverseLogger.warn( '@odata.id should not have a fragment'.format(odata_id)) elif 'Resource.ReferenceableMember' in allTypes: if fragment is not '': pass else: traverseLogger.warn( 'No fragment, but ReferenceableMembers require it {}'.format( uri_item)) if fragment_odata is not '': pass else: traverseLogger.warn( '@odata.id should have a fragment'.format(odata_id)) newResource = ResourceObj(name, uri, jsondata, typename, original_context, parent, isComplex, forceType=forceType) newResource.rtime = rtime newResource.status = status return newResource
def test_schema_object(self): # todo: consider no schema, consider service rfo = rfSchema.getSchemaObject( 'Example.Example', '/redfish/v1/$metadata#Example.Example') self.assertTrue(rfo is not None, 'SchemaObject not created')