Support Rollback of LCM Resource
Supported rollback LCM operation Implements: blueprint support-etsi-nfv-specs Spec: https://specs.openstack.org/openstack/tacker-specs/specs/victoria/support-etsi-nfv-based-errorhandling.html Change-Id: Ic5701c6c1379ee6e08515bf3086da39d75160f82
This commit is contained in:
parent
ffe4c40921
commit
4543b961eb
@ -777,6 +777,39 @@ Response Example
|
||||
.. literalinclude:: samples/vnflcm/show-vnflcm-operation-occurrence-response.json
|
||||
:language: javascript
|
||||
|
||||
Roll back a VNF lifecycle operation
|
||||
===================================
|
||||
|
||||
.. rest_method:: POST /vnflcm/v1/vnf_lcm_op_occs/{vnfLcmOpOccId}/rollback
|
||||
|
||||
The POST method initiates rolling back a VNF lifecycle operation if that operation has experienced a temporary failure,
|
||||
i.e. the related "Individual VNF LCM operation occurrence" resource is in "FAILED_TEMP" state.
|
||||
|
||||
In case of success of processing the asynchronous request, the "operationState" attribute in the representation of the
|
||||
parent resource shall be changed to "ROLLING_BACK" and the applicable "start" notification
|
||||
shall be emitted to indicate that rollback of the underlying VNF LCM operation occurrence is attempted.
|
||||
|
||||
Response Codes
|
||||
--------------
|
||||
|
||||
.. rest_status_code:: success status.yaml
|
||||
|
||||
- 202
|
||||
|
||||
.. rest_status_code:: error status.yaml
|
||||
|
||||
- 401
|
||||
- 403
|
||||
- 404
|
||||
- 409
|
||||
|
||||
Request Parameters
|
||||
------------------
|
||||
|
||||
.. rest_parameters:: parameters_vnflcm.yaml
|
||||
|
||||
- vnfLcmOpOccId: vnf_lcm_op_occ_id
|
||||
|
||||
Create a new subscription
|
||||
=========================
|
||||
|
||||
|
@ -1116,6 +1116,90 @@ class VnfLcmController(wsgi.Controller):
|
||||
return self._make_problem_detail(
|
||||
str(e), 500, title='Internal Server Error')
|
||||
|
||||
def _rollback(
|
||||
self,
|
||||
context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
vnf_lcm_op_occs,
|
||||
operation_params):
|
||||
|
||||
self.rpc_api.rollback(
|
||||
context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params)
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
|
||||
vnflcm_url = CONF.vnf_lcm.endpoint_url + \
|
||||
"/vnflcm/v1/vnf_lcm_op_occs/" + vnf_lcm_op_occs.id
|
||||
res = webob.Response()
|
||||
res.status_int = 202
|
||||
location = ('Location', vnflcm_url)
|
||||
res.headerlist.append(location)
|
||||
return res
|
||||
|
||||
def _get_rollback_vnf(self, context, vnf_instance_id):
|
||||
return self._vnfm_plugin.get_vnf(context, vnf_instance_id)
|
||||
|
||||
@wsgi.response(http_client.ACCEPTED)
|
||||
@wsgi.expected_errors((http_client.BAD_REQUEST, http_client.FORBIDDEN,
|
||||
http_client.NOT_FOUND, http_client.CONFLICT))
|
||||
def rollback(self, request, id):
|
||||
context = request.environ['tacker.context']
|
||||
context.can(vnf_lcm_policies.VNFLCM % 'rollback')
|
||||
|
||||
try:
|
||||
vnf_lcm_op_occs = objects.VnfLcmOpOcc.get_by_id(context, id)
|
||||
if vnf_lcm_op_occs.operation_state != 'FAILED_TEMP':
|
||||
return self._make_problem_detail(
|
||||
'OperationState IS NOT FAILED_TEMP',
|
||||
409,
|
||||
title='OperationState IS NOT FAILED_TEMP')
|
||||
|
||||
if vnf_lcm_op_occs.operation != 'INSTANTIATION' \
|
||||
and vnf_lcm_op_occs.operation != 'SCALE':
|
||||
return self._make_problem_detail(
|
||||
'OPERATION IS NOT INSTANTIATION/SCALE',
|
||||
409,
|
||||
title='OPERATION IS NOT INSTANTIATION/SCALE')
|
||||
|
||||
operation_params = jsonutils.loads(
|
||||
vnf_lcm_op_occs.operation_params)
|
||||
|
||||
if vnf_lcm_op_occs.operation == 'SCALE' \
|
||||
and operation_params['type'] == 'SCALE_IN':
|
||||
return self._make_problem_detail(
|
||||
'SCALE_IN CAN NOT ROLLBACK', 409,
|
||||
title='SCALE_IN CAN NOT ROLLBACK')
|
||||
|
||||
vnf_info = self._get_rollback_vnf(
|
||||
context, vnf_lcm_op_occs.vnf_instance_id)
|
||||
vnf_instance = self._get_vnf_instance(
|
||||
context, vnf_lcm_op_occs.vnf_instance_id)
|
||||
|
||||
vnf_lcm_op_occs.changed_info = None
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
return self._rollback(
|
||||
context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
vnf_lcm_op_occs,
|
||||
operation_params)
|
||||
except vnfm.VNFNotFound as vnf_e:
|
||||
return self._make_problem_detail(
|
||||
str(vnf_e), 404, title='VNF NOT FOUND')
|
||||
except exceptions.NotFound as occ_e:
|
||||
return self._make_problem_detail(
|
||||
str(occ_e), 404, title='VNF NOT FOUND')
|
||||
except webob.exc.HTTPNotFound as inst_e:
|
||||
return self._make_problem_detail(
|
||||
str(inst_e), 404, title='VNF NOT FOUND')
|
||||
except Exception as e:
|
||||
LOG.error(traceback.format_exc())
|
||||
return self._make_problem_detail(
|
||||
str(e), 500, title='Internal Server Error')
|
||||
|
||||
def _make_problem_detail(
|
||||
self,
|
||||
detail,
|
||||
|
@ -112,6 +112,13 @@ class VnflcmAPIRouter(wsgi.Router):
|
||||
"/vnf_instances/{id}/scale",
|
||||
methods, controller, default_resource)
|
||||
|
||||
# Allowed methods on
|
||||
# {apiRoot}/vnflcm/v1/vnf_lcm_op_occs/{vnfLcmOpOccId}/rollback resource
|
||||
methods = {"POST": "rollback"}
|
||||
self._setup_route(mapper,
|
||||
"/vnf_lcm_op_occs/{id}/rollback",
|
||||
methods, controller, default_resource)
|
||||
|
||||
methods = {"GET": "subscription_list", "POST": "register_subscription"}
|
||||
self._setup_route(mapper, "/subscriptions",
|
||||
methods, controller, default_resource)
|
||||
|
@ -1368,6 +1368,7 @@ class Conductor(manager.Manager):
|
||||
kwargs.get('is_automatic_invocation', False)
|
||||
error = kwargs.get('error', None)
|
||||
# Used for timing control when a failure occurs
|
||||
error_point = kwargs.get('error_point', 0)
|
||||
|
||||
if old_vnf_instance:
|
||||
vnf_instance_id = old_vnf_instance.id
|
||||
@ -1381,6 +1382,7 @@ class Conductor(manager.Manager):
|
||||
vnf_notif = self._get_vnf_notify(context, vnf_lcm_op_occs_id)
|
||||
vnf_notif.operation_state = operation_state
|
||||
if operation_state == fields.LcmOccsOperationState.FAILED_TEMP:
|
||||
vnf_notif.error_point = error_point
|
||||
error_details = objects.ProblemDetails(
|
||||
context=context,
|
||||
status=500,
|
||||
@ -1543,6 +1545,8 @@ class Conductor(manager.Manager):
|
||||
instantiate_vnf,
|
||||
vnf_lcm_op_occs_id):
|
||||
|
||||
vnf_dict['error_point'] = 1
|
||||
|
||||
self._instantiate_grant(context,
|
||||
vnf_instance,
|
||||
vnf_dict,
|
||||
@ -1565,12 +1569,15 @@ class Conductor(manager.Manager):
|
||||
self._change_vnf_status(context, vnf_instance.id,
|
||||
_INACTIVE_STATUS, 'PENDING_CREATE')
|
||||
|
||||
vnf_dict['error_point'] = 3
|
||||
self.vnflcm_driver.instantiate_vnf(context, vnf_instance,
|
||||
vnf_dict, instantiate_vnf)
|
||||
vnf_dict['error_point'] = 5
|
||||
self._build_instantiated_vnf_info(context,
|
||||
vnf_instance,
|
||||
instantiate_vnf_req=instantiate_vnf)
|
||||
|
||||
vnf_dict['error_point'] = 7
|
||||
self._update_vnf_attributes(context, vnf_dict,
|
||||
_PENDING_STATUS, _ACTIVE_STATUS)
|
||||
self.vnflcm_driver._vnf_instance_update(context, vnf_instance,
|
||||
@ -1604,7 +1611,8 @@ class Conductor(manager.Manager):
|
||||
vnf_instance=vnf_instance,
|
||||
request_obj=instantiate_vnf,
|
||||
operation_state=fields.LcmOccsOperationState.FAILED_TEMP,
|
||||
error=str(ex)
|
||||
error=str(ex),
|
||||
error_point=vnf_dict['error_point']
|
||||
)
|
||||
|
||||
@coordination.synchronized('{vnf_instance[id]}')
|
||||
@ -1887,6 +1895,11 @@ class Conductor(manager.Manager):
|
||||
notification_data['changed_info'] = changed_info.to_dict()
|
||||
self.send_notification(context, notification_data)
|
||||
|
||||
@coordination.synchronized('{vnf_instance[id]}')
|
||||
def rollback(self, context, vnf_info, vnf_instance, operation_params):
|
||||
self.vnflcm_driver.rollback_vnf(context, vnf_info,
|
||||
vnf_instance, operation_params)
|
||||
|
||||
|
||||
def init(args, **kwargs):
|
||||
CONF(args=args, project='tacker',
|
||||
|
@ -112,3 +112,16 @@ class VNFLcmRPCAPI(object):
|
||||
rpc_method = cctxt.cast if cast else cctxt.call
|
||||
return rpc_method(context, 'send_notification',
|
||||
notification=notification)
|
||||
|
||||
def rollback(self, context, vnf_info, vnf_instance,
|
||||
operation_params, cast=True):
|
||||
serializer = objects_base.TackerObjectSerializer()
|
||||
|
||||
client = rpc.get_client(self.target, version_cap=None,
|
||||
serializer=serializer)
|
||||
cctxt = client.prepare()
|
||||
rpc_method = cctxt.cast if cast else cctxt.call
|
||||
return rpc_method(context, 'rollback',
|
||||
vnf_info=vnf_info,
|
||||
vnf_instance=vnf_instance,
|
||||
operation_params=operation_params)
|
||||
|
@ -865,3 +865,87 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin):
|
||||
update({
|
||||
'resource': placement_obj.resource,
|
||||
'updated_at': timeutils.utcnow()}))
|
||||
|
||||
def update_vnf_rollback_status_err(self,
|
||||
context,
|
||||
vnf_info):
|
||||
vnf_lcm_op_occs = vnf_info['vnf_lcm_op_occ']
|
||||
if vnf_lcm_op_occs.operation == 'SCALE':
|
||||
self._cos_db_plg.create_event(
|
||||
context, res_id=vnf_info['id'],
|
||||
res_type=constants.RES_TYPE_VNF,
|
||||
res_state='ERROR',
|
||||
evt_type=constants.RES_EVT_SCALE,
|
||||
tstamp=timeutils.utcnow())
|
||||
else:
|
||||
self._cos_db_plg.create_event(
|
||||
context, res_id=vnf_info['id'],
|
||||
res_type=constants.RES_TYPE_VNF,
|
||||
res_state='ERROR',
|
||||
evt_type=constants.RES_EVT_CREATE,
|
||||
tstamp=timeutils.utcnow())
|
||||
|
||||
def _update_vnf_rollback_pre(self,
|
||||
context,
|
||||
vnf_info):
|
||||
vnf_lcm_op_occs = vnf_info['vnf_lcm_op_occ']
|
||||
if vnf_lcm_op_occs.operation == 'SCALE':
|
||||
self._cos_db_plg.create_event(
|
||||
context, res_id=vnf_info['id'],
|
||||
res_type=constants.RES_TYPE_VNF,
|
||||
res_state='ROLL_BACK',
|
||||
evt_type=constants.RES_EVT_SCALE,
|
||||
tstamp=timeutils.utcnow())
|
||||
else:
|
||||
self._cos_db_plg.create_event(
|
||||
context, res_id=vnf_info['id'],
|
||||
res_type=constants.RES_TYPE_VNF,
|
||||
res_state='ROLL_BACK',
|
||||
evt_type=constants.RES_EVT_CREATE,
|
||||
tstamp=timeutils.utcnow())
|
||||
|
||||
def _update_vnf_rollback(self,
|
||||
context,
|
||||
vnf_info,
|
||||
previous_statuses,
|
||||
status,
|
||||
vnf_instance=None,
|
||||
vnf_lcm_op_occ=None):
|
||||
with context.session.begin(subtransactions=True):
|
||||
timestamp = timeutils.utcnow()
|
||||
(self._model_query(context, VNF).
|
||||
filter(VNF.id == vnf_info['id']).
|
||||
filter(VNF.status == previous_statuses).
|
||||
update({'status': status,
|
||||
'updated_at': timestamp}))
|
||||
|
||||
dev_attrs = vnf_info.get('attributes', {})
|
||||
(context.session.query(VNFAttribute).
|
||||
filter(VNFAttribute.vnf_id == vnf_info['id']).
|
||||
filter(~VNFAttribute.key.in_(dev_attrs.keys())).
|
||||
delete(synchronize_session='fetch'))
|
||||
|
||||
vnf_lcm_op_occs = vnf_info['vnf_lcm_op_occ']
|
||||
if vnf_lcm_op_occs.operation == 'SCALE':
|
||||
for (key, value) in dev_attrs.items():
|
||||
if 'vim_auth' not in key:
|
||||
self._vnf_attribute_update_or_create(
|
||||
context, vnf_info['id'], key, value)
|
||||
self._cos_db_plg.create_event(
|
||||
context, res_id=vnf_info['id'],
|
||||
res_type=constants.RES_TYPE_VNF,
|
||||
res_state=status,
|
||||
evt_type=constants.RES_EVT_SCALE,
|
||||
tstamp=timestamp)
|
||||
else:
|
||||
self._cos_db_plg.create_event(
|
||||
context, res_id=vnf_info['id'],
|
||||
res_type=constants.RES_TYPE_VNF,
|
||||
res_state=status,
|
||||
evt_type=constants.RES_EVT_CREATE,
|
||||
tstamp=timestamp)
|
||||
if vnf_lcm_op_occ:
|
||||
vnf_lcm_op_occ.state_entered_time = timestamp
|
||||
vnf_lcm_op_occ.save()
|
||||
if vnf_instance:
|
||||
vnf_instance.save()
|
||||
|
@ -132,6 +132,17 @@ rules = [
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=VNFLCM % 'rollback',
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
description="Rollback a VNF instance.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/vnflcm/v1/vnf_lcm_op_occs/{vnfLcmOpOccId}/rollback'
|
||||
}
|
||||
]
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
|
@ -836,6 +836,252 @@ def vnf_scale():
|
||||
vim_id=uuidsentinel.vim_id)
|
||||
|
||||
|
||||
def vnflcm_rollback(error_point=7):
|
||||
return objects.VnfLcmOpOcc(
|
||||
state_entered_time=datetime.datetime(2000, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC),
|
||||
start_time=datetime.datetime(2000, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC),
|
||||
vnf_instance_id=uuidsentinel.vnf_instance_id,
|
||||
operation='SCALE',
|
||||
operation_state='FAILED_TEMP',
|
||||
is_automatic_invocation=False,
|
||||
operation_params='{"type": "SCALE_OUT", "aspect_id": "SP1"}',
|
||||
error_point=error_point,
|
||||
id=constants.UUID,
|
||||
created_at=datetime.datetime(2000, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC))
|
||||
|
||||
|
||||
def vnflcm_rollback_insta(error_point=7):
|
||||
return objects.VnfLcmOpOcc(
|
||||
state_entered_time=datetime.datetime(2000, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC),
|
||||
start_time=datetime.datetime(2000, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC),
|
||||
vnf_instance_id=uuidsentinel.vnf_instance_id,
|
||||
operation='INSTANTIATION',
|
||||
operation_state='FAILED_TEMP',
|
||||
is_automatic_invocation=False,
|
||||
operation_params='{}',
|
||||
error_point=error_point,
|
||||
id=constants.UUID,
|
||||
created_at=datetime.datetime(2000, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC))
|
||||
|
||||
|
||||
def vnflcm_rollback_active():
|
||||
return objects.VnfLcmOpOcc(
|
||||
state_entered_time=datetime.datetime(2000, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC),
|
||||
start_time=datetime.datetime(2000, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC),
|
||||
vnf_instance_id=uuidsentinel.vnf_instance_id,
|
||||
operation='SCALE',
|
||||
operation_state='ACTIVE',
|
||||
is_automatic_invocation=False,
|
||||
operation_params='{"type": "SCALE_OUT", "aspect_id": "SP1"}',
|
||||
error_point=7,
|
||||
id=constants.UUID,
|
||||
created_at=datetime.datetime(2000, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC))
|
||||
|
||||
|
||||
def vnflcm_rollback_ope():
|
||||
return objects.VnfLcmOpOcc(
|
||||
state_entered_time=datetime.datetime(2000, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC),
|
||||
start_time=datetime.datetime(2000, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC),
|
||||
vnf_instance_id=uuidsentinel.vnf_instance_id,
|
||||
operation='HEAL',
|
||||
operation_state='FAILED_TEMP',
|
||||
is_automatic_invocation=False,
|
||||
operation_params='{}',
|
||||
error_point=7,
|
||||
id=constants.UUID,
|
||||
created_at=datetime.datetime(2000, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC))
|
||||
|
||||
|
||||
def vnflcm_rollback_scale_in():
|
||||
return objects.VnfLcmOpOcc(
|
||||
state_entered_time=datetime.datetime(2000, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC),
|
||||
start_time=datetime.datetime(2000, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC),
|
||||
vnf_instance_id=uuidsentinel.vnf_instance_id,
|
||||
operation='SCALE',
|
||||
operation_state='FAILED_TEMP',
|
||||
is_automatic_invocation=False,
|
||||
operation_params='{"type": "SCALE_IN", "aspect_id": "SP1"}',
|
||||
error_point=7,
|
||||
id=constants.UUID,
|
||||
created_at=datetime.datetime(2000, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC))
|
||||
|
||||
|
||||
def vnf_rollback():
|
||||
return tacker.db.vnfm.vnfm_db.VNF(id=constants.UUID,
|
||||
vnfd_id=uuidsentinel.vnfd_id,
|
||||
name='test',
|
||||
status='ERROR',
|
||||
vim_id=uuidsentinel.vim_id)
|
||||
|
||||
|
||||
def vnf_dict():
|
||||
heat_temp = 'heat_template_version: ' + \
|
||||
'2013-05-23\ndescription: \'VNF Descriptor (TEST)' + \
|
||||
'\n\n \'\nparameters:\n current_num:\n type: ' + \
|
||||
'number\n nfv:\n type: json\nresources:\n ' + \
|
||||
'SP1_scale_out:\n type: OS::Heat::ScalingPolicy\n' + \
|
||||
' properties:\n auto_scaling_group_id: ' + \
|
||||
'{get_resource: SP1_group}\n adjustment_type: ' + \
|
||||
'change_in_capacity\n scaling_adjustment: 1\n ' + \
|
||||
'SP1_group:\n type: OS::Heat::AutoScalingGroup\n ' + \
|
||||
'properties:\n min_size: 0\n desired_capacity:' + \
|
||||
' {get_param: current_num}\n resource:\n ' + \
|
||||
'type: SP1_res.yaml\n properties:\n nfv:' + \
|
||||
' {get_param: nfv}\n max_size: 3\n SP1_scale_in:\n' + \
|
||||
' type: OS::Heat::ScalingPolicy\n properties:\n' + \
|
||||
' auto_scaling_group_id: {get_resource: SP1_group}\n' + \
|
||||
' adjustment_type: change_in_capacity\n ' + \
|
||||
'scaling_adjustment: -1\noutputs: {}\n'
|
||||
scale_g = '{\"scaleGroupDict\": { \"SP1\": { \"vdu\":' + \
|
||||
' [\"VDU1\"], \"num\": 1, \"maxLevel\": 3, \"initialNum\":' + \
|
||||
' 0, \"initialLevel\": 0, \"default\": 0 }}}'
|
||||
vnfd = 'tosca_definitions_version: ' + \
|
||||
'tosca_simple_yaml_1_2\n\ndescription: Simple deployment' + \
|
||||
' flavour for Sample VNF\n\nimports:\n' + \
|
||||
' - etsi_nfv_sol001_common_types.yaml\n' + \
|
||||
' - etsi_nfv_sol001_vnfd_types.yaml\n\n' + \
|
||||
'topology_template:\n node_templates:\n' + \
|
||||
' VNF:\n type: nec.ossmano.VNF\n' + \
|
||||
' properties:\n' + \
|
||||
' flavour_description: A simple flavour\n' + \
|
||||
' interfaces:\n Vnflcm:\n' + \
|
||||
' scale_start: noop\n' + \
|
||||
' scale: scale_standard\n' + \
|
||||
' scale_end: noop\n artifacts:\n' + \
|
||||
' hot:\n' + \
|
||||
' type: tosca.artifacts.Implementation.nfv.Hot\n' + \
|
||||
' file: ../Files/scale.yaml\n hot-nest:\n' + \
|
||||
' type: tosca.artifacts.Implementation.nfv.Hot\n' + \
|
||||
' file: ../Files/SP1_res.yaml\n' + \
|
||||
' properties:\n nest: "True"\n\n' + \
|
||||
' VDU1:\n type: tosca.nodes.nfv.Vdu.Compute\n' + \
|
||||
' properties:\n name: VDU1\n' + \
|
||||
' description: VDU1 compute node\n' + \
|
||||
' vdu_profile:\n' + \
|
||||
' min_number_of_instances: 1\n' + \
|
||||
' max_number_of_instances: 3\n\n' + \
|
||||
' capabilities:\n virtual_compute:\n' + \
|
||||
' properties:\n virtual_memory:\n' + \
|
||||
' virtual_mem_size: 512 MB\n' + \
|
||||
' virtual_cpu:\n' + \
|
||||
' num_virtual_cpu: 1\n' + \
|
||||
' virtual_local_storage:\n' + \
|
||||
' - size_of_storage: 1 GB\n' + \
|
||||
' requirements:\n' + \
|
||||
' - virtual_storage: VirtualStorage\n\n' + \
|
||||
' VirtualStorage:\n' + \
|
||||
' type: tosca.nodes.nfv.Vdu.VirtualBlockStorage\n' + \
|
||||
' properties:\n virtual_block_storage_data:\n' + \
|
||||
' size_of_storage: 1 GB\n' + \
|
||||
' rdma_enabled: true\n sw_image_data:\n' + \
|
||||
' name: VirtualStorage\n' + \
|
||||
' version: \'0.4.0\'\n checksum:\n' + \
|
||||
' algorithm: sha-512\n' + \
|
||||
' hash: 6513f21e44aa3da349f248188a44bc304a3' + \
|
||||
'653a04122d8fb4535423c8e1d14cd6a153f735bb0982e2161b5b5' + \
|
||||
'186106570c17a9e58b64dd39390617cd5a350f78\n' + \
|
||||
' container_format: bare\n' + \
|
||||
' disk_format: qcow2\n' + \
|
||||
' min_disk: 2 GB\n' + \
|
||||
' min_ram: 256 MB\n' + \
|
||||
' size: 1 GB\n\n CP1:\n' + \
|
||||
' type: tosca.nodes.nfv.VduCp\n' + \
|
||||
' properties:\n layer_protocols: [ ipv4 ]\n' + \
|
||||
' order: 2\n requirements:\n' + \
|
||||
' - virtual_binding: VDU1\n' + \
|
||||
' - virtual_link: internalVL1\n\n' + \
|
||||
' internalVL1:\n' + \
|
||||
' type: tosca.nodes.nfv.VnfVirtualLink\n' + \
|
||||
' properties:\n connectivity_type:\n' + \
|
||||
' layer_protocols: [ ipv4 ]\n' + \
|
||||
' description: Internal Virtual link in the VNF\n' + \
|
||||
' vl_profile:\n' + \
|
||||
' max_bitrate_requirements:\n' + \
|
||||
' root: 1048576\n' + \
|
||||
' leaf: 1048576\n' + \
|
||||
' min_bitrate_requirements:\n' + \
|
||||
' root: 1048576\n leaf: 1048576\n' + \
|
||||
' virtual_link_protocol_data:\n' + \
|
||||
' - associated_layer_protocol: ipv4\n' + \
|
||||
' l3_protocol_data:\n' + \
|
||||
' ip_version: ipv4\n' + \
|
||||
' cidr: 33.33.0.0/24\n\n policies:\n' + \
|
||||
' - scaling_aspects:\n' + \
|
||||
' type: tosca.policies.nfv.ScalingAspects\n' + \
|
||||
' properties:\n aspects:\n' + \
|
||||
' SP1:\n name: SP1_aspect\n' + \
|
||||
' description: SP1 scaling aspect\n' + \
|
||||
' max_scale_level: 2\n' + \
|
||||
' step_deltas:\n' + \
|
||||
' - delta_1\n\n' + \
|
||||
' - VDU1_initial_delta:\n' + \
|
||||
' type: tosca.policies.nfv.VduInitialDelta\n' + \
|
||||
' properties:\n initial_delta:\n' + \
|
||||
' number_of_instances: 0\n' + \
|
||||
' targets: [ VDU1 ]\n\n' + \
|
||||
' - VDU1_scaling_aspect_deltas:\n' + \
|
||||
' type: tosca.policies.nfv.VduScalingAspectDeltas\n' + \
|
||||
' properties:\n aspect: SP1\n' + \
|
||||
' deltas:\n delta_1:\n' + \
|
||||
' number_of_instances: 1\n' + \
|
||||
' targets: [ VDU1 ]\n\n' + \
|
||||
' - instantiation_levels:\n' + \
|
||||
' type: tosca.policies.nfv.InstantiationLevels\n' + \
|
||||
' properties:\n levels:\n' + \
|
||||
' instantiation_level_1:\n' + \
|
||||
' description: Smallest size\n' + \
|
||||
' scale_info:\n SP1:\n' + \
|
||||
' scale_level: 0\n' + \
|
||||
' instantiation_level_2:\n' + \
|
||||
' description: Largest size\n' + \
|
||||
' scale_info:\n SP1:\n' + \
|
||||
' scale_level: 3\n' + \
|
||||
' default_level: instantiation_level_1\n\n' + \
|
||||
' - VDU1_instantiation_levels:\n' + \
|
||||
' type: tosca.policies.nfv.VduInstantiationLevels\n' + \
|
||||
' properties:\n levels:\n' + \
|
||||
' instantiation_level_1:\n' + \
|
||||
' number_of_instances: 0\n' + \
|
||||
' instantiation_level_2:\n' + \
|
||||
' number_of_instances: 3\n' + \
|
||||
' targets: [ VDU1 ]\n'
|
||||
vnf_dict = {
|
||||
'attributes': {
|
||||
'heat_template': heat_temp,
|
||||
'scale_group': scale_g
|
||||
},
|
||||
'status': 'ERROR',
|
||||
'vnfd_id': '576acf48-b9df-491d-a57c-342de660ec78',
|
||||
'tenant_id': '13d2ca8de70d48b2a2e0dbac2c327c0b',
|
||||
'vim_id': '3f41faa7-5630-47d2-9d4a-1216953c8887',
|
||||
'instance_id': 'd1121d3c-368b-4ac2-b39d-835aa3e4ccd8',
|
||||
'placement_attr': {'vim_name': 'openstack-vim'},
|
||||
'id': 'a27fc58e-66ae-4031-bba4-efede318c60b',
|
||||
'name': 'vnf_create_1',
|
||||
'vnfd': {
|
||||
'attributes': {
|
||||
'vnfd_simple': vnfd
|
||||
}
|
||||
}
|
||||
}
|
||||
return vnf_dict
|
||||
|
||||
|
||||
class InjectContext(wsgi.Middleware):
|
||||
"""Add a 'tacker.context' to WSGI environ."""
|
||||
|
||||
|
@ -2535,7 +2535,7 @@ class TestController(base.TestCase):
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.ScaleVnfRequest, "obj_from_primitive")
|
||||
@mock.patch.object(tacker.db.vnfm.vnfm_db.VNFMPluginDb, "get_vnf")
|
||||
@mock.patch.object(controller.VnfLcmController, "_get_rollback_vnf")
|
||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||
@mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "send_notification")
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "create")
|
||||
@ -2594,3 +2594,223 @@ class TestController(base.TestCase):
|
||||
'STARTING')
|
||||
self.assertEqual(mock_send_notification.call_args[0][1].get(
|
||||
'isAutomaticInvocation'), 'False')
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "get_by_id")
|
||||
@mock.patch.object(controller.VnfLcmController, "_get_rollback_vnf")
|
||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||
@mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "rollback")
|
||||
def test_rollback(
|
||||
self,
|
||||
mock_rollback,
|
||||
mock_vnf_instance,
|
||||
mock_get_vnf,
|
||||
mock_lcm_by_id,
|
||||
mock_get_service_plugins):
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_lcm_op_occs/%s/rollback' % uuidsentinel.vnf_instance_id)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback()
|
||||
mock_lcm_by_id.return_value = vnf_lcm_op_occs
|
||||
vnf_obj = fakes.vnf_rollback()
|
||||
mock_get_vnf.return_value = vnf_obj
|
||||
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
task_state=fields.VnfInstanceTaskState.ERROR)
|
||||
mock_vnf_instance.return_value = vnf_instance
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(http_client.ACCEPTED, resp.status_code)
|
||||
mock_rollback.assert_called_once()
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "get_by_id")
|
||||
@mock.patch.object(controller.VnfLcmController, "_get_rollback_vnf")
|
||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||
@mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "rollback")
|
||||
def test_rollback_2(
|
||||
self,
|
||||
mock_rollback,
|
||||
mock_vnf_instance,
|
||||
mock_get_vnf,
|
||||
mock_lcm_by_id,
|
||||
mock_get_service_plugins):
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_lcm_op_occs/%s/rollback' % uuidsentinel.vnf_instance_id)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback_insta()
|
||||
mock_lcm_by_id.return_value = vnf_lcm_op_occs
|
||||
vnf_obj = fakes.vnf_rollback()
|
||||
mock_get_vnf.return_value = vnf_obj
|
||||
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
task_state=fields.VnfInstanceTaskState.ERROR)
|
||||
mock_vnf_instance.return_value = vnf_instance
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(http_client.ACCEPTED, resp.status_code)
|
||||
mock_rollback.assert_called_once()
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
def test_rollback_vnf_lcm_op_occs_access_error(self,
|
||||
mock_get_service_plugins):
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_lcm_op_occs/%s/rollback' % uuidsentinel.vnf_instance_id)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(500, resp.status_code)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "get_by_id")
|
||||
def test_rollback_lcm_not_found(self, mock_lcm_by_id,
|
||||
mock_get_service_plugins):
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_lcm_op_occs/%s/rollback' % constants.INVALID_UUID)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
|
||||
mock_lcm_by_id.side_effect = exceptions.NotFound(resource='table',
|
||||
name='vnf_lcm_op_occs')
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(http_client.NOT_FOUND, resp.status_code)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "get_by_id")
|
||||
def test_rollback_not_failed_temp(self, mock_lcm_by_id,
|
||||
mock_get_service_plugins):
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_lcm_op_occs/%s/rollback' % uuidsentinel.vnf_instance_id)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback_active()
|
||||
mock_lcm_by_id.return_value = vnf_lcm_op_occs
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(http_client.CONFLICT, resp.status_code)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "get_by_id",)
|
||||
def test_rollback_not_ope(self, mock_lcm_by_id,
|
||||
mock_get_service_plugins):
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_lcm_op_occs/%s/rollback' % uuidsentinel.vnf_instance_id)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback_ope()
|
||||
mock_lcm_by_id.return_value = vnf_lcm_op_occs
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(http_client.CONFLICT, resp.status_code)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "get_by_id")
|
||||
def test_rollback_not_scale_in(self, mock_lcm_by_id,
|
||||
mock_get_service_plugins):
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_lcm_op_occs/%s/rollback' % uuidsentinel.vnf_instance_id)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback_scale_in()
|
||||
mock_lcm_by_id.return_value = vnf_lcm_op_occs
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(http_client.CONFLICT, resp.status_code)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(controller.VnfLcmController, "_get_rollback_vnf")
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "get_by_id")
|
||||
def test_rollback_vnf_error(self, mock_lcm_by_id, mock_get_vnf,
|
||||
mock_get_service_plugins):
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_lcm_op_occs/%s/rollback' % uuidsentinel.vnf_instance_id)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback_insta()
|
||||
mock_lcm_by_id.return_value = vnf_lcm_op_occs
|
||||
mock_get_vnf.side_effect = Exception("error")
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(500, resp.status_code)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "get_by_id")
|
||||
@mock.patch.object(controller.VnfLcmController, "_get_rollback_vnf")
|
||||
def test_rollback_vnf_not_found(self, mock_get_vnf, mock_lcm_by_id,
|
||||
mock_get_service_plugins):
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_lcm_op_occs/%s/rollback' % uuidsentinel.vnf_instance_id)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback_insta()
|
||||
mock_lcm_by_id.return_value = vnf_lcm_op_occs
|
||||
mock_get_vnf.side_effect = vnfm.VNFNotFound(
|
||||
vnf_id=uuidsentinel.vnf_instance_id)
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(http_client.NOT_FOUND, resp.status_code)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "get_by_id")
|
||||
@mock.patch.object(controller.VnfLcmController, "_get_rollback_vnf")
|
||||
def test_rollback_vnf_instance_error(self, mock_get_vnf, mock_lcm_by_id,
|
||||
mock_get_service_plugins):
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_lcm_op_occs/%s/rollback' % uuidsentinel.vnf_instance_id)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback_insta()
|
||||
mock_lcm_by_id.return_value = vnf_lcm_op_occs
|
||||
vnf_obj = fakes.vnf_rollback()
|
||||
mock_get_vnf.return_value = vnf_obj
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(500, resp.status_code)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "get_by_id")
|
||||
@mock.patch.object(controller.VnfLcmController, "_get_rollback_vnf")
|
||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||
def test_rollback_vnf_instance_not_found(
|
||||
self, mock_vnf_instance, mock_get_vnf, mock_lcm_by_id,
|
||||
mock_get_service_plugins):
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_lcm_op_occs/%s/rollback' % uuidsentinel.vnf_instance_id)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback_insta()
|
||||
mock_lcm_by_id.return_value = vnf_lcm_op_occs
|
||||
vnf_obj = fakes.vnf_rollback()
|
||||
mock_get_vnf.return_value = vnf_obj
|
||||
|
||||
mock_vnf_instance.side_effect = vnfm.VNFNotFound(
|
||||
vnf_id=uuidsentinel.vnf_instance_id)
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(http_client.NOT_FOUND, resp.status_code)
|
||||
|
@ -20,12 +20,16 @@ from unittest import mock
|
||||
import yaml
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from heatclient.v1 import resources
|
||||
from tacker.common import driver_manager
|
||||
from tacker.common import exceptions
|
||||
from tacker.common import utils
|
||||
from tacker.conductor.conductorrpc.vnf_lcm_rpc import VNFLcmRPCAPI
|
||||
from tacker import context
|
||||
from tacker.db.common_services import common_services_db_plugin
|
||||
from tacker.manager import TackerManager
|
||||
from tacker import objects
|
||||
from tacker.objects import fields
|
||||
@ -36,6 +40,9 @@ from tacker.tests.unit.vnflcm import fakes
|
||||
from tacker.tests import utils as test_utils
|
||||
from tacker.tests import uuidsentinel
|
||||
from tacker.vnflcm import vnflcm_driver
|
||||
from tacker.vnfm.infra_drivers.openstack import heat_client
|
||||
from tacker.vnfm.infra_drivers.openstack import openstack as opn
|
||||
from tacker.vnfm import plugin
|
||||
from tacker.vnfm import vim_client
|
||||
|
||||
|
||||
@ -125,6 +132,8 @@ class FakeDriverManager(mock.Mock):
|
||||
if self.fail_method_name and \
|
||||
self.fail_method_name == 'post_heal_vnf':
|
||||
raise InfraDriverException("post_heal_vnf failed")
|
||||
if 'get_rollback_ids' in args:
|
||||
return [], [], ""
|
||||
|
||||
|
||||
class FakeVimClient(mock.Mock):
|
||||
@ -308,7 +317,8 @@ class TestVnflcmDriver(db_base.SqlTestCase):
|
||||
self.assertEqual(expected_error % vnf_instance_obj.id, str(error))
|
||||
self.assertEqual("NOT_INSTANTIATED",
|
||||
vnf_instance_obj.instantiation_state)
|
||||
self.assertEqual(2, mock_vnf_instance_save.call_count)
|
||||
# 2->1 reason: rollback_vnf_instantiated_resources deleted
|
||||
self.assertEqual(1, mock_vnf_instance_save.call_count)
|
||||
self.assertEqual(2, self._vnf_manager.invoke.call_count)
|
||||
mock_final_vnf_dict.assert_called_once()
|
||||
|
||||
@ -356,9 +366,11 @@ class TestVnflcmDriver(db_base.SqlTestCase):
|
||||
self.assertEqual(expected_error % vnf_instance_obj.id, str(error))
|
||||
self.assertEqual("NOT_INSTANTIATED",
|
||||
vnf_instance_obj.instantiation_state)
|
||||
self.assertEqual(3, mock_vnf_instance_save.call_count)
|
||||
self.assertEqual(5, self._vnf_manager.invoke.call_count)
|
||||
mock_final_vnf_dict.assert_called_once()
|
||||
# 3->1 reason: rollback_vnf_instantiated_resources deleted
|
||||
self.assertEqual(1, mock_vnf_instance_save.call_count)
|
||||
# 5->3 reason: rollback_vnf_instantiated_resources deleted
|
||||
self.assertEqual(3, self._vnf_manager.invoke.call_count)
|
||||
|
||||
shutil.rmtree(fake_csar)
|
||||
|
||||
@mock.patch('tacker.vnflcm.utils._make_final_vnf_dict')
|
||||
@ -904,3 +916,765 @@ class TestVnflcmDriver(db_base.SqlTestCase):
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
driver.scale(self.context, vnf_info, scale_vnf_request,
|
||||
vim_connection_info, scale_name_list, grp_id)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "save")
|
||||
@mock.patch.object(VNFLcmRPCAPI, "send_notification")
|
||||
@mock.patch.object(objects.VnfInstance, "save")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback_pre")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback")
|
||||
def test_rollback_vnf_7(
|
||||
self,
|
||||
mock_update,
|
||||
mock_up,
|
||||
mock_insta_save,
|
||||
mock_notification,
|
||||
mock_lcm_save,
|
||||
mock_get_service_plugins):
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
|
||||
vnf_instance.instantiated_vnf_info.instance_id =\
|
||||
uuidsentinel.instance_id
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback_insta()
|
||||
vnf_info = fakes.vnf_dict()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
operation_params = jsonutils.loads(vnf_lcm_op_occs.operation_params)
|
||||
|
||||
self._mock_vnf_manager()
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
driver.rollback_vnf(
|
||||
self.context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params)
|
||||
self.assertEqual(1, mock_lcm_save.call_count)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "save")
|
||||
@mock.patch.object(VNFLcmRPCAPI, "send_notification")
|
||||
@mock.patch.object(objects.VnfInstance, "save")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback_pre")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback")
|
||||
def test_rollback_vnf_6(
|
||||
self,
|
||||
mock_update,
|
||||
mock_up,
|
||||
mock_insta_save,
|
||||
mock_notification,
|
||||
mock_lcm_save,
|
||||
mock_get_service_plugins):
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
|
||||
vnf_instance.instantiated_vnf_info.instance_id =\
|
||||
uuidsentinel.instance_id
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback_insta(error_point=6)
|
||||
vnf_info = fakes.vnf_dict()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
operation_params = jsonutils.loads(vnf_lcm_op_occs.operation_params)
|
||||
|
||||
self._mock_vnf_manager()
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
driver.rollback_vnf(
|
||||
self.context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params)
|
||||
self.assertEqual(1, mock_lcm_save.call_count)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "save")
|
||||
@mock.patch.object(VNFLcmRPCAPI, "send_notification")
|
||||
@mock.patch.object(objects.VnfInstance, "save")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback_pre")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback")
|
||||
def test_rollback_vnf_5(
|
||||
self,
|
||||
mock_update,
|
||||
mock_up,
|
||||
mock_insta_save,
|
||||
mock_notification,
|
||||
mock_lcm_save,
|
||||
mock_get_service_plugins):
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
|
||||
vnf_instance.instantiated_vnf_info.instance_id =\
|
||||
uuidsentinel.instance_id
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback_insta(error_point=5)
|
||||
vnf_info = fakes.vnf_dict()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
operation_params = jsonutils.loads(vnf_lcm_op_occs.operation_params)
|
||||
|
||||
self._mock_vnf_manager()
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
driver.rollback_vnf(
|
||||
self.context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params)
|
||||
self.assertEqual(1, mock_lcm_save.call_count)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "save")
|
||||
@mock.patch.object(VNFLcmRPCAPI, "send_notification")
|
||||
@mock.patch.object(objects.VnfInstance, "save")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback_pre")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback")
|
||||
def test_rollback_vnf_4(
|
||||
self,
|
||||
mock_update,
|
||||
mock_up,
|
||||
mock_insta_save,
|
||||
mock_notification,
|
||||
mock_lcm_save,
|
||||
mock_get_service_plugins):
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
|
||||
vnf_instance.instantiated_vnf_info.instance_id =\
|
||||
uuidsentinel.instance_id
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback_insta(error_point=4)
|
||||
vnf_info = fakes.vnf_dict()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
operation_params = jsonutils.loads(vnf_lcm_op_occs.operation_params)
|
||||
|
||||
self._mock_vnf_manager()
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
driver.rollback_vnf(
|
||||
self.context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params)
|
||||
self.assertEqual(1, mock_lcm_save.call_count)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "save")
|
||||
@mock.patch.object(VNFLcmRPCAPI, "send_notification")
|
||||
@mock.patch.object(objects.VnfInstance, "save")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback_pre")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback")
|
||||
def test_rollback_vnf_3(
|
||||
self,
|
||||
mock_update,
|
||||
mock_up,
|
||||
mock_insta_save,
|
||||
mock_notification,
|
||||
mock_lcm_save,
|
||||
mock_get_service_plugins):
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
|
||||
vnf_instance.instantiated_vnf_info.instance_id =\
|
||||
uuidsentinel.instance_id
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback_insta(error_point=3)
|
||||
vnf_info = fakes.vnf_dict()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
operation_params = jsonutils.loads(vnf_lcm_op_occs.operation_params)
|
||||
|
||||
self._mock_vnf_manager()
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
driver.rollback_vnf(
|
||||
self.context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params)
|
||||
self.assertEqual(1, mock_lcm_save.call_count)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "save")
|
||||
@mock.patch.object(VNFLcmRPCAPI, "send_notification")
|
||||
@mock.patch.object(objects.VnfInstance, "save")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback_pre")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback")
|
||||
def test_rollback_vnf_scale(
|
||||
self,
|
||||
mock_update,
|
||||
mock_up,
|
||||
mock_insta_save,
|
||||
mock_notification,
|
||||
mock_lcm_save,
|
||||
mock_get_service_plugins):
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
|
||||
vnf_instance.instantiated_vnf_info.instance_id =\
|
||||
uuidsentinel.instance_id
|
||||
vnf_instance.instantiated_vnf_info.scale_status = []
|
||||
vnf_instance.instantiated_vnf_info.scale_status.append(
|
||||
objects.ScaleInfo(aspect_id='SP1', scale_level=0))
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback()
|
||||
vnf_info = fakes.vnf_dict()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
operation_params = jsonutils.loads(vnf_lcm_op_occs.operation_params)
|
||||
|
||||
self._mock_vnf_manager()
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
|
||||
driver.rollback_vnf(
|
||||
self.context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params)
|
||||
self.assertEqual(1, mock_lcm_save.call_count)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "save")
|
||||
@mock.patch.object(VNFLcmRPCAPI, "send_notification")
|
||||
@mock.patch.object(objects.VnfInstance, "save")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback_pre")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback")
|
||||
def test_rollback_vnf_scale_6(
|
||||
self,
|
||||
mock_update,
|
||||
mock_up,
|
||||
mock_insta_save,
|
||||
mock_notification,
|
||||
mock_lcm_save,
|
||||
mock_get_service_plugins):
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
|
||||
vnf_instance.instantiated_vnf_info.instance_id =\
|
||||
uuidsentinel.instance_id
|
||||
vnf_instance.instantiated_vnf_info.scale_status = []
|
||||
vnf_instance.instantiated_vnf_info.scale_status.append(
|
||||
objects.ScaleInfo(aspect_id='SP1', scale_level=0))
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback(error_point=6)
|
||||
vnf_info = fakes.vnf_dict()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
operation_params = jsonutils.loads(vnf_lcm_op_occs.operation_params)
|
||||
|
||||
self._mock_vnf_manager()
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
|
||||
driver.rollback_vnf(
|
||||
self.context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params)
|
||||
self.assertEqual(1, mock_lcm_save.call_count)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "save")
|
||||
@mock.patch.object(VNFLcmRPCAPI, "send_notification")
|
||||
@mock.patch.object(objects.VnfInstance, "save")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback_pre")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback")
|
||||
def test_rollback_vnf_scale_5(
|
||||
self,
|
||||
mock_update,
|
||||
mock_up,
|
||||
mock_insta_save,
|
||||
mock_notification,
|
||||
mock_lcm_save,
|
||||
mock_get_service_plugins):
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
|
||||
vnf_instance.instantiated_vnf_info.instance_id =\
|
||||
uuidsentinel.instance_id
|
||||
vnf_instance.instantiated_vnf_info.scale_status = []
|
||||
vnf_instance.instantiated_vnf_info.scale_status.append(
|
||||
objects.ScaleInfo(aspect_id='SP1', scale_level=0))
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback(error_point=5)
|
||||
vnf_info = fakes.vnf_dict()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
operation_params = jsonutils.loads(vnf_lcm_op_occs.operation_params)
|
||||
|
||||
self._mock_vnf_manager()
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
|
||||
driver.rollback_vnf(
|
||||
self.context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params)
|
||||
self.assertEqual(1, mock_lcm_save.call_count)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "save")
|
||||
@mock.patch.object(VNFLcmRPCAPI, "send_notification")
|
||||
@mock.patch.object(objects.VnfInstance, "save")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback_pre")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback")
|
||||
def test_rollback_vnf_scale_4(
|
||||
self,
|
||||
mock_update,
|
||||
mock_up,
|
||||
mock_insta_save,
|
||||
mock_notification,
|
||||
mock_lcm_save,
|
||||
mock_get_service_plugins):
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
|
||||
vnf_instance.instantiated_vnf_info.instance_id =\
|
||||
uuidsentinel.instance_id
|
||||
vnf_instance.instantiated_vnf_info.scale_status = []
|
||||
vnf_instance.instantiated_vnf_info.scale_status.append(
|
||||
objects.ScaleInfo(aspect_id='SP1', scale_level=0))
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback(error_point=4)
|
||||
vnf_info = fakes.vnf_dict()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
operation_params = jsonutils.loads(vnf_lcm_op_occs.operation_params)
|
||||
|
||||
self._mock_vnf_manager()
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
|
||||
driver.rollback_vnf(
|
||||
self.context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params)
|
||||
self.assertEqual(1, mock_lcm_save.call_count)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "save")
|
||||
@mock.patch.object(VNFLcmRPCAPI, "send_notification")
|
||||
@mock.patch.object(objects.VnfInstance, "save")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback_pre")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback")
|
||||
def test_rollback_vnf_scale_3(
|
||||
self,
|
||||
mock_update,
|
||||
mock_up,
|
||||
mock_insta_save,
|
||||
mock_notification,
|
||||
mock_lcm_save,
|
||||
mock_get_service_plugins):
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
|
||||
vnf_instance.instantiated_vnf_info.instance_id =\
|
||||
uuidsentinel.instance_id
|
||||
vnf_instance.instantiated_vnf_info.scale_status = []
|
||||
vnf_instance.instantiated_vnf_info.scale_status.append(
|
||||
objects.ScaleInfo(aspect_id='SP1', scale_level=0))
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback(error_point=3)
|
||||
vnf_info = fakes.vnf_dict()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
operation_params = jsonutils.loads(vnf_lcm_op_occs.operation_params)
|
||||
|
||||
self._mock_vnf_manager()
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
|
||||
driver.rollback_vnf(
|
||||
self.context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params)
|
||||
self.assertEqual(1, mock_lcm_save.call_count)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "save")
|
||||
def test_rollback_vnf_save_error(self, mock_lcm_save,
|
||||
mock_get_service_plugins):
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
|
||||
vnf_instance.instantiated_vnf_info.instance_id =\
|
||||
uuidsentinel.instance_id
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback_insta()
|
||||
vnf_info = fakes.vnf_dict()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
operation_params = jsonutils.loads(vnf_lcm_op_occs.operation_params)
|
||||
mock_lcm_save.side_effect = exceptions.DBAccessError()
|
||||
|
||||
self._mock_vnf_manager()
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
self.assertRaises(
|
||||
exceptions.DBAccessError,
|
||||
driver.rollback_vnf,
|
||||
self.context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "save")
|
||||
@mock.patch.object(common_services_db_plugin.CommonServicesPluginDb,
|
||||
"create_event")
|
||||
@mock.patch.object(heat_client.HeatClient, "__init__")
|
||||
@mock.patch.object(heat_client.HeatClient, "resource_get")
|
||||
@mock.patch.object(heat_client.HeatClient, "resource_get_list")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback_pre")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback")
|
||||
def test_rollback_vnf_scale_resource_error(
|
||||
self,
|
||||
mock_update,
|
||||
mock_up,
|
||||
mock_resource_get_list,
|
||||
mock_resource_get,
|
||||
mock_init,
|
||||
mock_event,
|
||||
mock_lcm_save,
|
||||
mock_get_service_plugins):
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
|
||||
vnf_instance.instantiated_vnf_info.instance_id =\
|
||||
uuidsentinel.instance_id
|
||||
vnf_instance.instantiated_vnf_info.scale_status = []
|
||||
vnf_instance.instantiated_vnf_info.scale_status.append(
|
||||
objects.ScaleInfo(aspect_id='SP1', scale_level=0))
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback()
|
||||
vnf_info = fakes.vnf_dict()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
vnf_info['scale_level'] = 0
|
||||
operation_params = jsonutils.loads(vnf_lcm_op_occs.operation_params)
|
||||
mock_init.return_value = None
|
||||
mock_resource_get.side_effect = exceptions.DBAccessError()
|
||||
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
self.assertRaises(
|
||||
exceptions.DBAccessError,
|
||||
driver.rollback_vnf,
|
||||
self.context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params)
|
||||
self.assertEqual(2, mock_lcm_save.call_count)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "save")
|
||||
@mock.patch.object(common_services_db_plugin.CommonServicesPluginDb,
|
||||
"create_event")
|
||||
@mock.patch.object(heat_client.HeatClient, "__init__")
|
||||
@mock.patch.object(heat_client.HeatClient, "resource_get")
|
||||
@mock.patch.object(heat_client.HeatClient, "resource_get_list")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback_pre")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback")
|
||||
def test_rollback_vnf_scale_resource_list_error(
|
||||
self,
|
||||
mock_update,
|
||||
mock_up,
|
||||
mock_resource_list,
|
||||
mock_resource_get,
|
||||
mock_init,
|
||||
mock_event,
|
||||
mock_lcm_save,
|
||||
mock_get_service_plugins):
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
|
||||
vnf_instance.instantiated_vnf_info.instance_id =\
|
||||
uuidsentinel.instance_id
|
||||
vnf_instance.instantiated_vnf_info.scale_status = []
|
||||
vnf_instance.instantiated_vnf_info.scale_status.append(
|
||||
objects.ScaleInfo(aspect_id='SP1', scale_level=0))
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback()
|
||||
vnf_info = fakes.vnf_dict()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
operation_params = jsonutils.loads(vnf_lcm_op_occs.operation_params)
|
||||
mock_init.return_value = None
|
||||
resource1 = resources.Resource(None, {
|
||||
'resource_name': 'SP1_group',
|
||||
'creation_time': '2020-01-01T00:00:00',
|
||||
'resource_status': 'CREATE_COMPLETE',
|
||||
'physical_resource_id': '30435eb8-1472-4cbc-abbe-00b395165ce7',
|
||||
'id': '1111'
|
||||
})
|
||||
mock_resource_get.return_value = resource1
|
||||
mock_resource_list.side_effect = exceptions.DBAccessError()
|
||||
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
self.assertRaises(
|
||||
exceptions.DBAccessError,
|
||||
driver.rollback_vnf,
|
||||
self.context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params)
|
||||
self.assertEqual(2, mock_lcm_save.call_count)
|
||||
self.assertEqual(2, mock_resource_list.call_count)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "save")
|
||||
@mock.patch.object(common_services_db_plugin.CommonServicesPluginDb,
|
||||
"create_event")
|
||||
@mock.patch.object(heat_client.HeatClient, "__init__")
|
||||
@mock.patch.object(plugin.VNFMMgmtMixin, "mgmt_call")
|
||||
@mock.patch.object(opn.OpenStack, "delete")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback_pre")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback")
|
||||
def test_rollback_vnf_delete_error(
|
||||
self,
|
||||
mock_update,
|
||||
mock_up,
|
||||
mock_delete,
|
||||
mock_mgmt,
|
||||
mock_init,
|
||||
mock_event,
|
||||
mock_lcm_save,
|
||||
mock_get_service_plugins):
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
|
||||
vnf_instance.instantiated_vnf_info.instance_id =\
|
||||
uuidsentinel.instance_id
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback_insta()
|
||||
vnf_info = fakes.vnf_dict()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
operation_params = jsonutils.loads(vnf_lcm_op_occs.operation_params)
|
||||
mock_init.return_value = None
|
||||
mock_delete.side_effect = exceptions.DBAccessError()
|
||||
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
self.assertRaises(
|
||||
exceptions.DBAccessError,
|
||||
driver.rollback_vnf,
|
||||
self.context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params)
|
||||
self.assertEqual(2, mock_lcm_save.call_count)
|
||||
self.assertEqual(1, mock_delete.call_count)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "save")
|
||||
@mock.patch.object(common_services_db_plugin.CommonServicesPluginDb,
|
||||
"create_event")
|
||||
@mock.patch.object(heat_client.HeatClient, "__init__")
|
||||
@mock.patch.object(plugin.VNFMMgmtMixin, "mgmt_call")
|
||||
@mock.patch.object(opn.OpenStack, "delete")
|
||||
@mock.patch.object(opn.OpenStack, "delete_wait")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback_pre")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback")
|
||||
def test_rollback_vnf_delete_wait_error(
|
||||
self,
|
||||
mock_update,
|
||||
mock_up,
|
||||
mock_delete_wait,
|
||||
mock_delete,
|
||||
mock_mgmt,
|
||||
mock_init,
|
||||
mock_event,
|
||||
mock_lcm_save,
|
||||
mock_get_service_plugins):
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
|
||||
vnf_instance.instantiated_vnf_info.instance_id =\
|
||||
uuidsentinel.instance_id
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback_insta()
|
||||
vnf_info = fakes.vnf_dict()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
operation_params = jsonutils.loads(vnf_lcm_op_occs.operation_params)
|
||||
mock_init.return_value = None
|
||||
mock_delete_wait.side_effect = exceptions.DBAccessError()
|
||||
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
self.assertRaises(
|
||||
exceptions.DBAccessError,
|
||||
driver.rollback_vnf,
|
||||
self.context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params)
|
||||
self.assertEqual(2, mock_lcm_save.call_count)
|
||||
self.assertEqual(1, mock_delete.call_count)
|
||||
self.assertEqual(1, mock_delete_wait.call_count)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "save")
|
||||
@mock.patch.object(common_services_db_plugin.CommonServicesPluginDb,
|
||||
"create_event")
|
||||
@mock.patch.object(heat_client.HeatClient, "__init__")
|
||||
@mock.patch.object(heat_client.HeatClient, "resource_get")
|
||||
@mock.patch.object(heat_client.HeatClient, "resource_get_list")
|
||||
@mock.patch.object(opn.OpenStack, "get_rollback_ids")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_rollback_mgmt_call")
|
||||
@mock.patch.object(opn.OpenStack, "scale_in_reverse")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback_pre")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback")
|
||||
def test_rollback_vnf_scale_update_error(
|
||||
self,
|
||||
mock_update,
|
||||
mock_up,
|
||||
mock_scale,
|
||||
mock_mgmt,
|
||||
mock_resource_get,
|
||||
mock_resource_get_list,
|
||||
mock_resource,
|
||||
mock_init,
|
||||
mock_event,
|
||||
mock_lcm_save,
|
||||
mock_get_service_plugins):
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
|
||||
vnf_instance.instantiated_vnf_info.instance_id =\
|
||||
uuidsentinel.instance_id
|
||||
vnf_instance.instantiated_vnf_info.scale_status = []
|
||||
vnf_instance.instantiated_vnf_info.scale_status.append(
|
||||
objects.ScaleInfo(aspect_id='SP1', scale_level=0))
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback()
|
||||
vnf_info = fakes.vnf_dict()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
vnf_info['scale_level'] = 0
|
||||
operation_params = jsonutils.loads(vnf_lcm_op_occs.operation_params)
|
||||
mock_init.return_value = None
|
||||
mock_resource_get.return_value = (
|
||||
['342bd357-7c4a-438c-9b5b-1f56702137d8'],
|
||||
['VDU1'],
|
||||
'49c1cf71-abd4-4fb1-afb3-5f63f3b04246')
|
||||
|
||||
mock_scale.side_effect = exceptions.DBAccessError()
|
||||
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
self.assertRaises(
|
||||
exceptions.DBAccessError,
|
||||
driver.rollback_vnf,
|
||||
self.context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params)
|
||||
self.assertEqual(2, mock_lcm_save.call_count)
|
||||
self.assertEqual(1, mock_scale.call_count)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "save")
|
||||
@mock.patch.object(common_services_db_plugin.CommonServicesPluginDb,
|
||||
"create_event")
|
||||
@mock.patch.object(heat_client.HeatClient, "__init__")
|
||||
@mock.patch.object(heat_client.HeatClient, "resource_get")
|
||||
@mock.patch.object(heat_client.HeatClient, "resource_get_list")
|
||||
@mock.patch.object(opn.OpenStack, "get_rollback_ids")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_rollback_mgmt_call")
|
||||
@mock.patch.object(opn.OpenStack, "scale_in_reverse")
|
||||
@mock.patch.object(opn.OpenStack, "scale_update_wait")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback_pre")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback")
|
||||
def test_rollback_vnf_scale_update_wait_error(
|
||||
self,
|
||||
mock_update,
|
||||
mock_up,
|
||||
mock_wait,
|
||||
mock_scale,
|
||||
mock_mgmt,
|
||||
mock_resource_get,
|
||||
mock_resource_get_list,
|
||||
mock_resource,
|
||||
mock_init,
|
||||
mock_event,
|
||||
mock_lcm_save,
|
||||
mock_get_service_plugins):
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
|
||||
vnf_instance.instantiated_vnf_info.instance_id =\
|
||||
uuidsentinel.instance_id
|
||||
vnf_instance.instantiated_vnf_info.scale_status = []
|
||||
vnf_instance.instantiated_vnf_info.scale_status.append(
|
||||
objects.ScaleInfo(aspect_id='SP1', scale_level=0))
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback()
|
||||
vnf_info = fakes.vnf_dict()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
vnf_info['scale_level'] = 0
|
||||
operation_params = jsonutils.loads(vnf_lcm_op_occs.operation_params)
|
||||
mock_init.return_value = None
|
||||
mock_resource_get.return_value = (
|
||||
['342bd357-7c4a-438c-9b5b-1f56702137d8'],
|
||||
['VDU1'],
|
||||
'49c1cf71-abd4-4fb1-afb3-5f63f3b04246')
|
||||
|
||||
mock_wait.side_effect = exceptions.DBAccessError()
|
||||
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
self.assertRaises(
|
||||
exceptions.DBAccessError,
|
||||
driver.rollback_vnf,
|
||||
self.context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params)
|
||||
self.assertEqual(2, mock_lcm_save.call_count)
|
||||
self.assertEqual(1, mock_scale.call_count)
|
||||
self.assertEqual(1, mock_wait.call_count)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "save")
|
||||
@mock.patch.object(common_services_db_plugin.CommonServicesPluginDb,
|
||||
"create_event")
|
||||
@mock.patch.object(heat_client.HeatClient, "__init__")
|
||||
@mock.patch.object(opn.OpenStack, "get_rollback_ids")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_rollback_mgmt_call")
|
||||
@mock.patch.object(opn.OpenStack, "scale_in_reverse")
|
||||
@mock.patch.object(opn.OpenStack, "scale_update_wait")
|
||||
@mock.patch.object(opn.OpenStack, "scale_resource_update")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback_pre")
|
||||
@mock.patch.object(vnflcm_driver.VnfLcmDriver, "_update_vnf_rollback")
|
||||
def test_rollback_vnf_scale_resource_get_error(
|
||||
self,
|
||||
mock_update,
|
||||
mock_up,
|
||||
mock_scale_resource,
|
||||
mock_wait,
|
||||
mock_scale,
|
||||
mock_mgmt,
|
||||
mock_resource_get,
|
||||
mock_init,
|
||||
mock_event,
|
||||
mock_lcm_save,
|
||||
mock_get_service_plugins):
|
||||
vnf_instance = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
|
||||
vnf_instance.instantiated_vnf_info.instance_id =\
|
||||
uuidsentinel.instance_id
|
||||
vnf_instance.instantiated_vnf_info.scale_status = []
|
||||
vnf_instance.instantiated_vnf_info.scale_status.append(
|
||||
objects.ScaleInfo(aspect_id='SP1', scale_level=0))
|
||||
vnf_lcm_op_occs = fakes.vnflcm_rollback()
|
||||
vnf_info = fakes.vnf_dict()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occs
|
||||
vnf_info['scale_level'] = 0
|
||||
operation_params = jsonutils.loads(vnf_lcm_op_occs.operation_params)
|
||||
mock_init.return_value = None
|
||||
mock_resource_get.return_value = (
|
||||
['342bd357-7c4a-438c-9b5b-1f56702137d8'],
|
||||
['VDU1'],
|
||||
'49c1cf71-abd4-4fb1-afb3-5f63f3b04246')
|
||||
resource1 = resources.Resource(None, {
|
||||
'resource_name': 'SP1_group',
|
||||
'creation_time': '2020-01-01T00:00:00',
|
||||
'resource_status': 'UPDATE_COMPLETE',
|
||||
'physical_resource_id': '30435eb8-1472-4cbc-abbe-00b395165ce7',
|
||||
'id': '1111'
|
||||
})
|
||||
|
||||
mock_wait.return_value = resource1
|
||||
mock_scale_resource.side_effect = exceptions.DBAccessError()
|
||||
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
self.assertRaises(
|
||||
exceptions.DBAccessError,
|
||||
driver.rollback_vnf,
|
||||
self.context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params)
|
||||
self.assertEqual(2, mock_lcm_save.call_count)
|
||||
self.assertEqual(1, mock_scale.call_count)
|
||||
self.assertEqual(1, mock_wait.call_count)
|
||||
self.assertEqual(2, mock_scale_resource.call_count)
|
||||
|
@ -35,6 +35,7 @@ from tacker.tests.common import helpers
|
||||
from tacker.tests import constants
|
||||
from tacker.tests.unit import base
|
||||
from tacker.tests.unit.db import utils
|
||||
from tacker.tests.unit.vnflcm import fakes
|
||||
from tacker.tests.unit.vnfm.infra_drivers.openstack.fixture_data import client
|
||||
from tacker.tests.unit.vnfm.infra_drivers.openstack.fixture_data import \
|
||||
fixture_data_utils as fd_utils
|
||||
@ -1950,3 +1951,97 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
scale_vnf_request=scale_vnf_request,
|
||||
region_name=None
|
||||
)
|
||||
|
||||
@mock.patch.object(hc.HeatClient, "resource_get")
|
||||
@mock.patch.object(hc.HeatClient, "resource_get_list")
|
||||
def test_get_rollback_ids(self, mock_list, mock_resource):
|
||||
resource1 = resources.Resource(None, {
|
||||
'resource_name': 'SP1_group',
|
||||
'creation_time': '2020-01-01T00:00:00',
|
||||
'resource_status': 'CREATE_COMPLETE',
|
||||
'physical_resource_id': '30435eb8-1472-4cbc-abbe-00b395165ce7',
|
||||
'id': '1111'
|
||||
})
|
||||
mock_resource.return_value = resource1
|
||||
res_list = []
|
||||
resource2 = resources.Resource(None, {
|
||||
'resource_name': 'aaaaaaaa',
|
||||
'creation_time': '2020-01-01T00:00:00',
|
||||
'resource_status': 'CREATE_COMPLETE',
|
||||
'physical_resource_id': '30435eb8-1472-4cbc-abbe-00b395165ce8',
|
||||
'id': '1111'
|
||||
})
|
||||
res_list.append(resource2)
|
||||
resource3 = resources.Resource(None, {
|
||||
'resource_name': 'bbbbbbbb',
|
||||
'creation_time': '2020-01-01T00:00:00',
|
||||
'resource_status': 'CREATE_COMPLETE',
|
||||
'physical_resource_id': '30435eb8-1472-4cbc-abbe-00b395165ce9',
|
||||
'id': '1111'
|
||||
})
|
||||
res_list.append(resource3)
|
||||
resource4 = resources.Resource(None, {
|
||||
'resource_name': 'cccccccc',
|
||||
'creation_time': '2020-01-01T00:00:01',
|
||||
'resource_status': 'CREATE_COMPLETE',
|
||||
'physical_resource_id': '30435eb8-1472-4cbc-abbe-00b395165ce0',
|
||||
'id': '1111'
|
||||
})
|
||||
res_list.append(resource4)
|
||||
mock_list.return_value = res_list
|
||||
|
||||
vnf_dict = fakes.vnf_dict()
|
||||
vnf_dict['res_num'] = 2
|
||||
|
||||
scale_id_list, scale_name_list, grp_id = \
|
||||
self.openstack.get_rollback_ids(
|
||||
None, self.context, vnf_dict, 'SP1', None, None)
|
||||
|
||||
self.assertEqual('30435eb8-1472-4cbc-abbe-00b395165ce7', grp_id)
|
||||
|
||||
@mock.patch.object(hc.HeatClient, "resource_get")
|
||||
@mock.patch.object(hc.HeatClient, "resource_get_list")
|
||||
def test_get_rollback_ids_0(self, mock_list, mock_resource):
|
||||
resource1 = resources.Resource(None, {
|
||||
'resource_name': 'SP1_group',
|
||||
'creation_time': '2020-01-01T00:00:00',
|
||||
'resource_status': 'CREATE_COMPLETE',
|
||||
'physical_resource_id': '30435eb8-1472-4cbc-abbe-00b395165ce7',
|
||||
'id': '1111'
|
||||
})
|
||||
mock_resource.return_value = resource1
|
||||
res_list = []
|
||||
resource2 = resources.Resource(None, {
|
||||
'resource_name': 'aaaaaaaa',
|
||||
'creation_time': '2020-01-01T00:00:00',
|
||||
'resource_status': 'CREATE_COMPLETE',
|
||||
'physical_resource_id': '30435eb8-1472-4cbc-abbe-00b395165ce8',
|
||||
'id': '1111'
|
||||
})
|
||||
res_list.append(resource2)
|
||||
resource3 = resources.Resource(None, {
|
||||
'resource_name': 'bbbbbbbb',
|
||||
'creation_time': '2020-01-01T00:00:00',
|
||||
'resource_status': 'CREATE_COMPLETE',
|
||||
'physical_resource_id': '30435eb8-1472-4cbc-abbe-00b395165ce9',
|
||||
'id': '1111'
|
||||
})
|
||||
res_list.append(resource3)
|
||||
resource4 = resources.Resource(None, {
|
||||
'resource_name': 'cccccccc',
|
||||
'creation_time': '2020-01-01T00:00:01',
|
||||
'resource_status': 'CREATE_COMPLETE',
|
||||
'physical_resource_id': '30435eb8-1472-4cbc-abbe-00b395165ce0',
|
||||
'id': '1111'
|
||||
})
|
||||
res_list.append(resource4)
|
||||
mock_list.return_value = res_list
|
||||
|
||||
vnf_dict = fakes.vnf_dict()
|
||||
vnf_dict['res_num'] = 0
|
||||
|
||||
scale_id_list, scale_name_list, grp_id = \
|
||||
self.openstack.get_rollback_ids(
|
||||
None, self.context, vnf_dict, 'SP1', None, None)
|
||||
|
||||
self.assertEqual('30435eb8-1472-4cbc-abbe-00b395165ce7', grp_id)
|
||||
|
@ -37,6 +37,7 @@ from tacker.plugins.common import constants
|
||||
from tacker.tests.unit.conductor import fakes
|
||||
from tacker.tests.unit.db import base as db_base
|
||||
from tacker.tests.unit.db import utils
|
||||
from tacker.tests.unit.vnflcm import fakes as vnflcm_fakes
|
||||
from tacker.vnfm import monitor
|
||||
from tacker.vnfm import plugin
|
||||
|
||||
@ -1326,3 +1327,53 @@ class TestVNFMPlugin(db_base.SqlTestCase):
|
||||
|
||||
self.vnfm_plugin.delete_placement_constraint(
|
||||
self.context, '7ddc38c3-a116-48b0-bfc1-68d7f306f467')
|
||||
|
||||
def test_update_vnf_rollback_pre_scale(self):
|
||||
vnf_info = {}
|
||||
vnf_lcm_op_occ = vnflcm_fakes.vnflcm_rollback()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occ
|
||||
vnf_info['id'] = uuidutils.generate_uuid()
|
||||
self.vnfm_plugin._update_vnf_rollback_pre(
|
||||
self.context, vnf_info)
|
||||
|
||||
def test_update_vnf_rollback_pre_insta(self):
|
||||
vnf_info = {}
|
||||
vnf_lcm_op_occ = vnflcm_fakes.vnflcm_rollback_insta()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occ
|
||||
vnf_info['id'] = uuidutils.generate_uuid()
|
||||
self.vnfm_plugin._update_vnf_rollback_pre(
|
||||
self.context, vnf_info)
|
||||
|
||||
def test_update_vnf_rollback_scale(self):
|
||||
vnf_info = {}
|
||||
vnf_lcm_op_occ = vnflcm_fakes.vnflcm_rollback()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occ
|
||||
vnf_info['id'] = uuidutils.generate_uuid()
|
||||
self.vnfm_plugin._update_vnf_rollback(
|
||||
self.context, vnf_info,
|
||||
'ERROR', 'ACTIVE')
|
||||
|
||||
def test_update_vnf_rollback_insta(self):
|
||||
vnf_info = {}
|
||||
vnf_lcm_op_occ = vnflcm_fakes.vnflcm_rollback_insta()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occ
|
||||
vnf_info['id'] = uuidutils.generate_uuid()
|
||||
self.vnfm_plugin._update_vnf_rollback(
|
||||
self.context, vnf_info,
|
||||
'ERROR', 'INACTIVE')
|
||||
|
||||
def test_update_vnf_rollback_status_err_scale(self):
|
||||
vnf_info = {}
|
||||
vnf_lcm_op_occ = vnflcm_fakes.vnflcm_rollback()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occ
|
||||
vnf_info['id'] = uuidutils.generate_uuid()
|
||||
self.vnfm_plugin.update_vnf_rollback_status_err(
|
||||
self.context, vnf_info)
|
||||
|
||||
def test_update_vnf_rollback_status_err_insta(self):
|
||||
vnf_info = {}
|
||||
vnf_lcm_op_occ = vnflcm_fakes.vnflcm_rollback_insta()
|
||||
vnf_info['vnf_lcm_op_occ'] = vnf_lcm_op_occ
|
||||
vnf_info['id'] = uuidutils.generate_uuid()
|
||||
self.vnfm_plugin.update_vnf_rollback_status_err(
|
||||
self.context, vnf_info)
|
||||
|
@ -47,52 +47,6 @@ LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
@utils.expects_func_args('vnf_instance')
|
||||
def rollback_vnf_instantiated_resources(function):
|
||||
"""Decorator to rollback resources created during vnf instantiation"""
|
||||
|
||||
def _rollback_vnf(vnflcm_driver, context, vnf_instance):
|
||||
vim_info = vnflcm_utils._get_vim(context,
|
||||
vnf_instance.vim_connection_info)
|
||||
|
||||
vim_connection_info = objects.VimConnectionInfo.obj_from_primitive(
|
||||
vim_info, context)
|
||||
|
||||
LOG.info("Rollback vnf %s", vnf_instance.id)
|
||||
try:
|
||||
vnflcm_driver._delete_vnf_instance_resources(context, vnf_instance,
|
||||
vim_connection_info)
|
||||
|
||||
if vnf_instance.instantiated_vnf_info:
|
||||
vnf_instance.instantiated_vnf_info.reinitialize()
|
||||
|
||||
vnflcm_driver._vnf_instance_update(context, vnf_instance,
|
||||
vim_connection_info=[], task_state=None)
|
||||
|
||||
LOG.info("Vnf %s rollback completed successfully", vnf_instance.id)
|
||||
except Exception as ex:
|
||||
LOG.error("Unable to rollback vnf instance "
|
||||
"%s due to error: %s", vnf_instance.id, ex)
|
||||
|
||||
@functools.wraps(function)
|
||||
def decorated_function(self, context, *args, **kwargs):
|
||||
try:
|
||||
return function(self, context, *args, **kwargs)
|
||||
except Exception as exp:
|
||||
with excutils.save_and_reraise_exception():
|
||||
wrapped_func = safe_utils.get_wrapped_function(function)
|
||||
keyed_args = inspect.getcallargs(wrapped_func, self, context,
|
||||
*args, **kwargs)
|
||||
vnf_instance = keyed_args['vnf_instance']
|
||||
LOG.error("Failed to instantiate vnf %(id)s. Error: %(error)s",
|
||||
{"id": vnf_instance.id,
|
||||
"error": six.text_type(exp)})
|
||||
|
||||
_rollback_vnf(self, context, vnf_instance)
|
||||
|
||||
return decorated_function
|
||||
|
||||
|
||||
@utils.expects_func_args('vnf_info', 'vnf_instance', 'scale_vnf_request')
|
||||
def revert_to_error_scale(function):
|
||||
"""Decorator to revert task_state to error on failure."""
|
||||
@ -218,6 +172,116 @@ def revert_to_error_task_state(function):
|
||||
return decorated_function
|
||||
|
||||
|
||||
@utils.expects_func_args('vnf_info', 'vnf_instance', 'operation_params')
|
||||
def revert_to_error_rollback(function):
|
||||
"""Decorator to revert task_state to error on failure."""
|
||||
|
||||
@functools.wraps(function)
|
||||
def decorated_function(self, context, *args, **kwargs):
|
||||
try:
|
||||
return function(self, context, *args, **kwargs)
|
||||
except Exception as ex:
|
||||
with excutils.save_and_reraise_exception():
|
||||
wrapped_func = safe_utils.get_wrapped_function(function)
|
||||
keyed_args = inspect.getcallargs(wrapped_func, self, context,
|
||||
*args, **kwargs)
|
||||
resource_changes = None
|
||||
try:
|
||||
vnf_info = keyed_args['vnf_info']
|
||||
vnf_instance = keyed_args['vnf_instance']
|
||||
operation_params = keyed_args['operation_params']
|
||||
vim_info = vnflcm_utils._get_vim(context,
|
||||
vnf_instance.vim_connection_info)
|
||||
vim_connection_info =\
|
||||
objects.VimConnectionInfo.obj_from_primitive(
|
||||
vim_info, context)
|
||||
vnf_lcm_op_occs = vnf_info['vnf_lcm_op_occ']
|
||||
if vnf_info.get('resource_changes'):
|
||||
resource_changes = vnf_info.get('resource_changes')
|
||||
else:
|
||||
if vnf_lcm_op_occs.operation == 'SCALE':
|
||||
scale_vnf_request =\
|
||||
objects.ScaleVnfRequest.obj_from_primitive(
|
||||
operation_params, context=context)
|
||||
scale_vnf_request_copy = \
|
||||
copy.deepcopy(scale_vnf_request)
|
||||
scale_vnf_request_copy.type = 'SCALE_IN'
|
||||
resource_changes = self._scale_resource_update(
|
||||
context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
scale_vnf_request_copy,
|
||||
vim_connection_info,
|
||||
error=True)
|
||||
else:
|
||||
resource_changes = self._term_resource_update(
|
||||
context,
|
||||
vnf_info,
|
||||
vnf_instance)
|
||||
except Exception as e:
|
||||
LOG.warning(traceback.format_exc())
|
||||
LOG.warning("Failed to scale resource update "
|
||||
"instance %(id)s. Error: %(error)s",
|
||||
{"id": vnf_instance.id, "error": e})
|
||||
|
||||
try:
|
||||
self._update_vnf_rollback_status_err(context, vnf_info)
|
||||
except Exception as e:
|
||||
LOG.warning("Failed to revert scale info for event "
|
||||
"instance %(id)s. Error: %(error)s",
|
||||
{"id": vnf_instance.id, "error": e})
|
||||
try:
|
||||
self._vnf_instance_update(context, vnf_instance)
|
||||
except Exception as e:
|
||||
LOG.warning("Failed to revert instantiation info for vnf "
|
||||
"instance %(id)s. Error: %(error)s",
|
||||
{"id": vnf_instance.id, "error": e})
|
||||
problem = objects.ProblemDetails(status=500,
|
||||
detail=str(ex))
|
||||
|
||||
try:
|
||||
timestamp = datetime.utcnow()
|
||||
vnf_lcm_op_occ = vnf_info['vnf_lcm_op_occ']
|
||||
vnf_lcm_op_occ.operation_state = 'FAILED_TEMP'
|
||||
vnf_lcm_op_occ.state_entered_time = timestamp
|
||||
if resource_changes:
|
||||
vnf_lcm_op_occ.resource_changes = resource_changes
|
||||
vnf_lcm_op_occ.error = problem
|
||||
vnf_lcm_op_occ.save()
|
||||
except Exception as e:
|
||||
LOG.warning("Failed to update vnf_lcm_op_occ for vnf "
|
||||
"instance %(id)s. Error: %(error)s",
|
||||
{"id": vnf_instance.id, "error": e})
|
||||
|
||||
try:
|
||||
notification = vnf_info['notification']
|
||||
notification['notificationStatus'] = 'RESULT'
|
||||
notification['operationState'] = 'FAILED_TEMP'
|
||||
notification['error'] = problem.to_dict()
|
||||
if resource_changes:
|
||||
resource_dict = resource_changes.to_dict()
|
||||
if resource_dict.get('affected_vnfcs'):
|
||||
notification['affectedVnfcs'] = \
|
||||
jsonutils.dump_as_bytes(
|
||||
resource_dict.get('affected_vnfcs'))
|
||||
if resource_dict.get('affected_virtual_links'):
|
||||
notification['affectedVirtualLinks'] = \
|
||||
jsonutils.dump_as_bytes(
|
||||
resource_dict.get(
|
||||
'affected_virtual_links'))
|
||||
if resource_dict.get('affected_virtual_storages'):
|
||||
notification['affectedVirtualStorages'] = \
|
||||
jsonutils.dump_as_bytes(
|
||||
resource_dict.get(
|
||||
'affected_virtual_storages'))
|
||||
self.rpc_api.sendNotification(context, notification)
|
||||
except Exception as e:
|
||||
LOG.warning("Failed to revert scale info for vnf "
|
||||
"instance %(id)s. Error: %(error)s",
|
||||
{"id": vnf_instance.id, "error": e})
|
||||
return decorated_function
|
||||
|
||||
|
||||
class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
|
||||
def __init__(self):
|
||||
@ -321,7 +385,6 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
error=encodeutils.exception_to_unicode(exp))
|
||||
|
||||
@log.log
|
||||
@rollback_vnf_instantiated_resources
|
||||
def instantiate_vnf(self, context, vnf_instance, vnf_dict,
|
||||
instantiate_vnf_req):
|
||||
|
||||
@ -589,8 +652,8 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
return scale_id_list, scale_name_list, grp_id
|
||||
|
||||
def _get_node_template_for_vnf(self, vnfd_dict):
|
||||
for node_template in vnfd_dict['topology_template']['\
|
||||
node_templates'].values():
|
||||
node_tmp = vnfd_dict['topology_template']['node_templates']
|
||||
for node_template in node_tmp.values():
|
||||
LOG.debug("node_template %s", node_template)
|
||||
if not re.match('^tosca', node_template['type']):
|
||||
LOG.debug("VNF node_template %s", node_template)
|
||||
@ -1007,3 +1070,380 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
if i != scale_vnf_request.number_of_steps - 1:
|
||||
if cooldown:
|
||||
time.sleep(cooldown)
|
||||
|
||||
def _term_resource_update(self, context, vnf_info, vnf_instance,
|
||||
error=False):
|
||||
if not vnf_instance.instantiated_vnf_info:
|
||||
resource_changes = objects.ResourceChanges()
|
||||
resource_changes.affected_vnfcs = []
|
||||
resource_changes.affected_virtual_links = []
|
||||
resource_changes.affected_virtual_storages = []
|
||||
vnf_info['resource_changes'] = resource_changes
|
||||
return resource_changes
|
||||
instantiated_vnf_before = copy.deepcopy(
|
||||
vnf_instance.instantiated_vnf_info)
|
||||
vnf_instance.instantiated_vnf_info.reinitialize()
|
||||
if not error:
|
||||
vnf_instance.vim_connection_info = []
|
||||
vnf_instance.task_state = None
|
||||
LOG.debug(
|
||||
"vnf_instance.instantiated_vnf_info %s",
|
||||
vnf_instance.instantiated_vnf_info)
|
||||
affected_vnfcs = []
|
||||
affected_virtual_storages = []
|
||||
affected_virtual_links = []
|
||||
for vnfc in instantiated_vnf_before.vnfc_resource_info:
|
||||
vnfc_delete = True
|
||||
for rsc in vnf_instance.instantiated_vnf_info.vnfc_resource_info:
|
||||
if vnfc.compute_resource.resource_id == \
|
||||
rsc.compute_resource.resource_id:
|
||||
vnfc_delete = False
|
||||
break
|
||||
if vnfc_delete:
|
||||
affected_vnfc = objects.AffectedVnfc(
|
||||
id=vnfc.id,
|
||||
vdu_id=vnfc.vdu_id,
|
||||
change_type='REMOVED',
|
||||
compute_resource=vnfc.compute_resource)
|
||||
affected_vnfcs.append(affected_vnfc)
|
||||
|
||||
for st in instantiated_vnf_before.virtual_storage_resource_info:
|
||||
st_delete = True
|
||||
for rsc in \
|
||||
vnf_instance.instantiated_vnf_info.\
|
||||
virtual_storage_resource_info:
|
||||
if st.storage_resource.resource_id == \
|
||||
rsc.storage_resource.resource_id:
|
||||
st_delete = False
|
||||
break
|
||||
if st_delete:
|
||||
affected_st = objects.AffectedVirtualStorage(
|
||||
id=st.id,
|
||||
virtual_storage_desc_id=st.virtual_storage_desc_id,
|
||||
change_type='REMOVED',
|
||||
storage_resource=st.storage_resource)
|
||||
affected_virtual_storages.append(affected_st)
|
||||
|
||||
for vl in instantiated_vnf_before.vnf_virtual_link_resource_info:
|
||||
vm_delete = False
|
||||
for rsc in \
|
||||
vnf_instance.instantiated_vnf_info.\
|
||||
vnf_virtual_link_resource_info:
|
||||
if st.network_resource.resource_id == \
|
||||
rsc.network_resource.resource_id:
|
||||
vm_delete = False
|
||||
break
|
||||
if vm_delete:
|
||||
affected_vl = objects.AffectedVirtualLink(
|
||||
id=vl.id,
|
||||
vnf_virtual_link_desc_id=vl.vnf_virtual_link_desc_id,
|
||||
change_type='REMOVED',
|
||||
network_resource=vl.network_resource)
|
||||
affected_virtual_links.append(affected_vl)
|
||||
vnf_lcm_op_occs = vnf_info['vnf_lcm_op_occ']
|
||||
resource_changes = objects.ResourceChanges()
|
||||
resource_changes.affected_vnfcs = []
|
||||
resource_changes.affected_virtual_links = []
|
||||
resource_changes.affected_virtual_storages = []
|
||||
if 'resource_changes' in vnf_lcm_op_occs \
|
||||
and vnf_lcm_op_occs.resource_changes:
|
||||
if 'affected_vnfcs' in vnf_lcm_op_occs.resource_changes:
|
||||
if len(vnf_lcm_op_occs.resource_changes.affected_vnfcs) > 0:
|
||||
resource_changes.affected_vnfcs.extend(
|
||||
vnf_lcm_op_occs.resource_changes.affected_vnfcs)
|
||||
if 'affected_virtual_storages' in vnf_lcm_op_occs.resource_changes:
|
||||
if len(vnf_lcm_op_occs.resource_changes.
|
||||
affected_virtual_storages) > 0:
|
||||
resource_changes.affected_virtual_storages.extend(
|
||||
vnf_lcm_op_occs.resource_changes.
|
||||
affected_virtual_storages)
|
||||
if 'affected_virtual_links' in vnf_lcm_op_occs.resource_changes:
|
||||
if len(vnf_lcm_op_occs.resource_changes.
|
||||
affected_virtual_links) > 0:
|
||||
resource_changes.affected_virtual_links.extend(
|
||||
vnf_lcm_op_occs.resource_changes.
|
||||
affected_virtual_links)
|
||||
resource_changes.affected_vnfcs.extend(affected_vnfcs)
|
||||
resource_changes.affected_virtual_storages.extend(
|
||||
affected_virtual_storages)
|
||||
resource_changes.affected_virtual_links.extend(affected_virtual_links)
|
||||
|
||||
vnf_info['resource_changes'] = resource_changes
|
||||
return resource_changes
|
||||
|
||||
def _rollback_vnf_pre(
|
||||
self,
|
||||
context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params,
|
||||
vim_connection_info):
|
||||
vnf_lcm_op_occs = vnf_info['vnf_lcm_op_occ']
|
||||
scale_id_list = []
|
||||
scale_name_list = []
|
||||
grp_id = None
|
||||
self._update_vnf_rollback_pre(context, vnf_info)
|
||||
if vnf_lcm_op_occs.operation == 'SCALE':
|
||||
scaleGroupDict = jsonutils.loads(
|
||||
vnf_info['attributes']['scale_group'])
|
||||
cap_size = scaleGroupDict['scaleGroupDict'][operation_params
|
||||
['aspect_id']]['default']
|
||||
vnf_info['res_num'] = cap_size
|
||||
scale_vnf_request = objects.ScaleVnfRequest.obj_from_primitive(
|
||||
operation_params, context=context)
|
||||
for scale in vnf_instance.instantiated_vnf_info.scale_status:
|
||||
if scale_vnf_request.aspect_id == scale.aspect_id:
|
||||
vnf_info['after_scale_level'] = scale.scale_level
|
||||
break
|
||||
if vnf_lcm_op_occs.operation == 'SCALE' \
|
||||
and vnf_lcm_op_occs.error_point >= 4:
|
||||
scale_id_list, scale_name_list, grp_id = self._vnf_manager.invoke(
|
||||
vim_connection_info.vim_type,
|
||||
'get_rollback_ids',
|
||||
plugin=self,
|
||||
context=context,
|
||||
vnf_dict=vnf_info,
|
||||
aspect_id=operation_params['aspect_id'],
|
||||
auth_attr=vim_connection_info.access_info,
|
||||
region_name=vim_connection_info.access_info.get('region_name')
|
||||
)
|
||||
if vnf_lcm_op_occs.error_point == 7:
|
||||
if vnf_lcm_op_occs.operation == 'SCALE':
|
||||
vnfd_yaml = vnf_info['vnfd']['attributes'].\
|
||||
get('vnfd_' +
|
||||
vnf_instance.instantiated_vnf_info.flavour_id, '')
|
||||
vnfd_dict = yaml.safe_load(vnfd_yaml)
|
||||
# mgmt_driver from vnfd
|
||||
vnf_node = self._get_node_template_for_vnf(vnfd_dict)
|
||||
if vnf_node and vnf_node.get('interfaces'):
|
||||
if vnf_node['interfaces'].get('Vnflcm'):
|
||||
if vnf_node['interfaces']['Vnflcm'].get('scale_start'):
|
||||
vnf_info['vnfd']['mgmt_driver'] = \
|
||||
vnf_node['interfaces']['Vnflcm']['scale_start']
|
||||
vnf_info['action'] = 'in'
|
||||
if len(scale_id_list) != 0 and vnf_info['vnfd'].get(
|
||||
'mgmt_driver'):
|
||||
if len(scale_id_list) > 1:
|
||||
stack_value = []
|
||||
stack_value = scale_id_list
|
||||
else:
|
||||
stack_value = scale_id_list[0]
|
||||
kwargs = {
|
||||
mgmt_constants.KEY_ACTION:
|
||||
mgmt_constants.ACTION_SCALE_IN_VNF,
|
||||
mgmt_constants.KEY_KWARGS:
|
||||
{'vnf': vnf_info},
|
||||
mgmt_constants.KEY_SCALE:
|
||||
stack_value,
|
||||
}
|
||||
self._rollback_mgmt_call(context, vnf_info, kwargs)
|
||||
|
||||
else:
|
||||
vnfd_yaml = vnf_info['vnfd']['attributes'].\
|
||||
get('vnfd_' +
|
||||
vnf_instance.instantiated_vnf_info.flavour_id, '')
|
||||
vnfd_dict = yaml.safe_load(vnfd_yaml)
|
||||
# mgmt_driver from vnfd
|
||||
vnf_node = self._get_node_template_for_vnf(vnfd_dict)
|
||||
if vnf_node and vnf_node.get('interfaces'):
|
||||
if vnf_node['interfaces'].get('Vnflcm'):
|
||||
if vnf_node['interfaces']['Vnflcm'].get(
|
||||
'termination_start'):
|
||||
vnf_info['vnfd']['mgmt_driver'] = vnf_node[
|
||||
'interfaces']['Vnflcm']['termination_start']
|
||||
if len(scale_id_list) != 0 and vnf_info['vnfd'].get(
|
||||
'mgmt_driver'):
|
||||
kwargs = {
|
||||
mgmt_constants.KEY_ACTION:
|
||||
mgmt_constants.ACTION_DELETE_VNF,
|
||||
mgmt_constants.KEY_KWARGS:
|
||||
{'vnf': vnf_info}
|
||||
}
|
||||
self._rollback_mgmt_call(context, vnf_info, kwargs)
|
||||
vnf_lcm_op_occs.error_point = 6
|
||||
|
||||
return scale_name_list, grp_id
|
||||
|
||||
def _rollback_vnf(
|
||||
self,
|
||||
context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params,
|
||||
vim_connection_info,
|
||||
scale_name_list,
|
||||
grp_id):
|
||||
vnf_lcm_op_occs = vnf_info['vnf_lcm_op_occ']
|
||||
if vnf_lcm_op_occs.error_point >= 4:
|
||||
if vnf_lcm_op_occs.operation == 'SCALE':
|
||||
scale_vnf_request = objects.ScaleVnfRequest.obj_from_primitive(
|
||||
operation_params, context=context)
|
||||
self._vnf_manager.invoke(
|
||||
vim_connection_info.vim_type,
|
||||
'scale_in_reverse',
|
||||
plugin=self,
|
||||
context=context,
|
||||
auth_attr=vim_connection_info.access_info,
|
||||
vnf_info=vnf_info,
|
||||
scale_vnf_request=scale_vnf_request,
|
||||
region_name=vim_connection_info.access_info.get(
|
||||
'region_name'),
|
||||
scale_name_list=scale_name_list,
|
||||
grp_id=grp_id)
|
||||
self._vnf_manager.invoke(
|
||||
vim_connection_info.vim_type,
|
||||
'scale_update_wait',
|
||||
plugin=self,
|
||||
context=context,
|
||||
auth_attr=vim_connection_info.access_info,
|
||||
vnf_info=vnf_info,
|
||||
region_name=vim_connection_info.access_info.get(
|
||||
'region_name'))
|
||||
|
||||
else:
|
||||
instance_id = vnf_instance.instantiated_vnf_info.instance_id
|
||||
access_info = vim_connection_info.access_info
|
||||
self._vnf_manager.invoke(vim_connection_info.vim_type,
|
||||
'delete', plugin=self, context=context,
|
||||
vnf_id=instance_id, auth_attr=access_info)
|
||||
|
||||
self._vnf_manager.invoke(vim_connection_info.vim_type,
|
||||
'delete_wait', plugin=self, context=context,
|
||||
vnf_id=instance_id, auth_attr=access_info)
|
||||
|
||||
vnf_lcm_op_occs.error_point = 3
|
||||
|
||||
def _update_vnf_rollback_pre(self, context, vnf_info):
|
||||
self._vnfm_plugin._update_vnf_rollback_pre(context, vnf_info)
|
||||
|
||||
def _update_vnf_rollback(self, context, vnf_info,
|
||||
vnf_instance, vnf_lcm_op_occs):
|
||||
self._vnfm_plugin._update_vnf_rollback(context, vnf_info,
|
||||
'ERROR',
|
||||
'ACTIVE',
|
||||
vnf_instance=vnf_instance,
|
||||
vnf_lcm_op_occ=vnf_lcm_op_occs)
|
||||
|
||||
def _update_vnf_rollback_status_err(self, context, vnf_info):
|
||||
self._vnfm_plugin._update_vnf_rollback_status_err(context, vnf_info)
|
||||
|
||||
def _rollback_mgmt_call(self, context, vnf_info, kwargs):
|
||||
self._vnfm_plugin.mgmt_call(context, vnf_info, kwargs)
|
||||
|
||||
def _rollback_vnf_post(
|
||||
self,
|
||||
context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params,
|
||||
vim_connection_info):
|
||||
vnf_lcm_op_occs = vnf_info['vnf_lcm_op_occ']
|
||||
if vnf_lcm_op_occs.operation == 'SCALE':
|
||||
scale_vnf_request = objects.ScaleVnfRequest.obj_from_primitive(
|
||||
operation_params, context=context)
|
||||
scale_vnf_request_copy = copy.deepcopy(scale_vnf_request)
|
||||
scale_vnf_request_copy.type = 'SCALE_IN'
|
||||
resource_changes = self._scale_resource_update(context, vnf_info,
|
||||
vnf_instance,
|
||||
scale_vnf_request_copy,
|
||||
vim_connection_info)
|
||||
|
||||
else:
|
||||
resource_changes = self._term_resource_update(
|
||||
context, vnf_info, vnf_instance)
|
||||
|
||||
vnf_lcm_op_occs.error_point = 2
|
||||
|
||||
timestamp = datetime.utcnow()
|
||||
vnf_lcm_op_occs.operation_state = 'ROLLED_BACK'
|
||||
vnf_lcm_op_occs.state_entered_time = timestamp
|
||||
vnf_lcm_op_occs.resource_changes = resource_changes
|
||||
self._update_vnf_rollback(context, vnf_info,
|
||||
vnf_instance,
|
||||
vnf_lcm_op_occs)
|
||||
notification = vnf_info['notification']
|
||||
notification['notificationStatus'] = 'RESULT'
|
||||
notification['operationState'] = 'ROLLED_BACK'
|
||||
resource_dict = resource_changes.to_dict()
|
||||
if resource_dict.get('affected_vnfcs'):
|
||||
notification['affectedVnfcs'] = resource_dict.get('affected_vnfcs')
|
||||
if resource_dict.get('affected_virtual_links'):
|
||||
notification['affectedVirtualLinks'] = \
|
||||
resource_dict.get('affected_virtual_links')
|
||||
if resource_dict.get('affected_virtual_storages'):
|
||||
notification['affectedVirtualStorages'] = \
|
||||
resource_dict.get('affected_virtual_storages')
|
||||
self.rpc_api.send_notification(context, notification)
|
||||
|
||||
@log.log
|
||||
@revert_to_error_rollback
|
||||
def rollback_vnf(self, context, vnf_info, vnf_instance, operation_params):
|
||||
LOG.info("Request received for rollback vnf '%s'", vnf_instance.id)
|
||||
vnf_lcm_op_occs = vnf_info['vnf_lcm_op_occ']
|
||||
if vnf_lcm_op_occs.operation == 'SCALE':
|
||||
scale_vnf_request = objects.ScaleVnfRequest.obj_from_primitive(
|
||||
operation_params, context=context)
|
||||
for scale in vnf_instance.instantiated_vnf_info.scale_status:
|
||||
if scale_vnf_request.aspect_id == scale.aspect_id:
|
||||
vnf_info['after_scale_level'] = scale.scale_level
|
||||
break
|
||||
|
||||
timestamp = datetime.utcnow()
|
||||
|
||||
vnf_lcm_op_occs.operation_state = 'ROLLING_BACK'
|
||||
vnf_lcm_op_occs.state_entered_time = timestamp
|
||||
LOG.debug("vnf_lcm_op_occs %s", vnf_lcm_op_occs)
|
||||
|
||||
insta_url = CONF.vnf_lcm.endpoint_url + \
|
||||
"/vnflcm/v1/vnf_instances/" + \
|
||||
vnf_instance.id
|
||||
vnflcm_url = CONF.vnf_lcm.endpoint_url + \
|
||||
"/vnflcm/v1/vnf_lcm_op_occs/" + \
|
||||
vnf_lcm_op_occs.id
|
||||
notification = {}
|
||||
notification['notificationType'] = \
|
||||
'VnfLcmOperationOccurrenceNotification'
|
||||
notification['vnfInstanceId'] = vnf_instance.id
|
||||
notification['notificationStatus'] = 'START'
|
||||
notification['operation'] = vnf_lcm_op_occs.operation
|
||||
notification['operationState'] = 'ROLLING_BACK'
|
||||
if vnf_lcm_op_occs.operation == 'SCALE':
|
||||
notification['isAutomaticInvocation'] = \
|
||||
vnf_lcm_op_occs.is_automatic_invocation
|
||||
else:
|
||||
notification['isAutomaticInvocation'] = False
|
||||
notification['vnfLcmOpOccId'] = vnf_lcm_op_occs.id
|
||||
notification['_links'] = {}
|
||||
notification['_links']['vnfInstance'] = {}
|
||||
notification['_links']['vnfInstance']['href'] = insta_url
|
||||
notification['_links']['vnfLcmOpOcc'] = {}
|
||||
notification['_links']['vnfLcmOpOcc']['href'] = vnflcm_url
|
||||
vnf_info['notification'] = notification
|
||||
vnf_lcm_op_occs.save()
|
||||
self.rpc_api.send_notification(context, notification)
|
||||
|
||||
vim_info = vnflcm_utils._get_vim(context,
|
||||
vnf_instance.vim_connection_info)
|
||||
|
||||
vim_connection_info = objects.VimConnectionInfo.obj_from_primitive(
|
||||
vim_info, context)
|
||||
|
||||
scale_name_list, grp_id = self._rollback_vnf_pre(
|
||||
context, vnf_info, vnf_instance,
|
||||
operation_params, vim_connection_info)
|
||||
|
||||
self._rollback_vnf(
|
||||
context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params,
|
||||
vim_connection_info,
|
||||
scale_name_list,
|
||||
grp_id)
|
||||
|
||||
self._rollback_vnf_post(
|
||||
context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
operation_params,
|
||||
vim_connection_info)
|
||||
|
@ -1379,3 +1379,12 @@ class Kubernetes(abstract_driver.VnfAbstractDriver,
|
||||
vim_connection_info,
|
||||
del_list):
|
||||
pass
|
||||
|
||||
def get_rollback_ids(self,
|
||||
plugin,
|
||||
context,
|
||||
vnf_dict,
|
||||
aspect_id,
|
||||
auth_attr,
|
||||
region_name):
|
||||
pass
|
||||
|
@ -275,6 +275,7 @@ class OpenStack(abstract_driver.VnfAbstractDriver,
|
||||
for name, value in nested_hot_dict.items():
|
||||
vnf['attributes'].update({name: self._format_base_hot(value)})
|
||||
|
||||
vnf['error_point'] = 4
|
||||
# Create heat-stack with BaseHOT and parameters
|
||||
stack = self._create_stack_with_user_data(
|
||||
heatclient, vnf, base_hot_dict,
|
||||
@ -1537,7 +1538,7 @@ class OpenStack(abstract_driver.VnfAbstractDriver,
|
||||
'parameters': paramDict,
|
||||
'existing': True}
|
||||
heatclient.update(vnf_info['instance_id'], **stack_update_param)
|
||||
stack_param = jsonutils.loads(vnf_info['attributes']['stack_param'])
|
||||
stack_param = yaml.safe_load(vnf_info['attributes']['stack_param'])
|
||||
stack_param.update(paramDict)
|
||||
vnf_info['attributes'].update({'stack_param': str(paramDict)})
|
||||
|
||||
@ -1842,3 +1843,66 @@ class OpenStack(abstract_driver.VnfAbstractDriver,
|
||||
vnf_info['removeResources'] = remove_resources
|
||||
vnf_info['affinity_list'] = []
|
||||
vnf_info['placement_constraint_list'] = []
|
||||
|
||||
@log.log
|
||||
def get_rollback_ids(self, plugin, context,
|
||||
vnf_dict,
|
||||
aspect_id,
|
||||
auth_attr,
|
||||
region_name):
|
||||
heatclient = hc.HeatClient(auth_attr, region_name)
|
||||
grp = heatclient.resource_get(vnf_dict['instance_id'],
|
||||
aspect_id + '_group')
|
||||
res_list = []
|
||||
for rsc in heatclient.resource_get_list(grp.physical_resource_id):
|
||||
scale_rsc = heatclient.resource_get(grp.physical_resource_id,
|
||||
rsc.resource_name)
|
||||
if 'COMPLETE' in scale_rsc.resource_status \
|
||||
and 'INIT_COMPLETE' != scale_rsc.resource_status:
|
||||
res_list.append(scale_rsc)
|
||||
res_list = sorted(
|
||||
res_list,
|
||||
key=lambda x: (x.creation_time, x.resource_name)
|
||||
)
|
||||
LOG.debug("res_list %s", res_list)
|
||||
heat_template = vnf_dict['attributes']['heat_template']
|
||||
group_name = aspect_id + '_group'
|
||||
|
||||
heat_resource = yaml.safe_load(heat_template)
|
||||
group_temp = heat_resource['resources'][group_name]
|
||||
group_prop = group_temp['properties']
|
||||
min_size = group_prop['min_size']
|
||||
|
||||
cap_size = vnf_dict['res_num']
|
||||
|
||||
if cap_size < min_size:
|
||||
cap_size = min_size
|
||||
|
||||
reversed_res_list = res_list[:cap_size]
|
||||
LOG.debug("reversed_res_list reverse %s", reversed_res_list)
|
||||
|
||||
# List of physical_resource_id before Rollback
|
||||
before_list = []
|
||||
# List of physical_resource_ids remaining after Rollback
|
||||
after_list = []
|
||||
# List of resource_name before Rollback
|
||||
before_rs_list = []
|
||||
# List of resource_names left after Rollback
|
||||
after_rs_list = []
|
||||
for rsc in res_list:
|
||||
before_list.append(rsc.physical_resource_id)
|
||||
before_rs_list.append(rsc.resource_name)
|
||||
for rsc in reversed_res_list:
|
||||
after_list.append(rsc.physical_resource_id)
|
||||
after_rs_list.append(rsc.resource_name)
|
||||
|
||||
# Make a list of the physical_resource_id and r
|
||||
# esource_name of the VMs that will actually be deleted
|
||||
if 0 < cap_size:
|
||||
return_list = list(set(before_list) - set(after_list))
|
||||
return_rs_list = list(set(before_rs_list) - set(after_rs_list))
|
||||
else:
|
||||
return_list = before_list
|
||||
return_rs_list = before_rs_list
|
||||
|
||||
return return_list, return_rs_list, grp.physical_resource_id
|
||||
|
@ -112,3 +112,13 @@ class VnfScaleAbstractDriver(extensions.PluginInterface):
|
||||
vim_connection_info,
|
||||
del_list):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_rollback_ids(self,
|
||||
plugin,
|
||||
context,
|
||||
vnf_dict,
|
||||
aspect_id,
|
||||
auth_attr,
|
||||
region_name):
|
||||
pass
|
||||
|
Loading…
Reference in New Issue
Block a user