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============================================
40 from pathlib import Path
41 from typing import Mapping
43 from preload.data import AbstractPreloadInstance
44 from preload.generator import (
46 get_or_create_template,
47 AbstractPreloadGenerator,
49 from preload.model import VnfModule, Port
51 THIS_DIR = os.path.dirname(os.path.abspath(__file__))
52 DATA_DIR = os.path.join(THIS_DIR, "vnfapi_data")
55 def get_or_create_network_template(network_role, vm_networks):
57 If the network role already exists in vm_networks, then
58 return that otherwise create a blank template and return that
60 return get_or_create_template(
61 DATA_DIR, "network-role", network_role, vm_networks, "vm-network"
65 class VnfApiPreloadGenerator(AbstractPreloadGenerator):
67 def supports_output_passing(cls):
75 def output_sub_dir(cls):
80 vnf_module: VnfModule,
81 preload_data: AbstractPreloadInstance,
84 self.module_incomplete = False
85 template = get_json_template(DATA_DIR, "preload_template")
86 self._populate(template, preload_data, vnf_module)
89 if preload_data.flag_incompletes and self.module_incomplete
92 filename = "{}{}.json".format(preload_data.preload_basename, incomplete)
93 outfile = output_dir.joinpath(filename)
94 with outfile.open("w") as f:
95 json.dump(template, f, indent=4)
100 preload_data: AbstractPreloadInstance,
101 vnf_module: VnfModule,
103 self._add_vnf_metadata(template, preload_data)
104 self._add_availability_zones(template, preload_data, vnf_module)
105 self._add_vnf_networks(template, preload_data, vnf_module)
106 self._add_vms(template, preload_data, vnf_module)
107 self._add_parameters(template, preload_data, vnf_module)
109 def _add_vnf_metadata(self, template: Mapping, preload: AbstractPreloadInstance):
110 vnf_meta = template["input"]["vnf-topology-information"][
111 "vnf-topology-identifier"
114 vnf_meta["vnf-name"] = self.normalize(preload.vnf_name, "vnf_name")
115 vnf_meta["generic-vnf-type"] = self.normalize(
118 "VALUE FOR: Concatenation of <Service Name>/"
119 "<VF Instance Name> MUST MATCH SDC",
121 vnf_meta["vnf-type"] = self.normalize(
122 preload.vf_module_model_name,
123 "vf-module-model-name",
124 "VALUE FOR: <vfModuleModelName> from CSAR or SDC",
127 def _add_availability_zones(
128 self, template: Mapping, preload: AbstractPreloadInstance, vnf_module: VnfModule
130 zones = template["input"]["vnf-topology-information"]["vnf-assignments"][
133 for i, zone_param in enumerate(vnf_module.availability_zones):
134 zone = preload.get_availability_zone(i, zone_param)
135 zones.append({"availability-zone": self.normalize(zone, zone_param, index=i)})
137 def add_floating_ips(
138 self, network_template: dict, port: Port, preload: AbstractPreloadInstance
140 # only one floating IP is really supported, in the preload model
141 # so for now we'll just use the last one. We might revisit this
142 # and if multiple floating params exist, then come up with an
143 # approach to pick just one
144 for ip in port.floating_ips:
145 ip_value = preload.get_floating_ip(
146 port.vm.vm_type, port.network.network_role, ip.ip_version, ip.param
148 key = "floating-ip" if ip.ip_version == 4 else "floating-ip-v6"
149 network_template[key] = self.normalize(ip_value, ip.param)
152 self, network_template: dict, port: Port, preload: AbstractPreloadInstance
154 for index, ip in port.fixed_ips_with_index:
155 ip_value = preload.get_fixed_ip(
157 port.network.network_role,
162 ip_value = self.normalize(ip_value, ip.param, index=index)
163 if ip.ip_version == 4:
164 network_template["network-ips"].append({"ip-address": ip_value})
165 network_template["ip-count"] += 1
167 network_template["network-ips-v6"].append({"ip-address": ip_value})
168 network_template["ip-count-ipv6"] += 1
170 def _add_vnf_networks(
171 self, template: Mapping, preload: AbstractPreloadInstance, vnf_module: VnfModule
173 networks = template["input"]["vnf-topology-information"]["vnf-assignments"][
176 for network in vnf_module.networks:
178 "network-role": network.network_role,
179 "network-name": self.normalize(
180 preload.get_network_name(network.network_role, network.name_param),
182 "VALUE FOR: network name for {}".format(network.name_param),
185 for subnet in network.subnet_params:
186 subnet_id = preload.get_subnet_id(
187 network.network_role, subnet.ip_version, subnet.param_name
191 "ipv6-subnet-id" if "_v6_" in subnet.param_name else "subnet-id"
193 network_data[key] = self.normalize(subnet_id, subnet.param_name)
195 subnet_name = preload.get_subnet_name(
196 network.network_role, subnet.ip_version, ""
200 if "_v6_" in subnet.param_name
203 msg = "VALUE FOR: name for {}".format(subnet.param_name)
204 value = self.normalize(
205 subnet_name, subnet.param_name, alt_message=msg
207 network_data[key] = value
208 networks.append(network_data)
211 self, template: Mapping, preload: AbstractPreloadInstance, vnf_module: VnfModule
213 vm_list = template["input"]["vnf-topology-information"]["vnf-assignments"][
216 for vm in vnf_module.virtual_machine_types:
217 vm_template = get_json_template(DATA_DIR, "vm")
218 vm_template["vm-type"] = vm.vm_type
219 vm_template["vm-count"] = vm.vm_count
220 for i, param in enumerate(sorted(vm.names)):
221 name = preload.get_vm_name(vm.vm_type, i, param)
222 vm_template["vm-names"]["vm-name"].append(self.normalize(name, param, index=i))
223 vm_list.append(vm_template)
224 vm_networks = vm_template["vm-networks"]
225 for port in vm.ports:
226 role = port.network.network_role
227 network_template = get_or_create_network_template(role, vm_networks)
228 network_template["network-role"] = role
229 network_template["network-role-tag"] = role
230 network_template["use-dhcp"] = "Y" if port.uses_dhcp else "N"
231 self.add_fixed_ips(network_template, port, preload)
232 self.add_floating_ips(network_template, port, preload)
235 self, template: Mapping, preload: AbstractPreloadInstance, vnf_module: VnfModule
237 params = template["input"]["vnf-topology-information"]["vnf-parameters"]
238 for key, value in vnf_module.preload_parameters.items():
239 preload_value = preload.get_vnf_parameter(key, value)
240 value = preload_value or value
243 "vnf-parameter-name": key,
244 "vnf-parameter-value": self.normalize(value, key),
247 for key, value in preload.get_additional_parameters().items():
250 "vnf-parameter-name": key,
251 "vnf-parameter-value": self.normalize(value, key),