summaryrefslogtreecommitdiffstats
path: root/validation-scripts/ice_validator/tests/utils
diff options
context:
space:
mode:
Diffstat (limited to 'validation-scripts/ice_validator/tests/utils')
-rw-r--r--validation-scripts/ice_validator/tests/utils/__init__.py39
-rw-r--r--validation-scripts/ice_validator/tests/utils/nested_files.py142
-rw-r--r--validation-scripts/ice_validator/tests/utils/nested_iterables.py213
-rw-r--r--validation-scripts/ice_validator/tests/utils/network_roles.py163
-rw-r--r--validation-scripts/ice_validator/tests/utils/ports.py179
-rw-r--r--validation-scripts/ice_validator/tests/utils/vm_types.py117
-rw-r--r--validation-scripts/ice_validator/tests/utils/volumes.py72
-rw-r--r--validation-scripts/ice_validator/tests/utils/yaml_custom_utils.py57
8 files changed, 982 insertions, 0 deletions
diff --git a/validation-scripts/ice_validator/tests/utils/__init__.py b/validation-scripts/ice_validator/tests/utils/__init__.py
new file mode 100644
index 0000000..e8f24cd
--- /dev/null
+++ b/validation-scripts/ice_validator/tests/utils/__init__.py
@@ -0,0 +1,39 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
diff --git a/validation-scripts/ice_validator/tests/utils/nested_files.py b/validation-scripts/ice_validator/tests/utils/nested_files.py
new file mode 100644
index 0000000..cc506d0
--- /dev/null
+++ b/validation-scripts/ice_validator/tests/utils/nested_files.py
@@ -0,0 +1,142 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
+import yaml
+import re
+from os import path
+
+
+def get_list_of_nested_files(yml, dirpath):
+ '''
+ return a list of all nested files
+ '''
+
+ if not hasattr(yml, 'items'):
+ return []
+
+ nested_files = []
+
+ for k, v in yml.items():
+ if isinstance(v, dict) and "type" in v:
+ t = v["type"]
+ if t.endswith(".yml") or t.endswith(".yaml"):
+ filepath = path.join(dirpath, t)
+ with open(filepath) as fh:
+ t_yml = yaml.load(fh)
+ nested_files.append(filepath)
+ nested_files.extend(get_list_of_nested_files(t_yml, dirpath))
+ elif t == "OS::Heat::ResourceGroup":
+ rdt = v["properties"]["resource_def"]["type"]
+ if rdt.endswith(".yml") or rdt.endswith(".yaml"):
+ filepath = path.join(dirpath, rdt)
+ with open(filepath) as fh:
+ rdt_yml = yaml.load(fh)
+ nested_files.append(filepath)
+ nested_files.extend(
+ get_list_of_nested_files(rdt_yml, dirpath))
+ if isinstance(v, dict):
+ nested_files.extend(
+ get_list_of_nested_files(v, dirpath))
+ elif isinstance(v, list):
+ for d in v:
+ nested_files.extend(
+ get_list_of_nested_files(d, dirpath))
+ return nested_files
+
+
+def check_for_invalid_nesting(yml, yaml_file, dirpath):
+ '''
+ return a list of all nested files
+ '''
+
+ if not hasattr(yml, 'items'):
+ return []
+
+ invalid_nesting = []
+ p = re.compile('^[A-z]*::[A-z]*::[A-z]*$')
+
+ for k, v in yml.items():
+ if isinstance(v, dict) and "type" in v:
+ t = v["type"]
+
+ if t.endswith(".yml") or t.endswith(".yaml"):
+ filepath = path.join(dirpath, t)
+ try:
+ with open(filepath) as fh:
+ t_yml = yaml.load(fh)
+ except Exception as e:
+ invalid_nesting.append(filepath)
+ print(e)
+ invalid_nesting.extend(
+ check_for_invalid_nesting(t_yml,
+ filepath,
+ dirpath))
+ elif t == "OS::Heat::ResourceGroup":
+ rd = v["properties"]["resource_def"]
+ if not isinstance(rd, dict):
+ invalid_nesting.append(yaml_file)
+ elif "type" not in rd:
+ invalid_nesting.append(yaml_file)
+ elif not p.match(rd["type"]) and not \
+ (rd["type"].endswith(".yml")
+ or rd["type"].endswith(".yaml")):
+ filepath = path.join(dirpath, rd["type"])
+ try:
+ with open(filepath) as fh:
+ rdt_yml = yaml.load(fh)
+ except Exception as e:
+ invalid_nesting.append(filepath)
+ print(e)
+ invalid_nesting.extend(
+ check_for_invalid_nesting(rdt_yml,
+ filepath,
+ dirpath))
+ if isinstance(v, dict):
+ invalid_nesting.extend(
+ check_for_invalid_nesting(v,
+ yaml_file,
+ dirpath))
+ elif isinstance(v, list):
+ for d in v:
+ invalid_nesting.extend(
+ check_for_invalid_nesting(d,
+ yaml_file,
+ dirpath))
+ return invalid_nesting
diff --git a/validation-scripts/ice_validator/tests/utils/nested_iterables.py b/validation-scripts/ice_validator/tests/utils/nested_iterables.py
new file mode 100644
index 0000000..19290c0
--- /dev/null
+++ b/validation-scripts/ice_validator/tests/utils/nested_iterables.py
@@ -0,0 +1,213 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
+
+def parse_nested_dict(d, key=""):
+ '''
+ parse the nested dictionary and return values of
+ given key of function parameter only
+ '''
+ nested_elements = []
+ for k, v in d.items():
+ if isinstance(v, dict):
+ sub_dict = parse_nested_dict(v, key)
+ nested_elements.extend(sub_dict)
+ else:
+ if key:
+ if k == key:
+ nested_elements.append(v)
+ else:
+ nested_elements.append(v)
+
+ return nested_elements
+
+
+def find_all_get_param_in_yml(yml):
+ '''
+ Recursively find all referenced parameters in a parsed yaml body
+ and return a list of parameters
+ '''
+ os_pseudo_parameters = ['OS::stack_name',
+ 'OS::stack_id',
+ 'OS::project_id']
+
+ if not hasattr(yml, 'items'):
+ return []
+ params = []
+ for k, v in yml.items():
+ if k == 'get_param' and v not in os_pseudo_parameters:
+ for item in (v if isinstance(v, list) else [v]):
+ if isinstance(item, dict):
+ params.extend(find_all_get_param_in_yml(item))
+ elif isinstance(item, str):
+ params.append(item)
+ continue
+ elif k == 'list_join':
+ for item in (v if isinstance(v, list) else [v]):
+ if isinstance(item, list):
+ for d in item:
+ params.extend(find_all_get_param_in_yml(d))
+ continue
+ if isinstance(v, dict):
+ params.extend(find_all_get_param_in_yml(v))
+ elif isinstance(v, list):
+ for d in v:
+ params.extend(find_all_get_param_in_yml(d))
+ return params
+
+
+def find_all_get_resource_in_yml(yml):
+ '''
+ Recursively find all referenced resources
+ in a parsed yaml body and return a list of resource ids
+ '''
+ if not hasattr(yml, 'items'):
+ return []
+ resources = []
+ for k, v in yml.items():
+ if k == 'get_resource':
+ if isinstance(v, list):
+ resources.append(v[0])
+ else:
+ resources.append(v)
+ continue
+ if isinstance(v, dict):
+ resources.extend(find_all_get_resource_in_yml(v))
+ elif isinstance(v, list):
+ for d in v:
+ resources.extend(find_all_get_resource_in_yml(d))
+ return resources
+
+
+def find_all_get_file_in_yml(yml):
+ '''
+ Recursively find all get_file in a parsed yaml body
+ and return the list of referenced files/urls
+ '''
+ if not hasattr(yml, 'items'):
+ return []
+ resources = []
+ for k, v in yml.items():
+ if k == 'get_file':
+ if isinstance(v, list):
+ resources.append(v[0])
+ else:
+ resources.append(v)
+ continue
+ if isinstance(v, dict):
+ resources.extend(find_all_get_file_in_yml(v))
+ elif isinstance(v, list):
+ for d in v:
+ resources.extend(find_all_get_file_in_yml(d))
+ return resources
+
+
+def find_all_get_resource_in_resource(resource):
+ '''
+ Recursively find all referenced resources
+ in a heat resource and return a list of resource ids
+ '''
+ if not hasattr(resource, 'items'):
+ return []
+
+ resources = []
+ for k, v in resource.items():
+ if k == 'get_resource':
+ if isinstance(v, list):
+ resources.append(v[0])
+ else:
+ resources.append(v)
+ continue
+ if isinstance(v, dict):
+ resources.extend(
+ find_all_get_resource_in_resource(v))
+ elif isinstance(v, list):
+ for d in v:
+ resources.extend(
+ find_all_get_resource_in_resource(d))
+ return resources
+
+
+def get_associated_resources_per_resource(resources):
+ '''
+ Recursively find all referenced resources for each resource
+ in a list of resource ids
+ '''
+ if not hasattr(resources, 'items'):
+ return None
+
+ resources_dict = {}
+ resources_dict["resources"] = {}
+ ref_resources = []
+
+ for res_key, res_value in resources.items():
+ get_resources = []
+
+ for k, v in res_value:
+ if k == 'get_resource' and\
+ isinstance(v, dict):
+ get_resources = find_all_get_resource_in_resource(v)
+
+ # if resources found, add to dict
+ if get_resources:
+ ref_resources.extend(get_resources)
+ resources_dict["resources"][res_key] = {
+ "res_value": res_value,
+ "get_resources": get_resources,
+ }
+
+ resources_dict["ref_resources"] = set(ref_resources)
+
+ return resources_dict
+
+
+def flatten(items):
+ '''
+ flatten items from any nested iterable
+ '''
+
+ merged_list = []
+ for item in items:
+ if isinstance(item, list):
+ sub_list = flatten(item)
+ merged_list.extend(sub_list)
+ else:
+ merged_list.append(item)
+ return merged_list
diff --git a/validation-scripts/ice_validator/tests/utils/network_roles.py b/validation-scripts/ice_validator/tests/utils/network_roles.py
new file mode 100644
index 0000000..5a551ab
--- /dev/null
+++ b/validation-scripts/ice_validator/tests/utils/network_roles.py
@@ -0,0 +1,163 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
+import re
+import socket
+
+
+def get_network_role_from_port(resource):
+ '''
+ get the network role from a neutron port resource
+ '''
+ if not isinstance(resource, dict):
+ return None
+ if 'type' not in resource:
+ return None
+ if resource['type'] != 'OS::Neutron::Port':
+ return None
+ if 'properties' not in resource:
+ return None
+
+ formats = [
+ ["network", "string", "internal",
+ re.compile(r'int_(.+?)_net_id')],
+ ["network", "string", "internal",
+ re.compile(r'int_(.+?)_net_name')],
+ ["network", "string", "external",
+ re.compile(r'(.+?)_net_id')],
+ ["network", "string", "external",
+ re.compile(r'(.+?)_net_name')],
+ ]
+
+ for k1, v1 in resource["properties"].items():
+ if k1 != 'network':
+ continue
+
+ # get the network id or name
+ network = (
+ v1.get('get_param') or
+ v1.get('get_resource'))
+ if not network:
+ continue
+
+ for v2 in formats:
+ m = v2[3].match(network)
+ if m and m.group(1):
+ return m.group(1)
+
+ return None
+
+
+def get_network_type_from_port(resource):
+ '''
+ get the network type from a neutron port resource
+ '''
+ if not isinstance(resource, dict):
+ return None
+ if 'type' not in resource:
+ return None
+ if resource['type'] != 'OS::Neutron::Port':
+ return None
+ if 'properties' not in resource:
+ return None
+
+ formats = [
+ ["network", "string", "internal",
+ re.compile(r'int_(.+?)_net_id')],
+ ["network", "string", "internal",
+ re.compile(r'int_(.+?)_net_name')],
+ ["network", "string", "external",
+ re.compile(r'(.+?)_net_id')],
+ ["network", "string", "external",
+ re.compile(r'(.+?)_net_name')],
+ ]
+
+ for k1, v1 in resource["properties"].items():
+ if k1 != 'network':
+ continue
+ if "get_param" not in v1:
+ continue
+ for v2 in formats:
+ m = v2[3].match(v1["get_param"])
+ if m and m.group(1):
+ return v2[2]
+
+ return None
+
+
+def is_valid_ip_address(ip_address, ip_type='ipv4'):
+ '''
+ check if an ip address is valid
+ '''
+ if ip_type == 'ipv4':
+ return is_valid_ipv4_address(ip_address)
+ elif ip_type == 'ipv6':
+ return is_valid_ipv6_address(ip_address)
+ return False
+
+
+def is_valid_ipv4_address(ip_address):
+ '''
+ check if an ip address of the type ipv4
+ is valid
+ '''
+ try:
+ socket.inet_pton(socket.AF_INET, ip_address)
+ except AttributeError:
+ try:
+ socket.inet_aton(ip_address)
+ except (OSError, socket.error):
+ return False
+ return ip_address.count('.') == 3
+ except (OSError, socket.error):
+ return False
+ return True
+
+
+def is_valid_ipv6_address(ip_address):
+ '''
+ check if an ip address of the type ipv6
+ is valid
+ '''
+ try:
+ socket.inet_pton(socket.AF_INET6, ip_address)
+ except (OSError, socket.error):
+ return False
+ return True
diff --git a/validation-scripts/ice_validator/tests/utils/ports.py b/validation-scripts/ice_validator/tests/utils/ports.py
new file mode 100644
index 0000000..51e920a
--- /dev/null
+++ b/validation-scripts/ice_validator/tests/utils/ports.py
@@ -0,0 +1,179 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
+from .network_roles import get_network_role_from_port
+from .vm_types import get_vm_type_for_nova_server
+import re
+
+
+def is_valid_ip_address(ip_address, vm_type, network_role, port_property):
+ '''
+ Check the ip_address to make sure it is properly formatted and
+ also contains {vm_type} and {network_role}
+ '''
+
+ allowed_formats = [
+ ["allowed_address_pairs", "string", "internal",
+ re.compile(r'(.+?)_int_(.+?)_floating_v6_ip')],
+ ["allowed_address_pairs", "string", "internal",
+ re.compile(r'(.+?)_int_(.+?)_floating_ip')],
+ ["allowed_address_pairs", "string", "external",
+ re.compile(r'(.+?)_floating_v6_ip')],
+ ["allowed_address_pairs", "string", "external",
+ re.compile(r'(.+?)_floating_ip')],
+ ["allowed_address_pairs", "string", "internal",
+ re.compile(r'(.+?)_int_(.+?)_v6_ip_\d+')],
+ ["allowed_address_pairs", "string", "internal",
+ re.compile(r'(.+?)_int_(.+?)_ip_\d+')],
+ ["allowed_address_pairs", "string", "external",
+ re.compile(r'(.+?)_v6_ip_\d+')],
+ ["allowed_address_pairs", "string", "external",
+ re.compile(r'(.+?)_ip_\d+')],
+ ["allowed_address_pairs", "comma_delimited_list",
+ "internal", re.compile(r'(.+?)_int_(.+?)_v6_ips')],
+ ["allowed_address_pairs", "comma_delimited_list",
+ "internal", re.compile(r'(.+?)_int_(.+?)_ips')],
+ ["allowed_address_pairs", "comma_delimited_list",
+ "external", re.compile(r'(.+?)_v6_ips')],
+ ["allowed_address_pairs", "comma_delimited_list",
+ "external", re.compile(r'(.+?)_ips')],
+ ["fixed_ips", "string", "internal",
+ re.compile(r'(.+?)_int_(.+?)_v6_ip_\d+')],
+ ["fixed_ips", "string", "internal",
+ re.compile(r'(.+?)_int_(.+?)_ip_\d+')],
+ ["fixed_ips", "string", "external",
+ re.compile(r'(.+?)_v6_ip_\d+')],
+ ["fixed_ips", "string", "external",
+ re.compile(r'(.+?)_ip_\d+')],
+ ["fixed_ips", "comma_delimited_list", "internal",
+ re.compile(r'(.+?)_int_(.+?)_v6_ips')],
+ ["fixed_ips", "comma_delimited_list", "internal",
+ re.compile(r'(.+?)_int_(.+?)_ips')],
+ ["fixed_ips", "comma_delimited_list", "external",
+ re.compile(r'(.+?)_v6_ips')],
+ ["fixed_ips", "comma_delimited_list", "external",
+ re.compile(r'(.+?)_ips')],
+ ]
+
+ for v3 in allowed_formats:
+ if v3[0] != port_property:
+ continue
+ # check if pattern matches
+ m = v3[3].match(ip_address)
+ if m:
+ if (v3[2] == "internal" and
+ len(m.groups()) > 1):
+ return m.group(1) == vm_type and\
+ m.group(2) == network_role
+ elif (v3[2] == "external" and
+ len(m.groups()) > 0):
+ return m.group(1) == vm_type + "_" + network_role
+
+ return False
+
+
+def get_invalid_ip_addresses(resources, port_property):
+ '''
+ Get a list of valid ip addresses for a heat resources section
+ '''
+ invalid_ip_addresses = []
+
+ for k, v in resources.items():
+ if not isinstance(v, dict):
+ continue
+ if 'type' not in v:
+ continue
+ if v['type'] not in 'OS::Nova::Server':
+ continue
+ if 'properties' not in v:
+ continue
+ if 'networks' not in v['properties']:
+ continue
+
+ port_resource = None
+
+ vm_type = get_vm_type_for_nova_server(v)
+ if not vm_type:
+ continue
+
+ # get all ports associated with the nova server
+ properties = v['properties']
+ for network in properties['networks']:
+ for k3, v3 in network.items():
+ if k3 != 'port':
+ continue
+ if not isinstance(v3, dict):
+ continue
+
+ if 'get_resource' in v3:
+ port_id = v3['get_resource']
+ if not resources[port_id]:
+ continue
+ port_resource = resources[port_id]
+ else:
+ continue
+
+ network_role = get_network_role_from_port(port_resource)
+ if not network_role:
+ continue
+
+ for k1, v1 in port_resource["properties"].items():
+ if k1 != port_property:
+ continue
+ for v2 in v1:
+ if "ip_address" not in v2:
+ continue
+ if "get_param" not in v2["ip_address"]:
+ continue
+
+ ip_address = v2["ip_address"]["get_param"]
+
+ if isinstance(ip_address, list):
+ ip_address = ip_address[0]
+
+ valid_ip_address = is_valid_ip_address(ip_address,
+ vm_type,
+ network_role,
+ port_property)
+
+ if not valid_ip_address:
+ invalid_ip_addresses.append(ip_address)
+
+ return invalid_ip_addresses
diff --git a/validation-scripts/ice_validator/tests/utils/vm_types.py b/validation-scripts/ice_validator/tests/utils/vm_types.py
new file mode 100644
index 0000000..5bd447b
--- /dev/null
+++ b/validation-scripts/ice_validator/tests/utils/vm_types.py
@@ -0,0 +1,117 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
+import re
+
+
+def get_vm_types_for_resource(resource):
+ '''
+ Get all unique vm_types for a resource
+ Notes:
+ - Returns set([]) if the resource is not formatted
+ properly, the passed resource is not a nova server
+ - If more than one vm_type is detected all vm_types will
+ be returned
+ '''
+ if not isinstance(resource, dict):
+ return set()
+ if 'type' not in resource:
+ return set()
+ if resource['type'] != 'OS::Nova::Server':
+ return set()
+ if 'properties' not in resource:
+ return set()
+
+ key_values = ["name", "flavor", "image"]
+ key_value_formats = [
+ ["name", "string",
+ re.compile(r'(.+?)_name_\d+')],
+ ["name", "comma_delimited_list",
+ re.compile(r'(.+?)_names')],
+ ["flavor", "string",
+ re.compile(r'(.+?)_flavor_name')],
+ ["image", "string",
+ re.compile(r'(.+?)_image_name')],
+ ]
+
+ vm_types = []
+ for k2, v2 in resource['properties'].items():
+ if k2 not in key_values:
+ continue
+ if "get_param" not in v2:
+ continue
+ formats = [v for v in key_value_formats if v[0] == k2]
+ for v3 in formats:
+ param = v2["get_param"]
+ if isinstance(param, list):
+ param = param[0]
+ m = v3[2].match(param)
+ if m and m.group(1):
+ vm_types.append(m.group(1))
+
+ return set(vm_types)
+
+
+def get_vm_type_for_nova_server(resource):
+ '''
+ Get the vm_type for a resource
+ Note: Returns None if not exactly one vm_type
+ is detected, if the resource is not formatted properly, or
+ the passed resource is not a nova server
+ '''
+ vm_types = get_vm_types_for_resource(resource)
+
+ # if more than one vm_type was identified, return None
+ if len(vm_types) > 1:
+ return None
+
+ return vm_types.pop()
+
+
+def get_vm_types(resources):
+ '''
+ Get all vm_types for a list of heat resources, do note that
+ some of the values retrieved may be invalid
+ '''
+ vm_types = []
+ for v in resources.values():
+ vm_types.extend(list(get_vm_types_for_resource(v)))
+
+ return set(vm_types)
diff --git a/validation-scripts/ice_validator/tests/utils/volumes.py b/validation-scripts/ice_validator/tests/utils/volumes.py
new file mode 100644
index 0000000..03ac611
--- /dev/null
+++ b/validation-scripts/ice_validator/tests/utils/volumes.py
@@ -0,0 +1,72 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
+import yaml
+from os import path
+
+
+def get_volume_resources(heat_template):
+ '''
+ get the resources from the volume template
+ Note: Returns an empty dict if there is no
+ volume template or for any other error
+ '''
+ basename = path.splitext(heat_template)[0]
+
+ for ext in ['.yaml', '.yml']:
+ volume_template = basename + '_volume' + ext
+ if path.isfile(volume_template):
+ break
+ else:
+ return {}
+
+ try:
+ with open(volume_template) as fh:
+ yml = yaml.load(fh)
+ except Exception as e:
+ print(e)
+ return {}
+
+ if 'outputs' not in yml:
+ return {}
+ if 'resources' not in yml:
+ return {}
+
+ return yml['resources']
diff --git a/validation-scripts/ice_validator/tests/utils/yaml_custom_utils.py b/validation-scripts/ice_validator/tests/utils/yaml_custom_utils.py
new file mode 100644
index 0000000..0d292fe
--- /dev/null
+++ b/validation-scripts/ice_validator/tests/utils/yaml_custom_utils.py
@@ -0,0 +1,57 @@
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
+from yaml.constructor import ConstructorError
+
+
+def raise_duplicates_keys(loader, node, deep=False):
+ """Raise error when duplicate keys found in yaml file."""
+
+ mapping = {}
+ for key_node, value_node in node.value:
+ key = loader.construct_object(key_node, deep=deep)
+ value = loader.construct_object(value_node, deep=deep)
+ if key in mapping:
+ raise ConstructorError(
+ "while constructing a mapping", node.start_mark,
+ "found duplicate key (%s)" % key, key_node.start_mark)
+ mapping[key] = value
+
+ return loader.construct_mapping(node, deep)