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.
- {redfish_interop_validator-2.2.1/redfish_interop_validator.egg-info → redfish_interop_validator-2.2.3}/PKG-INFO +1 -1
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/RedfishInteropValidator.py +1 -1
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/interop.py +91 -24
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/validateResource.py +3 -0
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3/redfish_interop_validator.egg-info}/PKG-INFO +1 -1
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/setup.py +1 -1
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/AUTHORS.md +0 -0
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/LICENSE.md +0 -0
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/README.md +0 -0
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/RedfishLogo.py +0 -0
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/__init__.py +0 -0
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/config.py +0 -0
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/profile.py +0 -0
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/redfish.py +0 -0
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/session.py +0 -0
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/tohtml.py +0 -0
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator/traverseInterop.py +0 -0
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator.egg-info/SOURCES.txt +0 -0
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator.egg-info/dependency_links.txt +0 -0
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator.egg-info/entry_points.txt +0 -0
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator.egg-info/requires.txt +0 -0
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/redfish_interop_validator.egg-info/top_level.txt +0 -0
- {redfish_interop_validator-2.2.1 → redfish_interop_validator-2.2.3}/setup.cfg +0 -0
|
@@ -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.
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
695
|
+
parameter_dictionary = profile_entry["Parameters"]
|
|
642
696
|
# problem: if dne, skip
|
|
643
697
|
# assume mandatory
|
|
644
|
-
for
|
|
645
|
-
item =
|
|
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
|
-
|
|
649
|
-
|
|
650
|
-
if
|
|
651
|
-
values_array =
|
|
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(
|
|
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(
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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 '
|
|
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
|
|
|
@@ -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.
|
|
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",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|