]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Add support for source security groups
authorSimon Pasquier <simon.pasquier@bull.net>
Wed, 14 Aug 2013 13:00:44 +0000 (15:00 +0200)
committerSimon Pasquier <simon.pasquier@bull.net>
Mon, 26 Aug 2013 07:45:06 +0000 (09:45 +0200)
This patch adds support for the SourceSecurityGroupName and
SourceSecurityGroupId properties. It covers Nova and Neutron.

Change-Id: Ic12512dfb4375ccccbe1282bb48b80cde16ceb9d
Fixes: bug #1193415
heat/common/exception.py
heat/engine/resources/security_group.py
heat/tests/test_security_group.py
heat/tests/test_vpc.py

index 08fdf8d1632a298f49f998ef7909dd1bedef6f21..74adf7c5bcbbd9463b36d9a7b38ee248381ca332 100644 (file)
@@ -337,3 +337,8 @@ class HTTPExceptionDisguise(Exception):
 
 class TemplateTooBig(HeatException):
     message = _('Template exceeds maximum allowed size.')
+
+
+class EgressRuleNotAllowed(HeatException):
+    message = _("Egress rules are only allowed when "
+                "Neutron is used and the 'VpcId' property is set.")
index f0925ad48c58547fea2de487e14fa8f3fff176e8..a6ade94862cc1f4cc670fe0c3f02a021e8564f98 100644 (file)
@@ -16,6 +16,7 @@
 from heat.engine import clients
 from heat.engine import resource
 
+from heat.common import exception
 from heat.openstack.common import log as logging
 
 logger = logging.getLogger(__name__)
@@ -34,6 +35,20 @@ class SecurityGroup(resource.Resource):
         else:
             self._handle_create_nova()
 
+    def _convert_to_neutron_rule(self, direction, sg_rule):
+        return {
+            'direction': direction,
+            'ethertype': 'IPv4',
+            'remote_ip_prefix': sg_rule.get('CidrIp'),
+            'port_range_min': sg_rule.get('FromPort'),
+            'port_range_max': sg_rule.get('ToPort'),
+            'protocol': sg_rule.get('IpProtocol'),
+            # Neutron understands both names and ids
+            'remote_group_id': sg_rule.get('SourceSecurityGroupId') or
+            sg_rule.get('SourceSecurityGroupName'),
+            'security_group_id': self.resource_id
+        }
+
     def _handle_create_neutron(self):
         from neutronclient.common.exceptions import NeutronClientException
         client = self.neutron()
@@ -43,28 +58,23 @@ class SecurityGroup(resource.Resource):
             'description': self.properties['GroupDescription']}
         })['security_group']
 
+        def sanitize_security_group(i):
+            # Neutron only accepts positive ints
+            if i.get('FromPort') is not None and int(i['FromPort']) < 0:
+                i['FromPort'] = None
+            if i.get('ToPort') is not None and int(i['ToPort']) < 0:
+                i['ToPort'] = None
+            if i.get('FromPort') is None and i.get('ToPort') is None:
+                i['CidrIp'] = None
+
         self.resource_id_set(sec['id'])
         if self.properties['SecurityGroupIngress']:
             for i in self.properties['SecurityGroupIngress']:
-                # Neutron only accepts positive ints
-                if int(i['FromPort']) < 0:
-                    i['FromPort'] = None
-                if int(i['ToPort']) < 0:
-                    i['ToPort'] = None
-                if i['FromPort'] is None and i['ToPort'] is None:
-                    i['CidrIp'] = None
-
+                sanitize_security_group(i)
                 try:
                     rule = client.create_security_group_rule({
-                        'security_group_rule': {
-                            'direction': 'ingress',
-                            'remote_ip_prefix': i['CidrIp'],
-                            'port_range_min': i['FromPort'],
-                            'ethertype': 'IPv4',
-                            'port_range_max': i['ToPort'],
-                            'protocol': i['IpProtocol'],
-                            'security_group_id': sec['id']
-                        }
+                        'security_group_rule':
+                        self._convert_to_neutron_rule('ingress', i)
                     })
                 except NeutronClientException as ex:
                     if ex.status_code == 409:
