From c44506bfd60b2dd6036e113464f1ea682cfaeb6c Mon Sep 17 00:00:00 2001 From: Kevin Benton Date: Fri, 17 Apr 2015 04:03:38 -0700 Subject: [PATCH] Don't update floating IP status if no change The floating IP status was going through all of the status update code every time the L3 agent sent in an update, even if the status didn't change. This patch skips sending updates to the server if the agent doesn't change the status. Change-Id: Ic3736bed3dc3e4ccb91f4acfabbf033949e09ce0 Partial-Bug: #1445412 --- neutron/agent/l3/agent.py | 6 +++++ neutron/agent/l3/router_info.py | 5 ++++ neutron/tests/unit/agent/l3/test_agent.py | 24 +++++++++++++++++++ .../tests/unit/agent/l3/test_router_info.py | 3 ++- 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/neutron/agent/l3/agent.py b/neutron/agent/l3/agent.py index 2c1c1696e..03f40d61c 100644 --- a/neutron/agent/l3/agent.py +++ b/neutron/agent/l3/agent.py @@ -29,6 +29,7 @@ from neutron.agent.l3 import ha_router from neutron.agent.l3 import legacy_router from neutron.agent.l3 import namespace_manager from neutron.agent.l3 import namespaces +from neutron.agent.l3 import router_info as rinf from neutron.agent.l3 import router_processing_queue as queue from neutron.agent.linux import external_process from neutron.agent.linux import ip_lib @@ -348,6 +349,11 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, ri.floating_ips = set(fip_statuses.keys()) for fip_id in existing_floating_ips - ri.floating_ips: fip_statuses[fip_id] = l3_constants.FLOATINGIP_STATUS_DOWN + # filter out statuses that didn't change + fip_statuses = {f: stat for f, stat in fip_statuses.items() + if stat != rinf.FLOATINGIP_STATUS_NOCHANGE} + if not fip_statuses: + return LOG.debug('Sending floating ip statuses: %s', fip_statuses) # Update floating IP status on the neutron server self.plugin_rpc.update_floatingip_statuses( diff --git a/neutron/agent/l3/router_info.py b/neutron/agent/l3/router_info.py index 3f0d801a6..adb668bc3 100644 --- a/neutron/agent/l3/router_info.py +++ b/neutron/agent/l3/router_info.py @@ -30,6 +30,7 @@ INTERNAL_DEV_PREFIX = namespaces.INTERNAL_DEV_PREFIX EXTERNAL_DEV_PREFIX = namespaces.EXTERNAL_DEV_PREFIX EXTERNAL_INGRESS_MARK_MASK = '0xffffffff' +FLOATINGIP_STATUS_NOCHANGE = object() class RouterInfo(object): @@ -247,6 +248,10 @@ class RouterInfo(object): {'id': fip['id'], 'status': fip_statuses.get(fip['id'])}) + # mark the status as not changed. we can't remove it because + # that's how the caller determines that it was removed + if fip_statuses[fip['id']] == fip['status']: + fip_statuses[fip['id']] = FLOATINGIP_STATUS_NOCHANGE fips_to_remove = ( ip_cidr for ip_cidr in existing_cidrs - new_cidrs if common_utils.is_cidr_host(ip_cidr)) diff --git a/neutron/tests/unit/agent/l3/test_agent.py b/neutron/tests/unit/agent/l3/test_agent.py index bdf62fbbd..6c1057c90 100644 --- a/neutron/tests/unit/agent/l3/test_agent.py +++ b/neutron/tests/unit/agent/l3/test_agent.py @@ -231,6 +231,7 @@ def prepare_router_data(ip_version=4, enable_snat=None, num_internal_ports=1, router[l3_constants.FLOATINGIP_KEY] = [{ 'id': _uuid(), 'port_id': _uuid(), + 'status': 'DOWN', 'floating_ip_address': '19.4.4.2', 'fixed_ip_address': '10.0.0.1'}] @@ -1274,6 +1275,7 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework): {'id': _uuid(), 'floating_ip_address': '15.1.2.3', 'fixed_ip_address': '192.168.0.1', + 'status': 'DOWN', 'floating_network_id': _uuid(), 'port_id': _uuid(), 'host': HOSTNAME}]} @@ -1690,6 +1692,27 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework): self.assertNotIn( router[l3_constants.INTERFACE_KEY][0], ri.internal_ports) + def test_process_router_floatingip_nochange(self): + agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) + with mock.patch.object( + agent.plugin_rpc, 'update_floatingip_statuses' + ) as mock_update_fip_status: + router = prepare_router_data(num_internal_ports=1) + fip1 = {'id': _uuid(), 'floating_ip_address': '8.8.8.8', + 'fixed_ip_address': '7.7.7.7', 'status': 'ACTIVE', + 'port_id': router[l3_constants.INTERFACE_KEY][0]['id']} + fip2 = copy.copy(fip1) + fip2.update({'id': _uuid(), 'status': 'DOWN'}) + router[l3_constants.FLOATINGIP_KEY] = [fip1, fip2] + + ri = legacy_router.LegacyRouter(router['id'], router, + **self.ri_kwargs) + ri.external_gateway_added = mock.Mock() + ri.process(agent) + # make sure only the one that went from DOWN->ACTIVE was sent + mock_update_fip_status.assert_called_once_with( + mock.ANY, ri.router_id, {fip2['id']: 'ACTIVE'}) + def test_process_router_floatingip_disabled(self): agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) with mock.patch.object( @@ -1701,6 +1724,7 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework): {'id': fip_id, 'floating_ip_address': '8.8.8.8', 'fixed_ip_address': '7.7.7.7', + 'status': 'DOWN', 'port_id': router[l3_constants.INTERFACE_KEY][0]['id']}] ri = legacy_router.LegacyRouter(router['id'], diff --git a/neutron/tests/unit/agent/l3/test_router_info.py b/neutron/tests/unit/agent/l3/test_router_info.py index 04aa55748..5e60aa12c 100644 --- a/neutron/tests/unit/agent/l3/test_router_info.py +++ b/neutron/tests/unit/agent/l3/test_router_info.py @@ -283,7 +283,8 @@ class TestFloatingIpWithMockDevice(BasicRouterTestCaseFramework): fip = { 'id': fip_id, 'port_id': _uuid(), 'floating_ip_address': '15.1.2.3', - 'fixed_ip_address': '192.168.0.2' + 'fixed_ip_address': '192.168.0.2', + 'status': 'DOWN' } ri = self._create_router() ri.add_floating_ip = mock.Mock( -- 2.45.2