Find security group profiles by project scope

If a security group exists with the same name in multiple projects, a
profile will not be able to created using that security group name.
This change will try to scope the security group to the user's project
during validation.  If the security group can not be found using the
project scope, it will try to find it without the project scope.

Change-Id: I595b3c348ce8133a273d8e26c664fffc32694705
This commit is contained in:
Duc Truong 2020-09-03 00:23:06 +00:00
parent 585bd14c70
commit 349c47379c
4 changed files with 57 additions and 4 deletions

View File

@ -52,8 +52,15 @@ class NeutronClient(base.DriverBase):
return port
@sdk.translate_exception
def security_group_find(self, name_or_id, ignore_missing=False):
sg = self.conn.network.find_security_group(name_or_id, ignore_missing)
def security_group_find(self, name_or_id, ignore_missing=False,
project_id=None):
if project_id is None:
attrs = {}
else:
attrs = {'project_id': project_id}
sg = self.conn.network.find_security_group(name_or_id, ignore_missing,
**attrs)
return sg
@sdk.translate_exception

View File

@ -495,7 +495,13 @@ class ServerProfile(base.Profile):
res = []
try:
for sg in sgs:
sg_obj = nc.security_group_find(sg)
try:
# try to find sg scoped by project first
sg_obj = nc.security_group_find(
sg, project_id=self.project)
except exc.InternalError:
# if it fails to find sg, try without project scope
sg_obj = nc.security_group_find(sg)
res.append(sg_obj.id)
except exc.InternalError as ex:
return str(ex)

View File

@ -76,6 +76,16 @@ class TestNeutronV2Driver(base.SenlinTestCase):
sg_id, False)
self.assertEqual(sg_obj, res)
def test_security_group_find_with_project_id(self):
sg_id = 'sg_identifier'
sg_obj = mock.Mock()
self.conn.network.find_security_group.return_value = sg_obj
res = self.nc.security_group_find(sg_id, project_id='fake_project_id')
self.conn.network.find_security_group.assert_called_once_with(
sg_id, False, project_id='fake_project_id')
self.assertEqual(sg_obj, res)
def test_subnet_get(self):
subnet_id = 'subnet_identifier'
subnet_obj = mock.Mock()

View File

@ -902,7 +902,37 @@ class TestNetworkValidation(base.SenlinTestCase):
if self.port_result:
self.nc.port_find.assert_called_once_with('PORT')
if self.sg_result:
self.nc.security_group_find.assert_called_once_with('default')
self.nc.security_group_find.assert_called_once_with(
'default', project_id=None)
if self.floating_result:
self.nc.floatingip_find.assert_called_once_with('FLOATINGIP')
def test_validation_with_project_scope(self):
self.nc.network_get.side_effect = self.net_result
self.nc.port_find.side_effect = self.port_result
self.nc.security_group_find.side_effect = self.sg_result
self.nc.floatingip_find.side_effect = self.floating_result
obj = mock.Mock(physical_id='NOVA_ID')
self.profile.project_scope = True
self.profile.project = 'FAKE_PROJECT_ID'
if self.success:
res = self.profile._validate_network(obj, self.inputs, self.reason)
self.assertEqual(self.result, res)
else:
ex = self.assertRaises(self.exception,
self.profile._validate_network,
obj, self.inputs, self.reason)
self.assertEqual(self.message, str(ex))
if self.net_result:
self.nc.network_get.assert_called_with('NET')
if self.port_result:
self.nc.port_find.assert_called_once_with('PORT')
if self.sg_result:
self.nc.security_group_find.assert_called_once_with(
'default', project_id='FAKE_PROJECT_ID')
if self.floating_result:
self.nc.floatingip_find.assert_called_once_with('FLOATINGIP')