Add tenant validation check between VIM and VNF

This patch adds a validation check between a VIM and a VNF regarding
tenant.
If tenants which a VIM and a VNF belong to are different each other,
Tacker will stop instantiating the VNF.

Implement: blueprint multi-tenant-policy
Change-Id: Ia966280c6d565b0021b29f593cd064daec0492f4
This commit is contained in:
Koichi Edagawa 2021-10-11 17:17:28 +09:00 committed by Wataru Juso
parent 0cd9cd8404
commit a7aee44d13
9 changed files with 78 additions and 126 deletions

View File

@ -431,3 +431,8 @@ class VnfConflictStateWithErrorPoint(Conflict):
class InvalidIpAddr(TackerException):
message = _('Invalid ip address value in resource %(id)s.')
class TenantMatchFailure(TackerException):
message = _('The tenants which target VNF and its VIM belongs to are '
'different each other.')

View File

@ -549,3 +549,16 @@ def get_change_ext_conn_request_obj():
get_change_ext_conn_request())
return objects.ChangeExtConnRequest.obj_from_primitive(
body, None)
def get_vim_obj():
return {
'vim_id': uuidsentinel.vim_id,
'vim_name': 'fake_vim',
'vim_type': 'openstack',
'vim_auth': {
'auth_url': 'http://localhost/identity',
'password': 'test_pw',
'username': 'test_user',
'project_name': 'test_project'},
'tenant': uuidsentinel.tenant_id}

View File

