Merge "Move and fix security group normalization"
This commit is contained in:
commit
3ecd9a405a
@ -97,6 +97,78 @@ class Normalizer(object):
|
||||
new_image['is_public'] = is_public
|
||||
return new_image
|
||||
|
||||
def _normalize_secgroups(self, groups):
|
||||
"""Normalize the structure of security groups
|
||||
|
||||
This makes security group dicts, as returned from nova, look like the
|
||||
security group dicts as returned from neutron. This does not make them
|
||||
look exactly the same, but it's pretty close.
|
||||
|
||||
:param list groups: A list of security group dicts.
|
||||
|
||||
:returns: A list of normalized dicts.
|
||||
"""
|
||||
ret = []
|
||||
for group in groups:
|
||||
ret.append(self._normalize_secgroup(group))
|
||||
return ret
|
||||
|
||||
def _normalize_secgroup(self, group):
|
||||
|
||||
rules = group.pop('security_group_rules', None)
|
||||
if not rules and 'rules' in group:
|
||||
rules = group.pop('rules')
|
||||
group['security_group_rules'] = self._normalize_secgroup_rules(rules)
|
||||
# neutron sets these. we don't care about it, but let's be the same
|
||||
project_id = group.get('project_id', group.get('tenant_id', ''))
|
||||
group['tenant_id'] = project_id
|
||||
group['project_id'] = project_id
|
||||
group['location'] = self.current_location
|
||||
return munch.Munch(group)
|
||||
|
||||
def _normalize_secgroup_rules(self, rules):
|
||||
"""Normalize the structure of nova security group rules
|
||||
|
||||
Note that nova uses -1 for non-specific port values, but neutron
|
||||
represents these with None.
|
||||
|
||||
:param list rules: A list of security group rule dicts.
|
||||
|
||||
:returns: A list of normalized dicts.
|
||||
"""
|
||||
ret = []
|
||||
for rule in rules:
|
||||
ret.append(self._normalize_secgroup_rule(rule))
|
||||
return ret
|
||||
|
||||
def _normalize_secgroup_rule(self, rule):
|
||||
ret = munch.Munch()
|
||||
ret['id'] = rule['id']
|
||||
ret['location'] = self.current_location
|
||||
ret['direction'] = rule.get('direction', 'ingress')
|
||||
ret['ethertype'] = rule.get('ethertype', 'IPv4')
|
||||
port_range_min = rule.get(
|
||||
'port_range_min', rule.get('from_port', None))
|
||||
if port_range_min == -1:
|
||||
port_range_min = None
|
||||
ret['port_range_min'] = port_range_min
|
||||
port_range_max = rule.get(
|
||||
'port_range_max', rule.get('to_port', None))
|
||||
if port_range_max == -1:
|
||||
port_range_max = None
|
||||
ret['port_range_max'] = port_range_max
|
||||
ret['protocol'] = rule.get('protocol', rule.get('ip_protocol'))
|
||||
ret['remote_ip_prefix'] = rule.get(
|
||||
'remote_ip_prefix', rule.get('ip_range', {}).get('cidr', None))
|
||||
ret['security_group_id'] = rule.get(
|
||||
'security_group_id', rule.get('parent_group_id'))
|
||||
ret['remote_group_id'] = rule.get('remote_group_id')
|
||||
project_id = rule.get('project_id', rule.get('tenant_id', ''))
|
||||
ret['tenant_id'] = project_id
|
||||
ret['project_id'] = project_id
|
||||
ret['remote_group_id'] = rule.get('remote_group_id')
|
||||
return ret
|
||||
|
||||
def _normalize_servers(self, servers):
|
||||
# Here instead of _utils because we need access to region and cloud
|
||||
# name from the cloud object
|
||||
|
@ -182,49 +182,6 @@ def normalize_keystone_services(services):
|
||||
return meta.obj_list_to_dict(ret)
|
||||
|
||||
|
||||
def normalize_nova_secgroups(groups):
|
||||
"""Normalize the structure of nova security groups
|
||||
|
||||
This makes security group dicts, as returned from nova, look like the
|
||||
security group dicts as returned from neutron. This does not make them
|
||||
look exactly the same, but it's pretty close.
|
||||
|
||||
:param list groups: A list of security group dicts.
|
||||
|
||||
:returns: A list of normalized dicts.
|
||||
"""
|
||||
ret = [{'id': g['id'],
|
||||
'name': g['name'],
|
||||
'description': g['description'],
|
||||
'security_group_rules': normalize_nova_secgroup_rules(g['rules'])
|
||||
} for g in groups]
|
||||
return meta.obj_list_to_dict(ret)
|
||||
|
||||
|
||||
def normalize_nova_secgroup_rules(rules):
|
||||
"""Normalize the structure of nova security group rules
|
||||
|
||||
Note that nova uses -1 for non-specific port values, but neutron
|
||||
represents these with None.
|
||||
|
||||
:param list rules: A list of security group rule dicts.
|
||||
|
||||
:returns: A list of normalized dicts.
|
||||
"""
|
||||
ret = [{'id': r['id'],
|
||||
'direction': 'ingress',
|
||||
'ethertype': 'IPv4',
|
||||
'port_range_min':
|
||||
None if r['from_port'] == -1 else r['from_port'],
|
||||
'port_range_max':
|
||||
None if r['to_port'] == -1 else 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 rules]
|
||||
return meta.obj_list_to_dict(ret)
|
||||
|
||||
|
||||
def normalize_nova_floating_ips(ips):
|
||||
"""Normalize the structure of Neutron floating IPs
|
||||
|
||||
|
@ -1510,7 +1510,7 @@ class OpenStackCloud(_normalize.Normalizer):
|
||||
groups = self.manager.submit_task(
|
||||
_tasks.ServerListSecurityGroups(server=server['id']))
|
||||
|
||||
return _utils.normalize_nova_secgroups(groups)
|
||||
return self._normalize_secgroups(groups)
|
||||
|
||||
def list_security_groups(self):
|
||||
"""List all available security groups.
|
||||
@ -1524,12 +1524,13 @@ class OpenStackCloud(_normalize.Normalizer):
|
||||
"Unavailable feature: security groups"
|
||||
)
|
||||
|
||||
groups = []
|
||||
# Handle neutron security groups
|
||||
if self._use_neutron_secgroups():
|
||||
# Neutron returns dicts, so no need to convert objects here.
|
||||
with _utils.neutron_exceptions(
|
||||
"Error fetching security group list"):
|
||||
return self.manager.submit_task(
|
||||
groups = self.manager.submit_task(
|
||||
_tasks.NeutronSecurityGroupList())['security_groups']
|
||||
|
||||
# Handle nova security groups
|
||||
@ -1537,7 +1538,7 @@ class OpenStackCloud(_normalize.Normalizer):
|
||||
with _utils.shade_exceptions("Error fetching security group list"):
|
||||
groups = self.manager.submit_task(
|
||||
_tasks.NovaSecurityGroupList())
|
||||
return _utils.normalize_nova_secgroups(groups)
|
||||
return self._normalize_secgroups(groups)
|
||||
|
||||
def list_servers(self, detailed=False):
|
||||
"""List all available servers.
|
||||
@ -5709,6 +5710,7 @@ class OpenStackCloud(_normalize.Normalizer):
|
||||
"Unavailable feature: security groups"
|
||||
)
|
||||
|
||||
group = None
|
||||
if self._use_neutron_secgroups():
|
||||
with _utils.neutron_exceptions(
|
||||
"Error creating security group {0}".format(name)):
|
||||
@ -5716,9 +5718,7 @@ class OpenStackCloud(_normalize.Normalizer):
|
||||
_tasks.NeutronSecurityGroupCreate(
|
||||
body=dict(security_group=dict(name=name,
|
||||
description=description))
|
||||
)
|
||||
)
|
||||
return group['security_group']
|
||||
))['security_group']
|
||||
|
||||
else:
|
||||
with _utils.shade_exceptions(
|
||||
@ -5729,7 +5729,7 @@ class OpenStackCloud(_normalize.Normalizer):
|
||||
name=name, description=description
|
||||
)
|
||||
)
|
||||
return _utils.normalize_nova_secgroups([group])[0]
|
||||
return self._normalize_secgroup(group)
|
||||
|
||||
def delete_security_group(self, name_or_id):
|
||||
"""Delete a security group
|
||||
@ -5791,9 +5791,9 @@ class OpenStackCloud(_normalize.Normalizer):
|
||||
"Unavailable feature: security groups"
|
||||
)
|
||||
|
||||
secgroup = self.get_security_group(name_or_id)
|
||||
group = self.get_security_group(name_or_id)
|
||||
|
||||
if secgroup is None:
|
||||
if group is None:
|
||||
raise OpenStackCloudException(
|
||||
"Security group %s not found." % name_or_id)
|
||||
|
||||
@ -5802,10 +5802,9 @@ class OpenStackCloud(_normalize.Normalizer):
|
||||
"Error updating security group {0}".format(name_or_id)):
|
||||
group = self.manager.submit_task(
|
||||
_tasks.NeutronSecurityGroupUpdate(
|
||||
security_group=secgroup['id'],
|
||||
security_group=group['id'],
|
||||
body={'security_group': kwargs})
|
||||
)
|
||||
return group['security_group']
|
||||
)['security_group']
|
||||
|
||||
else:
|
||||
with _utils.shade_exceptions(
|
||||
@ -5813,9 +5812,9 @@ class OpenStackCloud(_normalize.Normalizer):
|
||||
group=name_or_id)):
|
||||
group = self.manager.submit_task(
|
||||
_tasks.NovaSecurityGroupUpdate(
|
||||
group=secgroup['id'], **kwargs)
|
||||
group=group['id'], **kwargs)
|
||||
)
|
||||
return _utils.normalize_nova_secgroups([group])[0]
|
||||
return self._normalize_secgroup(group)
|
||||
|
||||
def create_security_group_rule(self,
|
||||
secgroup_name_or_id,
|
||||
@ -5901,7 +5900,7 @@ class OpenStackCloud(_normalize.Normalizer):
|
||||
_tasks.NeutronSecurityGroupRuleCreate(
|
||||
body={'security_group_rule': rule_def})
|
||||
)
|
||||
return rule['security_group_rule']
|
||||
return self._normalize_secgroup_rule(rule['security_group_rule'])
|
||||
|
||||
else:
|
||||
# NOTE: Neutron accepts None for protocol. Nova does not.
|
||||
@ -5944,7 +5943,7 @@ class OpenStackCloud(_normalize.Normalizer):
|
||||
group_id=remote_group_id
|
||||
)
|
||||
)
|
||||
return _utils.normalize_nova_secgroup_rules([rule])[0]
|
||||
return self._normalize_secgroup_rule(rule)
|
||||
|
||||
def delete_security_group_rule(self, rule_id):
|
||||
"""Delete a security group rule
|
||||
|
@ -12,6 +12,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
import testtools
|
||||
|
||||
from shade import _utils
|
||||
@ -79,7 +80,7 @@ class TestUtils(base.TestCase):
|
||||
}})
|
||||
self.assertEqual([el2, el3], ret)
|
||||
|
||||
def test_normalize_nova_secgroups(self):
|
||||
def test_normalize_secgroups(self):
|
||||
nova_secgroup = dict(
|
||||
id='abc123',
|
||||
name='nova_secgroup',
|
||||
@ -94,17 +95,38 @@ class TestUtils(base.TestCase):
|
||||
id='abc123',
|
||||
name='nova_secgroup',
|
||||
description='A Nova security group',
|
||||
tenant_id='',
|
||||
project_id='',
|
||||
location=dict(
|
||||
region_name='RegionOne',
|
||||
project=dict(
|
||||
domain_name=None,
|
||||
id=mock.ANY,
|
||||
domain_id=None,
|
||||
name='admin'),
|
||||
cloud='_test_cloud_'),
|
||||
security_group_rules=[
|
||||
dict(id='123', direction='ingress', ethertype='IPv4',
|
||||
port_range_min=80, port_range_max=81, protocol='tcp',
|
||||
remote_ip_prefix='0.0.0.0/0', security_group_id='xyz123')
|
||||
remote_ip_prefix='0.0.0.0/0', security_group_id='xyz123',
|
||||
tenant_id='',
|
||||
project_id='',
|
||||
remote_group_id=None,
|
||||
location=dict(
|
||||
region_name='RegionOne',
|
||||
project=dict(
|
||||
domain_name=None,
|
||||
id=mock.ANY,
|
||||
domain_id=None,
|
||||
name='admin'),
|
||||
cloud='_test_cloud_'))
|
||||
]
|
||||
)
|
||||
|
||||
retval = _utils.normalize_nova_secgroups([nova_secgroup])[0]
|
||||
retval = self.cloud._normalize_secgroup(nova_secgroup)
|
||||
self.assertEqual(expected, retval)
|
||||
|
||||
def test_normalize_nova_secgroups_negone_port(self):
|
||||
def test_normalize_secgroups_negone_port(self):
|
||||
nova_secgroup = dict(
|
||||
id='abc123',
|
||||
name='nova_secgroup',
|
||||
@ -115,11 +137,11 @@ class TestUtils(base.TestCase):
|
||||
]
|
||||
)
|
||||
|
||||
retval = _utils.normalize_nova_secgroups([nova_secgroup])[0]
|
||||
retval = self.cloud._normalize_secgroup(nova_secgroup)
|
||||
self.assertIsNone(retval['security_group_rules'][0]['port_range_min'])
|
||||
self.assertIsNone(retval['security_group_rules'][0]['port_range_max'])
|
||||
|
||||
def test_normalize_nova_secgroup_rules(self):
|
||||
def test_normalize_secgroup_rules(self):
|
||||
nova_rules = [
|
||||
dict(id='123', from_port=80, to_port=81, ip_protocol='tcp',
|
||||
ip_range={'cidr': '0.0.0.0/0'}, parent_group_id='xyz123')
|
||||
@ -127,9 +149,18 @@ class TestUtils(base.TestCase):
|
||||
expected = [
|
||||
dict(id='123', direction='ingress', ethertype='IPv4',
|
||||
port_range_min=80, port_range_max=81, protocol='tcp',
|
||||
remote_ip_prefix='0.0.0.0/0', security_group_id='xyz123')
|
||||
remote_ip_prefix='0.0.0.0/0', security_group_id='xyz123',
|
||||
tenant_id='', project_id='', remote_group_id=None,
|
||||
location=dict(
|
||||
region_name='RegionOne',
|
||||
project=dict(
|
||||
domain_name=None,
|
||||
id=mock.ANY,
|
||||
domain_id=None,
|
||||
name='admin'),
|
||||
cloud='_test_cloud_'))
|
||||
]
|
||||
retval = _utils.normalize_nova_secgroup_rules(nova_rules)
|
||||
retval = self.cloud._normalize_secgroup_rules(nova_rules)
|
||||
self.assertEqual(expected, retval)
|
||||
|
||||
def test_normalize_volumes_v1(self):
|
||||
|
@ -352,9 +352,9 @@ class TestSecurityGroups(base.TestCase):
|
||||
secgroup_name_or_id='nova-sec-group',
|
||||
direction='egress')
|
||||
|
||||
@mock.patch.object(shade._utils, 'normalize_nova_secgroups')
|
||||
@mock.patch.object(shade.OpenStackCloud, '_normalize_secgroups')
|
||||
@mock.patch.object(shade.OpenStackCloud, 'nova_client')
|
||||
def test_list_server_security_groups(self, mock_nova, mock_norm):
|
||||
def test_list_server_security_groups_nova(self, mock_nova, mock_norm):
|
||||
self.has_neutron = False
|
||||
server = dict(id='server_id')
|
||||
self.cloud.list_server_security_groups(server)
|
||||
|
Loading…
x
Reference in New Issue
Block a user