Fix Patch Individual VNF instance
In the condition when the vnf instance hasn't been instantiated, an error occurs when Patching Individual VNF instance. 1. Fix the exception caused by the NULL value of vnf's updated_at field. 2. Fix the exception happened when one of its attributes is not existed in method to_dict in Class VnfInfoModifications. 3. Fix the problem that vnfInstanceName and vnfInstanceDescription are not displayed in notification when vnfdId is included in the fields which need modified. 4. In the API reference, modify the method of modifying an "Individual VNF instance" resource from POST to PATCH. Closes-Bug: #1915100 Change-Id: Iddb5bb540b817d4fd24e2c7c12f885bd39f8662b
This commit is contained in:
parent
a98cd4eaa9
commit
a9cb385452
|
@ -616,7 +616,7 @@ Request Example
|
|||
Modify a VNF instance
|
||||
========================
|
||||
|
||||
.. rest_method:: POST /vnflcm/v1/vnf_instances/{vnfInstanceId}
|
||||
.. rest_method:: PATCH /vnflcm/v1/vnf_instances/{vnfInstanceId}
|
||||
|
||||
This method modifies an "Individual VNF instance" resource.
|
||||
|
||||
|
|
|
@ -802,7 +802,7 @@ class VnfLcmController(wsgi.Controller):
|
|||
|
||||
return self._view_builder.show_lcm_op_occs(vnf_lcm_op_occs)
|
||||
|
||||
@wsgi.response(http_client.OK)
|
||||
@wsgi.response(http_client.ACCEPTED)
|
||||
@wsgi.expected_errors((http_client.FORBIDDEN, http_client.NOT_FOUND))
|
||||
def update(self, request, id, body):
|
||||
context = request.environ['tacker.context']
|
||||
|
@ -906,7 +906,7 @@ class VnfLcmController(wsgi.Controller):
|
|||
vnf_lcm_opoccs = {
|
||||
'vnf_instance_id': id,
|
||||
'id': op_occs_uuid,
|
||||
'state_entered_time': vnf_data.get('updated_at'),
|
||||
'state_entered_time': timeutils.utcnow(),
|
||||
'operationParams': str(body)}
|
||||
|
||||
self.rpc_api.update(
|
||||
|
|
|
@ -2113,7 +2113,7 @@ class Conductor(manager.Manager):
|
|||
lcm_op_obj.operation = fields.InstanceOperation.MODIFY_INFO
|
||||
lcm_op_obj.is_automatic_invocation = 0
|
||||
lcm_op_obj.is_cancel_pending = 0
|
||||
lcm_op_obj.operationParams = vnf_lcm_opoccs.get('operationParams')
|
||||
lcm_op_obj.operation_params = vnf_lcm_opoccs.get('operationParams')
|
||||
|
||||
try:
|
||||
lcm_op_obj.create()
|
||||
|
@ -2161,7 +2161,9 @@ class Conductor(manager.Manager):
|
|||
vnfd_pkg_data)
|
||||
else:
|
||||
changed_info = objects.vnf_lcm_op_occs.VnfInfoModifications()
|
||||
if body_data.get('vnf_instance_name'):
|
||||
changed_info.vnf_instance_name = body_data.get('vnf_instance_name')
|
||||
if body_data.get('vnf_instance_description'):
|
||||
changed_info.vnf_instance_description = body_data.get(
|
||||
'vnf_instance_description')
|
||||
|
||||
|
|
|
@ -854,19 +854,24 @@ class VnfInfoModifications(base.TackerObject,
|
|||
return obj
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'vnf_instance_name': self.vnf_instance_name,
|
||||
'vnf_instance_description': self.vnf_instance_description,
|
||||
'metadata': self.metadata,
|
||||
'vim_connection_info': self.vim_connection_info,
|
||||
'vim_connection_info_delete_ids':
|
||||
self.vim_connection_info_delete_ids,
|
||||
'vnf_pkg_id': self.vnf_pkg_id,
|
||||
'vnfd_id': self.vnfd_id,
|
||||
'vnf_provider': self.vnf_provider,
|
||||
'vnf_product_name': self.vnf_product_name,
|
||||
'vnf_software_version': self.vnf_software_version,
|
||||
'vnfd_version': self.vnfd_version}
|
||||
"""For the attributes of this class, if an attribute exists and is not
|
||||
|
||||
null, it means that the attribute has been modified. This method
|
||||
|
||||
returns a dictionary containing the modified attributes.
|
||||
"""
|
||||
dct = {}
|
||||
for field in self.fields:
|
||||
if field in self and getattr(self, field):
|
||||
value = getattr(self, field)
|
||||
# Since the type of vim_connection_info is ListOfObjectsField,
|
||||
# the objects in vim_connection_info also need to be converted
|
||||
# into dictionary, otherwise an error will occur
|
||||
# when serialized.
|
||||
if field == "vim_connection_info":
|
||||
value = [vim_conn.to_dict() for vim_conn in value]
|
||||
dct[field] = value
|
||||
return dct
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
|
|
|
@ -158,8 +158,8 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
|
|||
'state_entered_time': datetime.datetime(
|
||||
1900, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC),
|
||||
'operationParams': {
|
||||
"key": "value"}}
|
||||
'operationParams': 'operationParams'
|
||||
}
|
||||
return vnf_lcm_opoccs
|
||||
|
||||
def _create_vnfd_pkg_data(self):
|
||||
|
@ -2974,6 +2974,50 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
|
|||
self.vnfd_pkg_data,
|
||||
vnfd_id)
|
||||
|
||||
@mock.patch.object(conductor_server, 'revert_update_lcm')
|
||||
@mock.patch.object(t_context.get_admin_context().session, "add")
|
||||
@mock.patch.object(objects.vnf_lcm_op_occs.VnfLcmOpOcc, "save")
|
||||
@mock.patch.object(objects.VnfInstance, "update")
|
||||
@mock.patch.object(objects.vnf_lcm_op_occs.VnfLcmOpOcc, "create")
|
||||
def test_update_lcm_without_vnf_instance_name(self, mock_create,
|
||||
mock_update, mock_save,
|
||||
mock_add, mock_revert):
|
||||
mock_create.return_value = "OK"
|
||||
mock_update.return_value = datetime.datetime(
|
||||
1900, 1, 1, 1, 1, 1, tzinfo=iso8601.UTC)
|
||||
mock_add.return_value = "OK"
|
||||
mock_save.return_value = "OK"
|
||||
vnfd_id = "2c69a161-0000-4b0f-bcf8-391f8fc76600"
|
||||
self.body_data.pop('vnf_instance_name')
|
||||
self.conductor.update(
|
||||
self.context,
|
||||
self.vnf_lcm_opoccs,
|
||||
self.body_data,
|
||||
self.vnfd_pkg_data,
|
||||
vnfd_id)
|
||||
|
||||
@mock.patch.object(conductor_server, 'revert_update_lcm')
|
||||
@mock.patch.object(t_context.get_admin_context().session, "add")
|
||||
@mock.patch.object(objects.vnf_lcm_op_occs.VnfLcmOpOcc, "save")
|
||||
@mock.patch.object(objects.VnfInstance, "update")
|
||||
@mock.patch.object(objects.vnf_lcm_op_occs.VnfLcmOpOcc, "create")
|
||||
def test_update_lcm_without_vnf_instance_description(self, mock_create,
|
||||
mock_update, mock_save,
|
||||
mock_add, mock_revert):
|
||||
mock_create.return_value = "OK"
|
||||
mock_update.return_value = datetime.datetime(
|
||||
1900, 1, 1, 1, 1, 1, tzinfo=iso8601.UTC)
|
||||
mock_add.return_value = "OK"
|
||||
mock_save.return_value = "OK"
|
||||
vnfd_id = "2c69a161-0000-4b0f-bcf8-391f8fc76600"
|
||||
self.body_data.pop('vnf_instance_description')
|
||||
self.conductor.update(
|
||||
self.context,
|
||||
self.vnf_lcm_opoccs,
|
||||
self.body_data,
|
||||
self.vnfd_pkg_data,
|
||||
vnfd_id)
|
||||
|
||||
def test_update_vim(self):
|
||||
vim_id = uuidsentinel.vim_id
|
||||
status = "REACHABLE"
|
||||
|
|
|
@ -968,9 +968,18 @@ def vnflcm_fail_check_added_params(error_point=7):
|
|||
vim_level_resource_type="OS::Neutron::Net"),
|
||||
ext_link_ports=[ext_link_port_info]
|
||||
)
|
||||
vim_connection_info = {"id": 'f8c35bd0-4d67-4436-9f11-14b8a84c92aa',
|
||||
"vim_id": 'f8c35bd0-4d67-4436-9f11-14b8a84c92aa',
|
||||
"vim_type": 'openstack',
|
||||
"access_info": {"key1": 'value1', "key2": 'value2'}}
|
||||
changed_info_values = objects.VnfInfoModifications(
|
||||
vnf_instance_name="fake_name",
|
||||
vnf_instance_description="fake_vnf_instance_description",
|
||||
metadata={'key': 'value'},
|
||||
vim_connection_info=[VimConnectionInfo(**vim_connection_info)],
|
||||
vim_connection_info_delete_ids=[
|
||||
'f8c35bd0-4d67-4436-9f11-14b8a84c92bb'],
|
||||
vnf_pkg_id='f26f181d-7891-4720-b022-b074ec1733ef',
|
||||
vnfd_id="f26f181d-7891-4720-b022-b074ec1733ef",
|
||||
vnf_provider="fake_vnf_provider",
|
||||
vnf_product_name="fake_vnf_product_name",
|
||||
|
@ -1413,10 +1422,15 @@ VNFLCMOPOCC_RESPONSE = {
|
|||
}]
|
||||
},
|
||||
'changedInfo': {
|
||||
'metadata': {},
|
||||
'vimConnectionInfo': [],
|
||||
'vimConnectionInfoDeleteIds': [],
|
||||
'vnfPkgId': None,
|
||||
'metadata': {'key': 'value'},
|
||||
'vimConnectionInfo': [
|
||||
{"id": 'f8c35bd0-4d67-4436-9f11-14b8a84c92aa',
|
||||
"vimId": 'f8c35bd0-4d67-4436-9f11-14b8a84c92aa',
|
||||
"vimType": 'openstack',
|
||||
'interfaceInfo': {},
|
||||
"accessInfo": {"key1": 'value1', "key2": 'value2'}}],
|
||||
'vimConnectionInfoDeleteIds': ['f8c35bd0-4d67-4436-9f11-14b8a84c92bb'],
|
||||
'vnfPkgId': 'f26f181d-7891-4720-b022-b074ec1733ef',
|
||||
'vnfInstanceName': 'fake_name',
|
||||
'vnfInstanceDescription': "fake_vnf_instance_description",
|
||||
'vnfdId': 'f26f181d-7891-4720-b022-b074ec1733ef',
|
||||
|
@ -1528,11 +1542,20 @@ def fake_vnf_lcm_op_occs():
|
|||
}
|
||||
resource_changes_obj = objects.ResourceChanges(**resource_changes)
|
||||
|
||||
vim_connection_info = {
|
||||
"id": 'f8c35bd0-4d67-4436-9f11-14b8a84c92aa',
|
||||
"vim_id": 'f8c35bd0-4d67-4436-9f11-14b8a84c92aa',
|
||||
"vim_type": 'openstack',
|
||||
"access_info": {"key1": 'value1', "key2": 'value2'}}
|
||||
changed_info = {
|
||||
"vnf_instance_name": "fake_name",
|
||||
"vnf_instance_description":
|
||||
"fake_vnf_instance_description",
|
||||
"metadata": {},
|
||||
'metadata': {'key': 'value'},
|
||||
'vim_connection_info': [VimConnectionInfo(**vim_connection_info)],
|
||||
'vim_connection_info_delete_ids': [
|
||||
'f8c35bd0-4d67-4436-9f11-14b8a84c92bb'],
|
||||
'vnf_pkg_id': 'f26f181d-7891-4720-b022-b074ec1733ef',
|
||||
"vnfd_id": "f26f181d-7891-4720-b022-b074ec1733ef",
|
||||
"vnf_provider": "fake_vnf_provider",
|
||||
"vnf_product_name": "fake_vnf_product_name",
|
||||
|
|
Loading…
Reference in New Issue