@ -1668,14 +1668,6 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
vnfd_key = 'vnfd_' + vnf_instance.instantiated_vnf_info.flavour_id
vnfd_yaml = vnf_dict['vnfd']['attributes'].get(vnfd_key, '')
mock_vnfd_dict.return_value = yaml.safe_load(vnfd_yaml)
vim_obj = {'vim_id': uuidsentinel.vim_id,
'vim_name': 'fake_vim',
'vim_type': 'openstack',
'vim_auth': {
'auth_url': 'http://localhost/identity',
'password': 'test_pw',
'username': 'test_user',
'project_name': 'test_project'}}
vimAssets = {'computeResourceFlavours': [
{'vimConnectionId': uuidsentinel.vim_id,
'vnfdVirtualComputeDescId': 'CDU1',
@ -1695,7 +1687,7 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
json_data = grant_dict
mock_grants.return_value = MockResponse(json_data=json_data)
mock_vim.return_value = vim_obj
mock_vim.return_value = fakes.get_vim_obj()
mock_d1.return_value = []
mock_placement.return_value = []
self.conductor.heal(self.context, vnf_instance, vnf_dict,
@ -1852,14 +1844,6 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
vnf_lcm_op_occs_id = 'a9c36d21-21aa-4692-8922-7999bbcae08c'
mock_exec.return_value = True
mock_act.return_value = None
vim_obj = {'vim_id': uuidsentinel.vim_id,
'vim_name': 'fake_vim',
'vim_type': 'openstack',
'vim_auth': {
'auth_url': 'http://localhost/identity',
'password': 'test_pw',
'username': 'test_user',
'project_name': 'test_project'}}
vimAssets = {'computeResourceFlavours': [
{'vimConnectionId': uuidsentinel.vim_id,
'vnfdVirtualComputeDescId': 'CDU1',
@ -1904,7 +1888,7 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
json_data = grant_dict
mock_grants.return_value = MockResponse(json_data=json_data)
mock_vim.return_value = vim_obj
mock_vim.return_value = fakes.get_vim_obj()
mock_d1.return_value = ['ST1']
res_str = '[{"id_type": "RES_MGMT", "resource_id": ' + \
'"2c6e5cc7-240d-4458-a683-1fe648351200", ' + \
@ -1988,14 +1972,6 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
vnf_lcm_op_occs_id = 'a9c36d21-21aa-4692-8922-7999bbcae08c'
mock_exec.return_value = True
mock_act.return_value = None
vim_obj = {'vim_id': uuidsentinel.vim_id,
'vim_name': 'fake_vim',
'vim_type': 'openstack',
'vim_auth': {
'auth_url': 'http://localhost/identity',
'password': 'test_pw',
'username': 'test_user',
'project_name': 'test_project'}}
vimAssets = {'computeResourceFlavours': [
{'vimConnectionId': uuidsentinel.vim_id,
'vnfdVirtualComputeDescId': 'CDU1',
@ -2020,7 +1996,7 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
json_data = grant_dict
mock_grants.return_value = MockResponse(json_data=json_data)
mock_vim.return_value = vim_obj
mock_vim.return_value = fakes.get_vim_obj()
mock_d1.return_value = []
mock_placement.return_value = []
self.assertRaises(exceptions.ValidationError,
@ -2090,18 +2066,10 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
vnf_lcm_op_occs_id = 'a9c36d21-21aa-4692-8922-7999bbcae08c'
mock_exec.return_value = True
mock_act.return_value = None
vim_obj = {'vim_id': uuidsentinel.vim_id,
'vim_name': 'fake_vim',
'vim_type': 'openstack',
'vim_auth': {
'auth_url': 'http://localhost/identity',
'password': 'test_pw',
'username': 'test_user',
'project_name': 'test_project'}}
mock_grants.side_effect = \
requests.exceptions.HTTPError("MockException")
mock_vim.return_value = vim_obj
mock_vim.return_value = fakes.get_vim_obj()
mock_d1.return_value = []
mock_placement.return_value = []
self.assertRaises(requests.exceptions.HTTPError,
@ -2282,16 +2250,8 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
fields.VnfInstanceState.INSTANTIATED,
scale_status="scale_status")
scale_vnf_request = fakes.scale_request("SCALE_IN", 1)
vim_obj = {'vim_id': uuidsentinel.vim_id,
'vim_name': 'fake_vim',
'vim_type': 'openstack',
'vim_auth': {
'auth_url': 'http://localhost/identity',
'password': 'test_pw',
'username': 'test_user',
'project_name': 'test_project'}}
mock_vim.return_value = vim_obj
mock_vim.return_value = fakes.get_vim_obj()
mock_d1.return_value = ([], [], "", "")
vnf_info['addResources'] = []
vnf_info['removeResources'] = []
@ -2355,16 +2315,8 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
fields.VnfInstanceState.INSTANTIATED,
scale_status="scale_status")
scale_vnf_request = fakes.scale_request("SCALE_IN", 1)
vim_obj = {'vim_id': uuidsentinel.vim_id,
'vim_name': 'fake_vim',
'vim_type': 'openstack',
'vim_auth': {
'auth_url': 'http://localhost/identity',
'password': 'test_pw',
'username': 'test_user',
'project_name': 'test_project'}}
mock_vim.return_value = vim_obj
mock_vim.return_value = fakes.get_vim_obj()
removeResources = []
resRemoveResource = []
resource = objects.ResourceDefinition(
@ -2485,16 +2437,8 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
fields.VnfInstanceState.INSTANTIATED,
scale_status="scale_status")
scale_vnf_request = fakes.scale_request("SCALE_OUT", 1)
vim_obj = {'vim_id': uuidsentinel.vim_id,
'vim_name': 'fake_vim',
'vim_type': 'openstack',
'vim_auth': {
'auth_url': 'http://localhost/identity',
'password': 'test_pw',
'username': 'test_user',
'project_name': 'test_project'}}
mock_vim.return_value = vim_obj
mock_vim.return_value = fakes.get_vim_obj()
addResources = []
resAddResource = []
resource = objects.ResourceDefinition(
@ -2634,16 +2578,8 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
fields.VnfInstanceState.INSTANTIATED,
scale_status="scale_status")
scale_vnf_request = fakes.scale_request("SCALE_OUT", 1)
vim_obj = {'vim_id': uuidsentinel.vim_id,
'vim_name': 'fake_vim',
'vim_type': 'openstack',
'vim_auth': {
'auth_url': 'http://localhost/identity',
'password': 'test_pw',
'username': 'test_user',
'project_name': 'test_project'}}
mock_vim.return_value = vim_obj
mock_vim.return_value = fakes.get_vim_obj()
addResources = []
resource = objects.ResourceDefinition(
id='2c6e5cc7-240d-4458-a683-1fe648351280',
@ -2736,16 +2672,8 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
fields.VnfInstanceState.INSTANTIATED,
scale_status="scale_status")
scale_vnf_request = fakes.scale_request("SCALE_OUT", 1)
vim_obj = {'vim_id': uuidsentinel.vim_id,
'vim_name': 'fake_vim',
'vim_type': 'openstack',
'vim_auth': {
'auth_url': 'http://localhost/identity',
'password': 'test_pw',
'username': 'test_user',
'project_name': 'test_project'}}
mock_vim.return_value = vim_obj
mock_vim.return_value = fakes.get_vim_obj()
addResources = []
resource = objects.ResourceDefinition(
id='2c6e5cc7-240d-4458-a683-1fe648351280',

View File

@ -739,6 +739,30 @@ def get_dummy_vim_connection_info():
'vim_id': 'fake_vim_id', 'vim_type': 'openstack', 'extra': {}}
def get_dummy_openstack_vim_obj():
return {'vim_id': uuidsentinel.vim_id,
'vim_name': 'fake_vim',
'vim_type': 'openstack',
'vim_auth': {
'auth_url': 'http://localhost/identity',
'password': 'test_pw',
'username': 'test_user',
'project_name': 'test_project'},
'tenant': uuidsentinel.tenant_id}
def get_dummy_kubernetes_vim_obj():
return {'vim_id': uuidsentinel.vim_id,
'vim_name': 'fake_vim',
'vim_type': 'kubernetes',
'vim_auth': {
'auth_url': 'http://localhost/8443',
'password': 'test_pw',
'username': 'test_user',
'project_name': 'test_project'},
'tenant': uuidsentinel.tenant_id}
def get_dummy_instantiate_vnf_request(**updates):
instantiate_vnf_request = {
'additional_params': None, 'created_at': '', 'deleted': '',

View File

@ -130,10 +130,13 @@ class MgmtVnfLcmDriverTest(db_base.SqlTestCase):
def _stub_get_vim(self):
vim_obj = {'vim_id': '6261579e-d6f3-49ad-8bc3-a9cb974778ff',
'vim_name': 'fake_vim', 'vim_auth':
{'auth_url': 'http://localhost/identity', 'password':
'test_pw', 'username': 'test_user', 'project_name':
'test_project'}, 'vim_type': 'openstack'}
'vim_name': 'fake_vim',
'vim_auth':
{'auth_url': 'http://localhost/identity',
'password': 'test_pw', 'username': 'test_user',
'project_name': 'test_project'},
'vim_type': 'openstack',
'tenant': uuidsentinel.tenant_id}
self.vim_client.get_vim.return_value = vim_obj
@mock.patch('tacker.vnflcm.utils.get_default_scale_status')

View File

@ -184,10 +184,12 @@ class TestVnflcmDriver(db_base.SqlTestCase):
def _stub_get_vim(self):
vim_obj = {'vim_id': '6261579e-d6f3-49ad-8bc3-a9cb974778ff',
'vim_name': 'fake_vim', 'vim_auth':
{'auth_url': 'http://localhost/identity', 'password':
'test_pw', 'username': 'test_user', 'project_name':
'test_project'}, 'vim_type': 'openstack'}
'vim_name': 'fake_vim',
'vim_auth': {'auth_url': 'http://localhost/identity',
'password': 'test_pw', 'username': 'test_user',
'project_name': 'test_project'},
'vim_type': 'openstack',
'tenant': uuidsentinel.tenant_id}
self.vim_client.get_vim.return_value = vim_obj
@mock.patch('tacker.vnflcm.utils.get_default_scale_status')
@ -1228,16 +1230,7 @@ class TestVnflcmDriver(db_base.SqlTestCase):
# Heal as per SOL003 i.e. without vnfcInstanceId
heal_vnf_req = objects.HealVnfRequest()
vim_obj = {'vim_id': uuidsentinel.vim_id,
'vim_name': 'fake_vim',
'vim_type': 'openstack',
'vim_auth': {
'auth_url': 'http://localhost/identity',
'password': 'test_pw',
'username': 'test_user',
'project_name': 'test_project'}}
mock_vim.return_value = vim_obj
mock_vim.return_value = fakes.get_dummy_openstack_vim_obj()
vnf_instance = fakes.return_vnf_instance(
fields.VnfInstanceState.INSTANTIATED)
@ -1915,15 +1908,8 @@ class TestVnflcmDriver(db_base.SqlTestCase):
None]
mock_vnf_package_vnfd.return_value = fakes.return_vnf_package_vnfd()
driver = vnflcm_driver.VnfLcmDriver()
vim_obj = {'vim_id': uuidsentinel.vim_id,
'vim_name': 'fake_vim',
'vim_type': 'kubernetes',
'vim_auth': {
'auth_url': 'http://localhost:8443',
'password': 'test_pw',
'username': 'test_user',
'project_name': 'test_project'}}
self.vim_client.get_vim.return_value = vim_obj
self.vim_client.get_vim.return_value = \
fakes.get_dummy_kubernetes_vim_obj()
driver.scale_vnf(self.context, vnf_info, vnf_instance,
scale_vnf_request)
@ -1959,15 +1945,8 @@ class TestVnflcmDriver(db_base.SqlTestCase):
mock_vnfd_dict.return_value = fakes.vnfd_dict_cnf()
mock_yaml_safe_load.return_value = fakes.vnfd_dict_cnf()
driver = vnflcm_driver.VnfLcmDriver()
vim_obj = {'vim_id': uuidsentinel.vim_id,
'vim_name': 'fake_vim',
'vim_type': 'kubernetes',
'vim_auth': {
'auth_url': 'http://localhost:8443',
'password': 'test_pw',
'username': 'test_user',
'project_name': 'test_project'}}
self.vim_client.get_vim.return_value = vim_obj
self.vim_client.get_vim.return_value = \
fakes.get_dummy_kubernetes_vim_obj()
driver.scale_vnf(self.context, vnf_info, vnf_instance,
scale_vnf_request)
@ -3013,15 +2992,8 @@ class TestVnflcmDriver(db_base.SqlTestCase):
mock_vnfd_dict.return_value = fakes.vnfd_dict_cnf()
operation_params = jsonutils.loads(vnf_lcm_op_occs.operation_params)
mock_yaml_safe_load.return_value = fakes.vnfd_dict_cnf()
vim_obj = {'vim_id': uuidsentinel.vim_id,
'vim_name': 'fake_vim',
'vim_type': 'kubernetes',
'vim_auth': {
'auth_url': 'http://localhost:8443',
'password': 'test_pw',
'username': 'test_user',
'project_name': 'test_project'}}
self.vim_client.get_vim.return_value = vim_obj
self.vim_client.get_vim.return_value = \
fakes.get_dummy_kubernetes_vim_obj()
self._mock_vnf_manager()
driver = vnflcm_driver.VnfLcmDriver()

View File

@ -1255,5 +1255,6 @@ def fake_k8s_vim_obj():
'username': 'test_user',
'project_name': 'test_project'},
'vim_type': 'kubernetes',
'tenant': uuidsentinel.tenant_id,
'extra': {}}
return vim_obj

View File

@ -64,6 +64,7 @@ def _get_vim(context, vim_connection_info):
vim_info = {'id': vim_res['vim_id'], 'vim_id': vim_res['vim_id'],
'vim_type': vim_res['vim_type'],
'access_info': vim_res['vim_auth'],
'tenant_id': vim_res['tenant'],
'extra': vim_res.get('extra', {})}
return vim_info

View File

@ -514,6 +514,11 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
vim_info = vnflcm_utils._get_vim(context,
instantiate_vnf_req.vim_connection_info)
if vim_info['tenant_id'] != vnf_instance.tenant_id:
LOG.error('The tenants which target VNF and its VIM belongs to '
'are different each other.')
raise exceptions.TenantMatchFailure()
vim_connection_info = objects.VimConnectionInfo.obj_from_primitive(
vim_info, context)