tacker/tacker/db/migration/migrate_to_v2.py

1058 lines
43 KiB
Python

# Copyright 2022 KDDI
# 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 ast
import os
from oslo_config import cfg
from oslo_log import log as logging
from oslo_serialization import jsonutils
from oslo_utils import timeutils
from oslo_utils import uuidutils
from tacker._i18n import _
from tacker.common import exceptions
from tacker import context
from tacker.db import api as db_api
from tacker.db.db_sqlalchemy import api
from tacker.db.db_sqlalchemy import models
from tacker.db.nfvo import nfvo_db
from tacker.db.nfvo import nfvo_db_plugin
from tacker.db.vnfm import vnfm_db
from tacker import objects
from tacker.sol_refactored.common import vim_utils
from tacker.sol_refactored.infra_drivers.openstack import heat_utils
from tacker.sol_refactored import objects as objects_v2
from tacker.sol_refactored.objects.v2 import fields as v2fields
from tacker.vnfm import vim_client
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
def env(*_vars, **kwargs):
# Search for the first defined of possibly many env vars.
# Returns the first environment variable defined in vars, or
# returns the default defined in kwargs.
for v in _vars:
value = os.environ.get(v, None)
if value:
return value
return kwargs.get('default', '')
OPTS = [cfg.StrOpt('user_domain_id',
default=env("OS_USER_DOMAIN_ID", default='default'),
help='User Domain Id'),
cfg.StrOpt('project_domain_id',
default=env("OS_DOMAIN_ID", default='default'),
help='Project Domain Id'),
cfg.StrOpt('password',
default=env("OS_PASSWORD", default="default"),
help='User Password'),
cfg.StrOpt('username',
default=env("OS_USERNAME", default="default"),
help='User Name'),
cfg.StrOpt('user_domain_name',
default=env("OS_USER_DOMAIN_NAME", default='Default'),
help='Use Domain Name'),
cfg.StrOpt('project_name',
default=env("OS_PROJECT_NAME", default='default'),
help='Project Name'),
cfg.StrOpt('project_domain_name',
default=env("OS_PROJECT_DOMAIN_NAME", default='Default'),
help='Project Domain Name'),
cfg.StrOpt('auth_url',
default=env("OS_AUTH_URL",
default='http://localhost/identity/v3'),
help='Keystone endpoint')]
CONF.register_opts(OPTS, 'keystone_authtoken')
def option_error_check(all_flag, api_ver, keep_orig, mark_delete, vnf_id):
if all_flag:
if api_ver or mark_delete or vnf_id:
msg = _("--all cannot be used with --api-ver, "
"--mark-delete or --vnf-id")
raise exceptions.InvalidInput(error_message=msg)
else:
if not vnf_id:
msg = _("either --all or --vnf-id must be used")
raise exceptions.InvalidInput(error_message=msg)
if api_ver:
if not mark_delete:
msg = _("--api-ver must be used with --mark-delete")
raise exceptions.InvalidInput(error_message=msg)
if api_ver not in {"v1", "v2"}:
msg = _("v1 or v2 must be specified for --api-ver")
raise exceptions.InvalidInput(error_message=msg)
if mark_delete:
if not api_ver:
msg = _("--mark-delete must be used with --api-ver")
raise exceptions.InvalidInput(error_message=msg)
if keep_orig:
msg = _("--mark-delete cannot be used with --keep-orig")
raise exceptions.InvalidInput(error_message=msg)
def migrate_to_v2_tables(tacker_config, all_flag, api_ver,
keep_orig, mark_delete, vnf_id):
option_error_check(all_flag, api_ver, keep_orig, mark_delete, vnf_id)
admin_context = context.get_admin_context()
objects.register_all()
objects_v2.register_all()
CONF.database = tacker_config.database
if mark_delete:
if api_ver == "v1":
mark_delete_v1(admin_context, vnf_id)
elif api_ver == "v2":
mark_delete_v2(admin_context, vnf_id)
return
vnf_ids = [vnf_id]
if all_flag:
vnf_ids = get_all_vnfs(admin_context)
for vnf_instance_id in vnf_ids:
create_vnf_instance_v2(admin_context, vnf_instance_id)
create_vnf_lcm_op_occs_v2(admin_context, vnf_instance_id)
if not keep_orig:
mark_delete_v1(admin_context, vnf_instance_id)
@db_api.context_manager.writer
def mark_delete_v1(context, vnf_id):
objects.vnf_instance._destroy_vnf_instance(context, vnf_id)
vnf_inst = \
objects.vnf_instance._vnf_instance_get_by_id(
context, vnf_id, columns_to_join=["instantiated_vnf_info"],
read_deleted="yes")
now = timeutils.utcnow()
updated_values = {
'deleted_at': now,
'status': 'PENDING_DELETE'}
api.model_query(context, vnfm_db.VNFAttribute)\
.filter_by(vnf_id=vnf_id).delete()
vnf_attrs = api.model_query(context, vnfm_db.VNFAttribute)\
.filter_by(vnf_id=vnf_id).all()
api.model_query(context, vnfm_db.VNF)\
.filter_by(id=vnf_id).update(updated_values)
vnf = api.model_query(context, vnfm_db.VNF)\
.filter_by(id=vnf_id).first()
now = timeutils.utcnow()
updated_values = {
'deleted': True,
'deleted_at': now}
_vnf_lcm_op_occs = api.model_query(context, models.VnfLcmOpOccs)\
.filter_by(vnf_instance_id=vnf_id)
for occ in _vnf_lcm_op_occs:
api.model_query(context, models.VnfLcmOpOccs)\
.filter_by(id=occ.id).first().update(updated_values)
vnf_lcm_op_occs = api.model_query(context, models.VnfLcmOpOccs)\
.filter_by(vnf_instance_id=vnf_id)
return vnf_inst, vnf_attrs, vnf, vnf_lcm_op_occs
@db_api.context_manager.writer
def mark_delete_v2(context, vnf_id):
# Target object tables are VnfInstanceV2, VnfLcmOpOccV2
vnf_inst_v2 = objects_v2.VnfInstanceV2.get_by_id(context, vnf_id)
vnf_inst_v2.delete(context)
op_occs_v2 = objects_v2.VnfLcmOpOccV2.get_by_filter(context,
vnfInstanceId=vnf_id)
for op_occ in op_occs_v2:
op_occ.delete(context)
def get_all_vnfs(context):
vnfs = objects.vnf_instance._vnf_instance_list(context,
columns_to_join=None)
vnf_ids = []
for vnf in vnfs:
vnf_ids.append(vnf.id)
return vnf_ids
def _to_vnf_instance_v2_instantiated_vnf_info(inst_info, vnf, op_occs):
if not inst_info:
return None
fields = {
"flavourId": inst_info.flavour_id,
"vnfState": inst_info.vnf_state,
"scaleStatus": _to_scale_status_v2(inst_info.scale_status),
"maxScaleLevels": _to_max_scale_levels(vnf.attributes),
"extCpInfo": _to_ext_cp_info_v2(inst_info.ext_cp_info),
"extVirtualLinkInfo":
_to_ext_virtual_link_info_v2(
inst_info.ext_virtual_link_info,
inst_info.vnf_virtual_link_resource_info, op_occs),
"extManagedVirtualLinkInfo":
_to_ext_managed_virtual_link_info_v2(
inst_info.ext_managed_virtual_link_info),
"monitoringParameters": _to_monitoring_parameters(vnf.attributes),
"localizationLanguage": _to_localization_language(vnf.attributes),
"vnfcResourceInfo":
_to_vnfc_resource_info_v2(
inst_info.vnfc_resource_info,
inst_info.ext_virtual_link_info,
inst_info.vnf_virtual_link_resource_info),
"vnfVirtualLinkResourceInfo":
_to_vnf_virtual_link_resource_info_v2(
inst_info.vnf_virtual_link_resource_info,
inst_info.ext_virtual_link_info,
inst_info.ext_managed_virtual_link_info),
"virtualStorageResourceInfo":
_to_virtual_storage_resource_info_v2(
inst_info.virtual_storage_resource_info),
"vnfcInfo": _to_vnfc_info_v2(inst_info.vnfc_resource_info)}
return objects_v2.VnfInstanceV2_InstantiatedVnfInfo(**fields)
def _to_vim_connection_info(vim_con_infos, vim_infos):
# NOTE: The key of VimConnectionInfo doesn't exist in v1.
# Therefore any value can be set to the key.
# The values like vim_0, vim_1.. are set here.
dict_info = {}
for i, info in enumerate(vim_con_infos):
_info = info.get("tacker_object.data")
try:
vim_auth = vim_client.VimClient()._build_vim_auth(vim_infos[i])
vim_info = {
'vim_auth': vim_auth,
'vim_id': vim_infos[i]['id'],
'vim_name': vim_infos[i].get('name', vim_infos[i]['id']),
'vim_type': vim_infos[i]['type'],
'tenant': vim_infos[i]['tenant_id'],
'placement_attr': vim_infos[i].get('placement_attr', {}),
'extra': vim_infos[i].get('extra', {})}
vim_info_obj = vim_utils.vim_to_conn_info(vim_info)
except Exception as ex:
LOG.debug('Fail to get vim info %s', ex)
fields = {
"vimId": _info.get("vim_id"),
"vimType": _info.get("vim_type"),
"interfaceInfo": _info.get("interface_info"),
"accessInfo": _info.get("access_info"),
"extra": _info.get("extra")}
vim_info_obj = objects_v2.VimConnectionInfo(**fields)
dict_info["vim{}".format(i)] = vim_info_obj
return dict_info
def _to_scale_status_v2(scale_status_list):
scale_status_v2_list = []
for scale_status in scale_status_list:
_scale_status = scale_status["tacker_object.data"]
fields = {
"aspectId": _scale_status.get("aspect_id"),
"scaleLevel": _scale_status.get("scale_level")}
scale_status_v2_list.append(objects_v2.ScaleInfoV2(**fields))
return scale_status_v2_list
def _to_max_scale_levels(vnf_attributes):
# NOTE: maxScaleLevels is not defined in SOL003 v2.6.1.
# Related information can be got from vnf_attributes table.
scale_infos_v2 = []
for attr in vnf_attributes:
if attr.key == 'scale_group':
val = ast.literal_eval(attr.value)
if val.get("scaleGroupDict"):
for aspect_id, scale_info in val.get("scaleGroupDict").items():
fields = {
"aspectId": aspect_id,
"scaleLevel": scale_info.get("maxLevel")}
scale_infos_v2.append(objects_v2.ScaleInfoV2(**fields))
return scale_infos_v2
def _to_ext_cp_info_v2(ext_cp_infos):
ext_cp_infos_v2 = []
for ext_cp_info in ext_cp_infos:
_ext_cp_info = ext_cp_info["tacker_object.data"]
# NOTE: Since cpConfigId is not defined in SOL003 v2.6.1,
# there are no related information in v1 tables.
# Therefore any value can be set to cpConfigId.
# The value of <cpd_id>_0 is set here.
fields = {
"id": _ext_cp_info.get("id"),
"cpdId": _ext_cp_info.get("cpd_id"),
"cpConfigId": _ext_cp_info.get("cpd_id") + "_0",
"cpProtocolInfo":
_to_cp_protocol_info_v2(_ext_cp_info.get("cp_protocol_info")),
"extLinkPortId": _ext_cp_info.get("ext_link_port_id"),
"associatedVnfcCpId": _ext_cp_info.get("associated_vnfc_cp_id")}
ext_cp_infos_v2.append(objects_v2.VnfExtCpInfoV2(**fields))
return ext_cp_infos_v2
def _to_cp_protocol_info_v2(cp_protocol_infos):
cp_protocol_infos_v2 = []
for cp_protocol_info in cp_protocol_infos:
_cp_protocol_info = cp_protocol_info.get("tacker_object.data")
_ip_over_ethernet = _cp_protocol_info.get("ip_over_ethernet")
fields = {"layerProtocol": _cp_protocol_info.get("layer_protocol")}
if _ip_over_ethernet:
fields.update({"ipOverEthernet":
_to_ip_over_ethernet_address_info_v2(
_ip_over_ethernet.get("tacker_object.data"))})
cp_protocol_infos_v2.append(objects_v2.CpProtocolInfoV2(**fields))
return cp_protocol_infos_v2
def _to_ip_over_ethernet_address_info_v2(ip_over_ethernet):
fields = {
"macAddress": ip_over_ethernet.get("mac_address"),
"ipAddresses":
_to_ip_over_ethernet_address_info_v2_ip_addresses(
ip_over_ethernet.get("ip_addresses"))}
return objects_v2.IpOverEthernetAddressInfoV2(**fields)
def _to_ip_over_ethernet_address_info_v2_ip_addresses(ip_addresses):
ip_over_eth_add_info_v2_ip_addresses = []
for ip_address in ip_addresses:
_ip_address = ip_address.get("tacker_object.data")
fields = {
"type": _ip_address.get("type"),
"addresses": _ip_address.get("addresses"),
"isDynamic": _ip_address.get("is_dynamic"),
"subnetId": _ip_address.get("subnet_id")}
ip_over_eth_add_info_v2_ip_addresses.append(
objects_v2.IpOverEthernetAddressInfoV2_IpAddresses(**fields))
return ip_over_eth_add_info_v2_ip_addresses
def _to_ext_virtual_link_info_v2(ext_vls, vnf_vl_rscs, op_occs):
ext_vls_v2 = []
for ext_vl in ext_vls:
_ext_vl = ext_vl.get("tacker_object.data")
resource_handle_data = \
_ext_vl.get("resource_handle").get("tacker_object.data")
fields = {
"id": _ext_vl.get("id"),
"resourceHandle": _to_resource_handle(resource_handle_data),
"extLinkPorts":
_to_ext_link_port_info_v2(_ext_vl.get("id"), vnf_vl_rscs),
"currentVnfExtCpData":
_to_current_vnf_ext_cp_data(_ext_vl.get("id"), op_occs)}
ext_vls_v2.append(objects_v2.ExtVirtualLinkInfoV2(**fields))
return ext_vls_v2
def _to_resource_handle(resource_handle_data):
fields = {
'vimConnectionId': resource_handle_data.get("vim_connection_id"),
'resourceProviderId': resource_handle_data.get("resource_provider_id"),
'resourceId': resource_handle_data.get("resource_id"),
'vimLevelResourceType':
resource_handle_data.get("vim_level_resource_type")}
resource_handle = objects_v2.ResourceHandle(**fields)
return resource_handle
def _to_ext_link_port_info_v2(ext_vl_id, vnf_vl_res_infos):
ext_link_port_infos_v2 = []
for vnf_vl_res_info in vnf_vl_res_infos:
_vnf_vl_res_info = vnf_vl_res_info.get("tacker_object.data")
if _vnf_vl_res_info.get("vnf_virtual_link_desc_id") == ext_vl_id:
vnf_link_ports = _vnf_vl_res_info.get("vnf_link_ports")
for link_port in vnf_link_ports:
_link_port = link_port.get("tacker_object.data")
resource_handle_data = \
_link_port.get("resource_handle").get("tacker_object.data")
fields = {
"id": _link_port.get("id"),
"resourceHandle":
_to_resource_handle(resource_handle_data),
"cpInstanceId": _link_port.get("cp_instance_id")}
ext_link_port_infos_v2.append(
objects_v2.ExtLinkPortInfoV2(**fields))
return ext_link_port_infos_v2
def _to_current_vnf_ext_cp_data(ext_vl_id, vnf_op_occs):
# NOTE: Since CurrentVnfExtCpData is not defined in SOL003 v2.6.1,
# this field can't be passed from v1 api objects.
# The data type of CurrentVnfExtCpData is defined as
# VnfExtCpData in SOL003 v3.3.1,
# and the data is passed from InstantiateVnfRequest
# or ChangeExtVnfConnectivityRequest.
# Therefore this field is created from VnfLcmOpOccs objects
# whose operation is INSTANTIATE or CHANGE_EXT_CONN.
current_vnf_ext_cp_data = []
ext_cps = {}
_vnf_op_occs = \
vnf_op_occs.filter(models.VnfLcmOpOccs.operation_state == "COMPLETED",
models.VnfLcmOpOccs.operation.in_(["INSTANTIATE",
"CHANGE_EXT_CONN"])).order_by(
models.VnfLcmOpOccs.start_time).all()
for op_occ in _vnf_op_occs:
operation_param = ast.literal_eval(op_occ.operation_params)
ext_vls = operation_param.get("extVirtualLinks")
for ext_vl in ext_vls:
if ext_vl.get("id") == ext_vl_id:
for ext_cp in ext_vl.get("extCps"):
cpd_id = ext_cp.get("cpdId")
ext_cps.update({
cpd_id: ext_cp.get("cpConfig")})
for cpd_id, cp_config in ext_cps.items():
fields = {
"cpdId": cpd_id,
"cpConfig": {
"{}_0".format(cpd_id): _to_vnf_ext_cp_config(cp_config[0])}}
current_vnf_ext_cp_data.append(objects_v2.VnfExtCpData(**fields))
return current_vnf_ext_cp_data
def _to_vnf_ext_cp_config(cp_config):
fields = {
"linkPortId": cp_config.get("linkPortId"),
"cpProtocolData":
_to_cp_protocol_data(cp_config.get("cpProtocolData", []))}
return objects_v2.VnfExtCpConfig(**fields)
def _to_cp_protocol_data(cp_protocol_data_list):
_cp_protocol_data_list = []
for cp_protocol_data in cp_protocol_data_list:
fields = {
"layerProtocol": cp_protocol_data.get("layerProtocol"),
"ipOverEthernet":
_to_ip_over_ethernet_address_data(
cp_protocol_data.get("ipOverEthernet"))}
_cp_protocol_data_list.append(objects_v2.CpProtocolData(**fields))
return _cp_protocol_data_list
def _to_ip_over_ethernet_address_data(ip_over_ethernet):
fields = {
"macAddress": ip_over_ethernet.get("macAddress"),
"ipAddresses":
_to_ip_over_ethernet_address_data_ip_addresses(
ip_over_ethernet.get("ipAddresses", []))}
return objects_v2.IpOverEthernetAddressData(**fields)
def _to_ip_over_ethernet_address_data_ip_addresses(ip_addresses):
ip_over_eth_add_data_ip_addresses = []
for ip_address in ip_addresses:
fields = {
"type": ip_address.get("type"),
"fixedAddresses": ip_address.get("fixedAddresses"),
"numDynamicAddresses": ip_address.get("numDynamicAddresses"),
"addressRange":
_to_ip_over_eth_address_data_ip_addresses_address_range(
ip_address.get("addressRange")),
"subnetId": ip_address.get("subnetId")}
ip_over_eth_add_data_ip_addresses.append(
objects_v2.IpOverEthernetAddressData_IpAddresses(**fields))
return ip_over_eth_add_data_ip_addresses
def _to_ip_over_eth_address_data_ip_addresses_address_range(address_range):
if not address_range:
return None
fields = {
"minAddress": address_range.get("minAddress"),
"maxAddress": address_range.get("maxAddress")}
return objects_v2.\
IpOverEthernetAddressData_IpAddresses_AddressRange(**fields)
def _to_ext_managed_virtual_link_info_v2(ext_mng_vl_infos):
ext_mng_vl_infos_v2 = []
for ext_mng_vl_info in ext_mng_vl_infos:
_ext_mng_vl_info = ext_mng_vl_info.get("tacker_object.data")
resource_handle_data = \
_ext_mng_vl_info.get("network_resource").get("tacker_object.data")
fields = {
"id": _ext_mng_vl_info.get("id"),
"vnfVirtualLinkDescId":
_ext_mng_vl_info.get("vnf_virtual_link_desc_id"),
"networkResource": _to_resource_handle(resource_handle_data),
"vnfLinkPorts": _to_vnf_link_port_info_v2(
_ext_mng_vl_info.get("vnf_link_ports", []))}
ext_mng_vl_infos_v2.append(
objects_v2.ExtManagedVirtualLinkInfoV2(**fields))
return ext_mng_vl_infos_v2
def _to_vnf_link_port_info_v2(vnf_link_ports):
vnf_link_port_infos_v2 = []
for vnf_link_port in vnf_link_ports:
_vnf_link_port = vnf_link_port.get("tacker_object.data")
resource_handle_data = \
_vnf_link_port.get("resource_handle").get("tacker_object.data")
# NOTE: cpInstanceType is not defined in the v1 vnfLinkPortInfo.
# The value is temporarily set as "EXT_CP" here
# and updated later if needed,
# because vnfcResourceInfoV2 object is needed to determine
# the value of cpInstanceId but the object doesn't exist at the moment.
fields = {
"id": _vnf_link_port.get("id"),
"resourceHandle": _to_resource_handle(resource_handle_data),
"cpInstanceId": _vnf_link_port.get("cp_instance_id"),
"cpInstanceType": "EXT_CP"}
vnf_link_port_infos_v2.append(objects_v2.VnfLinkPortInfoV2(**fields))
return vnf_link_port_infos_v2
def _to_vnfc_resource_info_v2(vnfc_rsc_infos, ext_vl_infos, vnf_vl_res_infos):
vnfc_rsc_infos_v2 = []
for vnfc_rsc_info in vnfc_rsc_infos:
_vnfc_rsc_info = vnfc_rsc_info.get("tacker_object.data")
resource_handle_data = \
_vnfc_rsc_info.get("compute_resource").get("tacker_object.data")
fields = {
"id": _vnfc_rsc_info.get("id"),
"vduId": _vnfc_rsc_info.get("vdu_id"),
"computeResource": _to_resource_handle(resource_handle_data),
"storageResourceIds":
_vnfc_rsc_info.get("storage_resource_ids"),
"vnfcCpInfo":
_to_vnfc_resource_info_v2_vnfc_cp_info(
_vnfc_rsc_info.get("vnfc_cp_info", []),
ext_vl_infos, vnf_vl_res_infos),
"metadata": _vnfc_rsc_info.get("metadata")}
vnfc_rsc_infos_v2.append(objects_v2.VnfcResourceInfoV2(**fields))
return vnfc_rsc_infos_v2
def _to_vnfc_resource_info_v2_vnfc_cp_info(vnfc_cp_infos,
ext_vl_infos, vnf_vl_res_infos):
# NOTE:In v1 api, the field of vnfLinkPortId is set
# even if cps are connected to external networks.
# Therefore vnfLinkPortId in v1 is migrated to vnfExtCpId in v2
# when cp is exposed, or migrated to vnfLinkPortId in v2 otherwise.
vnfc_rsc_info_v2_vnfc_cp_infos = []
for vnfc_cp_info in vnfc_cp_infos:
_vnfc_cp_info = vnfc_cp_info.get("tacker_object.data")
fields = {
"id": _vnfc_cp_info.get("id"),
"cpdId": _vnfc_cp_info.get("cpd_id")}
vnfc_rsc_info_v2_vnfc_cp_info = \
objects_v2.VnfcResourceInfoV2_VnfcCpInfo(**fields)
ext_vl_ids = \
[ext_vl_info.get("tacker_object.data").get("id")
for ext_vl_info in ext_vl_infos]
ext_vl_res_infos = \
[vnf_vl_res_info.get("tacker_object.data") for vnf_vl_res_info in
vnf_vl_res_infos if vnf_vl_res_info.get("tacker_object.data").
get("vnf_virtual_link_desc_id") in ext_vl_ids]
for ext_vl_res_info in ext_vl_res_infos:
for vnf_link_port in ext_vl_res_info.get("vnf_link_ports"):
_vnf_link_port = vnf_link_port.get("tacker_object.data")
if _vnf_link_port.get("id") == \
_vnfc_cp_info.get("vnf_link_port_id"):
vnfc_rsc_info_v2_vnfc_cp_info.vnfExtCpId = \
_vnfc_cp_info.get("vnf_link_port_id")
vnfc_rsc_info_v2_vnfc_cp_info.vnfLinkPortId = None
if not vnfc_rsc_info_v2_vnfc_cp_info.obj_attr_is_set("vnfExtCpId"):
vnfc_rsc_info_v2_vnfc_cp_info.vnfExtCpId = None
vnfc_rsc_info_v2_vnfc_cp_info.vnfLinkPortId = \
_vnfc_cp_info.get("vnf_link_port_id")
vnfc_rsc_info_v2_vnfc_cp_infos.append(vnfc_rsc_info_v2_vnfc_cp_info)
return vnfc_rsc_info_v2_vnfc_cp_infos
def _to_monitoring_parameters(vnf_attributes):
# NOTE: monitoringParameters is not defined in the v1 InstantiatedVnfInfo.
# Related information can be got from vnf_attributes table.
monitor_params_v2 = []
for attr in vnf_attributes:
if attr.key == 'param_values':
val = ast.literal_eval(attr.value)
params = val.get("monitoring_parameters")
if params:
for param in params:
fields = {
"id": param.get("id", uuidutils.generate_uuid()),
"vnfdId": param.get("vnfd_id"),
"name": param.get("name"),
"performanceMetric": param.get("performance_metric")}
monitor_params_v2.append(
objects_v2.MonitoringParameterV2(**fields))
return monitor_params_v2
def _to_localization_language(vnf_attributes):
# NOTE: localizationLanguages not defined in the v1 InstantiatedVnfInfo.
# Related information can be got from vnf_attributes table.
for attr in vnf_attributes:
if attr.key == 'param_values':
val = ast.literal_eval(attr.value)
if val.get("localization_languages"):
return val.get("localization_languages")[0]
return None
def _to_vnf_virtual_link_resource_info_v2(vl_rsc_infos,
ext_vl_infos, ext_managed_vl_infos):
vl_rsc_infos_v2 = []
ext_vl_ids = [ext_vl_info.get("tacker_object.data").get("id") for
ext_vl_info in ext_vl_infos]
ext_managed_vl_desc_ids = \
[ext_managed_vl_info.get(
"tacker_object.data").get("vnf_virtual_link_desc_id") for
ext_managed_vl_info in ext_managed_vl_infos]
for vl_rsc_info in vl_rsc_infos:
_vl_rsc_info = vl_rsc_info.get("tacker_object.data")
resource_handle_data = \
_vl_rsc_info.get("network_resource").get("tacker_object.data")
vl_desc_id = _vl_rsc_info.get("vnf_virtual_link_desc_id")
if vl_desc_id not in ext_vl_ids + ext_managed_vl_desc_ids:
fields = {
"id": _vl_rsc_info.get("id"),
"vnfVirtualLinkDescId": vl_desc_id,
"networkResource": _to_resource_handle(resource_handle_data),
"vnfLinkPorts": _to_vnf_link_port_info_v2(
_vl_rsc_info.get("vnf_link_ports"))}
vl_rsc_infos_v2.append(
objects_v2.VnfVirtualLinkResourceInfoV2(**fields))
return vl_rsc_infos_v2
def _to_virtual_storage_resource_info_v2(vstorage_infos):
vstorage_infos_v2 = []
for vstorage_info in vstorage_infos:
_vstorage_info = vstorage_info.get("tacker_object.data")
resource_handle_data = \
_vstorage_info.get("storage_resource").get("tacker_object.data")
fields = {
"id": _vstorage_info.get("id"),
"virtualStorageDescId":
_vstorage_info.get("virtual_storage_desc_id"),
"storageResource": _to_resource_handle(resource_handle_data)}
vstorage_infos_v2.append(
objects_v2.VirtualStorageResourceInfoV2(**fields))
return vstorage_infos_v2
def _to_vnf_configurable_properties(vnf_attributes):
# NOTE: configurableProperties is not defined in the v1 vnfInstance.
# Related information can be got from vnf_attributes table.
for attr in vnf_attributes:
if attr.key == 'param_values':
val = ast.literal_eval(attr.value)
if val.get("configurable_properties"):
return val.get("configurable_properties")
return None
def _to_vnfc_info_v2(vnfc_res_infos):
vnfc_infos_v2 = []
for vnfc_res_info in vnfc_res_infos:
_vnfc_res_info = vnfc_res_info.get("tacker_object.data")
fields = {
"id": f'{_vnfc_res_info.get("vdu_id")}-{_vnfc_res_info.get("id")}',
"vduId": _vnfc_res_info.get("vdu_id"),
"vnfcResourceInfoId": _vnfc_res_info.get("id"),
"vnfcState": "STARTED"}
vnfc_infos_v2.append(objects_v2.VnfcInfoV2(**fields))
return vnfc_infos_v2
def _set_cp_instance_type(instance_v2):
# NOTE: If target cp is connected to extManagedVirtualLinkInfo
# or vnfVirtualLinkResourceInfo, its cpInstanceType is set as "VNFC_CP".
for vl_type in ["extManagedVirtualLinkInfo", "vnfVirtualLinkResourceInfo"]:
for vl_info in instance_v2.instantiatedVnfInfo.get(vl_type, []):
for vnf_link_port in vl_info.vnfLinkPorts:
port_id = vnf_link_port.id
vnfc_resource_infos = \
instance_v2.instantiatedVnfInfo.get("vnfcResourceInfo", [])
for vnfc_resource_info in vnfc_resource_infos:
for vnfc_cp_info in vnfc_resource_info.get("vnfcCpInfo"):
if vnfc_cp_info.vnfLinkPortId == port_id:
vnf_link_port.cpInstanceType = "VNFC_CP"
def _get_vim(context, vim_con_info):
vim_id = vim_con_info.get("tacker_object.data").get("vim_id")
return api.model_query(context, nfvo_db.Vim).filter_by(id=vim_id).first()
def _set_stack_id(inst_v2, vnf):
heat_client = heat_utils.HeatClient(inst_v2.vimConnectionInfo["vim0"])
stack_names = []
stack_names.append(f"vnflcm_{inst_v2.id}")
stack_names.append(f"{inst_v2.vnfInstanceName}_{inst_v2.id}")
failure_count = \
[attr.get("value") for attr in
vnf.attributes if attr.get("key") == "failure_count"]
if failure_count != []:
stack_names[1] += f"-RESPAWN-{failure_count[0]}"
for stack_name in stack_names:
try:
heat_reses = heat_client.get_resources(stack_name)
except Exception as e:
LOG.debug('heat resources not found %s', e)
for vnfc_res_info in inst_v2.instantiatedVnfInfo.vnfcResourceInfo:
for res in heat_reses:
if res["physical_resource_id"] == \
vnfc_res_info.computeResource.resourceId:
stack_id = heat_utils.get_resource_stack_id(res)
vnfc_res_info.metadata = {"stack_id": stack_id}
@db_api.context_manager.writer
def create_vnf_instance_v2(context, vnf_id):
_vnf_instance = objects.vnf_instance._vnf_instance_get_by_id(
context, vnf_id, columns_to_join=None, read_deleted="no")
_vnf_info = _vnf_instance.instantiated_vnf_info
_vnf = api.model_query(
context, vnfm_db.VNF).filter_by(id=_vnf_instance.id).first()
_vnf_op_occs = \
api.model_query(context, models.VnfLcmOpOccs, read_deleted="no",
project_only=True).filter(models.VnfLcmOpOccs.
vnf_instance_id == _vnf_instance.id)
_vims = [_get_vim(context, vim_con_info) for
vim_con_info in _vnf_instance.vim_connection_info]
nfvo = nfvo_db_plugin.NfvoPluginDb()
_vim_infos = \
[nfvo.get_vim(context, vim.id, mask_password=False) for vim in _vims]
inst_v2 = objects_v2.VnfInstanceV2(
id=_vnf_instance.id,
vnfInstanceName=_vnf_instance.vnf_instance_name,
vnfInstanceDescription=_vnf_instance.vnf_instance_description,
vnfdId=_vnf_instance.vnfd_id,
vnfProvider=_vnf_instance.vnf_provider,
vnfProductName=_vnf_instance.vnf_product_name,
vnfSoftwareVersion=_vnf_instance.vnf_software_version,
vnfdVersion=_vnf_instance.vnfd_version,
vnfConfigurableProperties=_to_vnf_configurable_properties(
_vnf.attributes),
vimConnectionInfo=_to_vim_connection_info(
_vnf_instance.vim_connection_info, _vim_infos),
instantiationState=_vnf_instance.instantiation_state,
instantiatedVnfInfo=_to_vnf_instance_v2_instantiated_vnf_info(
_vnf_info, _vnf, _vnf_op_occs),
metadata=_vnf_instance.vnf_metadata,)
if inst_v2.instantiatedVnfInfo:
_set_cp_instance_type(inst_v2)
if inst_v2.vimConnectionInfo["vim0"].accessInfo.get("project"):
_set_stack_id(inst_v2, _vnf)
inst_v2.create(context)
return inst_v2
def _create_operation_params_v2(dict_operation_params_v1, operation):
fields = dict_operation_params_v1
# convert list -> dict
if "vimConnectionInfo" in fields.keys():
fields["vimConnectionInfo"] = \
{"vim_{}".format(index): vimConnectionInfo
for index, vimConnectionInfo
in enumerate(fields["vimConnectionInfo"])}
# convert list -> dict
if "extVirtualLinks" in fields.keys():
for extVirtualLink in fields["extVirtualLinks"]:
for extCp in extVirtualLink["extCps"]:
extCp["cpConfig"] = \
{"{}_{}".format(extCp["cpdId"], index): cpConfig_item
for index, cpConfig_item
in enumerate(extCp["cpConfig"])}
if operation == v2fields.LcmOperationType.INSTANTIATE:
cls = objects_v2.InstantiateVnfRequest
elif operation == v2fields.LcmOperationType.SCALE:
cls = objects_v2.ScaleVnfRequest
elif operation == v2fields.LcmOperationType.SCALE_TO_LEVEL:
cls = objects_v2.ScaleVnfToLevelRequest
elif operation == v2fields.LcmOperationType.CHANGE_FLAVOUR:
cls = objects_v2.ChangeVnfFlavourRequest
elif operation == v2fields.LcmOperationType.OPERATE:
cls = objects_v2.OperateVnfRequest
elif operation == v2fields.LcmOperationType.HEAL:
cls = objects_v2.HealVnfRequest
elif operation == v2fields.LcmOperationType.CHANGE_EXT_CONN:
cls = objects_v2.ChangeExtVnfConnectivityRequest
elif operation == v2fields.LcmOperationType.TERMINATE:
cls = objects_v2.TerminateVnfRequest
elif operation == v2fields.LcmOperationType.MODIFY_INFO:
cls = objects_v2.VnfInfoModificationRequest
elif operation == v2fields.LcmOperationType.CREATE_SNAPSHOT:
cls = objects_v2.CreateVnfSnapshotRequest
elif operation == v2fields.LcmOperationType.REVERT_TO_SNAPSHOT:
cls = objects_v2.RevertToVnfSnapshotRequest
elif operation == v2fields.LcmOperationType.CHANGE_VNFPKG:
cls = objects_v2.ChangeCurrentVnfPkgRequest
return cls.from_dict(fields)
def _create_resource_changes_v2(dict_resource_changes):
resource_changes = dict_resource_changes
# create affected_vnfcs_v2 list
affected_vnfcs_v2 = []
for affected_vnfc in resource_changes["affected_vnfcs"]:
fields = {
"id": affected_vnfc["id"],
'vduId': affected_vnfc["vdu_id"],
'changeType': affected_vnfc["change_type"],
'affectedVnfcCpIds': affected_vnfc["affected_vnfc_cp_ids"],
'addedStorageResourceIds':
affected_vnfc["added_storage_resource_ids"],
'removedStorageResourceIds':
affected_vnfc["removed_storage_resource_ids"],
# v1 -> v2
'computeResource':
objects_v2.ResourceHandle(**affected_vnfc["compute_resource"]),
'vnfdId': None,
'resourceDefinitionId': None,
'zoneId': None,
'metadata': None,
}
affected_vnfcs_v2.append(objects_v2.AffectedVnfcV2(**fields))
# create affected_virtual_links_v2 list
affected_vls_v2 = []
for affected_vl in resource_changes["affected_virtual_links"]:
fields = {
'id': affected_vl["id"],
'vnfVirtualLinkDescId':
affected_vl["vnf_virtual_link_desc_id"],
'changeType': affected_vl["change_type"],
# v1 -> v2
'vnfdId': None,
'networkResource':
objects_v2.ResourceHandle(
**affected_vl["network_resource"]),
'vnfLinkPortIds': None,
'resourceDefinitionId': None,
'zoneId': None,
'metadata': None
}
affected_vls_v2.append(objects_v2.AffectedVirtualLinkV2(**fields))
# create affected_virtual_storages_v2 list
affected_vstorages_v2 = []
for affected_vstorage \
in resource_changes.get("affected_virtual_storages", []):
fields = {
'id': affected_vstorage["id"],
'virtualStorageDescId':
affected_vstorage["virtual_storage_desc_id"],
'changeType': affected_vstorage["change_type"],
# v1 -> v2
'storageResource': objects_v2.ResourceHandle(
**affected_vstorage["storage_resource"]),
'vnfdId': None,
'resourceDefinitionId': None,
'zoneId': None,
'metadata': None
}
affected_vstorages_v2.append(
objects_v2.AffectedVirtualStorageV2(**fields))
fields = {
"affectedVnfcs": affected_vnfcs_v2,
"affectedVirtualLinks": affected_vls_v2,
"affectedVirtualStorages": affected_vstorages_v2,
"affectedExtLinkPorts": None}
return objects_v2.VnfLcmOpOccV2_ResourceChanges(**fields)
def _create_vnf_info_modifications_v2(
dict_changed_info, operation, dict_operation_param_v2):
changed_info = dict_changed_info
operation_param_v2 = dict_operation_param_v2
if changed_info is None or operation not in ["MODIFY_INFO"]:
return None
else:
fields = {
'vnfInstanceName': changed_info["vnf_instance_name"],
'vnfInstanceDescription': changed_info["vnf_instance_description"],
'metadata': changed_info["metadata"],
'vnfdId': changed_info["vnfd_id"],
'vnfProvider': changed_info["vnf_provider"],
'vnfProductName': changed_info["vnf_product_name"],
'vnfSoftwareVersion': changed_info["vnf_software_version"],
'vnfdVersion': changed_info["vnfd_version"],
# v1 -> v2
'extensions': None,
'vnfcInfoModifications': None,
'vnfConfigurableProperties':
operation_param_v2.get("vnfConfigurableProperties", None),
'vimConnectionInfo':
operation_param_v2.get("vimConnectionInfo", None)
}
return objects_v2.VnfInfoModificationsV2(**fields)
def _create_list_of_ext_virtual_link_infos_v2(
list_of_dict_changed_ext_connectivity, operation, operation_param_v2):
changed_ext_connectivity = list_of_dict_changed_ext_connectivity
if changed_ext_connectivity is None or \
operation not in ["INSTANTIATE", "CHANGE_EXT_CONN"]:
return None
else:
ext_vl_infos_v2 = []
for ext_vl_info in changed_ext_connectivity:
# create resourceHandle
resource_handle_v1 = ext_vl_info["resource_handle"]
fields = {
'vimConnectionId': resource_handle_v1["vim_connection_id"],
'resourceId': resource_handle_v1["resource_id"],
'vimLevelResourceType':
resource_handle_v1["vim_level_resource_type"],
# v1 -> v2
'resourceProviderId': None}
ext_vl_info_resourceHandle_v2 = objects_v2.ResourceHandle(**fields)
# create list of extLinkPorts
ext_link_ports_v2 = []
for ext_link_port in ext_vl_info["ext_link_ports"]:
# create resourceHandle
resource_handle_v1 = ext_link_port["resource_handle"]
fields = {
'vimConnectionId':
resource_handle_v1["vim_connection_id"],
'resourceProviderId': None,
'resourceId': resource_handle_v1["resource_id"],
'vimLevelResourceType':
resource_handle_v1["vim_level_resource_type"]}
ext_link_port_resourceHandle_v2 = \
objects_v2.ResourceHandle(**fields)
fields = {
'id': ext_link_port["id"],
'resourceHandle': ext_link_port_resourceHandle_v2,
'cpInstanceId': ext_link_port["cp_instance_id"]}
ext_link_port_v2 = objects_v2.ExtLinkPortInfoV2(**fields)
ext_link_ports_v2.append(ext_link_port_v2)
# create currentVnfExtCpData
_currentVnfExtCpData = []
for extVirtualLink in operation_param_v2.extVirtualLinks:
if extVirtualLink.id == ext_vl_info["id"]:
_currentVnfExtCpData = extVirtualLink.extCps
break
fields = {
'id': ext_vl_info["id"],
'resourceHandle': ext_vl_info_resourceHandle_v2,
'extLinkPorts': ext_link_ports_v2,
'currentVnfExtCpData': _currentVnfExtCpData}
ext_vl_infos_v2.append(objects_v2.ExtVirtualLinkInfoV2(**fields))
return ext_vl_infos_v2
def _create_vnf_lcm_op_occ_v2(context, op_occ_v1):
# create v2 ProblemDetails
_ProblemDetails_v2 = None
if op_occ_v1.error:
_ProblemDetails_v2 = \
objects_v2.ProblemDetails(**jsonutils.loads(op_occ_v1.error))
# create v2 OperationParam
_dict_operation_params = jsonutils.loads(op_occ_v1.operation_params)
_operation = op_occ_v1.operation
_OperationParam_v2 = \
_create_operation_params_v2(_dict_operation_params, _operation)
# create VnfLcmOpOccV2_ResourceChanges
_dict_resource_changes = jsonutils.loads(op_occ_v1.resource_changes)
_VnfLcmOpOccV2_ResourceChanges = \
_create_resource_changes_v2(_dict_resource_changes)
# create VnfInfoModificationsV2
_VnfInfoModificationsV2 = None
if op_occ_v1.changed_info:
_dict_changed_info = jsonutils.loads(op_occ_v1.changed_info)
_operation = op_occ_v1.operation
_dict_operation_param = dict(_OperationParam_v2)
_VnfInfoModificationsV2 = \
_create_vnf_info_modifications_v2(
_dict_changed_info, _operation, _dict_operation_param)
# create list of ExtVirtualLinkInfoV2
_list_of_ExtVirtualLinkInfoV2 = []
if op_occ_v1.changed_ext_connectivity != []:
_list_of_dict_changed_ext_conn = \
jsonutils.loads(op_occ_v1.changed_ext_connectivity)
_operation = op_occ_v1.operation
_list_of_ExtVirtualLinkInfoV2 = \
_create_list_of_ext_virtual_link_infos_v2(
_list_of_dict_changed_ext_conn, _operation, _OperationParam_v2)
vnf_lcm_op_occ_v2 = objects_v2.VnfLcmOpOccV2(
id=op_occ_v1.id,
operationState=op_occ_v1.operation_state,
stateEnteredTime=op_occ_v1.state_entered_time,
startTime=op_occ_v1.start_time,
vnfInstanceId=op_occ_v1.vnf_instance_id,
grantId=op_occ_v1.grant_id,
operation=op_occ_v1.operation,
isAutomaticInvocation=op_occ_v1.is_automatic_invocation,
isCancelPending=op_occ_v1.is_cancel_pending,
# v1 -> v2
changedExtConnectivity=_list_of_ExtVirtualLinkInfoV2,
error=_ProblemDetails_v2,
resourceChanges=_VnfLcmOpOccV2_ResourceChanges,
operationParams=_OperationParam_v2,
changedInfo=_VnfInfoModificationsV2,
cancelMode=None,
modificationsTriggeredByVnfPkgChange=None,
vnfSnapshotInfoId=None,
# _links=
)
vnf_lcm_op_occ_v2.create(context)
return vnf_lcm_op_occ_v2
@db_api.context_manager.writer
def create_vnf_lcm_op_occs_v2(context, vnf_id):
_op_occs_v2 = []
# get all op_occ_v1 in (vnf_instance_id==vnf_id)
_list_op_occs_v1 = \
api.model_query(
context,
models.VnfLcmOpOccs,
read_deleted="no",
project_only=True
).filter(models.VnfLcmOpOccs.vnf_instance_id == vnf_id)\
.order_by(models.VnfLcmOpOccs.start_time).all()
for _op_occ_v1 in _list_op_occs_v1:
_op_occ_v2 = _create_vnf_lcm_op_occ_v2(context, _op_occ_v1)
_op_occs_v2.append(_op_occ_v2)
return _op_occs_v2