]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Expose ha_state per router to agent binding via API
authorAssaf Muller <amuller@redhat.com>
Sun, 5 Oct 2014 12:02:59 +0000 (15:02 +0300)
committerAssaf Muller <amuller@redhat.com>
Mon, 23 Mar 2015 21:56:36 +0000 (17:56 -0400)
l3-agent-list-hosting-router will now return with a new 'ha_state'
attribute, per agent. It signifies the HA state of the router on that
agent.

Implements: blueprint report-ha-router-master
Change-Id: Ie0f53b7565d53ff791b0cdcca20be2b4415b49cc

neutron/db/l3_agentschedulers_db.py
neutron/db/l3_hamode_db.py
neutron/db/l3_hascheduler_db.py
neutron/tests/unit/db/test_l3_ha_db.py
neutron/tests/unit/test_l3_schedulers.py

index 9d9e926bae80cdfdb3b0dee7eb5e918d824b91fb..b929544791276c48825d9fdaf0f0adf9caec20e1 100644 (file)
@@ -342,14 +342,9 @@ class L3AgentSchedulerDbMixin(l3agentscheduler.L3AgentSchedulerPluginBase,
         with context.session.begin(subtransactions=True):
             bindings = self._get_l3_bindings_hosting_routers(
                 context, [router_id])
-            results = []
-            for binding in bindings:
-                l3_agent_dict = self._make_agent_dict(binding.l3_agent)
-                results.append(l3_agent_dict)
-            if results:
-                return {'agents': results}
-            else:
-                return {'agents': []}
+
+        return {'agents': [self._make_agent_dict(binding.l3_agent) for
+                           binding in bindings]}
 
     def get_l3_agents(self, context, active=None, filters=None):
         query = context.session.query(agents_db.Agent)
index a7ddfdadc7daa03815d4db3b3e390522bca02dc0..2e9284ca2cc64361da8375a6db8b0198f8a549cd 100644 (file)
@@ -436,6 +436,12 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin):
 
         return query.all()
 
+    def get_l3_bindings_hosting_router_with_ha_states(
+            self, context, router_id):
+        """Return a list of [(agent, ha_state), ...]."""
+        bindings = self.get_ha_router_port_bindings(context, [router_id])
+        return [(binding.agent, binding.state) for binding in bindings]
+
     def _process_sync_ha_data(self, context, routers, host):
         routers_dict = dict((router['id'], router) for router in routers)
 
index a4bbbd55b6de8bb42e95d6d4230bd1edc56fbbb7..d3a60e36658573fe3d78c950ebc6bab3263e7ddb 100644 (file)
@@ -59,3 +59,24 @@ class L3_HA_scheduler_db_mixin(l3_sch_db.L3AgentSchedulerDbMixin):
             order_by('count'))
 
         return [record[0] for record in query]
+
+    def _get_agents_dict_for_router(self, agents_and_states):
+        agents = []
+        for agent, ha_state in agents_and_states:
+            l3_agent_dict = self._make_agent_dict(agent)
+            l3_agent_dict['ha_state'] = ha_state
+            agents.append(l3_agent_dict)
+        return {'agents': agents}
+
+    def list_l3_agents_hosting_router(self, context, router_id):
+        with context.session.begin(subtransactions=True):
+            router_db = self._get_router(context, router_id)
+            if router_db.extra_attributes.ha:
+                bindings = self.get_l3_bindings_hosting_router_with_ha_states(
+                    context, router_id)
+            else:
+                bindings = self._get_l3_bindings_hosting_routers(
+                    context, [router_id])
+                bindings = [(binding.l3_agent, None) for binding in bindings]
+
+        return self._get_agents_dict_for_router(bindings)
index b1bbf3e978957cb6d0ea88c8824beb3f2b5c0869..5939d878231a492f42a150ce07209293399ad35e 100644 (file)
@@ -26,6 +26,7 @@ from neutron.extensions import l3
 from neutron.extensions import l3_ext_ha_mode
 from neutron import manager
 from neutron.openstack.common import uuidutils
+from neutron.scheduler import l3_agent_scheduler
 from neutron.tests.unit import testlib_api
 from neutron.tests.unit import testlib_plugin
 
