redfish-interop-validator 2.2.1__tar.gz → 2.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. {redfish_interop_validator-2.2.1/redfish_interop_validator.egg-info → redfish_interop_validator-2.2.3}/PKG-INFO +1 -1
  2. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/RedfishInteropValidator.py +1 -1
  3. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/interop.py +91 -24
  4. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/validateResource.py +3 -0
  5. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3/redfish_interop_validator.egg-info}/PKG-INFO +1 -1
  6. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/setup.py +1 -1
  7. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/AUTHORS.md +0 -0
  8. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/LICENSE.md +0 -0
  9. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/README.md +0 -0
  10. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/RedfishLogo.py +0 -0
  11. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/__init__.py +0 -0
  12. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/config.py +0 -0
  13. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/profile.py +0 -0
  14. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/redfish.py +0 -0
  15. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/session.py +0 -0
  16. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/tohtml.py +0 -0
  17. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/traverseInterop.py +0 -0
  18. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator.egg-info/SOURCES.txt +0 -0
  19. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator.egg-info/dependency_links.txt +0 -0
  20. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator.egg-info/entry_points.txt +0 -0
  21. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator.egg-info/requires.txt +0 -0
  22. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator.egg-info/top_level.txt +0 -0
  23. {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: redfish_interop_validator
3
- Version: 2.2.1
3
+ Version: 2.2.3
4
4
  Summary: Redfish Interop Validator
5
5
  Home-page: https://github.com/DMTF/Redfish-Interop-Validator
6
6
  Author: DMTF, https://www.dmtf.org/standards/feedback
@@ -17,7 +17,7 @@ import redfish_interop_validator.traverseInterop as traverseInterop
17
17
  from redfish_interop_validator.profile import getProfiles, checkProfileAgainstSchema, hashProfile
18
18
  from redfish_interop_validator.validateResource import validateSingleURI, validateURITree
19
19
 
20
- tool_version = '2.2.1'
20
+ tool_version = '2.2.3'
21
21
 
22
22
  # Set up the custom debug levels
23
23
  VERBOSE1 = logging.INFO - 1
@@ -247,6 +247,7 @@ def validateWriteRequirement(profile_entry, parent_object_payload, resource_head
247
247
  return msgInterop('WriteRequirement', profile_entry, expected_str, 'Writable' if is_writeable else 'Not Writable',
248
248
  testResultEnum.PASS if is_writeable else result_not_supported), True
249
249
 
250
+
250
251
  def checkComparison(val, compareType, target):
251
252
  """
252
253
  Validate a given comparison option, given a value and a target set
@@ -278,6 +279,7 @@ def checkComparison(val, compareType, target):
278
279
  else:
279
280
  continue
280
281
  paramPass = len(alltarget) == len(target)
282
+
281
283
  if compareType == "LinkToResource":
282
284
  if val == REDFISH_ABSENT:
283
285
  paramPass = False
@@ -299,7 +301,7 @@ def checkComparison(val, compareType, target):
299
301
  if compareType == "Present":
300
302
  paramPass = val != REDFISH_ABSENT
301
303
 
302
- if isinstance(target, list):
304
+ if isinstance(target, list) and val != REDFISH_ABSENT:
303
305
  if compareType == "Equal":
304
306
  paramPass = val in target
305
307
  elif compareType == "NotEqual":
@@ -316,6 +318,10 @@ def checkComparison(val, compareType, target):
316
318
  paramPass = val <= value
317
319
  if paramPass is False:
318
320
  break
321
+ elif compareType in ["Equal", "NotEqual", "GreaterThan", "GreaterThanOrEqual", "LessThan", "LessThanOrEqual"]:
322
+ if not isinstance(target, list):
323
+ my_logger.warn('CompareType {} requires a list of values'.format(compareType))
324
+
319
325
  my_logger.debug('\tpass ' + str(paramPass))
320
326
  return msgInterop('Comparison', target, compareType, val, paramPass),\
321
327
  paramPass
@@ -557,7 +563,8 @@ def validatePropertyRequirement(propResourceObj, profile_entry, rf_payload_tuple
557
563
  # problem: if dne, skip?
558
564
 
559
565
  # Read Requirement is default mandatory if not present
560
- msg, success = validateRequirement(profile_entry.get('ReadRequirement', 'Mandatory'), redfish_value, parent_object_tuple=redfish_parent_payload)
566
+ requirement_entry = profile_entry.get('ReadRequirement', 'Mandatory')
567
+ msg, requirement_success = validateRequirement(requirement_entry, redfish_value, parent_object_tuple=redfish_parent_payload)
561
568
  msgs.append(msg)
562
569
  msg.name = item_name + '.' + msg.name
563
570
 
@@ -582,7 +589,12 @@ def validatePropertyRequirement(propResourceObj, profile_entry, rf_payload_tuple
582
589
  # Default to AnyOf
583
590
 
584
591
  my_compare = profile_entry.get("Comparison", "AnyOf")
585
- msg, success = checkComparison(redfish_value, my_compare, profile_entry.get("Values", []))
592
+ my_values = profile_entry.get("Values", [])
593
+ # If absent and not comparing for absence...
594
+ if redfish_value == REDFISH_ABSENT and my_compare not in ['Absent', 'Present']:
595
+ msg, success = msgInterop('Comparison', my_values, my_compare, REDFISH_ABSENT, testResultEnum.NOT_TESTED), True
596
+ else:
597
+ msg, success = checkComparison(redfish_value, my_compare, my_values)
586
598
  msgs.append(msg)
587
599
  msg.name = item_name + '.' + msg.name
588
600
 
@@ -620,51 +632,96 @@ def validateActionRequirement(profile_entry, rf_payload_tuple, actionname):
620
632
  my_logger.verbose1('actionRequirement \n\tval: ' + str(rf_payload_item if not isinstance(
621
633
  rf_payload_item, dict) else 'dict') + ' ' + str(profile_entry))
622
634
 
635
+ action_readrequirement = profile_entry.get('ReadRequirement', "Mandatory")
636
+ actioninfo_requirement = profile_entry.get('ActionInfo', "None")
637
+
623
638
  if "ReadRequirement" in profile_entry:
624
639
  # problem: if dne, skip
625
- msg, success = validateRequirement(profile_entry.get('ReadRequirement', "Mandatory"), rf_payload_item)
640
+ msg, success = validateRequirement(action_readrequirement, rf_payload_item)
626
641
  msgs.append(msg)
627
642
  msg.name = actionname + '.' + msg.name
628
643
  msg.success = testResultEnum.PASS if success else testResultEnum.FAIL
629
-
644
+
630
645
  propDoesNotExist = (rf_payload_item == REDFISH_ABSENT)
631
646
  if propDoesNotExist:
632
647
  return msgs, counts
648
+
633
649
  if "@Redfish.ActionInfo" in rf_payload_item:
634
650
  vallink = rf_payload_item['@Redfish.ActionInfo']
635
651
  success, rf_payload_action, code, elapsed, _ = callResourceURI(vallink)
636
652
  if not success:
637
653
  rf_payload_action = None
638
654
 
655
+ if 'ActionInfo' in profile_entry and actioninfo_requirement in ["None"]:
656
+ # Create message if None is explicitly listed in the profile
657
+ msg = msgInterop('ActionInfo', 'None', '-', '-', testResultEnum.OK)
658
+ msg.name = actionname + '.' + msg.name
659
+ msgs.append(msg)
660
+
661
+ if actioninfo_requirement not in ["None"]:
662
+ if propDoesNotExist:
663
+ # not tested if action isn't present
664
+ msg = msgInterop('ActionInfo', actioninfo_requirement, '-', '-', testResultEnum.NOT_TESTED)
665
+
666
+ elif actioninfo_requirement == "Mandatory":
667
+ if rf_payload_action is None:
668
+ if "@Redfish.ActionInfo" in rf_payload_item:
669
+ my_logger.error('Mandatory @Redfish.ActionInfo for {} listed on action but URI get was not successful'.format(actionname))
670
+ else:
671
+ my_logger.error('@Redfish.ActionInfo for {} not listed, but is Mandatory'.format(actionname))
672
+ msg = msgInterop('ActionInfo', actioninfo_requirement, '-', '-', testResultEnum.FAIL)
673
+ else:
674
+ msg = msgInterop('ActionInfo', actioninfo_requirement, '-', '-', testResultEnum.PASS)
675
+
676
+ elif actioninfo_requirement == "Recommended":
677
+ if rf_payload_action is None:
678
+ if "@Redfish.ActionInfo" in rf_payload_item:
679
+ my_logger.warn('Recommended @Redfish.ActionInfo for {} listed on action but URI get was not successful'.format(actionname))
680
+ msg = msgInterop('ActionInfo', actioninfo_requirement, '-', '-', testResultEnum.WARN)
681
+ else:
682
+ my_logger.info('Recommended @Redfish.ActionInfo for {} not listed'.format(actionname))
683
+ msg = msgInterop('ActionInfo', actioninfo_requirement, '-', '-', testResultEnum.PASS)
684
+ else:
685
+ msg = msgInterop('ActionInfo', actioninfo_requirement, '-', '-', testResultEnum.PASS)
686
+
687
+ else:
688
+ my_logger.warn('Term "ActionInfo" has unknown value {}'.format(actioninfo_requirement))
689
+ msg = msgInterop('ActionInfo', actioninfo_requirement, '-', '-', testResultEnum.WARN)
690
+ msg.name = actionname + '.' + msg.name
691
+ msgs.append(msg)
692
+
639
693
  # problem: if dne, skip
640
694
  if "Parameters" in profile_entry:
641
- innerDict = profile_entry["Parameters"]
695
+ parameter_dictionary = profile_entry["Parameters"]
642
696
  # problem: if dne, skip
643
697
  # assume mandatory
644
- for k in innerDict:
645
- item = innerDict[k]
698
+ for param in parameter_dictionary:
699
+ item = parameter_dictionary[param]
700
+ # Get Allowable Values for parameter
646
701
  values_array = None
702
+ # If our action info exists at all, prefer it
647
703
  if rf_payload_action is not None:
648
- action_by_name = rf_payload_action['Parameters']
649
- my_action = [x for x in action_by_name if x['Name'] == k]
650
- if my_action:
651
- values_array = my_action[0].get('AllowableValues')
704
+ parameter_by_name = rf_payload_action['Parameters']
705
+ my_parameter = [x for x in parameter_by_name if x['Name'] == param]
706
+ if my_parameter:
707
+ values_array = my_parameter[0].get('AllowableValues')
708
+ # Otherwise check for AllowableValues as additional property
652
709
  if values_array is None:
653
- values_array = rf_payload_item.get(str(k) + '@Redfish.AllowableValues', REDFISH_ABSENT)
710
+ values_array = rf_payload_item.get(str(param) + '@Redfish.AllowableValues', REDFISH_ABSENT)
654
711
  if values_array == REDFISH_ABSENT:
655
- my_logger.warning('\tNo such ActionInfo exists for this Action, and no AllowableValues exists. Cannot validate the following parameters: {}'.format(k))
712
+ my_logger.warning('\tNo such ActionInfo exists for this Action, and no AllowableValues exists. Cannot validate the following parameters: {}'.format(param))
656
713
  msg = msgInterop('', item, '-', '-', testResultEnum.WARN)
657
- msg.name = "{}.{}.{}".format(actionname, k, msg.name)
714
+ msg.name = "{}.{}.{}".format(actionname, param, msg.name)
658
715
  msgs.append(msg)
659
716
  else:
660
717
  msg, success = validateRequirement(item.get('ReadRequirement', "Mandatory"), values_array)
661
718
  msgs.append(msg)
662
- msg.name = "{}.{}.{}".format(actionname, k, msg.name)
719
+ msg.name = "{}.{}.{}".format(actionname, param, msg.name)
663
720
  if "ParameterValues" in item:
664
721
  msg, success = validateSupportedValues(
665
722
  item["ParameterValues"], values_array)
666
723
  msgs.append(msg)
667
- msg.name = "{}.{}.{}".format(actionname, k, msg.name)
724
+ msg.name = "{}.{}.{}".format(actionname, param, msg.name)
668
725
  if "RecommendedValues" in item:
669
726
  msg, success = validateSupportedValues(
670
727
  item["RecommendedValues"], values_array)
@@ -677,7 +734,7 @@ def validateActionRequirement(profile_entry, rf_payload_tuple, actionname):
677
734
  msg.success = testResultEnum.PASS
678
735
 
679
736
  msgs.append(msg)
680
- msg.name = "{}.{}.{}".format(actionname, k, msg.name)
737
+ msg.name = "{}.{}.{}".format(actionname, param, msg.name)
681
738
  # consider requirement before anything else, what if action
682
739
  # if the action doesn't exist, you can't check parameters
683
740
  # if it doesn't exist, what should not be checked for action
@@ -724,17 +781,27 @@ def validateInteropResource(propResourceObj, interop_profile, rf_payload):
724
781
 
725
782
  if "UseCases" in interop_profile:
726
783
  for use_case in interop_profile['UseCases']:
727
- entry_title = use_case.get("UseCaseTitle", "NoName").replace(' ','_')
728
- my_logger.debug('UseCase {}'.format(entry_title))
784
+ entry_title = use_case.get("UseCaseTitle", "NoName").replace(' ', '_')
785
+ entry_type = use_case.get("UseCaseType", "Normal")
786
+ my_logger.debug('UseCase {} {}'.format(entry_title, entry_type))
729
787
 
730
788
  # Check if we have a valid UseCase
731
- if 'URIs' not in use_case and 'UseCaseKeyProperty' not in use_case:
789
+ if 'URIs' not in use_case and 'UseCaseKeyProperty' not in use_case and entry_type != 'AbsentResource':
732
790
  my_logger.error('UseCase does not have URIs or UseCaseKeyProperty...')
733
791
 
734
- if 'UseCaseKeyProperty' in use_case:
792
+ if entry_type == 'AbsentResource':
793
+ my_status = rf_payload.get('Status')
794
+ if my_status:
795
+ use_case_applies = my_status.get('State') == 'Absent'
796
+ else:
797
+ use_case_applies = False
798
+ if 'URIs' in use_case:
799
+ use_case_applies = use_case_applies and checkInteropURI(propResourceObj, use_case['URIs'])
800
+
801
+ elif 'UseCaseKeyProperty' in use_case:
735
802
  entry_key, entry_comparison, entry_values = use_case['UseCaseKeyProperty'], use_case['UseCaseComparison'], use_case['UseCaseKeyValues']
736
803
 
737
- _, use_case_applies = checkComparison(rf_payload.get(entry_key), entry_comparison, entry_values)
804
+ _, use_case_applies = checkComparison(rf_payload.get(entry_key, REDFISH_ABSENT), entry_comparison, entry_values)
738
805
 
739
806
  # Check if URI applies to this usecase as well
740
807
  if 'URIs' in use_case:
@@ -742,7 +809,7 @@ def validateInteropResource(propResourceObj, interop_profile, rf_payload):
742
809
 
743
810
  elif 'URIs' in use_case:
744
811
  use_case_applies = checkInteropURI(propResourceObj, use_case['URIs'])
745
-
812
+
746
813
  else:
747
814
  use_case_applies = False
748
815
 
@@ -192,6 +192,9 @@ def validateSingleURI(URI, profile, uriName='', expectedType=None, expectedSchem
192
192
 
193
193
  for msg in results[uriName]['messages']:
194
194
  msg.parent_results = results
195
+ if msg.success == interop.testResultEnum.NOT_TESTED:
196
+ counts['notTested'] += 1
197
+
195
198
 
196
199
  return True, counts, results, (links, limited_links), resource_obj
197
200
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: redfish_interop_validator
3
- Version: 2.2.1
3
+ Version: 2.2.3
4
4
  Summary: Redfish Interop Validator
5
5
  Home-page: https://github.com/DMTF/Redfish-Interop-Validator
6
6
  Author: DMTF, https://www.dmtf.org/standards/feedback
@@ -11,7 +11,7 @@ with open("README.md", "r", "utf-8") as f:
11
11
 
12
12
  setup(
13
13
  name="redfish_interop_validator",
14
- version="2.2.1",
14
+ version="2.2.3",
15
15
  description="Redfish Interop Validator",
16
16
  long_description=long_description,
17
17
  long_description_content_type="text/markdown",