@@ -74,18 +84,17 @@ class SecurityGroup(resource.Resource):
                         # unexpected error
                         raise
         if self.properties['SecurityGroupEgress']:
+            # Delete the default rules which allow all egress traffic
+            for rule in sec['security_group_rules']:
+                if rule['direction'] == 'egress':
+                    client.delete_security_group_rule(rule['id'])
+
             for i in self.properties['SecurityGroupEgress']:
+                sanitize_security_group(i)
                 try:
                     rule = client.create_security_group_rule({
-                        'security_group_rule': {
-                            'direction': 'egress',
-                            'remote_ip_prefix': i['CidrIp'],
-                            'port_range_min': i['FromPort'],
-                            'ethertype': 'IPv4',
-                            'port_range_max': i['ToPort'],
-                            'protocol': i['IpProtocol'],
-                            'security_group_id': sec['id']
-                        }
+                        'security_group_rule':
+                        self._convert_to_neutron_rule('egress', i)
                     })
                 except NeutronClientException as ex:
                     if ex.status_code == 409:
@@ -113,12 +122,22 @@ class SecurityGroup(resource.Resource):
         if self.properties['SecurityGroupIngress']:
             rules_client = self.nova().security_group_rules
             for i in self.properties['SecurityGroupIngress']:
+                source_group_id = None
+                if i.get('SourceSecurityGroupId') is not None:
+                    source_group_id = i['SourceSecurityGroupId']
+                elif i.get('SourceSecurityGroupName') is not None:
+                    for group in groups:
+                        if group.name == i['SourceSecurityGroupName']:
+                            source_group_id = group.id
+                            break
                 try:
-                    rule = rules_client.create(sec.id,
-                                               i['IpProtocol'],
-                                               i['FromPort'],
-                                               i['ToPort'],
-                                               i['CidrIp'])
+                    rule = rules_client.create(
+                        sec.id,
+                        i.get('IpProtocol'),
+                        i.get('FromPort'),
+                        i.get('ToPort'),
+                        i.get('CidrIp'),
+                        source_group_id)
                 except clients.novaclient.exceptions.BadRequest as ex:
                     if ex.message.find('already exists') >= 0:
                         # no worries, the rule is already there
@@ -181,6 +200,16 @@ class SecurityGroup(resource.Resource):
         else:
             return self.physical_resource_name()
 
