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
changes/22/748422/20
Aldinson Esto 2 years ago committed by Koichi Edagawa
parent ffe4c40921
commit 4543b961eb
  1. 33
      api-ref/source/v1/vnflcm.inc
  2. 84
      tacker/api/vnflcm/v1/controller.py
  3. 7
      tacker/api/vnflcm/v1/router.py
  4. 15
      tacker/conductor/conductor_server.py
  5. 13
      tacker/conductor/conductorrpc/vnf_lcm_rpc.py
  6. 84
      tacker/db/vnfm/vnfm_db.py
  7. 11
      tacker/policies/vnf_lcm.py
  8. 246
      tacker/tests/unit/vnflcm/fakes.py
  9. 222
      tacker/tests/unit/vnflcm/test_controller.py
  10. 782
      tacker/tests/unit/vnflcm/test_vnflcm_driver.py
  11. 95
      tacker/tests/unit/vnfm/infra_drivers/openstack/test_openstack_driver.py
  12. 51
      tacker/tests/unit/vnfm/test_plugin.py
  13. 538
      tacker/vnflcm/vnflcm_driver.py
  14. 9
      tacker/vnfm/infra_drivers/kubernetes/kubernetes_driver.py
  15. 66
      tacker/vnfm/infra_drivers/openstack/openstack.py
  16. 10
      tacker/vnfm/infra_drivers/scale_driver.py

@ -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