]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Re-added 0004-Fix-Metering-doesn-t-respect-the-l3-agent-binding.patch
authorThomas Goirand <thomas@goirand.fr>
Mon, 14 Apr 2014 17:13:44 +0000 (01:13 +0800)
committerThomas Goirand <thomas@goirand.fr>
Mon, 14 Apr 2014 17:13:44 +0000 (01:13 +0800)
Change-Id: I68fbd4f84ba31430ec110fc31148610798fa56cb

Rewritten-From: 95731a06f1325efe51a5e25cc384a5ba31a394ee

trusty/debian/patches/0004-Fix-Metering-doesn-t-respect-the-l3-agent-binding.patch [new file with mode: 0644]
trusty/debian/patches/series

diff --git a/trusty/debian/patches/0004-Fix-Metering-doesn-t-respect-the-l3-agent-binding.patch b/trusty/debian/patches/0004-Fix-Metering-doesn-t-respect-the-l3-agent-binding.patch
new file mode 100644 (file)
index 0000000..22c87f4
--- /dev/null
@@ -0,0 +1,470 @@
+From: Sylvain Afchain <sylvain.afchain@enovance.com>
+Date: Tue, 7 Jan 2014 09:36:58 +0000 (+0100)
+Subject: Fix Metering doesn't respect the l3 agent binding
+X-Git-Url: https://review.openstack.org/gitweb?p=openstack%2Fneutron.git;a=commitdiff_plain;h=901d676b8bcbb3e731ba44a4e574e9ae998f486e
+
+Fix Metering doesn't respect the l3 agent binding
+
+This patch fix the issue by changing the call to
+find the plugin which handles the l3 which is now
+the l3_router service plugin instead of the old mixin.
+
+Also change the unit tests to use the l3 service plugin
+instead of the l3 mixin and refactor the rpc callbacks
+part.
+
+Co-Authored-By: Ala Rezmerita <ala.rezmerita@cloudwatt.com>
+Closes-bug: #1257354
+Change-Id: Ide26f825005fa63cd3fcc75fa91fffb947e0be7a
+---
+
+Index: neutron/neutron/api/rpc/agentnotifiers/metering_rpc_agent_api.py
+===================================================================
+--- neutron.orig/neutron/api/rpc/agentnotifiers/metering_rpc_agent_api.py      2014-04-11 14:04:11.000000000 +0800
++++ neutron/neutron/api/rpc/agentnotifiers/metering_rpc_agent_api.py   2014-04-15 01:13:25.000000000 +0800
+@@ -20,6 +20,7 @@
+ from neutron import manager
+ from neutron.openstack.common import log as logging
+ from neutron.openstack.common.rpc import proxy
++from neutron.plugins.common import constants as service_constants
+ LOG = logging.getLogger(__name__)
+@@ -35,7 +36,8 @@
+     def _agent_notification(self, context, method, routers):
+         """Notify l3 metering agents hosted by l3 agent hosts."""
+         adminContext = context.is_admin and context or context.elevated()
+-        plugin = manager.NeutronManager.get_plugin()
++        plugin = manager.NeutronManager.get_service_plugins().get(
++            service_constants.L3_ROUTER_NAT)
+         l3_routers = {}
+         for router in routers:
+@@ -71,7 +73,8 @@
+     def _notification(self, context, method, routers):
+         """Notify all the agents that are hosting the routers."""
+-        plugin = manager.NeutronManager.get_plugin()
++        plugin = manager.NeutronManager.get_service_plugins().get(
++            service_constants.L3_ROUTER_NAT)
+         if utils.is_extension_supported(
+             plugin, constants.L3_AGENT_SCHEDULER_EXT_ALIAS):
+             self._agent_notification(context, method, routers)
+Index: neutron/neutron/db/metering/metering_db.py
+===================================================================
+--- neutron.orig/neutron/db/metering/metering_db.py    2014-02-27 18:27:07.000000000 +0800
++++ neutron/neutron/db/metering/metering_db.py 2014-04-15 01:13:25.000000000 +0800
+@@ -227,12 +227,13 @@
+         return routers_dict.values()
+-    def get_sync_data_metering(self, context, label_id=None):
+-        with context.session.begin(subtransactions=True):
+-            if label_id:
+-                label = self._get_by_id(context, MeteringLabel, label_id)
+-                labels = [label]
+-            else:
+-                labels = self._get_collection_query(context, MeteringLabel)
++    def get_sync_data_metering(self, context, label_id=None, router_ids=None):
++        labels = context.session.query(MeteringLabel)
++
++        if label_id:
++            labels = labels.filter(MeteringLabel.id == label_id)
++        elif router_ids:
++            labels = (labels.join(MeteringLabel.routers).
++                      filter(l3_db.Router.id.in_(router_ids)))
+         return self._process_sync_metering_data(labels)
+Index: neutron/neutron/db/metering/metering_rpc.py
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ neutron/neutron/db/metering/metering_rpc.py        2014-04-15 01:13:25.000000000 +0800
+@@ -0,0 +1,59 @@
++# Copyright (C) 2014 eNovance SAS <licensing@enovance.com>
++#
++# Author: Sylvain Afchain <sylvain.afchain@enovance.com>
++#
++# Licensed under the Apache License, Version 2.0 (the "License"); you may
++# not use this file except in compliance with the License. You may obtain
++# a copy of the License at
++#
++#      http://www.apache.org/licenses/LICENSE-2.0
++#
++# Unless required by applicable law or agreed to in writing, software
++# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
++# License for the specific language governing permissions and limitations
++# under the License.
++
++from neutron.common import constants as consts
++from neutron.common import rpc as p_rpc
++from neutron.common import utils
++from neutron import manager
++from neutron.openstack.common import log as logging
++from neutron.plugins.common import constants as service_constants
++
++LOG = logging.getLogger(__name__)
++
++
++class MeteringRpcCallbacks(object):
++
++    RPC_API_VERSION = '1.0'
++
++    def __init__(self, meter_plugin):
++        self.meter_plugin = meter_plugin
++
++    def create_rpc_dispatcher(self):
++        return p_rpc.PluginRpcDispatcher([self])
++
++    def get_sync_data_metering(self, context, **kwargs):
++        l3_plugin = manager.NeutronManager.get_service_plugins().get(
++            service_constants.L3_ROUTER_NAT)
++        if not l3_plugin:
++            return
++
++        host = kwargs.get('host')
++        if not utils.is_extension_supported(
++            l3_plugin, consts.L3_AGENT_SCHEDULER_EXT_ALIAS) or not host:
++            return self.meter_plugin.get_sync_data_metering(context)
++        else:
++            agents = l3_plugin.get_l3_agents(context, filters={'host': [host]})
++            if not agents:
++                LOG.error(_('Unable to find agent %s.'), host)
++                return
++
++            routers = l3_plugin.list_routers_on_l3_agent(context, agents[0].id)
++            router_ids = [router['id'] for router in routers['routers']]
++            if not router_ids:
++                return
++
++        return self.meter_plugin.get_sync_data_metering(context,
++                                                        router_ids=router_ids)
+Index: neutron/neutron/services/metering/agents/metering_agent.py
+===================================================================
+--- neutron.orig/neutron/services/metering/agents/metering_agent.py    2014-04-11 14:04:11.000000000 +0800
++++ neutron/neutron/services/metering/agents/metering_agent.py 2014-04-15 01:13:25.000000000 +0800
+@@ -88,7 +88,7 @@
+         self.label_tenant_id = {}
+         self.routers = {}
+         self.metering_infos = {}
+-        super(MeteringAgent, self).__init__(host=self.conf.host)
++        super(MeteringAgent, self).__init__(host=host)
+     def _load_drivers(self):
+         """Loads plugin-driver from configuration."""
+Index: neutron/neutron/services/metering/metering_plugin.py
+===================================================================
+--- neutron.orig/neutron/services/metering/metering_plugin.py  2013-12-10 00:11:32.000000000 +0800
++++ neutron/neutron/services/metering/metering_plugin.py       2014-04-15 01:13:25.000000000 +0800
+@@ -15,26 +15,12 @@
+ # under the License.
+ from neutron.api.rpc.agentnotifiers import metering_rpc_agent_api
+-from neutron.common import rpc as p_rpc
+ from neutron.common import topics
+ from neutron.db.metering import metering_db
++from neutron.db.metering import metering_rpc
+ from neutron.openstack.common import rpc
+-class MeteringCallbacks(metering_db.MeteringDbMixin):
+-
+-    RPC_API_VERSION = '1.0'
+-
+-    def __init__(self, plugin):
+-        self.plugin = plugin
+-
+-    def create_rpc_dispatcher(self):
+-        return p_rpc.PluginRpcDispatcher([self])
+-
+-    def get_sync_data_metering(self, context, **kwargs):
+-        return super(MeteringCallbacks, self).get_sync_data_metering(context)
+-
+-
+ class MeteringPlugin(metering_db.MeteringDbMixin):
+     """Implementation of the Neutron Metering Service Plugin."""
+     supported_extension_aliases = ["metering"]
+@@ -42,7 +28,7 @@
+     def __init__(self):
+         super(MeteringPlugin, self).__init__()
+-        self.callbacks = MeteringCallbacks(self)
++        self.callbacks = metering_rpc.MeteringRpcCallbacks(self)
+         self.conn = rpc.create_connection(new=True)
+         self.conn.create_consumer(
+Index: neutron/neutron/tests/unit/services/metering/test_metering_plugin.py
+===================================================================
+--- neutron.orig/neutron/tests/unit/services/metering/test_metering_plugin.py  2014-04-15 01:12:00.000000000 +0800
++++ neutron/neutron/tests/unit/services/metering/test_metering_plugin.py       2014-04-15 01:13:25.000000000 +0800
+@@ -17,11 +17,16 @@
+ import mock
+ from neutron.api.v2 import attributes as attr
++from neutron.common import constants as n_constants
++from neutron.common import topics
+ from neutron import context
+ from neutron.db import agents_db
+ from neutron.db import l3_agentschedulers_db
++from neutron.db.metering import metering_rpc
+ from neutron.extensions import l3 as ext_l3
+ from neutron.extensions import metering as ext_metering
++from neutron import manager
++from neutron.openstack.common import timeutils
+ from neutron.openstack.common import uuidutils
+ from neutron.plugins.common import constants
+ from neutron.tests.unit.db.metering import test_db_metering
+@@ -31,7 +36,7 @@
+ _uuid = uuidutils.generate_uuid
+-DB_METERING_PLUGIN_KLASS = (
++METERING_SERVICE_PLUGIN_KLASS = (
+     "neutron.services.metering."
+     "metering_plugin.MeteringPlugin"
+ )
+@@ -65,8 +70,9 @@
+     )
+     def setUp(self):
+-        service_plugins = {'metering_plugin_name': DB_METERING_PLUGIN_KLASS}
+         plugin = 'neutron.tests.unit.test_l3_plugin.TestL3NatIntPlugin'
++        service_plugins = {'metering_plugin_name':
++                           METERING_SERVICE_PLUGIN_KLASS}
+         ext_mgr = MeteringTestExtensionManager()
+         super(TestMeteringPlugin, self).setUp(plugin=plugin, ext_mgr=ext_mgr,
+                                               service_plugins=service_plugins)
+@@ -251,12 +257,8 @@
+                 self.assertEqual(tenant_id, router['router']['tenant_id'])
+-class TestRouteIntPlugin(l3_agentschedulers_db.L3AgentSchedulerDbMixin,
+-                         test_l3_plugin.TestL3NatIntPlugin):
+-    supported_extension_aliases = ["router", "l3_agent_scheduler"]
+-
+-
+ class TestMeteringPluginL3AgentScheduler(
++        l3_agentschedulers_db.L3AgentSchedulerDbMixin,
+         test_db_plugin.NeutronDbPluginV2TestCase,
+         test_l3_plugin.L3NatTestCaseMixin,
+         test_db_metering.MeteringPluginDbTestCaseMixin):
+@@ -266,10 +268,18 @@
+         for k in ext_metering.RESOURCE_ATTRIBUTE_MAP.keys()
+     )
+-    def setUp(self):
+-        service_plugins = {'metering_plugin_name': DB_METERING_PLUGIN_KLASS}
+-        plugin_str = ('neutron.tests.unit.services.metering.'
+-                      'test_metering_plugin.TestRouteIntPlugin')
++    def setUp(self, plugin_str=None, service_plugins=None, scheduler=None):
++        if not plugin_str:
++            plugin_str = ('neutron.tests.unit.test_l3_plugin.'
++                          'TestL3NatIntAgentSchedulingPlugin')
++
++        if not service_plugins:
++            service_plugins = {'metering_plugin_name':
++                               METERING_SERVICE_PLUGIN_KLASS}
++
++        if not scheduler:
++            scheduler = plugin_str
++
+         ext_mgr = MeteringTestExtensionManager()
+         super(TestMeteringPluginL3AgentScheduler,
+               self).setUp(plugin=plugin_str, ext_mgr=ext_mgr,
+@@ -291,7 +301,7 @@
+                                         return_value=self.ctx)
+         self.mock_context = self.context_patch.start()
+-        self.l3routers_patch = mock.patch(plugin_str +
++        self.l3routers_patch = mock.patch(scheduler +
+                                           '.get_l3_agents_hosting_routers')
+         self.l3routers_mock = self.l3routers_patch.start()
+@@ -299,30 +309,40 @@
+     def test_add_metering_label_rpc_call(self):
+         second_uuid = 'e27fe2df-376e-4ac7-ae13-92f050a21f84'
+-        expected = {'args': {'routers': [{'status': 'ACTIVE',
+-                                          'name': 'router1',
+-                                          'gw_port_id': None,
+-                                          'admin_state_up': True,
+-                                          'tenant_id': self.tenant_id,
+-                                          '_metering_labels': [
+-                                              {'rules': [],
+-                                               'id': second_uuid}],
+-                                          'id': self.uuid},
+-                                         {'status': 'ACTIVE',
+-                                          'name': 'router2',
+-                                          'gw_port_id': None,
+-                                          'admin_state_up': True,
+-                                          'tenant_id': self.tenant_id,
+-                                          '_metering_labels': [
+-                                              {'rules': [],
+-                                               'id': second_uuid}],
+-                                          'id': second_uuid}]},
+-                    'namespace': None,
+-                    'method': 'add_metering_label'}
++        expected1 = {'args': {'routers': [{'status': 'ACTIVE',
++                                           'name': 'router1',
++                                           'gw_port_id': None,
++                                           'admin_state_up': True,
++                                           'tenant_id': self.tenant_id,
++                                           '_metering_labels': [
++                                               {'rules': [],
++                                                'id': second_uuid}],
++                                           'id': self.uuid}]},
++                     'namespace': None,
++                     'method': 'add_metering_label'}
++        expected2 = {'args': {'routers': [{'status': 'ACTIVE',
++                                           'name': 'router2',
++                                           'gw_port_id': None,
++                                           'admin_state_up': True,
++                                           'tenant_id': self.tenant_id,
++                                           '_metering_labels': [
++                                               {'rules': [],
++                                                'id': second_uuid}],
++                                           'id': second_uuid}]},
++                     'namespace': None,
++                     'method': 'add_metering_label'}
++
++        # bind each router to a specific agent
++        agent1 = agents_db.Agent(host='agent1')
++        agent2 = agents_db.Agent(host='agent2')
++
++        agents = {self.uuid: agent1,
++                  second_uuid: agent2}
++
++        def side_effect(context, routers, admin_state_up, active):
++            return [agents[routers[0]]]
+-        agent_host = 'l3_agent_host'
+-        agent = agents_db.Agent(host=agent_host)
+-        self.l3routers_mock.return_value = [agent]
++        self.l3routers_mock.side_effect = side_effect
+         with self.router(name='router1', tenant_id=self.tenant_id,
+                          set_context=True):
+@@ -331,7 +351,99 @@
+                              set_context=True):
+                 with self.metering_label(tenant_id=self.tenant_id,
+                                          set_context=True):
+-                    topic = "%s.%s" % (self.topic, agent_host)
+-                    self.mock_cast.assert_called_with(self.ctx,
+-                                                      expected,
+-                                                      topic=topic)
++
++                    topic1 = "%s.%s" % (self.topic, 'agent1')
++                    topic2 = "%s.%s" % (self.topic, 'agent2')
++
++                    # check if there is a call per agent
++                    expected = [mock.call(self.ctx, expected1, topic=topic1),
++                                mock.call(self.ctx, expected2, topic=topic2)]
++
++                    self.mock_cast.assert_has_calls(expected, any_order=True)
++
++
++class TestMeteringPluginL3AgentSchedulerServicePlugin(
++        TestMeteringPluginL3AgentScheduler):
++
++    """Unit tests for the case where separate service plugin
++    implements L3 routing.
++    """
++
++    def setUp(self):
++        l3_plugin = ('neutron.tests.unit.test_l3_plugin.'
++                     'TestL3NatAgentSchedulingServicePlugin')
++        service_plugins = {'metering_plugin_name':
++                           METERING_SERVICE_PLUGIN_KLASS,
++                           'l3_plugin_name': l3_plugin}
++
++        plugin_str = ('neutron.tests.unit.test_l3_plugin.'
++                      'TestNoL3NatPlugin')
++
++        super(TestMeteringPluginL3AgentSchedulerServicePlugin, self).setUp(
++            plugin_str=plugin_str, service_plugins=service_plugins,
++            scheduler=l3_plugin)
++
++
++class TestMeteringPluginRpcFromL3Agent(
++        test_db_plugin.NeutronDbPluginV2TestCase,
++        test_l3_plugin.L3NatTestCaseMixin,
++        test_db_metering.MeteringPluginDbTestCaseMixin):
++
++    resource_prefix_map = dict(
++        (k.replace('_', '-'), constants.COMMON_PREFIXES[constants.METERING])
++        for k in ext_metering.RESOURCE_ATTRIBUTE_MAP
++    )
++
++    def setUp(self):
++        service_plugins = {'metering_plugin_name':
++                           METERING_SERVICE_PLUGIN_KLASS}
++
++        plugin = ('neutron.tests.unit.test_l3_plugin.'
++                  'TestL3NatIntAgentSchedulingPlugin')
++
++        ext_mgr = MeteringTestExtensionManager()
++        super(TestMeteringPluginRpcFromL3Agent,
++              self).setUp(plugin=plugin, service_plugins=service_plugins,
++                          ext_mgr=ext_mgr)
++
++        self.meter_plugin = manager.NeutronManager.get_service_plugins().get(
++            constants.METERING)
++
++        self.adminContext = context.get_admin_context()
++        self._register_l3_agent('agent1')
++
++    def _register_l3_agent(self, host):
++        agent = {
++            'binary': 'neutron-l3-agent',
++            'host': host,
++            'topic': topics.L3_AGENT,
++            'configurations': {},
++            'agent_type': n_constants.AGENT_TYPE_L3,
++            'start_flag': True
++        }
++        callback = agents_db.AgentExtRpcCallback()
++        callback.report_state(self.adminContext,
++                              agent_state={'agent_state': agent},
++                              time=timeutils.strtime())
++
++    def test_get_sync_data_metering(self):
++        with self.subnet() as subnet:
++            s = subnet['subnet']
++            self._set_net_external(s['network_id'])
++            with self.router(name='router1', subnet=subnet) as router:
++                r = router['router']
++                self._add_external_gateway_to_router(r['id'], s['network_id'])
++                with self.metering_label(tenant_id=r['tenant_id']):
++                    callbacks = metering_rpc.MeteringRpcCallbacks(
++                        self.meter_plugin)
++                    data = callbacks.get_sync_data_metering(self.adminContext,
++                                                            host='agent1')
++                    self.assertEqual('router1', data[0]['name'])
++
++                    self._register_l3_agent('agent2')
++                    data = callbacks.get_sync_data_metering(self.adminContext,
++                                                            host='agent2')
++                    self.assertFalse(data)
++
++                self._remove_external_gateway_from_router(
++                    r['id'], s['network_id'])
+Index: neutron/neutron/tests/unit/test_l3_plugin.py
+===================================================================
+--- neutron.orig/neutron/tests/unit/test_l3_plugin.py  2014-04-15 01:12:00.000000000 +0800
++++ neutron/neutron/tests/unit/test_l3_plugin.py       2014-04-15 01:13:25.000000000 +0800
+@@ -277,6 +277,15 @@
+         return "L3 Routing Service Plugin for testing"
++# A L3 routing with L3 agent scheduling service plugin class for tests with
++# plugins that delegate away L3 routing functionality
++class TestL3NatAgentSchedulingServicePlugin(TestL3NatServicePlugin,
++                                            l3_agentschedulers_db.
++                                            L3AgentSchedulerDbMixin):
++
++    supported_extension_aliases = ["router", "l3_agent_scheduler"]
++
++
+ class L3NatTestCaseMixin(object):
+     def _create_router(self, fmt, tenant_id, name=None,
index a93e36f99b66ce2043b58fda437ce2041bbdfa89..40769f9cf18722183e800b4ac15508c70e38b7e3 100644 (file)
@@ -1,3 +1,4 @@
 fix-alembic-migration-with-sqlite3.patch
 better-config-default.patch
 OVS_lib_defer_apply_doesn_t_handle_concurrency.patch
+0004-Fix-Metering-doesn-t-respect-the-l3-agent-binding.patch