Split security group list operations

Security groups can come from either nova or neutron or not be
available by the vendor. This uses a new flag from os-client-config
to determine where we should get the list from. Also, a new exception
is added for features that are not supported.

This required a minimum version bump in os-client-config.

Change-Id: I4474341ebc255700a06247846c6350981437e8ae
This commit is contained in:
David Shrewsbury 2015-05-04 17:26:36 -04:00 committed by Monty Taylor
parent 3fef40f07e
commit a4e9d5cfc0
5 changed files with 89 additions and 10 deletions

View File

@ -2,7 +2,7 @@ pbr>=0.11,<2.0
bunch
jsonpatch
os-client-config>=1.0.0
os-client-config>=1.2.0
six
python-novaclient>=2.21.0

View File

@ -238,6 +238,8 @@ class OpenStackCloud(object):
self.api_versions = _get_service_values(kwargs, 'api_version')
self.image_api_use_tasks = image_api_use_tasks
self.secgroup_source = kwargs.get('secgroup_source', None)
(self.verify, self.cert) = _ssl_args(verify, cacert, cert, key)
self._cache = cache.make_region(
@ -804,15 +806,58 @@ class OpenStackCloud(object):
"Error fetching flavor list: %s" % e)
def list_security_groups(self):
try:
return meta.obj_list_to_dict(
self.manager.submitTask(_tasks.SecurityGroupList())
# Handle neutron security groups
if self.secgroup_source == 'neutron':
# Neutron returns dicts, so no need to convert objects here.
try:
groups = self.manager.submitTask(
_tasks.NeutronSecurityGroupList())['security_groups']
except Exception as e:
self.log.debug(
"neutron could not list security groups: {message}".format(
message=str(e)),
exc_info=True)
raise OpenStackCloudException(
"Error fetching security group list"
)
return groups
# Handle nova security groups
elif self.secgroup_source == 'nova':
try:
groups = meta.obj_list_to_dict(
self.manager.submitTask(_tasks.NovaSecurityGroupList())
)
except Exception as e:
self.log.debug(
"nova could not list security groups: {message}".format(
message=str(e)),
exc_info=True)
raise OpenStackCloudException(
"Error fetching security group list"
)
# Make Nova data look like Neutron data. This doesn't make them
# look exactly the same, but pretty close.
return [{'id': g['id'],
'name': g['name'],
'description': g['description'],
'security_group_rules': [{
'id': r['id'],
'direction': 'ingress',
'ethertype': 'IPv4',
'port_range_min': r['from_port'],
'port_range_max': r['to_port'],
'protocol': r['ip_protocol'],
'remote_ip_prefix': r['ip_range'].get('cidr', None),
'security_group_id': r['parent_group_id'],
} for r in g['rules']]
} for g in groups]
# Security groups not supported
else:
raise OpenStackCloudUnavailableFeature(
"Unavailable feature: security groups"
)
except Exception as e:
self.log.debug(
"security group list failed: %s" % e, exc_info=True)
raise OpenStackCloudException(
"Error fetching security group list: %s" % e)
def list_servers(self):
try:

View File

@ -192,7 +192,12 @@ class VolumeAttach(task_manager.Task):
client.nova_client.volumes.create_server_volume(**self.args)
class SecurityGroupList(task_manager.Task):
class NeutronSecurityGroupList(task_manager.Task):
def main(self, client):
return client.neutron_client.list_security_groups()
class NovaSecurityGroupList(task_manager.Task):
def main(self, client):
return client.nova_client.security_groups.list()

View File

@ -38,3 +38,7 @@ class OpenStackCloudUnavailableService(OpenStackCloudException):
class OpenStackCloudUnavailableExtension(OpenStackCloudException):
pass
class OpenStackCloudUnavailableFeature(OpenStackCloudException):
pass

View File

@ -324,6 +324,31 @@ class TestShade(base.TestCase):
flavor2 = self.cloud.get_flavor(1)
self.assertEquals(vanilla, flavor2)
@mock.patch.object(shade.OpenStackCloud, 'neutron_client')
@mock.patch.object(shade.OpenStackCloud, 'nova_client')
def test_list_security_groups_neutron(self, mock_nova, mock_neutron):
self.cloud.secgroup_source = 'neutron'
self.cloud.list_security_groups()
self.assertTrue(mock_neutron.list_security_groups.called)
self.assertFalse(mock_nova.security_groups.list.called)
@mock.patch.object(shade.OpenStackCloud, 'neutron_client')
@mock.patch.object(shade.OpenStackCloud, 'nova_client')
def test_list_security_groups_nova(self, mock_nova, mock_neutron):
self.cloud.secgroup_source = 'nova'
self.cloud.list_security_groups()
self.assertFalse(mock_neutron.list_security_groups.called)
self.assertTrue(mock_nova.security_groups.list.called)
@mock.patch.object(shade.OpenStackCloud, 'neutron_client')
@mock.patch.object(shade.OpenStackCloud, 'nova_client')
def test_list_security_groups_none(self, mock_nova, mock_neutron):
self.cloud.secgroup_source = None
self.assertRaises(shade.OpenStackCloudUnavailableFeature,
self.cloud.list_security_groups)
self.assertFalse(mock_neutron.list_security_groups.called)
self.assertFalse(mock_nova.security_groups.list.called)
class TestShadeOperator(base.TestCase):