tacker/tacker/vnflcm/utils.py

1388 lines
53 KiB
Python

# 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.lcm_user_data import utils as userdata_utils
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
extra = vim_connection_info[0].extra
else:
vim_id = None
region_name = None
extra = {}
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})
if extra:
for key, value in extra.items():
vim_res['extra'][key] = value
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'],
'extra': vim_res.get('extra', {})}
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_vnfd_dict(context, vnfd_id, flavour_id):
return _get_vnfd_dict(context, vnfd_id, flavour_id)
def _get_vnflcm_interface(context, interface, vnf_instance, flavour_id):
'''Gets the interface found in vnfd
...
node_templates:
VNF:
interfaces:
Vnflcm:
<interface>
'''
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).get(vdu)
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
def get_stack_param(context, vnf_dict, heal_vnf_request, inst_vnf_info):
stack_param = {}
vnfc_resources = []
# get vnfc resources
if not heal_vnf_request.vnfc_instance_id:
# include all vnfc resources
vnfc_resources = [
resource for resource in inst_vnf_info.vnfc_resource_info]
else:
for vnfc_resource in inst_vnf_info.vnfc_resource_info:
if vnfc_resource.id in heal_vnf_request.vnfc_instance_id:
vnfc_resources.append(vnfc_resource)
def _update_stack_params(
context, base_hot_dict, nested_hot_dict, vnfd_dict):
param_base_hot_dict = copy.deepcopy(nested_hot_dict)
param_base_hot_dict['heat_template'] = base_hot_dict
initial_param_dict = (
userdata_utils.create_initial_param_server_port_dict(
param_base_hot_dict)
)
del initial_param_dict['nfv']['CP']
vdu_flavor_dict = (
userdata_utils.create_vdu_flavor_capability_name_dict(vnfd_dict)
)
vdu_image_dict = userdata_utils.create_sw_image_dict(vnfd_dict)
final_param_dict = userdata_utils.create_final_param_dict(
initial_param_dict, vdu_flavor_dict, vdu_image_dict, {})
return final_param_dict['nfv']['VDU']
# get HOT dict
base_hot_dict, nested_hot_dict = get_base_nest_hot_dict(
context, inst_vnf_info.flavour_id, vnf_dict['vnfd_id'])
vnfd_dict = yaml.safe_load(
vnf_dict['vnfd']['attributes']['vnfd_' + inst_vnf_info.flavour_id])
if 'stack_param' in vnf_dict['attributes'].keys():
stack_param = yaml.safe_load(
vnf_dict['attributes']['stack_param'])
updated_vdu_params = _update_stack_params(
context, base_hot_dict, nested_hot_dict, vnfd_dict)
for vnfc_resource in vnfc_resources:
vdu_id = vnfc_resource.vdu_id
if (updated_vdu_params.get(vdu_id) and
stack_param['nfv']['VDU'].get(vdu_id)):
stack_param['nfv']['VDU'].update({
vdu_id: updated_vdu_params.get(vdu_id)
})
return stack_param