# Copyright (C) 2020 NTT DATA # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file 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. import copy import os import yaml from oslo_config import cfg from oslo_log import log as logging from oslo_utils import uuidutils from toscaparser import tosca_template from tacker.common import exceptions from tacker.common import utils from tacker.extensions import nfvo from tacker import objects from tacker.objects import fields from tacker.tosca import utils as toscautils from tacker.vnfm import vim_client LOG = logging.getLogger(__name__) CONF = cfg.CONF def _get_vim(context, vim_connection_info): vim_client_obj = vim_client.VimClient() if vim_connection_info: vim_id = vim_connection_info[0].vim_id access_info = vim_connection_info[0].access_info if access_info: region_name = access_info.get('region') else: region_name = None else: vim_id = None region_name = None try: vim_res = vim_client_obj.get_vim( context, vim_id, region_name=region_name) except nfvo.VimNotFoundException: raise exceptions.VimConnectionNotFound(vim_id=vim_id) vim_res['vim_auth'].update({'region': region_name}) vim_info = {'id': vim_res['vim_id'], 'vim_id': vim_res['vim_id'], 'vim_type': vim_res['vim_type'], 'access_info': vim_res['vim_auth']} return vim_info def _get_vnfd_dict(context, vnfd_id, flavour_id): vnfd_dict = _get_flavour_based_vnfd( _get_vnf_package_path(context, vnfd_id), flavour_id) # Remove requirements from substitution mapping vnfd_dict.get('topology_template').get( 'substitution_mappings').pop('requirements') return vnfd_dict def _get_vnflcm_interface(context, interface, vnf_instance, flavour_id): '''Gets the interface found in vnfd ... node_templates: VNF: interfaces: Vnflcm: ''' interface_value = None vnfd_dict = _get_vnfd_dict(context, vnf_instance.vnfd_id, flavour_id) if not isinstance(vnfd_dict, dict): raise exceptions.InvalidContentType(msg="VNFD not valid") if vnfd_dict.get('topology_template'): topology_template = vnfd_dict.get('topology_template') if topology_template.get('node_templates'): node_templates = topology_template.get('node_templates') if node_templates.get('VNF'): vnf = node_templates.get('VNF') if vnf.get('interfaces'): interfaces = vnf.get('interfaces') if interfaces.get('Vnflcm'): vnflcm = interfaces.get('Vnflcm') if vnflcm: interface_value = vnflcm.get(interface) return interface_value def _build_affected_resources(vnf_instance, change_type=fields.ResourceChangeType.ADDED): '''build affected resources from vnf_instance instantiated info ''' affected_resources = {} instantiated_vnf_info = vnf_instance.instantiated_vnf_info if hasattr(instantiated_vnf_info, 'instance_id'): if instantiated_vnf_info.instance_id: affected_resources['affectedVnfcs'] = [] affected_resources['affectedVirtualLinks'] = [] affected_resources['affectedVirtualStorages'] = [] # build AffectedVnfc vnfc_resource_info = \ instantiated_vnf_info.vnfc_resource_info for vnfc_resource in vnfc_resource_info: data = {} data['id'] = vnfc_resource.id data['vduId'] = vnfc_resource.vdu_id data['changeType'] = change_type data['computeResource'] = \ vnfc_resource.compute_resource.to_dict() data['metadata'] = vnfc_resource.metadata affected_resources['affectedVnfcs'].append(data) # build AffectedVirtualLink vnf_virtual_link = \ instantiated_vnf_info.vnf_virtual_link_resource_info for vnf_vl_info in vnf_virtual_link: data = {} data['id'] = vnf_vl_info.id data['vnfVirtualLinkDescId'] = \ vnf_vl_info.vnf_virtual_link_desc_id data['changeType'] = change_type data['networkResource'] = \ vnf_vl_info.network_resource.to_dict() data['metadata'] = {} affected_resources['affectedVirtualLinks'].append(data) # build affectedVirtualStorages virtual_storage = \ instantiated_vnf_info.virtual_storage_resource_info for vnf_storage_info in virtual_storage: data = {} data['id'] = vnf_storage_info.id data['virtualStorageDescId'] = \ vnf_storage_info.virtual_storage_desc_id data['changeType'] = change_type data['storageResource'] = \ vnf_storage_info.storage_resource.to_dict() data['metadata'] = {} affected_resources['affectedVirtualStorages'].append(data) return utils.convert_snakecase_to_camelcase(affected_resources) def _get_affected_resources(old_vnf_instance=None, new_vnf_instance=None, extra_list=None): '''get_affected_resources returns affected resources in new_vnf_instance not present in old_vnf_instance. if extra_list (list of physical resource ids) is present, included to affected resources ''' def _get_affected_cpids(affected_vnfc, vnf_instance): affected_cpids = [] instantiated_vnf_info = vnf_instance.instantiated_vnf_info for vnfc_resource in instantiated_vnf_info.vnfc_resource_info: if vnfc_resource.id == affected_vnfc['id']: for vnfc_cp in vnfc_resource.vnfc_cp_info: if vnfc_cp.cpd_id: affected_cpids.append(vnfc_cp.cpd_id) if vnfc_cp.vnf_ext_cp_id: affected_cpids.append(vnfc_cp.vnf_ext_cp_id) return affected_cpids def _get_added_storageids(affected_vnfc, vnf_instance): affected_storage_ids = [] instantiated_vnf_info = vnf_instance.instantiated_vnf_info for vnfc_resource in instantiated_vnf_info.vnfc_resource_info: if vnfc_resource.id == affected_vnfc['id']: for storage_resource_id in vnfc_resource.storage_resource_ids: virtual_storage = \ instantiated_vnf_info.virtual_storage_resource_info for virt_storage_res_info in virtual_storage: if virt_storage_res_info.id == storage_resource_id: affected_storage_ids.append( virt_storage_res_info.virtual_storage_desc_id) return affected_storage_ids def diff_list(old_list, new_list): diff = [] for item in new_list: if item not in old_list: diff.append(item) return diff affected_resources = {} affected_resources['affectedVnfcs'] = [] affected_resources['affectedVirtualLinks'] = [] affected_resources['affectedVirtualStorages'] = [] if not old_vnf_instance: affected_resources = _build_affected_resources( new_vnf_instance, fields.ResourceChangeType.ADDED) # add affected cpids and add added storageids for affected_vnfc in affected_resources['affectedVnfcs']: affected_vnfc['affectedVnfcCpIds'] = _get_affected_cpids( affected_vnfc, new_vnf_instance) affected_vnfc['addedStorageResourceIds'] = _get_added_storageids( affected_vnfc, new_vnf_instance) elif not new_vnf_instance: affected_resources = _build_affected_resources(old_vnf_instance, fields.ResourceChangeType.REMOVED) # add affected cpids and add remove storageids for affected_vnfc in affected_resources['affectedVnfcs']: affected_vnfc['affectedVnfcCpIds'] = _get_affected_cpids( affected_vnfc, old_vnf_instance) affected_vnfc['removedStorageResourceIds'] = _get_added_storageids( affected_vnfc, old_vnf_instance) elif old_vnf_instance and new_vnf_instance: old_affected_resources = _build_affected_resources(old_vnf_instance) new_affected_resources = _build_affected_resources(new_vnf_instance, fields.ResourceChangeType.MODIFIED) # get resource_ids old_vnfc_resource_ids = [] for vnfc_resource in old_affected_resources.get('affectedVnfcs', []): old_vnfc_resource_ids.append( vnfc_resource['computeResource']['resourceId']) # remove extra_list items in old_vnfc_resource_ids # so that this items will be considered new if extra_list: for item in extra_list: if item in old_vnfc_resource_ids: index = old_vnfc_resource_ids.index(item) old_vnfc_resource_ids.pop(index) new_vnfc_resource_ids = [] for vnfc_resource in new_affected_resources.get('affectedVnfcs', []): resource_id = vnfc_resource['computeResource']['resourceId'] new_vnfc_resource_ids.append(resource_id) old_vnf_vl_resource_ids = [] for vnf_vl_info in old_affected_resources.get( 'affectedVirtualLinks', []): resource_id = vnf_vl_info['networkResource']['resourceId'] old_vnf_vl_resource_ids.append(resource_id) new_vnf_vl_resource_ids = [] for vnf_vl_info in new_affected_resources.get( 'affectedVirtualLinks', []): resource_id = vnf_vl_info['networkResource']['resourceId'] new_vnf_vl_resource_ids.append(resource_id) old_vnf_storage_resource_ids = [] for vnf_storage_info in old_affected_resources.get( 'affectedVirtualStorages', []): resource_id = vnf_storage_info['storageResource']['resourceId'] old_vnf_storage_resource_ids.append(resource_id) new_vnf_storage_resource_ids = [] for vnf_storage_info in new_affected_resources.get( 'affectedVirtualStorages', []): resource_id = vnf_storage_info['storageResource']['resourceId'] new_vnf_storage_resource_ids.append(resource_id) # get difference between resource_ids vnfc_resource_ids = diff_list(old_vnfc_resource_ids, new_vnfc_resource_ids) vnf_vl_resource_ids = diff_list(old_vnf_vl_resource_ids, new_vnf_vl_resource_ids) vnf_storage_resource_ids = diff_list(old_vnf_storage_resource_ids, new_vnf_storage_resource_ids) # return new affected resources for affected_vls in new_affected_resources['affectedVirtualLinks']: if (affected_vls['networkResource'] ['resourceId'] in vnf_vl_resource_ids): affected_resources['affectedVirtualLinks'].append(affected_vls) affected_storages = new_affected_resources['affectedVirtualStorages'] for affected_storage in affected_storages: if (affected_storage['storageResource'] ['resourceId'] in vnf_storage_resource_ids): affected_resources['affectedVirtualStorages'].append( affected_storage) for affected_vnfc in new_affected_resources['affectedVnfcs']: if (affected_vnfc['computeResource'] ['resourceId'] in vnfc_resource_ids): # update affected affectedVnfcCpIds affected_vnfc['affectedVnfcCpIds'] = _get_affected_cpids( affected_vnfc, new_vnf_instance) affected_resources['affectedVnfcs'].append(affected_vnfc) return affected_resources def _get_vnf_package_id(context, vnfd_id): vnf_package = objects.VnfPackageVnfd.get_by_id(context, vnfd_id) return vnf_package.package_uuid def _create_grant_request(vnfd_dict, package_uuid): node_templates = vnfd_dict.get('topology_template', {}).get('node_templates', {}) vnf_software_images = {} if not node_templates: return vnf_software_images def _build_vnf_software_image(sw_image_data, artifact_image_path): vnf_sw_image = objects.VnfSoftwareImage() vnf_sw_image.image_path = artifact_image_path vnf_sw_image.name = sw_image_data.get('name') vnf_sw_image.version = sw_image_data.get('version') if sw_image_data.get('checksum'): checksum = sw_image_data.get('checksum') if checksum.get('algorithm'): vnf_sw_image.algorithm = checksum.get('algorithm') if checksum.get('hash'): vnf_sw_image.hash = checksum.get('hash') vnf_sw_image.container_format = sw_image_data.get( 'container_format') vnf_sw_image.disk_format = sw_image_data.get('disk_format') if sw_image_data.get('min_disk'): min_disk = utils.MemoryUnit.convert_unit_size_to_num( sw_image_data.get('min_disk'), 'GB') vnf_sw_image.min_disk = min_disk else: vnf_sw_image.min_disk = 0 if sw_image_data.get('min_ram'): min_ram = utils.MemoryUnit.convert_unit_size_to_num( sw_image_data.get('min_ram'), 'MB') vnf_sw_image.min_ram = min_ram else: vnf_sw_image.min_ram = 0 return vnf_sw_image def _get_image_path(artifact_image_path, package_uuid): vnf_package_path = CONF.vnf_package.vnf_package_csar_path artifact_image_path = os.path.join( vnf_package_path, package_uuid, artifact_image_path.split('../')[-1]) return artifact_image_path for node, value in node_templates.items(): if not value.get( 'type') in ['tosca.nodes.nfv.Vdu.Compute', 'tosca.nodes.nfv.Vdu.VirtualBlockStorage']: continue sw_image_data = value.get('properties', {}).get('sw_image_data') artifacts = value.get('artifacts', {}) for artifact, sw_image in artifacts.items(): artifact_image_path = None if isinstance(sw_image, str): artifact_image_path = sw_image elif sw_image.get('type') == 'tosca.artifacts.nfv.SwImage': artifact_image_path = sw_image.get('file', {}) if sw_image_data and artifact_image_path: is_url = utils.is_url(artifact_image_path) if not is_url: artifact_image_path = _get_image_path(artifact_image_path, package_uuid) vnf_software_image = _build_vnf_software_image( sw_image_data, artifact_image_path) vnf_software_images[node] = vnf_software_image break return vnf_software_images def _make_final_vnf_dict(vnfd_dict, id, name, param_values, vnf_dict=None): if vnf_dict: final_vnf_dict = vnf_dict final_vnf_dict['vnfd']['attributes'].\ update({'vnfd': str(vnfd_dict)}) final_vnf_dict['attributes'].\ update({'param_values': str(param_values)}) final_vnf_dict['attributes'].\ update({'stack_name': name or ("vnflcm_" + id)}) return final_vnf_dict else: return {'vnfd': { 'attributes': { 'vnfd': str(vnfd_dict)}}, 'id': id, 'name': name, 'attributes': { 'param_values': str(param_values), 'stack_name': name or ("vnflcm_" + id)}} def _get_flavour_based_vnfd(csar_path, flavour_id): ext = (".yaml", ".yml") file_path_and_data = {} imp_list = [] for item in os.listdir(csar_path): src_path = os.path.join(csar_path, item) if os.path.isdir(src_path): for file in os.listdir(src_path): if file.endswith(ext): source_file_path = os.path.join(src_path, file) with open(source_file_path) as file_obj: data = yaml.safe_load(file_obj) substitution_map = data.get( 'topology_template', {}).get('substitution_mappings', {}) if substitution_map.get( 'properties', {}).get('flavour_id') == flavour_id: if data.get('imports'): for imp in data.get('imports'): imp_path = os.path.join(src_path, imp) imp_list.append(imp_path) data.update({'imports': imp_list}) return data elif src_path.endswith(ext): with open(src_path) as file_obj: file_data = yaml.safe_load(file_obj) substitution_map = file_data.get( 'topology_template', {}).get('substitution_mappings', {}) if substitution_map.get( 'properties', {}).get('flavour_id') == flavour_id: if file_data.get('imports'): for imp in file_data.get('imports'): imp_list.append(os.path.join(src_path, imp)) file_data.update({'imports': imp_list}) return file_data return file_path_and_data def _get_param_data(vnfd_dict, instantiate_vnf_req): param_value = {} additional_param = instantiate_vnf_req.additional_params if additional_param is None: additional_param = {} substitution_map = vnfd_dict.get('topology_template', {}).get('substitution_mappings', {}) input_attributes = vnfd_dict.get('topology_template', {}).get('inputs') if substitution_map is not None: subs_map_node_type = substitution_map.get('node_type') # Get properties in lower-level VNFD for top-level VNFD node_templates = vnfd_dict.get('topology_template', {}).get('node_templates', {}) for node in node_templates.values(): if node.get('type') == subs_map_node_type: node_property = node.get('properties', {}) if node_property: param_value.update(node_property) # Import `_type.yaml` file and get default properties. # If new value provided in additional_param, the property is updated. import_paths = vnfd_dict.get('imports', {}) for imp_path in import_paths: with open(imp_path) as file_obj: import_data = yaml.safe_load(file_obj) imp_node_type = import_data.get('node_types') if imp_node_type: for key, value in imp_node_type.items(): if key == subs_map_node_type: properties = value.get('properties') if properties: for key, prop in properties.items(): if additional_param.get(key): param_value.update({ key: additional_param.get(key)}) # If the parameter is provided in lower-level # VNFD, use it. Otherwise use the default. elif not param_value.get(key): param_value.update( {key: prop.get('default')}) for input_attr, value in input_attributes.items(): if additional_param.get(input_attr): param_value.update({input_attr: additional_param.get( input_attr)}) return param_value def _get_vim_connection_info_from_vnf_req(vnf_instance, instantiate_vnf_req): vim_connection_obj_list = [] if not instantiate_vnf_req.vim_connection_info: # add default vim if len(vnf_instance.vim_connection_info): vim_connection_obj_list.append(vnf_instance.vim_connection_info[0]) return vim_connection_obj_list for vim_connection in instantiate_vnf_req.vim_connection_info: vim_conn = objects.VimConnectionInfo(id=vim_connection.id, vim_id=vim_connection.vim_id, vim_type=vim_connection.vim_type, access_info=vim_connection.access_info, interface_info=vim_connection.interface_info) vim_connection_obj_list.append(vim_conn) # add default vim if len(vnf_instance.vim_connection_info): if vim_conn.id and vnf_instance.vim_connection_info[0].id: is_default_vim_exist = [vim_conn for vim_conn in vim_connection_obj_list if vim_conn.id == vnf_instance.vim_connection_info[0].id] if not len(is_default_vim_exist): vim_connection_obj_list.append(vnf_instance. vim_connection_info[0]) return vim_connection_obj_list def _build_instantiated_vnf_info(vnfd_dict, instantiate_vnf_req, vnf_instance, vim_id): inst_vnf_info = vnf_instance.instantiated_vnf_info inst_vnf_info.vnf_state = fields.VnfOperationalStateType.STARTED node_templates = vnfd_dict.get( 'topology_template', {}).get('node_templates') vnfc_resource_info, virtual_storage_resource_info = \ _get_vnfc_resource_info(vnfd_dict, instantiate_vnf_req, vim_id) inst_vnf_info.vnfc_resource_info = vnfc_resource_info tmp_insta_vnf_info = copy.deepcopy(inst_vnf_info) inst_vnf_info.ext_cp_info = _set_ext_cp_info(instantiate_vnf_req, inst_vnf_info=tmp_insta_vnf_info) inst_vnf_info.ext_virtual_link_info = _set_ext_virtual_link_info( instantiate_vnf_req, inst_vnf_info.ext_cp_info) inst_vnf_info.virtual_storage_resource_info = \ virtual_storage_resource_info inst_vnf_info.vnf_virtual_link_resource_info = \ _build_vnf_virtual_link_resource_info( node_templates, instantiate_vnf_req, inst_vnf_info.vnfc_resource_info, vim_id) inst_vnf_info.ext_managed_virtual_link_info = \ _build_ext_managed_virtual_link_info(instantiate_vnf_req, inst_vnf_info) inst_vnf_info.additional_params = instantiate_vnf_req.additional_params vnf_instance.instantiated_vnf_info = inst_vnf_info def _update_instantiated_vnf_info(change_ext_conn_req, vnf_instance): inst_vnf_info = vnf_instance.instantiated_vnf_info tmp_insta_vnf_info = copy.deepcopy(inst_vnf_info) inst_vnf_info.ext_cp_info = _update_ext_cp_info(change_ext_conn_req, inst_vnf_info=tmp_insta_vnf_info) inst_vnf_info.ext_virtual_link_info = _update_ext_virtual_link_info( change_ext_conn_req, inst_vnf_info=tmp_insta_vnf_info) inst_vnf_info.vnf_virtual_link_resource_info = \ _update_vnf_virtual_link_resource_info(change_ext_conn_req, inst_vnf_info) vnf_instance.instantiated_vnf_info = inst_vnf_info def _get_compute_nodes(vnfd_dict, instantiate_vnf_req): """Read the node templates and prepare VDU data in below format { 'VDU1': { 'CP': [CP1, CP2], 'VIRTUAL_STORAGE': [virtual_storage1] }, } """ node_templates = vnfd_dict.get( 'topology_template', {}).get('node_templates') vdu_resources = {} for key, value in node_templates.items(): if value.get('type') != 'tosca.nodes.nfv.Vdu.Compute': continue desired_capacity = _convert_desired_capacity( instantiate_vnf_req.instantiation_level_id, vnfd_dict, key) cp_list = _get_cp_for_vdu(key, node_templates) virtual_storages = [] requirements = value.get('requirements', []) for requirement in requirements: if requirement.get('virtual_storage'): virtual_storages.append( requirement.get('virtual_storage')) vdu_resources[key] = {"CP": cp_list, "VIRTUAL_STORAGE": virtual_storages, "COUNT": desired_capacity} return vdu_resources def _get_virtual_link_nodes(node_templates): virtual_link_nodes = {} for key, value in node_templates.items(): if value.get('type') == 'tosca.nodes.nfv.VnfVirtualLink': cp_list = _get_cp_for_vl(key, node_templates) virtual_link_nodes[key] = cp_list return virtual_link_nodes def _get_cp_for_vdu(vdu, node_templates): cp_list = [] for key, value in node_templates.items(): if value.get('type') != 'tosca.nodes.nfv.VduCp': continue requirements = value.get('requirements', []) for requirement in requirements: if requirement.get('virtual_binding') and vdu == \ requirement.get('virtual_binding'): cp_list.append(key) return cp_list def _get_cp_for_vl(vl, node_templates): cp_list = [] for key, value in node_templates.items(): if value.get('type') != 'tosca.nodes.nfv.VduCp': continue requirements = value.get('requirements', []) for requirement in requirements: if requirement.get('virtual_link') and vl == \ requirement.get('virtual_link'): cp_list.append(key) return cp_list def _build_vnf_virtual_link_resource_info(node_templates, instantiate_vnf_req, vnfc_resource_info, vim_id): virtual_link_nodes_with_cp = _get_virtual_link_nodes(node_templates) # Read the external networks and extcps from InstantiateVnfRequest for ext_virt_link in instantiate_vnf_req.ext_virtual_links: virtual_link_nodes_with_cp[ext_virt_link.id] = [extcp.cpd_id for extcp in ext_virt_link.ext_cps] virtual_link_resource_info_list = [] def _get_network_resource(vl_node): resource_handle = objects.ResourceHandle() found = False for ext_mg_vl in instantiate_vnf_req.ext_managed_virtual_links: if ext_mg_vl.vnf_virtual_link_desc_id == vl_node: resource_handle.resource_id = ext_mg_vl.resource_id resource_handle.vim_connection_id = \ ext_mg_vl.vim_connection_id # TODO(tpatil): This cannot be set here. resource_handle.vim_level_resource_type = \ 'OS::Neutron::Net' found = True break if not found: # check if it exists in the ext_virtual_links for ext_virt_link in instantiate_vnf_req.ext_virtual_links: if ext_virt_link.id == vl_node: resource_handle.resource_id = ext_virt_link.resource_id resource_handle.vim_connection_id = \ ext_virt_link.vim_connection_id # TODO(tpatil): This cannot be set here. resource_handle.vim_level_resource_type = \ 'OS::Neutron::Net' found = True break return resource_handle def _get_vnf_link_port_info(cp): vnf_link_port_info = objects.VnfLinkPortInfo() vnf_link_port_info.id = uuidutils.generate_uuid() resource_handle = objects.ResourceHandle() for ext_virt_link in instantiate_vnf_req.ext_virtual_links: for extcp in ext_virt_link.ext_cps: if extcp.cpd_id == cp: for cpconfig in extcp.cp_config: if cpconfig.link_port_id: resource_handle.resource_id = \ cpconfig.link_port_id resource_handle.vim_connection_id = \ ext_virt_link.vim_connection_id # TODO(tpatil): This shouldn't be set here. resource_handle.vim_level_resource_type = \ 'OS::Neutron::Port' break vnf_link_port_info.resource_handle = resource_handle return vnf_link_port_info for node, cp_list in virtual_link_nodes_with_cp.items(): vnf_vl_resource_info = objects.VnfVirtualLinkResourceInfo() vnf_vl_resource_info.id = uuidutils.generate_uuid() vnf_vl_resource_info.vnf_virtual_link_desc_id = node vnf_vl_resource_info.network_resource = _get_network_resource(node) vnf_link_port_info_list = [] for cp in cp_list: for vnfc_resource in vnfc_resource_info: for vnfc_cp in vnfc_resource.vnfc_cp_info: if vnfc_cp.cpd_id == cp: vnf_link_port_info = _get_vnf_link_port_info(cp) vnf_link_port_info.cp_instance_id = vnfc_cp.id # Identifier of the "vnfLinkPorts" structure in the # "vnfVirtualLinkResourceInfo" structure. vnfc_cp.vnf_link_port_id = vnf_link_port_info.id vnf_link_port_info_list.append(vnf_link_port_info) vnf_vl_resource_info.vnf_link_ports = vnf_link_port_info_list virtual_link_resource_info_list.append(vnf_vl_resource_info) return virtual_link_resource_info_list def _update_vnf_virtual_link_resource_info(change_ext_conn_req, inst_vnf_info): def _update(change_ext_conn_req, vnf_vl_resource_info): for ext_virtual_link in change_ext_conn_req.ext_virtual_links: if (ext_virtual_link.id == vnf_vl_resource_info.vnf_virtual_link_desc_id): res_handle = objects.ResourceHandle() res_handle.resource_id = ext_virtual_link.resource_id nw_res = vnf_vl_resource_info.network_resource res_handle.vim_connection_id = nw_res.vim_connection_id res_handle.vim_level_resource_type = \ nw_res.vim_level_resource_type new_vnf_vl_resource_info = \ objects.VnfVirtualLinkResourceInfo( id=vnf_vl_resource_info.id, vnf_virtual_link_desc_id=vnf_vl_resource_info. vnf_virtual_link_desc_id, network_resource=res_handle, vnf_link_ports=vnf_vl_resource_info.vnf_link_ports) return new_vnf_vl_resource_info return None vnf_virtual_link_resource_list = [] for vnf_vl_res_info in inst_vnf_info.vnf_virtual_link_resource_info: updated_vnf_vl_res_info = \ _update(change_ext_conn_req, vnf_vl_res_info) if updated_vnf_vl_res_info: vnf_virtual_link_resource_list.append(updated_vnf_vl_res_info) else: vnf_virtual_link_resource_list.append(vnf_vl_res_info) return vnf_virtual_link_resource_list def _build_vnf_cp_info(instantiate_vnf_req, cp_list): vnfc_cp_info_list = [] if not cp_list: return vnfc_cp_info_list def _set_vnf_exp_cp_id_protocol_data(vnfc_cp_info): for ext_virt_link in instantiate_vnf_req.ext_virtual_links: for extcp in ext_virt_link.ext_cps: if extcp.cpd_id == cp: vnfc_cp_info.cp_protocol_info = \ _set_cp_protocol_info(extcp) for cpconfig in extcp.cp_config: vnfc_cp_info.vnf_ext_cp_id = cpconfig.link_port_id break for cp in cp_list: vnfc_cp_info = objects.VnfcCpInfo() vnfc_cp_info.id = uuidutils.generate_uuid() vnfc_cp_info.cpd_id = cp _set_vnf_exp_cp_id_protocol_data(vnfc_cp_info) vnfc_cp_info_list.append(vnfc_cp_info) return vnfc_cp_info_list def _build_virtual_storage_info(virtual_storages): for storage_node in virtual_storages: virtual_storage = objects.VirtualStorageResourceInfo() virtual_storage.id = uuidutils.generate_uuid() virtual_storage.virtual_storage_desc_id = storage_node virtual_storage.storage_resource = objects.ResourceHandle() yield virtual_storage def _get_vnfc_resource_info(vnfd_dict, instantiate_vnf_req, vim_id): vdu_resources = _get_compute_nodes(vnfd_dict, instantiate_vnf_req) vnfc_resource_info_list = [] virtual_storage_resource_info_list = [] def _build_vnfc_resource_info(vdu, vdu_resource): vnfc_resource_info = objects.VnfcResourceInfo() vnfc_resource_info.id = uuidutils.generate_uuid() vnfc_resource_info.vdu_id = vdu vnfc_resource_info.compute_resource = objects.ResourceHandle() vnfc_cp_info_list = _build_vnf_cp_info(instantiate_vnf_req, vdu_resource.get("CP")) vnfc_resource_info.vnfc_cp_info = vnfc_cp_info_list virtual_storages = vdu_resource.get("VIRTUAL_STORAGE") vdu_storages = [] for storage in _build_virtual_storage_info(virtual_storages): vdu_storages.append(storage) virtual_storage_resource_info_list.append(storage) storage_resource_ids = [info.id for info in vdu_storages] vnfc_resource_info.storage_resource_ids = storage_resource_ids return vnfc_resource_info for vdu, vdu_resource in vdu_resources.items(): count = vdu_resource.get('COUNT', 1) for num_instance in range(count): vnfc_resource_info = _build_vnfc_resource_info(vdu, vdu_resource) vnfc_resource_info_list.append(vnfc_resource_info) return vnfc_resource_info_list, virtual_storage_resource_info_list def _set_ext_cp_info(instantiate_vnf_req, inst_vnf_info=None): ext_cp_info_list = [] vnfc_info = [] if inst_vnf_info.vnfc_resource_info: vnfc_info = inst_vnf_info.vnfc_resource_info if not instantiate_vnf_req.ext_virtual_links: return ext_cp_info_list for ext_virt_link in instantiate_vnf_req.ext_virtual_links: if not ext_virt_link.ext_cps: continue for ext_cp in ext_virt_link.ext_cps: ext_cp_info = objects.VnfExtCpInfo( id=uuidutils.generate_uuid(), cpd_id=ext_cp.cpd_id, cp_protocol_info=_set_cp_protocol_info(ext_cp), ext_link_port_id=_get_ext_link_port_id(ext_virt_link, ext_cp.cpd_id), associated_vnfc_cp_id=_get_associated_vnfc_cp_id(vnfc_info, ext_cp.cpd_id)) ext_cp_info_list.append(ext_cp_info) return ext_cp_info_list def _update_ext_cp_info(change_ext_conn_req, inst_vnf_info): def _update(change_ext_conn_req, ext_cp_info): for ext_virt_link in change_ext_conn_req.ext_virtual_links: if not ext_virt_link.ext_cps: continue for ext_cp in ext_virt_link.ext_cps: if ext_cp.cpd_id == ext_cp_info.cpd_id: new_ext_cp_info = objects.VnfExtCpInfo( id=ext_cp_info.id, cpd_id=ext_cp.cpd_id, cp_protocol_info=_set_cp_protocol_info(ext_cp), associated_vnfc_cp_id=ext_cp_info. associated_vnfc_cp_id) return new_ext_cp_info return None ext_cp_info_list = [] for ext_cp_info in inst_vnf_info.ext_cp_info: updated_ext_cp_info = _update(change_ext_conn_req, ext_cp_info) if updated_ext_cp_info: ext_cp_info_list.append(updated_ext_cp_info) else: ext_cp_info_list.append(ext_cp_info) return ext_cp_info_list def _get_ext_link_port_id(ext_virtual_link, cpd_id): if not ext_virtual_link.ext_link_ports: return for ext_link in ext_virtual_link.ext_link_ports: if ext_link.id == cpd_id: return ext_link.id def _get_associated_vnfc_cp_id(vnfc_info, cpd_id): if not isinstance(vnfc_info, list): return for vnfc in vnfc_info: if vnfc.vnfc_cp_info: for cp_info in vnfc.vnfc_cp_info: if cp_info.cpd_id == cpd_id: return vnfc.id def _build_ip_over_ethernet_address_info(cp_protocol_data): """Convert IpOverEthernetAddressData to IpOverEthernetAddressInfo""" if not cp_protocol_data.ip_over_ethernet: return ip_over_ethernet_add_info = objects.IpOverEthernetAddressInfo() ip_over_ethernet_add_info.mac_address = \ cp_protocol_data.ip_over_ethernet.mac_address if not cp_protocol_data.ip_over_ethernet.ip_addresses: return ip_over_ethernet_add_info ip_address_list = [] for ip_address in cp_protocol_data.ip_over_ethernet.ip_addresses: ip_address_info = objects.vnf_instantiated_info.IpAddress( type=ip_address.type, addresses=ip_address.fixed_addresses, is_dynamic=True if ip_address.num_dynamic_addresses else False, subnet_id=ip_address.subnet_id) ip_address_list.append(ip_address_info) ip_over_ethernet_add_info.ip_addresses = ip_address_list return ip_over_ethernet_add_info def _build_cp_protocol_info(cp_protocol_data): ip_over_ethernet_add_info = _build_ip_over_ethernet_address_info( cp_protocol_data) cp_protocol_info = objects.CpProtocolInfo( layer_protocol=cp_protocol_data.layer_protocol, ip_over_ethernet=ip_over_ethernet_add_info) return cp_protocol_info def _set_cp_protocol_info(ext_cp): """Convert CpProtocolData to CpProtocolInfo""" cp_protocol_info_list = [] if not ext_cp.cp_config: return cp_protocol_info_list for cp_config in ext_cp.cp_config: for cp_protocol_data in cp_config.cp_protocol_data: cp_protocol_info = _build_cp_protocol_info(cp_protocol_data) cp_protocol_info_list.append(cp_protocol_info) return cp_protocol_info_list def _set_ext_virtual_link_info(instantiate_vnf_req, ext_cp_info): ext_virtual_link_list = [] if not instantiate_vnf_req.ext_virtual_links: return ext_virtual_link_list for ext_virtual_link in instantiate_vnf_req.ext_virtual_links: res_handle = objects.ResourceHandle() res_handle.resource_id = ext_virtual_link.resource_id res_handle.vim_connection_id = ext_virtual_link.vim_connection_id ext_virtual_link_info = objects.ExtVirtualLinkInfo( id=ext_virtual_link.id, resource_handle=res_handle, ext_link_ports=_set_ext_link_port(ext_virtual_link, ext_cp_info)) ext_virtual_link_list.append(ext_virtual_link_info) return ext_virtual_link_list def _update_ext_virtual_link_info(change_ext_conn_req, inst_vnf_info): def _update(change_ext_conn_req, ext_virtual_link_info): for ext_virtual_link in change_ext_conn_req.ext_virtual_links: if ext_virtual_link.id == ext_virtual_link_info.id: res_handle = objects.ResourceHandle() res_handle.resource_id = ext_virtual_link.resource_id new_ext_virtual_link_info = objects.ExtVirtualLinkInfo( id=ext_virtual_link_info.id, resource_handle=res_handle, ext_link_ports=ext_virtual_link_info.ext_link_ports) res_handle.vim_connection_id = \ ext_virtual_link_info.resource_handle.vim_connection_id new_ext_virtual_link_info = objects.ExtVirtualLinkInfo( id=ext_virtual_link_info.id, resource_handle=res_handle, ext_link_ports=ext_virtual_link_info.ext_link_ports) return new_ext_virtual_link_info return None ext_virtual_link_list = [] for ext_virtual_link_info in inst_vnf_info.ext_virtual_link_info: updated_ext_virtual_link_info = \ _update(change_ext_conn_req, ext_virtual_link_info) if updated_ext_virtual_link_info: ext_virtual_link_list.append(updated_ext_virtual_link_info) else: ext_virtual_link_list.append(ext_virtual_link_info) return ext_virtual_link_list def _set_ext_link_port(ext_virtual_links, ext_cp_info): ext_link_port_list = [] if not ext_virtual_links.ext_link_ports: return ext_link_port_list for ext_link_port in ext_virtual_links.ext_link_ports: resource_handle = ext_link_port.resource_handle.obj_clone() cp_instance_id = None if ext_virtual_links.ext_cps: for ext_cp in ext_cp_info: cp_instance_id = ext_cp.id ext_link_port_info = objects.ExtLinkPortInfo(id=ext_link_port.id, resource_handle=resource_handle, cp_instance_id=cp_instance_id) ext_link_port_list.append(ext_link_port_info) return ext_link_port_list def _build_ext_managed_virtual_link_info(instantiate_vnf_req, inst_vnf_info): def _network_resource(ext_managed_vl): resource_handle = objects.ResourceHandle( resource_id=ext_managed_vl.resource_id) # TODO(tpatil): Remove hard coding of resource type as # OS::Neutron::Net resource type is specific to OpenStack infra # driver. It could be different for other infra drivers like # Kubernetes. resource_handle.vim_level_resource_type = 'OS::Neutron::Net' resource_handle.vim_connection_id = \ ext_managed_vl.vim_connection_id return resource_handle ext_managed_virtual_link_info = [] ext_managed_virt_link_from_req = \ instantiate_vnf_req.ext_managed_virtual_links for ext_managed_vl in ext_managed_virt_link_from_req: ext_managed_virt_info = objects.ExtManagedVirtualLinkInfo() ext_managed_virt_info.id = ext_managed_vl.id ext_managed_virt_info.vnf_virtual_link_desc_id =\ ext_managed_vl.vnf_virtual_link_desc_id ext_managed_virt_info.network_resource =\ _network_resource(ext_managed_vl) # Populate the vnf_link_ports from vnf_virtual_link_resource_info # of instantiated_vnf_info. for vnf_vl_res_info in inst_vnf_info.vnf_virtual_link_resource_info: if ext_managed_vl.vnf_virtual_link_desc_id ==\ vnf_vl_res_info.vnf_virtual_link_desc_id: vnf_link_ports = [] for vnf_lp in vnf_vl_res_info.vnf_link_ports: vnf_link_ports.append(vnf_lp.obj_clone()) ext_managed_virt_info.vnf_link_ports = vnf_link_ports ext_managed_virtual_link_info.append(ext_managed_virt_info) return ext_managed_virtual_link_info def _convert_desired_capacity(inst_level_id, vnfd_dict, vdu): aspect_delta_dict = {} aspect_vdu_dict = {} inst_level_dict = {} aspect_id_dict = {} vdu_delta_dict = {} aspect_max_level_dict = {} desired_capacity = 1 tosca = tosca_template.ToscaTemplate(parsed_params={}, a_file=False, yaml_dict_tpl=vnfd_dict) tosca_policies = tosca.topology_template.policies default_inst_level_id = toscautils._extract_policy_info( tosca_policies, inst_level_dict, aspect_delta_dict, aspect_id_dict, aspect_vdu_dict, vdu_delta_dict, aspect_max_level_dict) if vdu_delta_dict.get(vdu) is None: return desired_capacity if inst_level_id: instantiation_level = inst_level_id elif default_inst_level_id: instantiation_level = default_inst_level_id else: return desired_capacity al_dict = inst_level_dict.get(instantiation_level) if not al_dict: return desired_capacity for aspect_id, level_num in al_dict.items(): delta_id = aspect_id_dict.get(aspect_id) if delta_id is not None: delta_num = \ aspect_delta_dict.get(aspect_id).get(delta_id) vdus = aspect_vdu_dict.get(aspect_id) initial_delta = None if vdu in vdus: initial_delta = vdu_delta_dict.get(vdu) if initial_delta is not None: desired_capacity = initial_delta + delta_num * level_num return desired_capacity def _get_vnf_package_path(context, vnfd_id): return os.path.join(CONF.vnf_package.vnf_package_csar_path, _get_vnf_package_id(context, vnfd_id)) def get_base_nest_hot_dict(context, flavour_id, vnfd_id): base_hot_path = os.path.join(_get_vnf_package_path(context, vnfd_id), 'BaseHOT', flavour_id) nested_hot_path = os.path.join(base_hot_path, 'nested') ext = (".yaml", ".yml") base_hot_dict = None nested_hot_dict = {} if os.path.exists(base_hot_path): for file in os.listdir(base_hot_path): if file.endswith(ext): with open(os.path.join(base_hot_path, file)) as file_obj: base_hot_dict = yaml.safe_load(file_obj) if os.path.exists(nested_hot_path): for file in os.listdir(nested_hot_path): if file.endswith(ext): with open(os.path.join(nested_hot_path, file)) as file_obj: nested_hot = yaml.safe_load(file_obj) nested_hot_dict[file] = nested_hot LOG.debug("Loaded base hot: %s", base_hot_dict) LOG.debug("Loaded nested_hot_dict: %s", nested_hot_dict) return base_hot_dict, nested_hot_dict def get_extract_policy_infos(tosca): aspect_delta_dict = {} aspect_vdu_dict = {} inst_level_dict = {} aspect_id_dict = {} vdu_delta_dict = {} aspect_max_level_dict = {} tosca_policies = tosca.topology_template.policies default_inst_level_id = toscautils._extract_policy_info( tosca_policies, inst_level_dict, aspect_delta_dict, aspect_id_dict, aspect_vdu_dict, vdu_delta_dict, aspect_max_level_dict) extract_policy_infos = dict() extract_policy_infos['inst_level_dict'] = inst_level_dict extract_policy_infos['aspect_delta_dict'] = aspect_delta_dict extract_policy_infos['aspect_id_dict'] = aspect_id_dict extract_policy_infos['aspect_vdu_dict'] = aspect_vdu_dict extract_policy_infos['vdu_delta_dict'] = vdu_delta_dict extract_policy_infos['aspect_max_level_dict'] = aspect_max_level_dict extract_policy_infos['default_inst_level_id'] = default_inst_level_id return extract_policy_infos def get_scale_delta_num(extract_policy_infos, aspect_id): delta_num = 1 if extract_policy_infos['aspect_id_dict'] is None: return delta_num delta_id = extract_policy_infos['aspect_id_dict'].get(aspect_id) if delta_id is None: return delta_num delta_num = \ extract_policy_infos['aspect_delta_dict'].get(aspect_id).get(delta_id) return delta_num def get_default_scale_status(context, vnf_instance, vnfd_dict): default_scale_status = None vnfd_dict = _get_vnfd_dict(context, vnf_instance.vnfd_id, vnf_instance.instantiated_vnf_info.flavour_id) tosca = tosca_template.ToscaTemplate(parsed_params={}, a_file=False, yaml_dict_tpl=vnfd_dict) extract_policy_infos = get_extract_policy_infos(tosca) if extract_policy_infos['inst_level_dict'] is None: return default_scale_status default_inst_level_id = extract_policy_infos['default_inst_level_id'] default_al_dict = \ extract_policy_infos['inst_level_dict'].get(default_inst_level_id) if default_al_dict is None: return default_scale_status default_scale_status = [] for aspect_id, level_num in default_al_dict.items(): default_scale_status.append( objects.ScaleInfo( aspect_id=aspect_id, scale_level=level_num)) return default_scale_status def get_target_vdu_def_dict(extract_policy_infos, aspect_id, tosca): vdu_def_dict = {} tosca_node_tpls = tosca.topology_template.nodetemplates if extract_policy_infos['aspect_vdu_dict'] is None: return vdu_def_dict vdus = extract_policy_infos['aspect_vdu_dict'].get(aspect_id) if vdus is None: return vdu_def_dict for nt in tosca_node_tpls: for node_name, node_value in nt.templates.items(): if node_name in vdus: vdu_def_dict[node_name] = node_value return vdu_def_dict def _get_changed_ext_connectivity( old_vnf_instance=None, new_vnf_instance=None): changed_ext_connectivities = [] if not old_vnf_instance or not new_vnf_instance: return changed_ext_connectivities old_vnf_vl_res_info = \ old_vnf_instance.instantiated_vnf_info.\ vnf_virtual_link_resource_info new_vnf_vl_res_info = \ new_vnf_instance.instantiated_vnf_info.\ vnf_virtual_link_resource_info def _compare_vnf_link_ports(old_vnf_link_ports, new_vnf_link_ports): differed_vnf_link_ports = [] for old_vnf_link_port in old_vnf_link_ports: for new_vnf_link_port in new_vnf_link_ports: if old_vnf_link_port.id == new_vnf_link_port.id: if (old_vnf_link_port.resource_handle.resource_id != new_vnf_link_port.resource_handle.resource_id): differed_vnf_link_ports.append(new_vnf_link_port) return differed_vnf_link_ports for old_vl_res in old_vnf_vl_res_info: for new_vl_res in new_vnf_vl_res_info: if old_vl_res.id == new_vl_res.id: changed_ext_connectivity = objects.ExtVirtualLinkInfo( id=new_vl_res.id, resource_handle=new_vl_res.network_resource, ext_link_ports=[]) differed_vnf_link_ports = _compare_vnf_link_ports( old_vl_res.vnf_link_ports, new_vl_res.vnf_link_ports) for link_port in differed_vnf_link_ports: changed_ext_link_port = objects.ExtLinkPortInfo( id=link_port.id, resource_handle=link_port.resource_handle, cp_instance_id=link_port.cp_instance_id) changed_ext_connectivity.ext_link_ports.\ append(changed_ext_link_port) if changed_ext_connectivity.ext_link_ports: changed_ext_connectivities.append( changed_ext_connectivity) LOG.debug('changed_ext_connectivities: {}'.format( changed_ext_connectivities)) return changed_ext_connectivities