[VVP] Update validations based on VNFRQTS-637
[vvp/validation-scripts.git] / ice_validator / tests / utils / ports.py
1 # -*- coding: utf8 -*-
2 # ============LICENSE_START=======================================================
3 # org.onap.vvp/validation-scripts
4 # ===================================================================
5 # Copyright © 2019 AT&T Intellectual Property. All rights reserved.
6 # ===================================================================
7 #
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
12 #
13 #             http://www.apache.org/licenses/LICENSE-2.0
14 #
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.
20 #
21 #
22 #
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
27 #
28 #             https://creativecommons.org/licenses/by/4.0/
29 #
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.
35 #
36 # ============LICENSE_END============================================
37 #
38 #
39 from tests.structures import Heat
40 from tests.helpers import parameter_type_to_heat_type, prop_iterator
41 from . import nested_dict
42
43
44 AAP_EXEMPT_CAVEAT = (
45     "If this VNF is not able to adhere to this requirement, please consult the Heat "
46     "Orchestration Template guidelines for more information. If you are knowingly "
47     "violating this requirement after reading the guidelines, then add the parameter "
48     "to the aap_exempt list under this resources metadata to suppress this warning."
49 )
50
51
52 def get_aap_exemptions(resource_props):
53     """
54     Gets the list of parameters that the Heat author has exempted from following
55     the naming conventions associated with AAP.
56
57     :param resource_props: dict of properties under the resource ID
58     :return: list of all parameters to exempt or an empty list
59     """
60     metadata = resource_props.get("metadata") or {}
61     return metadata.get("aap_exempt") or []
62
63
64 def check_parameter_format(
65     yaml_file, regx, intext, resource_processor, *properties, exemptions_allowed=False
66 ):
67     """
68     yaml_file: input file to check
69     regx: dictionary containing the regex to use to validate parameter
70     intext: internal or external
71     resource_processor: resource type specific helper, defined in structures.py
72     properties: arg list of property that is being checked
73     exemptions_allowed: If True, then parameters in the aap_exempt list are allowed to
74                         not follow the rules
75     """
76
77     invalid_parameters = []
78     heat = Heat(filepath=yaml_file)
79     resource_type = resource_processor.resource_type
80     resources = heat.get_resource_by_type(resource_type)
81     heat_parameters = heat.parameters
82     for rid, resource in resources.items():
83         resource_intext, port_match = resource_processor.get_rid_match_tuple(rid)
84         if not port_match:
85             continue  # port resource ID not formatted correctely
86
87         if (
88             resource_intext != intext
89         ):  # skipping if type (internal/external) doesn't match
90             continue
91
92         for param in prop_iterator(resource, *properties):
93             if (
94                 param
95                 and isinstance(param, dict)
96                 and "get_resource" not in param
97                 and "get_attr" not in param
98             ):
99                 # checking parameter uses get_param
100                 parameter = param.get("get_param")
101                 if not parameter:
102                     msg = (
103                         "Unexpected parameter format for {} {} property {}: {}. "
104                         "Please consult the heat guidelines documentation for details."
105                     ).format(resource_type, rid, properties, param)
106                     invalid_parameters.append(msg)  # should this be a failure?
107                     continue
108
109                 # getting parameter if the get_param uses list, and getting official
110                 # HEAT parameter type
111                 parameter_type = parameter_type_to_heat_type(parameter)
112                 if parameter_type == "comma_delimited_list":
113                     parameter = parameter[0]
114                 elif parameter_type != "string":
115                     continue
116
117                 # checking parameter format = parameter type defined in parameters
118                 # section
119                 heat_parameter_type = nested_dict.get(
120                     heat_parameters, parameter, "type"
121                 )
122                 if not heat_parameter_type or heat_parameter_type != parameter_type:
123                     msg = (
124                         "{} {} parameter {} defined as type {} "
125                         + "is being used as type {} in the heat template"
126                     ).format(
127                         resource_type,
128                         properties,
129                         parameter,
130                         heat_parameter_type,
131                         parameter_type,
132                     )
133                     invalid_parameters.append(msg)  # should this actually be an error?
134                     continue
135
136                 if exemptions_allowed and parameter in get_aap_exemptions(resource):
137                     continue
138
139                 # if parameter type is not in regx dict, then it is not supported
140                 # by automation
141                 regx_dict = regx[resource_intext].get(parameter_type)
142                 if not regx_dict:
143                     msg = (
144                         "{} {} parameter {} defined as type {} "
145                         "which is required by platform data model for proper "
146                         "assignment and inventory."
147                     ).format(resource_type, properties, parameter, parameter_type)
148                     if exemptions_allowed:
149                         msg = "WARNING: {} {}".format(msg, AAP_EXEMPT_CAVEAT)
150                     invalid_parameters.append(msg)
151                     continue
152
153                 # checking if param adheres to guidelines format
154                 regexp = regx[resource_intext][parameter_type]["machine"]
155                 readable_format = regx[resource_intext][parameter_type]["readable"]
156                 match = regexp.match(parameter)
157                 if not match:
158                     msg = (
159                         "{} {} property {} parameter {} does not follow {} "
160                         "format {} which is required by platform data model for proper "
161                         "assignment and inventory."
162                     ).format(
163                         resource_type,
164                         rid,
165                         properties,
166                         parameter,
167                         resource_intext,
168                         readable_format,
169                     )
170                     if exemptions_allowed:
171                         msg = "WARNING: {} {}".format(msg, AAP_EXEMPT_CAVEAT)
172                     invalid_parameters.append(msg)
173                     continue
174
175                 # checking that parameter includes correct vm_type/network_role
176                 parameter_checks = regx.get("parameter_to_resource_comparisons", [])
177                 for check in parameter_checks:
178                     resource_match = port_match.group(check)
179                     if (
180                         resource_match
181                         and not parameter.startswith(resource_match)
182                         and parameter.find("_{}_".format(resource_match)) == -1
183                     ):
184                         msg = (
185                             "{0} {1} property {2} parameter "
186                             "{3} {4} does match resource {4} {5}"
187                         ).format(
188                             resource_type,
189                             rid,
190                             properties,
191                             parameter,
192                             check,
193                             resource_match,
194                         )
195                         invalid_parameters.append(msg)
196                         continue
197
198     assert not invalid_parameters, "%s" % "\n".join(invalid_parameters)
199
200
201 def get_list_of_ports_attached_to_nova_server(nova_server):
202     networks_list = nova_server.get("properties", {}).get("networks")
203
204     port_ids = []
205     if networks_list:
206         for network in networks_list:
207             network_prop = network.get("port")
208             if network_prop:
209                 pid = network_prop.get("get_param")
210                 if not pid:
211                     pid = network_prop.get("get_resource")
212                 port_ids.append(pid)
213
214     return port_ids