tacker/tacker/sol_refactored/common/lcm_op_occ_utils.py

375 lines
14 KiB
Python

# Copyright (C) 2021 Nippon Telegraph and Telephone Corporation
# 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.
from datetime import datetime
from oslo_log import log as logging
from oslo_utils import uuidutils
from tacker.sol_refactored.common import exceptions as sol_ex
from tacker.sol_refactored.common import subscription_utils as subsc_utils
from tacker.sol_refactored.common import vnf_instance_utils as inst_utils
from tacker.sol_refactored import objects
from tacker.sol_refactored.objects.v2 import fields
LOG = logging.getLogger(__name__) # not used at the moment
def get_lcmocc(context, lcmocc_id):
lcmocc = objects.VnfLcmOpOccV2.get_by_id(context, lcmocc_id)
if lcmocc is None:
raise sol_ex.VnfLcmOpOccNotFound(lcmocc_id=id)
return lcmocc
def get_lcmocc_all(context):
return objects.VnfLcmOpOccV2.get_all(context)
def lcmocc_href(lcmocc_id, endpoint):
return "{}/v2/vnflcm/vnf_lcm_op_occs/{}".format(endpoint, lcmocc_id)
def lcmocc_task_href(lcmocc_id, task, endpoint):
return "{}/v2/vnflcm/vnf_lcm_op_occs/{}/{}".format(endpoint, lcmocc_id,
task)
def make_lcmocc_links(lcmocc, endpoint):
links = objects.VnfLcmOpOccV2_Links()
links.self = objects.Link(href=lcmocc_href(lcmocc.id, endpoint))
links.vnfInstance = objects.Link(
href=inst_utils.inst_href(lcmocc.vnfInstanceId, endpoint))
links.retry = objects.Link(
href=lcmocc_task_href(lcmocc.id, 'retry', endpoint))
links.rollback = objects.Link(
href=lcmocc_task_href(lcmocc.id, 'rollback', endpoint))
links.fail = objects.Link(
href=lcmocc_task_href(lcmocc.id, 'fail', endpoint))
# TODO(oda-g): add when implemented
# links.grant
# links.cancel
# links.vnfSnapshot
return links
def make_lcmocc_notif_data(subsc, lcmocc, endpoint):
notif_data = objects.VnfLcmOperationOccurrenceNotificationV2(
id=uuidutils.generate_uuid(),
notificationType="VnfLcmOperationOccurrenceNotification",
subscriptionId=subsc.id,
timeStamp=datetime.utcnow(),
operationState=lcmocc.operationState,
vnfInstanceId=lcmocc.vnfInstanceId,
operation=lcmocc.operation,
isAutomaticInvocation=lcmocc.isAutomaticInvocation,
verbosity=subsc.verbosity,
vnfLcmOpOccId=lcmocc.id,
_links=objects.LccnLinksV2(
vnfInstance=objects.NotificationLink(
href=inst_utils.inst_href(lcmocc.vnfInstanceId, endpoint)),
subscription=objects.NotificationLink(
href=subsc_utils.subsc_href(subsc.id, endpoint)),
vnfLcmOpOcc=objects.NotificationLink(
href=lcmocc_href(lcmocc.id, endpoint))
)
)
if lcmocc.operationState == fields.LcmOperationStateType.STARTING:
notif_data.notificationStatus = 'START'
else:
notif_data.notificationStatus = 'RESULT'
if lcmocc.obj_attr_is_set('error'):
notif_data.error = lcmocc.error
if notif_data.verbosity == fields.LcmOpOccNotificationVerbosityType.FULL:
if lcmocc.obj_attr_is_set('resourceChanges'):
attrs = ['affectedVnfcs',
'affectedVirtualLinks',
'affectedExtLinkPorts',
'affectedVirtualStorages']
for attr in attrs:
if lcmocc.resourceChanges.obj_attr_is_set(attr):
notif_data[attr] = lcmocc.resourceChanges[attr]
attrs = ['changedInfo',
'changedExtConnectivity',
'modificationsTriggeredByVnfPkgChange']
for attr in attrs:
if lcmocc.obj_attr_is_set(attr):
notif_data[attr] = lcmocc[attr]
return notif_data
def _make_affected_vnfc(vnfc, change_type):
affected_vnfc = objects.AffectedVnfcV2(
id=vnfc.id,
vduId=vnfc.vduId,
changeType=change_type,
computeResource=vnfc.computeResource
)
if vnfc.obj_attr_is_set('vnfcCpInfo'):
cp_ids = [cp.id for cp in vnfc.vnfcCpInfo]
affected_vnfc.affectedVnfcCpIds = cp_ids
if vnfc.obj_attr_is_set('storageResourceIds'):
str_ids = vnfc.storageResourceIds
if change_type == 'ADDED':
affected_vnfc.addedStorageResourceIds = str_ids
else: # 'REMOVED'
affected_vnfc.removedStorageResourceIds = str_ids
return affected_vnfc
def _make_affected_vl(vl, change_type):
affected_vl = objects.AffectedVirtualLinkV2(
id=vl.id,
vnfVirtualLinkDescId=vl.vnfVirtualLinkDescId,
changeType=change_type,
networkResource=vl.networkResource
)
if vl.obj_attr_is_set('vnfLinkPorts'):
affected_vl.vnfLinkPortIds = [port.id for port in vl.vnfLinkPorts]
return affected_vl
def _make_affected_vls_link_port_change(vls_saved, vls, common_vls):
affected_vls = []
for vl_id in common_vls:
old_ports = set()
new_ports = set()
for vl in vls_saved:
if vl.id == vl_id:
old_vl = vl
if vl.obj_attr_is_set('vnfLinkPorts'):
old_ports = {port.id for port in vl.vnfLinkPorts}
for vl in vls:
if vl.id == vl_id:
new_vl = vl
if vl.obj_attr_is_set('vnfLinkPorts'):
new_ports = {port.id for port in vl.vnfLinkPorts}
add_ports = new_ports - old_ports
rm_ports = old_ports - new_ports
# assume there are not add_ports and rm_ports at the same time.
if add_ports:
affected_vl = objects.AffectedVirtualLinkV2(
id=new_vl.id,
vnfVirtualLinkDescId=new_vl.vnfVirtualLinkDescId,
changeType='LINK_PORT_ADDED',
networkResource=new_vl.networkResource,
vnfLinkPortIds=list(add_ports)
)
affected_vls.append(affected_vl)
elif rm_ports:
affected_vl = objects.AffectedVirtualLinkV2(
id=old_vl.id,
vnfVirtualLinkDescId=old_vl.vnfVirtualLinkDescId,
changeType='LINK_PORT_REMOVED',
networkResource=old_vl.networkResource,
vnfLinkPortIds=list(rm_ports)
)
affected_vls.append(affected_vl)
return affected_vls
def _make_affected_strg(strg, change_type):
return objects.AffectedVirtualStorageV2(
id=strg.id,
virtualStorageDescId=strg.virtualStorageDescId,
changeType=change_type,
storageResource=strg.storageResource
)
def _make_affected_ext_link_ports(inst_info_saved, inst_info):
affected_ext_link_ports = []
ext_vl_ports_saved = set()
ext_vl_ports = set()
if inst_info_saved.obj_attr_is_set('extVirtualLinkInfo'):
for ext_vl in inst_info_saved.extVirtualLinkInfo:
if ext_vl.obj_attr_is_set('extLinkPorts'):
ext_vl_ports_saved |= {port.id
for port in ext_vl.extLinkPorts}
if inst_info.obj_attr_is_set('extVirtualLinkInfo'):
for ext_vl in inst_info.extVirtualLinkInfo:
if ext_vl.obj_attr_is_set('extLinkPorts'):
ext_vl_ports |= {port.id
for port in ext_vl.extLinkPorts}
add_ext_vl_ports = ext_vl_ports - ext_vl_ports_saved
rm_ext_vl_ports = ext_vl_ports_saved - ext_vl_ports
if add_ext_vl_ports:
for ext_vl in inst_info.extVirtualLinkInfo:
if not ext_vl.obj_attr_is_set('extLinkPorts'):
continue
affected_ext_link_ports += [
objects.AffectedExtLinkPortV2(
id=port.id,
changeType='ADDED',
extCpInstanceId=port.cpInstanceId,
resourceHandle=port.resourceHandle
)
for port in ext_vl.extLinkPorts
if port.id in add_ext_vl_ports
]
if rm_ext_vl_ports:
for ext_vl in inst_info_saved.extVirtualLinkInfo:
if not ext_vl.obj_attr_is_set('extLinkPorts'):
continue
affected_ext_link_ports += [
objects.AffectedExtLinkPortV2(
id=port.id,
changeType='REMOVED',
extCpInstanceId=port.cpInstanceId,
resourceHandle=port.resourceHandle
)
for port in ext_vl.extLinkPorts
if port.id in rm_ext_vl_ports
]
return affected_ext_link_ports
def update_lcmocc(lcmocc, inst_saved, inst):
# make ResourceChanges of lcmocc from instantiatedVnfInfo.
# NOTE: grant related info such as resourceDefinitionId, zoneId
# and so on are not included in lcmocc since such info are not
# included in instantiatedVnfInfo.
if inst_saved.obj_attr_is_set('instantiatedVnfInfo'):
inst_info_saved = inst_saved.instantiatedVnfInfo
else:
# dummy
inst_info_saved = objects.VnfInstanceV2_InstantiatedVnfInfo()
inst_info = inst.instantiatedVnfInfo
# NOTE: objects may be re-created. so compare 'id' instead of object
# itself.
def _calc_diff(attr):
# NOTE: instantiatedVnfInfo object is dict compat
objs_saved = set()
if inst_info_saved.obj_attr_is_set(attr):
objs_saved = {obj.id for obj in inst_info_saved[attr]}
objs = set()
if inst_info.obj_attr_is_set(attr):
objs = {obj.id for obj in inst_info[attr]}
# return removed_objs, added_objs, common_objs
return objs_saved - objs, objs - objs_saved, objs_saved & objs
removed_vnfcs, added_vnfcs, _ = _calc_diff('vnfcResourceInfo')
affected_vnfcs = []
if removed_vnfcs:
affected_vnfcs += [_make_affected_vnfc(vnfc, 'REMOVED')
for vnfc in inst_info_saved.vnfcResourceInfo
if vnfc.id in removed_vnfcs]
if added_vnfcs:
affected_vnfcs += [_make_affected_vnfc(vnfc, 'ADDED')
for vnfc in inst_info.vnfcResourceInfo
if vnfc.id in added_vnfcs]
removed_vls, added_vls, common_vls = _calc_diff(
'vnfVirtualLinkResourceInfo')
affected_vls = []
if removed_vls:
affected_vls += [_make_affected_vl(vl, 'REMOVED')
for vl in inst_info_saved.vnfVirtualLinkResourceInfo
if vl.id in removed_vls]
if added_vls:
affected_vls += [_make_affected_vl(vl, 'ADDED')
for vl in inst_info.vnfVirtualLinkResourceInfo
if vl.id in added_vls]
if common_vls:
affected_vls += _make_affected_vls_link_port_change(
inst_info_saved.vnfVirtualLinkResourceInfo,
inst_info.vnfVirtualLinkResourceInfo, common_vls)
removed_mgd_vls, added_mgd_vls, common_mgd_vls = _calc_diff(
'extManagedVirtualLinkInfo')
if removed_mgd_vls:
affected_vls += [_make_affected_vl(vl, 'LINK_PORT_REMOVED')
for vl in inst_info_saved.extManagedVirtualLinkInfo
if vl.id in removed_mgd_vls]
if added_mgd_vls:
affected_vls += [_make_affected_vl(vl, 'LINK_PORT_ADDED')
for vl in inst_info.extManagedVirtualLinkInfo
if vl.id in added_mgd_vls]
if common_mgd_vls:
affected_vls += _make_affected_vls_link_port_change(
inst_info_saved.extManagedVirtualLinkInfo,
inst_info.extManagedVirtualLinkInfo, common_mgd_vls)
removed_strgs, added_strgs, _ = _calc_diff('virtualStorageResourceInfo')
affected_strgs = []
if removed_strgs:
affected_strgs += [
_make_affected_strg(strg, 'REMOVED')
for strg in inst_info_saved.virtualStorageResourceInfo
if strg.id in removed_strgs
]
if added_strgs:
affected_strgs += [_make_affected_strg(strg, 'ADDED')
for strg in inst_info.virtualStorageResourceInfo
if strg.id in added_strgs]
affected_ext_link_ports = _make_affected_ext_link_ports(
inst_info_saved, inst_info)
if (affected_vnfcs or affected_vls or affected_strgs or
affected_ext_link_ports):
change_info = objects.VnfLcmOpOccV2_ResourceChanges()
if affected_vnfcs:
change_info.affectedVnfcs = affected_vnfcs
if affected_vls:
change_info.affectedVirtualLinks = affected_vls
if affected_strgs:
change_info.affectedVirtualStorages = affected_strgs
if affected_ext_link_ports:
change_info.affectedExtLinkPorts = affected_ext_link_ports
lcmocc.resourceChanges = change_info
def get_grant_req_and_grant(context, lcmocc):
grant_reqs = objects.GrantRequestV1.get_by_filter(context,
vnfLcmOpOccId=lcmocc.id)
grant = objects.GrantV1.get_by_id(context, lcmocc.grantId)
if not grant_reqs or grant is None:
raise sol_ex.GrantRequestOrGrantNotFound(lcmocc_id=lcmocc.id)
# len(grant_reqs) == 1 because vnfLcmOpOccId is primary key.
return grant_reqs[0], grant
def check_lcmocc_in_progress(context, inst_id):
# if the controller or conductor executes an operation for the vnf
# instance (i.e. operationState is ...ING), other operation for
# the same vnf instance is exculded by the coordinator.
# check here is existence of lcmocc for the vnf instance with
# FAILED_TEMP operationState.
lcmoccs = objects.VnfLcmOpOccV2.get_by_filter(
context, vnfInstanceId=inst_id,
operationState=fields.LcmOperationStateType.FAILED_TEMP)
if lcmoccs:
raise sol_ex.OtherOperationInProgress(inst_id=inst_id)