2 # ============LICENSE_START====================================================
3 # org.onap.vvp/validation-scripts
4 # ===================================================================
5 # Copyright © 2019 AT&T Intellectual Property. All rights reserved.
6 # ===================================================================
8 # Unless otherwise specified, all software contained herein is licensed
9 # under the Apache License, Version 2.0 (the "License");
10 # you may not use this software except in compliance with the License.
11 # You may obtain a copy of the License at
13 # http://www.apache.org/licenses/LICENSE-2.0
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS,
17 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 # See the License for the specific language governing permissions and
19 # limitations under the License.
23 # Unless otherwise specified, all documentation contained herein is licensed
24 # under the Creative Commons License, Attribution 4.0 Intl. (the "License");
25 # you may not use this documentation except in compliance with the License.
26 # You may obtain a copy of the License at
28 # https://creativecommons.org/licenses/by/4.0/
30 # Unless required by applicable law or agreed to in writing, documentation
31 # distributed under the License is distributed on an "AS IS" BASIS,
32 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
33 # See the License for the specific language governing permissions and
34 # limitations under the License.
36 # ============LICENSE_END============================================
47 from .structures import CinderVolumeAttachmentProcessor
48 from .structures import NovaServerProcessor
49 from .structures import get_all_resources
50 from .helpers import validates
55 class VmClassValidator(object):
56 """validate VM class has unique type
61 self.vm_classes = None
66 def __call__(self, resources):
67 """return (possibly empty) list of error message strings
70 pytest.skip("No resources found")
71 self.vm_counts = collections.defaultdict(set)
72 self.vm_classes = collections.defaultdict(set)
73 self.vm_rids = collections.defaultdict(set)
74 self.vm_types = collections.defaultdict(set)
75 va_config, self.va_count = CinderVolumeAttachmentProcessor.get_config(resources)
77 pytest.skip("No Cinder Volume Attachment configurations found")
78 for rid, resource in resources.items():
79 vm_class = NovaServerProcessor.get_vm_class(resource)
81 vm_class["cinder_volume_attachment"] = va_config.get(rid)
82 match = NovaServerProcessor.get_rid_match_tuple(rid)[1]
84 vm_type = match.groupdict().get("vm_type")
86 self.vm_classes[vm_class].add(rid)
87 self.vm_types[vm_type].add(vm_class)
88 self.vm_counts[vm_type].add(self.va_count.get(rid))
89 self.vm_rids[vm_type].add(rid)
90 if not self.vm_classes:
91 pytest.skip("No vm_classes found")
92 return self.get_errors()
95 """return (possibly empty) list of error message strings
98 for k, v in self.vm_types.items():
101 "vm-type %s has class conflict %s"
102 % (k, ", ".join(str(list(self.vm_classes[c])) for c in v))
107 % ", ".join([str(key_diff(classes[0], c)) for c in classes[1:]])
109 for k, v in self.vm_counts.items():
112 "Attachment count conflict %s"
113 % ({rid: self.va_count.get(rid) for rid in self.vm_rids[k]})
118 def key_diff(d1, d2, prefix=""):
119 """Return list of keys which differ between d1 and d2 (dicts)
121 diff = [prefix + k for k in d1 if k not in d2]
122 diff.extend(prefix + k for k in d2 if k not in d1)
123 if isinstance(d1, dict) and isinstance(d2, dict):
124 for k, v1 in d1.items():
125 if k in d2 and v1 != d2[k]:
127 if isinstance(v1, type(v2)) and isinstance(v1, (dict, frozenset)):
128 diff.extend(key_diff(v1, v2, prefix=prefix + k + "."))
130 diff.append(prefix + k)
134 @validates("R-01455")
135 def test_vm_class_has_unique_type(yaml_files):
137 When a VNF’s Heat Orchestration Template creates a Virtual
138 Machine (i.e., OS::Nova::Server), each “class” of VMs MUST be
139 assigned a VNF unique vm-type; where “class” defines VMs that
140 MUST have the following identical characteristics:
142 1. OS::Nova::Server resource property flavor value
143 2. OS::Nova::Server resource property image value
144 3. Cinder Volume attachments
145 Each VM in the “class” MUST have the identical Cinder
147 4. Network attachments and IP address requirements
148 Each VM in the “class” MUST have the the identical number of
149 ports connecting to the identical networks and requiring the
150 identical IP address configuration
152 resources = get_all_resources(yaml_files)
153 errors = VmClassValidator()(resources)
154 assert not errors, "\n".join(errors)