@@ -93,12 +94,43 @@ class L3HATestFramework(testlib_api.SqlTestCase,
 
     def _bind_router(self, router_id):
         with self.admin_ctx.session.begin(subtransactions=True):
-            bindings = self.plugin.get_ha_router_port_bindings(self.admin_ctx,
-                                                               [router_id])
-
-            for agent_id, binding in zip(
-                    [self.agent1['id'], self.agent2['id']], bindings):
-                binding.l3_agent_id = agent_id
+            scheduler = l3_agent_scheduler.ChanceScheduler()
+            agents_db = self.plugin.get_agents_db(self.admin_ctx)
+            scheduler.bind_ha_router_to_agents(
+                self.plugin,
+                self.admin_ctx,
+                router_id,
+                agents_db)
+
+    def test_get_ha_router_port_bindings(self):
+        router = self._create_router()
+        self._bind_router(router['id'])
+        bindings = self.plugin.get_ha_router_port_bindings(
+            self.admin_ctx, [router['id']])
+        binding_dicts = [{'router_id': binding['router_id'],
+                          'l3_agent_id': binding['l3_agent_id']}
+                         for binding in bindings]
+        self.assertIn({'router_id': router['id'],
+                       'l3_agent_id': self.agent1['id']}, binding_dicts)
+        self.assertIn({'router_id': router['id'],
+                       'l3_agent_id': self.agent2['id']}, binding_dicts)
+
+    def test_get_l3_bindings_hosting_router_with_ha_states_ha_router(self):
+        router = self._create_router()
+        self._bind_router(router['id'])
+        self.plugin.update_routers_states(
+            self.admin_ctx, {router['id']: 'active'}, self.agent1['host'])
+        bindings = self.plugin.get_l3_bindings_hosting_router_with_ha_states(
+            self.admin_ctx, router['id'])
+        agent_ids = [(agent[0]['id'], agent[1]) for agent in bindings]
+        self.assertIn((self.agent1['id'], 'active'), agent_ids)
+        self.assertIn((self.agent2['id'], 'standby'), agent_ids)
+
+    def test_get_l3_bindings_hosting_router_with_ha_states_not_scheduled(self):
+        router = self._create_router(ha=False)
+        bindings = self.plugin.get_l3_bindings_hosting_router_with_ha_states(
+            self.admin_ctx, router['id'])
+        self.assertEqual([], bindings)
 
 
 class L3HATestCase(L3HATestFramework):
index b60a791de40b5da7ddd1b313b88bcc6e7500ca6a..6ecf3bf5d54c5b5c3da6cd611d509934672a2201 100644 (file)
@@ -1239,6 +1239,37 @@ class L3AgentSchedulerDbMixinTestCase(L3HATestCaseMixin):
             self.plugin.reschedule_routers_from_down_agents()
             self.assertFalse(reschedule.called)
 
+    def test_list_l3_agents_hosting_ha_router(self):
+        router = self._create_ha_router()
+        self.plugin.schedule_router(self.adminContext, router['id'])
+
+        agents = self.plugin.list_l3_agents_hosting_router(
+            self.adminContext, router['id'])['agents']
+        for agent in agents:
+            self.assertEqual('standby', agent['ha_state'])
+
+        self.plugin.update_routers_states(
+            self.adminContext, {router['id']: 'active'}, self.agent1.host)
+        agents = self.plugin.list_l3_agents_hosting_router(
+            self.adminContext, router['id'])['agents']
+        for agent in agents:
+            expected_state = ('active' if agent['host'] == self.agent1.host
+                              else 'standby')
+            self.assertEqual(expected_state, agent['ha_state'])
+
+    def test_list_l3_agents_hosting_legacy_router(self):
+        router = self._create_ha_router(ha=False)
+        self.plugin.schedule_router(self.adminContext, router['id'])
+
+        agents = self.plugin.list_l3_agents_hosting_router(
+            self.adminContext, router['id'])['agents']
+        for agent in agents:
+            self.assertIsNone(agent['ha_state'])
+
+    def test_get_agents_dict_for_router_unscheduled_returns_empty_list(self):
+        self.assertEqual({'agents': []},
+                         self.plugin._get_agents_dict_for_router([]))
+
 
 class L3HAChanceSchedulerTestCase(L3HATestCaseMixin):