+    def validate(self):
+        res = super(SecurityGroup, self).validate()
+        if res:
+            return res
+
+        if self.properties['SecurityGroupEgress'] and not(
+                self.properties['VpcId'] and
+                clients.neutronclient is not None):
+            raise exception.EgressRuleNotAllowed()
+
 
 def resource_mapping():
     return {
index e8e12f2c06c73d3fdb2fde02f32bfb9830495424..d3af56bcb0a714545e3dd4da0ade7aee0673d62e 100644 (file)
@@ -15,6 +15,7 @@
 import collections
 
 from heat.engine import clients
+from heat.common import exception
 from heat.common import template_format
 from heat.engine import parser
 from heat.engine import resource
@@ -55,6 +56,24 @@ Resources:
           FromPort : 80
           ToPort : 80
           CidrIp : 0.0.0.0/0
+        - IpProtocol: tcp
+          SourceSecurityGroupName: test
+        - IpProtocol: icmp
+          SourceSecurityGroupId: 1
+'''
+
+    test_template_nova_with_egress = '''
+HeatTemplateFormatVersion: '2012-12-12'
+Resources:
+  the_sg:
+    Type: AWS::EC2::SecurityGroup
+    Properties:
+      GroupDescription: HTTP and SSH access
+      SecurityGroupEgress:
+        - IpProtocol: tcp
+          FromPort: 22
+          ToPort: 22
+          CidrIp: 0.0.0.0/0
 '''
 
     test_template_neutron = '''
@@ -74,11 +93,14 @@ Resources:
           FromPort : 80
           ToPort : 80
           CidrIp : 0.0.0.0/0
+        - IpProtocol: tcp
+          SourceSecurityGroupId: wwww
       SecurityGroupEgress:
         - IpProtocol: tcp
           FromPort: 22
           ToPort: 22
           CidrIp: 10.0.1.0/24
+        - SourceSecurityGroupName: xxxx
 '''
 
     def setUp(self):
@@ -142,9 +164,13 @@ Resources:
 
         clients.OpenStackClients.nova('compute').AndReturn(self.fc)
         nova_sgr.SecurityGroupRuleManager.create(
-            2, 'tcp', 22, 22, '0.0.0.0/0').AndReturn(None)
+            2, 'tcp', 22, 22, '0.0.0.0/0', None).AndReturn(None)
+        nova_sgr.SecurityGroupRuleManager.create(
+            2, 'tcp', 80, 80, '0.0.0.0/0', None).AndReturn(None)
         nova_sgr.SecurityGroupRuleManager.create(
-            2, 'tcp', 80, 80, '0.0.0.0/0').AndReturn(None)
+            2, 'tcp', None, None, None, 1).AndReturn(None)
+        nova_sgr.SecurityGroupRuleManager.create(
+            2, 'icmp', None, None, None, 1).AndReturn(None)
 
         # delete script
         clients.OpenStackClients.nova('compute').AndReturn(self.fc)
@@ -172,6 +198,28 @@ Resources:
                     'cidr': '0.0.0.0/0'
                 },
                 'id': 131
+            }, {
+                'from_port': None,
+                'group': {
+                    'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
+                    'name': 'test'
+                },
+                'ip_protocol': 'tcp',
+                'to_port': None,
+                'parent_group_id': 2,
+                'ip_range': {},
+                'id': 132
+            }, {
+                'from_port': None,
+                'group': {
+                    'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
+                    'name': 'test'
+                },
+                'ip_protocol': 'icmp',
+                'to_port': None,
+                'parent_group_id': 2,
+                'ip_range': {},
+                'id': 133
             }]
         ))
         clients.OpenStackClients.nova('compute').AndReturn(self.fc)
@@ -179,6 +227,10 @@ Resources:
         clients.OpenStackClients.nova('compute').AndReturn(self.fc)
         nova_sgr.SecurityGroupRuleManager.delete(131).AndReturn(None)
         clients.OpenStackClients.nova('compute').AndReturn(self.fc)
+        nova_sgr.SecurityGroupRuleManager.delete(132).AndReturn(None)
+        clients.OpenStackClients.nova('compute').AndReturn(self.fc)
+        nova_sgr.SecurityGroupRuleManager.delete(133).AndReturn(None)
+        clients.OpenStackClients.nova('compute').AndReturn(self.fc)
         nova_sg.SecurityGroupManager.delete(2).AndReturn(None)
 
         self.m.ReplayAll()
@@ -197,20 +249,36 @@ Resources:
         #create script
         clients.OpenStackClients.nova('compute').AndReturn(self.fc)
         sg_name = utils.PhysName('test_stack', 'the_sg')
-        nova_sg.SecurityGroupManager.list().AndReturn([NovaSG(
-            id=2,
-            name=sg_name,
-            description='HTTP and SSH access',
-            rules=[],
-        )])
+        nova_sg.SecurityGroupManager.list().AndReturn([
+            NovaSG(
+                id=2,
+                name=sg_name,
+                description='HTTP and SSH access',
+                rules=[],
+            ),
+            NovaSG(
+                id=1,
+                name='test',
+                description='FAKE_SECURITY_GROUP',
+                rules=[],
+            )
+        ])
 
         clients.OpenStackClients.nova('compute').AndReturn(self.fc)
         nova_sgr.SecurityGroupRuleManager.create(
-            2, 'tcp', 22, 22, '0.0.0.0/0').AndRaise(
+            2, 'tcp', 22, 22, '0.0.0.0/0', None).AndRaise(
+                clients.novaclient.exceptions.BadRequest(
+                    400, 'Rule already exists'))
+        nova_sgr.SecurityGroupRuleManager.create(
+            2, 'tcp', 80, 80, '0.0.0.0/0', None).AndReturn(
                 clients.novaclient.exceptions.BadRequest(
                     400, 'Rule already exists'))
         nova_sgr.SecurityGroupRuleManager.create(
-            2, 'tcp', 80, 80, '0.0.0.0/0').AndReturn(
+            2, 'tcp', None, None, None, 1).AndReturn(
+                clients.novaclient.exceptions.BadRequest(
+                    400, 'Rule already exists'))
+        nova_sgr.SecurityGroupRuleManager.create(
+            2, 'icmp', None, None, None, 1).AndReturn(
                 clients.novaclient.exceptions.BadRequest(
                     400, 'Rule already exists'))
 
@@ -240,6 +308,28 @@ Resources:
                     'cidr': '0.0.0.0/0'
                 },
                 'id': 131
+            }, {
+                'from_port': None,
+                'group': {
+                    'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
+                    'name': 'test'
+                },
+                'ip_protocol': 'tcp',
+                'to_port': None,
+                'parent_group_id': 2,
+                'ip_range': {},
+                'id': 132
+            }, {
+                'from_port': None,
+                'group': {
+                    'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
+                    'name': 'test'
+                },
+                'ip_protocol': 'icmp',
+                'to_port': None,
+                'parent_group_id': 2,
+                'ip_range': {},
+                'id': 133
             }]
         ))
         clients.OpenStackClients.nova('compute').AndReturn(self.fc)
@@ -249,6 +339,12 @@ Resources:
         nova_sgr.SecurityGroupRuleManager.delete(131).AndRaise(
             clients.novaclient.exceptions.NotFound('goneburger'))
         clients.OpenStackClients.nova('compute').AndReturn(self.fc)
+        nova_sgr.SecurityGroupRuleManager.delete(132).AndRaise(
+            clients.novaclient.exceptions.NotFound('goneburger'))
+        clients.OpenStackClients.nova('compute').AndReturn(self.fc)
+        nova_sgr.SecurityGroupRuleManager.delete(133).AndRaise(
+            clients.novaclient.exceptions.NotFound('goneburger'))
+        clients.OpenStackClients.nova('compute').AndReturn(self.fc)
         nova_sg.SecurityGroupManager.delete(2).AndReturn(None)
 
         clients.OpenStackClients.nova('compute').AndReturn(self.fc)
@@ -271,6 +367,13 @@ Resources:
 
         self.m.VerifyAll()
 
+    def test_security_group_nova_with_egress_rules(self):
+        t = template_format.parse(self.test_template_nova_with_egress)
+        stack = self.parse_stack(t)
+
+        sg = stack['the_sg']
+        self.assertRaises(exception.EgressRuleNotAllowed, sg.validate)
+
     @utils.stack_delete_after
     def test_security_group_neutron(self):
         #create script
@@ -287,7 +390,29 @@ Resources:
                 'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
                 'name': sg_name,
                 'description': 'HTTP and SSH access',
-                'security_group_rules': [],
+                'security_group_rules': [{
+                    "direction": "egress",
+                    "ethertype": "IPv4",
+                    "id": "aaaa-1",
+                    "port_range_max": None,
+                    "port_range_min": None,
+                    "protocol": None,
+                    "remote_group_id": None,
+                    "remote_ip_prefix": None,
+                    "security_group_id": "aaaa",
+                    "tenant_id": "f18ca530cc05425e8bac0a5ff92f7e88"
+                }, {
+                    "direction": "egress",
+                    "ethertype": "IPv6",
+                    "id": "aaaa-2",
+                    "port_range_max": None,
+                    "port_range_min": None,
+                    "protocol": None,
+                    "remote_group_id": None,
+                    "remote_ip_prefix": None,
+                    "security_group_id": "aaaa",
+                    "tenant_id": "f18ca530cc05425e8bac0a5ff92f7e88"
+                }],
                 'id': 'aaaa'
             }
         })
@@ -295,6 +420,7 @@ Resources:
         neutronclient.Client.create_security_group_rule({
             'security_group_rule': {
                 'direction': 'ingress',
+                'remote_group_id': None,
                 'remote_ip_prefix': '0.0.0.0/0',
                 'port_range_min': 22,
                 'ethertype': 'IPv4',
@@ -305,6 +431,7 @@ Resources:
         }).AndReturn({
             'security_group_rule': {
                 'direction': 'ingress',
+                'remote_group_id': None,
                 'remote_ip_prefix': '0.0.0.0/0',
                 'port_range_min': 22,
                 'ethertype': 'IPv4',
@@ -317,6 +444,7 @@ Resources:
         neutronclient.Client.create_security_group_rule({
             'security_group_rule': {
                 'direction': 'ingress',
+                'remote_group_id': None,
                 'remote_ip_prefix': '0.0.0.0/0',
                 'port_range_min': 80,
                 'ethertype': 'IPv4',
@@ -327,6 +455,7 @@ Resources:
         }).AndReturn({
             'security_group_rule': {
                 'direction': 'ingress',
+                'remote_group_id': None,
                 'remote_ip_prefix': '0.0.0.0/0',
                 'port_range_min': 80,
                 'ethertype': 'IPv4',
@@ -336,9 +465,38 @@ Resources:
                 'id': 'cccc'
             }
         })
+        neutronclient.Client.create_security_group_rule({
+            'security_group_rule': {
+                'direction': 'ingress',
+                'remote_group_id': 'wwww',
+                'remote_ip_prefix': None,
+                'port_range_min': None,
+                'ethertype': 'IPv4',
+                'port_range_max': None,
+                'protocol': 'tcp',
+                'security_group_id': 'aaaa'
+            }
+        }).AndReturn({
+            'security_group_rule': {
+                'direction': 'ingress',
+                'remote_group_id': 'wwww',
+                'remote_ip_prefix': None,
+                'port_range_min': None,
+                'ethertype': 'IPv4',
+                'port_range_max': None,
+                'protocol': 'tcp',
+                'security_group_id': 'aaaa',
+                'id': 'dddd'
+            }
+        })
+        neutronclient.Client.delete_security_group_rule('aaaa-1').AndReturn(
+            None)
+        neutronclient.Client.delete_security_group_rule('aaaa-2').AndReturn(
+            None)
         neutronclient.Client.create_security_group_rule({
             'security_group_rule': {
                 'direction': 'egress',
+                'remote_group_id': None,
                 'remote_ip_prefix': '10.0.1.0/24',
                 'port_range_min': 22,
                 'ethertype': 'IPv4',
@@ -349,13 +507,38 @@ Resources:
         }).AndReturn({
             'security_group_rule': {
                 'direction': 'egress',
+                'remote_group_id': None,
                 'remote_ip_prefix': '10.0.1.0/24',
                 'port_range_min': 22,
                 'ethertype': 'IPv4',
                 'port_range_max': 22,
                 'protocol': 'tcp',
                 'security_group_id': 'aaaa',
-                'id': 'dddd'
+                'id': 'eeee'
+            }
+        })
+        neutronclient.Client.create_security_group_rule({
+            'security_group_rule': {
+                'direction': 'egress',
+                'remote_group_id': 'xxxx',
+                'remote_ip_prefix': None,
+                'port_range_min': None,
+                'ethertype': 'IPv4',
+                'port_range_max': None,
+                'protocol': None,
+                'security_group_id': 'aaaa'
+            }
+        }).AndReturn({
+            'security_group_rule': {
+                'direction': 'egress',
+                'remote_group_id': 'xxxx',
+                'remote_ip_prefix': None,
+                'port_range_min': None,
+                'ethertype': 'IPv4',
+                'port_range_max': None,
+                'protocol': None,
+                'security_group_id': 'aaaa',
+                'id': 'ffff'
             }
         })
 
@@ -372,6 +555,7 @@ Resources:
                     'id': 'bbbb',
                     'ethertype': 'IPv4',
                     'security_group_id': 'aaaa',
+                    'remote_group_id': None,
                     'remote_ip_prefix': '0.0.0.0/0',
                     'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
                     'port_range_min': 22
@@ -382,24 +566,50 @@ Resources:
                     'id': 'cccc',
                     'ethertype': 'IPv4',
                     'security_group_id': 'aaaa',
+                    'remote_group_id': None,
                     'remote_ip_prefix': '0.0.0.0/0',
                     'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
                     'port_range_min': 80
+                }, {
+                    'direction': 'ingress',
+                    'protocol': 'tcp',
+                    'port_range_max': None,
+                    'id': 'dddd',
+                    'ethertype': 'IPv4',
+                    'security_group_id': 'aaaa',
+                    'remote_group_id': 'wwww',
+                    'remote_ip_prefix': None,
+                    'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
+                    'port_range_min': None
                 }, {
                     'direction': 'egress',
                     'protocol': 'tcp',
                     'port_range_max': 22,
-                    'id': 'dddd',
+                    'id': 'eeee',
                     'ethertype': 'IPv4',
                     'security_group_id': 'aaaa',
+                    'remote_group_id': None,
                     'remote_ip_prefix': '10.0.1.0/24',
                     'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
                     'port_range_min': 22
+                }, {
+                    'direction': 'egress',
+                    'protocol': None,
+                    'port_range_max': None,
+                    'id': 'ffff',
+                    'ethertype': 'IPv4',
+                    'security_group_id': 'aaaa',
+                    'remote_group_id': None,
+                    'remote_ip_prefix': None,
+                    'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
+                    'port_range_min': None
                 }],
                 'id': 'aaaa'}})
         neutronclient.Client.delete_security_group_rule('bbbb').AndReturn(None)
         neutronclient.Client.delete_security_group_rule('cccc').AndReturn(None)
         neutronclient.Client.delete_security_group_rule('dddd').AndReturn(None)
+        neutronclient.Client.delete_security_group_rule('eeee').AndReturn(None)
+        neutronclient.Client.delete_security_group_rule('ffff').AndReturn(None)
         neutronclient.Client.delete_security_group('aaaa').AndReturn(None)
 
         self.m.ReplayAll()
@@ -437,6 +647,7 @@ Resources:
         neutronclient.Client.create_security_group_rule({
             'security_group_rule': {
                 'direction': 'ingress',
+                'remote_group_id': None,
                 'remote_ip_prefix': '0.0.0.0/0',
                 'port_range_min': 22,
                 'ethertype': 'IPv4',
@@ -449,6 +660,7 @@ Resources:
         neutronclient.Client.create_security_group_rule({
             'security_group_rule': {
                 'direction': 'ingress',
+                'remote_group_id': None,
                 'remote_ip_prefix': '0.0.0.0/0',
                 'port_range_min': 80,
                 'ethertype': 'IPv4',
@@ -458,9 +670,23 @@ Resources:
             }
         }).AndRaise(
             NeutronClientException(status_code=409))
+        neutronclient.Client.create_security_group_rule({
+            'security_group_rule': {
+                'direction': 'ingress',
+                'remote_group_id': 'wwww',
+                'remote_ip_prefix': None,
+                'port_range_min': None,
+                'ethertype': 'IPv4',
+                'port_range_max': None,
+                'protocol': 'tcp',
+                'security_group_id': 'aaaa'
+            }
+        }).AndRaise(
+            NeutronClientException(status_code=409))
         neutronclient.Client.create_security_group_rule({
             'security_group_rule': {
                 'direction': 'egress',
+                'remote_group_id': None,
                 'remote_ip_prefix': '10.0.1.0/24',
                 'port_range_min': 22,
                 'ethertype': 'IPv4',
@@ -470,6 +696,19 @@ Resources:
             }
         }).AndRaise(
             NeutronClientException(status_code=409))
+        neutronclient.Client.create_security_group_rule({
+            'security_group_rule': {
+                'direction': 'egress',
+                'remote_group_id': 'xxxx',
+                'remote_ip_prefix': None,
+                'port_range_min': None,
+                'ethertype': 'IPv4',
+                'port_range_max': None,
+                'protocol': None,
+                'security_group_id': 'aaaa'
+            }
+        }).AndRaise(
+            NeutronClientException(status_code=409))
 
         # delete script
         neutronclient.Client.show_security_group('aaaa').AndReturn({
@@ -484,6 +723,7 @@ Resources:
                     'id': 'bbbb',
                     'ethertype': 'IPv4',
                     'security_group_id': 'aaaa',
+                    'remote_group_id': None,
                     'remote_ip_prefix': '0.0.0.0/0',
                     'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
                     'port_range_min': 22
@@ -494,19 +734,43 @@ Resources:
                     'id': 'cccc',
                     'ethertype': 'IPv4',
                     'security_group_id': 'aaaa',
+                    'remote_group_id': None,
                     'remote_ip_prefix': '0.0.0.0/0',
                     'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
                     'port_range_min': 80
+                }, {
+                    'direction': 'ingress',
+                    'protocol': 'tcp',
+                    'port_range_max': None,
+                    'id': 'dddd',
+                    'ethertype': 'IPv4',
+                    'security_group_id': 'aaaa',
+                    'remote_group_id': 'wwww',
+                    'remote_ip_prefix': None,
+                    'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
+                    'port_range_min': None
                 }, {
                     'direction': 'egress',
                     'protocol': 'tcp',
                     'port_range_max': 22,
-                    'id': 'dddd',
+                    'id': 'eeee',
                     'ethertype': 'IPv4',
                     'security_group_id': 'aaaa',
+                    'remote_group_id': None,
                     'remote_ip_prefix': '10.0.1.0/24',
                     'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
                     'port_range_min': 22
+                }, {
+                    'direction': 'egress',
+                    'protocol': None,
+                    'port_range_max': None,
+                    'id': 'ffff',
+                    'ethertype': 'IPv4',
+                    'security_group_id': 'aaaa',
+                    'remote_group_id': None,
+                    'remote_ip_prefix': None,
+                    'tenant_id': 'f18ca530cc05425e8bac0a5ff92f7e88',
+                    'port_range_min': None
                 }],
                 'id': 'aaaa'}})
         neutronclient.Client.delete_security_group_rule('bbbb').AndRaise(
@@ -515,6 +779,10 @@ Resources:
             NeutronClientException(status_code=404))
         neutronclient.Client.delete_security_group_rule('dddd').AndRaise(
             NeutronClientException(status_code=404))
+        neutronclient.Client.delete_security_group_rule('eeee').AndRaise(
+            NeutronClientException(status_code=404))
+        neutronclient.Client.delete_security_group_rule('ffff').AndRaise(
+            NeutronClientException(status_code=404))
         neutronclient.Client.delete_security_group('aaaa').AndRaise(
             NeutronClientException(status_code=404))
 
index 9c6246a595df53ccf030d0a71aae3950f94b9911..103dc2bb1b81c30cfcb8c813c34ee87ca7266122 100644 (file)
@@ -192,6 +192,7 @@ class VPCTestBase(HeatTestCase):
         neutronclient.Client.create_security_group_rule({
             'security_group_rule': {
                 'direction': 'ingress',
+                'remote_group_id': None,
                 'remote_ip_prefix': '0.0.0.0/0',
                 'port_range_min': 22,
                 'ethertype': 'IPv4',
@@ -202,6 +203,7 @@ class VPCTestBase(HeatTestCase):
         }).AndReturn({
             'security_group_rule': {
                 'direction': 'ingress',
+                'remote_group_id': None,
                 'remote_ip_prefix': '0.0.0.0/0',
                 'port_range_min': 22,
                 'ethertype': 'IPv4',
@@ -226,6 +228,7 @@ class VPCTestBase(HeatTestCase):
                     'id': 'bbbb',
                     'ethertype': 'IPv4',
                     'security_group_id': 'eeee',
+                    'remote_group_id': None,
                     'remote_ip_prefix': '0.0.0.0/0',
                     'tenant_id': 'c1210485b2424d48804aad5d39c61b8f',
                     'port_range_min': 22