From 764f018f50ac7cd42c29efeabaccbb5aec21f6f4 Mon Sep 17 00:00:00 2001 From: shihanzhang Date: Mon, 1 Jun 2015 16:17:37 +0800 Subject: [PATCH] Fix ipset can't be destroyed when last rule is deleted 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 | 14 ++++++++++++ .../unit/agent/test_securitygroups_rpc.py | 22 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/neutron/db/securitygroups_rpc_base.py b/neutron/db/securitygroups_rpc_base.py index 7ae461d74..156399404 100644 --- a/neutron/db/securitygroups_rpc_base.py +++ b/neutron/db/securitygroups_rpc_base.py @@ -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 [] diff --git a/neutron/tests/unit/agent/test_securitygroups_rpc.py b/neutron/tests/unit/agent/test_securitygroups_rpc.py index 030899cf7..1cc7afd59 100644 --- a/neutron/tests/unit/agent/test_securitygroups_rpc.py +++ b/neutron/tests/unit/agent/test_securitygroups_rpc.py @@ -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() -- 2.45.2