375 lines
14 KiB
Python
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)
|