]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Fix ipset can't be destroyed when last rule is deleted
authorshihanzhang <shihanzhang@huawei.com>
Mon, 1 Jun 2015 08:17:37 +0000 (16:17 +0800)
committershihanzhang <shihanzhang@huawei.com>
Mon, 3 Aug 2015 04:57:11 +0000 (12:57 +0800)
when it deletes a security group all rules, it should
include this sg information in RPC method
'security_group_info_for_devices', otherwise the ports
in this sg can't corrcectly update their iptables and
ipset sets.

Change-Id: Ibb071ce84590bd46cda2c1e010a566e75e22b4d2
Closes-bug: #1460562

neutron/db/securitygroups_rpc_base.py
neutron/tests/unit/agent/test_securitygroups_rpc.py

index 7ae461d74c7902ab5acb45488e68b7564db528b1..15639940431b16ea87906093613a04ed6195c8fd 100644 (file)
@@ -205,6 +205,11 @@ class SecurityGroupServerRpcMixin(sg_db.SecurityGroupDbMixin):
             if rule_dict not in sg_info['security_groups'][security_group_id]:
                 sg_info['security_groups'][security_group_id].append(
                     rule_dict)
+        # Update the security groups info if they don't have any rules
+        sg_ids = self._select_sg_ids_for_ports(context, ports)
+        for (sg_id, ) in sg_ids:
+            if sg_id not in sg_info['security_groups']:
+                sg_info['security_groups'][sg_id] = []
 
         sg_info['sg_member_ips'] = remote_security_group_info
         # the provider rules do not belong to any security group, so these
@@ -223,6 +228,15 @@ class SecurityGroupServerRpcMixin(sg_db.SecurityGroupDbMixin):
                     sg_info['sg_member_ips'][sg_id][ethertype].add(ip)
         return sg_info
 
+    def _select_sg_ids_for_ports(self, context, ports):
+        if not ports:
+            return []
+        sg_binding_port = sg_db.SecurityGroupPortBinding.port_id
+        sg_binding_sgid = sg_db.SecurityGroupPortBinding.security_group_id
+        query = context.session.query(sg_binding_sgid)
+        query = query.filter(sg_binding_port.in_(ports.keys()))
+        return query.all()
+
     def _select_rules_for_ports(self, context, ports):
         if not ports:
             return []
index 030899cf7a677dd8e3d247ad17e4f323c50d241a..1cc7afd594d9445f418ad7dd32e3a1ca0b1f7756 100644 (file)
@@ -242,6 +242,28 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
     def test_sg_rules_for_devices_ipv4_ingress_port_range_min_port_1(self):
         self._test_sg_rules_for_devices_ipv4_ingress_port_range(1, 10)
 
+    def test_security_group_info_for_ports_with_no_rules(self):
+        with self.network() as n,\
+                self.subnet(n),\
+                self.security_group() as sg:
+            sg_id = sg['security_group']['id']
+            self._delete_default_security_group_egress_rules(sg_id)
+
+            res = self._create_port(
+                self.fmt, n['network']['id'],
+                security_groups=[sg_id])
+            ports_rest = self.deserialize(self.fmt, res)
+            port_id = ports_rest['port']['id']
+            self.rpc.devices = {port_id: ports_rest['port']}
+            devices = [port_id]
+            ctx = context.get_admin_context()
+            sg_info = self.rpc.security_group_info_for_devices(
+                ctx, devices=devices)
+
+            expected = {sg_id: []}
+            self.assertEqual(expected, sg_info['security_groups'])
+            self._delete('ports', port_id)
+
     @contextlib.contextmanager
     def _port_with_addr_pairs_and_security_group(self):
         plugin_obj = manager.NeutronManager.get_plugin()