diff --git a/neutron/agent/firewall.py b/neutron/agent/firewall.py index 1f3e18961eb..424ed64d923 100644 --- a/neutron/agent/firewall.py +++ b/neutron/agent/firewall.py @@ -162,6 +162,13 @@ class FirewallDriver(object): """ raise NotImplementedError() + def process_trusted_ports(self, port_ids): + """Process ports that are trusted and shouldn't be filtered.""" + pass + + def remove_trusted_ports(self, port_ids): + pass + class NoopFirewallDriver(FirewallDriver): """Noop Firewall Driver. diff --git a/neutron/agent/securitygroups_rpc.py b/neutron/agent/securitygroups_rpc.py index f0d4953d3d9..21df1ddea5b 100644 --- a/neutron/agent/securitygroups_rpc.py +++ b/neutron/agent/securitygroups_rpc.py @@ -128,6 +128,7 @@ class SecurityGroupAgentRpc(object): else: devices = self.plugin_rpc.security_group_rules_for_devices( self.context, list(device_ids)) + trusted_devices = list(set(device_ids) - set(devices.keys())) with self.firewall.defer_apply(): if self.use_enhanced_rpc: @@ -142,6 +143,7 @@ class SecurityGroupAgentRpc(object): else: LOG.debug("Prepare port filter for %s", device['device']) self.firewall.prepare_port_filter(device) + self.firewall.process_trusted_ports(trusted_devices) def _update_security_group_info(self, security_groups, security_group_member_ips): @@ -213,9 +215,10 @@ class SecurityGroupAgentRpc(object): with self.firewall.defer_apply(): for device_id in device_ids: device = self.firewall.ports.get(device_id) - if not device: - continue - self.firewall.remove_port_filter(device) + if device: + self.firewall.remove_port_filter(device) + else: + self.firewall.remove_trusted_ports([device_id]) @skip_if_noopfirewall_or_firewall_disabled def refresh_firewall(self, device_ids=None): diff --git a/neutron/tests/unit/agent/test_securitygroups_rpc.py b/neutron/tests/unit/agent/test_securitygroups_rpc.py index 1c42999c62d..b234757311d 100644 --- a/neutron/tests/unit/agent/test_securitygroups_rpc.py +++ b/neutron/tests/unit/agent/test_securitygroups_rpc.py @@ -871,6 +871,7 @@ class SecurityGroupAgentRpcTestCase(BaseSecurityGroupAgentRpcTestCase): self.firewall.assert_has_calls([mock.call.defer_apply(), mock.call.prepare_port_filter( self.fake_device), + mock.call.process_trusted_ports([]), mock.call.defer_apply(), mock.call.remove_port_filter( self.fake_device), @@ -896,6 +897,35 @@ class SecurityGroupAgentRpcTestCase(BaseSecurityGroupAgentRpcTestCase): self.assertFalse(self.agent.plugin_rpc. security_group_rules_for_devices.called) + def test_prepare_devices_filter_with_trusted_ports(self): + devices_to_filter = {k: {'device': k} for k in range(4, 8)} + all_devices = range(10) + expected_devices = [0, 1, 2, 3, 8, 9] + self.agent._use_enhanced_rpc = True + with mock.patch.object( + self.agent.plugin_rpc, + 'security_group_info_for_devices', + return_value={ + 'devices': devices_to_filter, + 'security_groups': {}, + 'sg_member_ips': {}}): + with mock.patch.object( + self.agent.firewall, 'process_trusted_ports') as m_process: + self.agent.prepare_devices_filter(all_devices) + m_process.assert_called_once_with(expected_devices) + + def test_remove_devices_filter_with_trusted_ports(self): + all_devices = range(10) + firewall_managed_ports = {k: k for k in range(4, 8)} + trusted_port_ids = [0, 1, 2, 3, 8, 9] + with mock.patch.object(self.agent, 'firewall') as mock_firewall: + mock_firewall.ports = firewall_managed_ports + self.agent.remove_devices_filter(all_devices) + mock_firewall.remove_port_filter.assert_has_calls( + [mock.call(i) for i in firewall_managed_ports.keys()]) + mock_firewall.remove_trusted_ports( + [mock.call([i]) for i in trusted_port_ids]) + def test_security_groups_rule_updated(self): self.agent.refresh_firewall = mock.Mock() self.agent.prepare_devices_filter(['fake_port_id']) @@ -937,17 +967,21 @@ class SecurityGroupAgentRpcTestCase(BaseSecurityGroupAgentRpcTestCase): self.agent.refresh_firewall() calls = [mock.call.defer_apply(), mock.call.prepare_port_filter(self.fake_device), + mock.call.process_trusted_ports(['fake_port_id']), mock.call.defer_apply(), - mock.call.update_port_filter(self.fake_device)] + mock.call.update_port_filter(self.fake_device), + mock.call.process_trusted_ports([])] self.firewall.assert_has_calls(calls) def test_refresh_firewall_devices(self): self.agent.prepare_devices_filter(['fake_port_id']) - self.agent.refresh_firewall([self.fake_device]) + self.agent.refresh_firewall([self.fake_device['device']]) calls = [mock.call.defer_apply(), mock.call.prepare_port_filter(self.fake_device), + mock.call.process_trusted_ports(['fake_port_id']), mock.call.defer_apply(), - mock.call.update_port_filter(self.fake_device)] + mock.call.update_port_filter(self.fake_device), + mock.call.process_trusted_ports([])] self.firewall.assert_has_calls(calls) def test_refresh_firewall_none(self): @@ -959,7 +993,7 @@ class SecurityGroupAgentRpcTestCase(BaseSecurityGroupAgentRpcTestCase): self.agent.plugin_rpc.security_group_info_for_devices = mock.Mock() self.agent.plugin_rpc.security_group_rules_for_devices = mock.Mock() self.agent.firewall.defer_apply = mock.Mock() - self.agent.refresh_firewall([self.fake_device]) + self.agent.refresh_firewall([self.fake_device['device']]) self.assertFalse(self.agent.plugin_rpc. security_group_info_for_devices.called) self.assertFalse(self.agent.plugin_rpc. @@ -1010,6 +1044,7 @@ class SecurityGroupAgentEnhancedRpcTestCase( tmp_mock2, mock.call.prepare_port_filter( self.fake_device), + mock.call.process_trusted_ports([]), mock.call.defer_apply(), mock.call.remove_port_filter( self.fake_device), @@ -1066,19 +1101,21 @@ class SecurityGroupAgentEnhancedRpcTestCase( mock.call.update_security_group_members( 'fake_sgid2', {'IPv4': [], 'IPv6': []}), mock.call.prepare_port_filter(self.fake_device), + mock.call.process_trusted_ports(['fake_port_id']), mock.call.defer_apply(), mock.call.update_security_group_rules('fake_sgid2', []), mock.call.update_security_group_rules( 'fake_sgid1', [{'remote_group_id': 'fake_sgid2'}]), mock.call.update_security_group_members( 'fake_sgid2', {'IPv4': [], 'IPv6': []}), - mock.call.update_port_filter(self.fake_device)] + mock.call.update_port_filter(self.fake_device), + mock.call.process_trusted_ports([])] self.firewall.assert_has_calls(calls) def test_refresh_firewall_devices_enhanced_rpc(self): self.agent.prepare_devices_filter(['fake_device']) - self.agent.refresh_firewall([self.fake_device]) + self.agent.refresh_firewall([self.fake_device['device']]) calls = [mock.call.defer_apply(), mock.call.update_security_group_rules('fake_sgid2', []), mock.call.update_security_group_rules('fake_sgid1', [ @@ -1087,13 +1124,15 @@ class SecurityGroupAgentEnhancedRpcTestCase( 'IPv4': [], 'IPv6': [] }), mock.call.prepare_port_filter(self.fake_device), + mock.call.process_trusted_ports([]), mock.call.defer_apply(), mock.call.update_security_group_rules('fake_sgid2', []), mock.call.update_security_group_rules('fake_sgid1', [ {'remote_group_id': 'fake_sgid2'}]), mock.call.update_security_group_members('fake_sgid2', { 'IPv4': [], 'IPv6': []}), - mock.call.update_port_filter(self.fake_device) + mock.call.update_port_filter(self.fake_device), + mock.call.process_trusted_ports([]), ] self.firewall.assert_has_calls(calls)