"Fossies" - the Fresh Open Source Software Archive

Member "neutron-14.0.3/neutron/tests/unit/db/test_agentschedulers_db.py" (22 Oct 2019, 79396 Bytes) of package /linux/misc/openstack/neutron-14.0.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "test_agentschedulers_db.py": 14.0.2_vs_15.0.0.

    1 # Copyright (c) 2013 OpenStack Foundation.
    2 #
    3 # Licensed under the Apache License, Version 2.0 (the "License");
    4 # you may not use this file except in compliance with the License.
    5 # You may obtain a copy of the License at
    6 #
    7 #    http://www.apache.org/licenses/LICENSE-2.0
    8 #
    9 # Unless required by applicable law or agreed to in writing, software
   10 # distributed under the License is distributed on an "AS IS" BASIS,
   11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
   12 # implied.
   13 # See the License for the specific language governing permissions and
   14 # limitations under the License.
   15 
   16 import datetime
   17 
   18 import mock
   19 from neutron_lib.api.definitions import dhcpagentscheduler as das_apidef
   20 from neutron_lib import constants
   21 from neutron_lib import context
   22 from neutron_lib.plugins import constants as plugin_constants
   23 from neutron_lib.plugins import directory
   24 from neutron_lib import rpc as n_rpc
   25 from neutron_lib.tests.unit import fake_notifier
   26 from oslo_config import cfg
   27 from oslo_db import exception as db_exc
   28 import oslo_messaging
   29 from oslo_utils import uuidutils
   30 from webob import exc
   31 
   32 from neutron.api import extensions
   33 from neutron.api.rpc.agentnotifiers import dhcp_rpc_agent_api
   34 from neutron.api.rpc.agentnotifiers import l3_rpc_agent_api
   35 from neutron.api.rpc.handlers import dhcp_rpc
   36 from neutron.api.rpc.handlers import l3_rpc
   37 from neutron.db import agents_db
   38 from neutron.db import agentschedulers_db
   39 from neutron.db.models import agent as agent_model
   40 from neutron.extensions import l3agentscheduler
   41 from neutron.objects import agent as ag_obj
   42 from neutron.objects import l3agent as rb_obj
   43 from neutron.tests.common import helpers
   44 from neutron.tests.unit.api import test_extensions
   45 from neutron.tests.unit.db import test_db_base_plugin_v2 as test_plugin
   46 from neutron.tests.unit.extensions import test_agent
   47 from neutron.tests.unit.extensions import test_l3
   48 from neutron.tests.unit import testlib_api
   49 from neutron import wsgi
   50 
   51 
   52 L3_HOSTA = 'hosta'
   53 DHCP_HOSTA = 'hosta'
   54 L3_HOSTB = 'hostb'
   55 DHCP_HOSTC = 'hostc'
   56 DHCP_HOSTD = 'hostd'
   57 
   58 DEVICE_OWNER_COMPUTE = ''.join([constants.DEVICE_OWNER_COMPUTE_PREFIX,
   59                                 'test:',
   60                                 DHCP_HOSTA])
   61 
   62 
   63 class AgentSchedulerTestMixIn(object):
   64 
   65     block_dhcp_notifier = False
   66 
   67     def _request_list(self, path, admin_context=True,
   68                       expected_code=exc.HTTPOk.code):
   69         req = self._path_req(path, admin_context=admin_context)
   70         res = req.get_response(self.ext_api)
   71         self.assertEqual(expected_code, res.status_int)
   72         return self.deserialize(self.fmt, res)
   73 
   74     def _path_req(self, path, method='GET', data=None,
   75                   query_string=None,
   76                   admin_context=True):
   77         content_type = 'application/%s' % self.fmt
   78         body = None
   79         if data is not None:  # empty dict is valid
   80             body = wsgi.Serializer().serialize(data, content_type)
   81         if admin_context:
   82             return testlib_api.create_request(
   83                 path, body, content_type, method, query_string=query_string)
   84         else:
   85             return testlib_api.create_request(
   86                 path, body, content_type, method, query_string=query_string,
   87                 context=context.Context('', 'tenant_id'))
   88 
   89     def _path_create_request(self, path, data, admin_context=True):
   90         return self._path_req(path, method='POST', data=data,
   91                               admin_context=admin_context)
   92 
   93     def _path_show_request(self, path, admin_context=True):
   94         return self._path_req(path, admin_context=admin_context)
   95 
   96     def _path_delete_request(self, path, admin_context=True):
   97         return self._path_req(path, method='DELETE',
   98                               admin_context=admin_context)
   99 
  100     def _path_update_request(self, path, data, admin_context=True):
  101         return self._path_req(path, method='PUT', data=data,
  102                               admin_context=admin_context)
  103 
  104     def _list_routers_hosted_by_l3_agent(self, agent_id,
  105                                          expected_code=exc.HTTPOk.code,
  106                                          admin_context=True):
  107         path = "/agents/%s/%s.%s" % (agent_id,
  108                                      l3agentscheduler.L3_ROUTERS,
  109                                      self.fmt)
  110         return self._request_list(path, expected_code=expected_code,
  111                                   admin_context=admin_context)
  112 
  113     def _list_networks_hosted_by_dhcp_agent(self, agent_id,
  114                                             expected_code=exc.HTTPOk.code,
  115                                             admin_context=True):
  116         path = "/agents/%s/%s.%s" % (agent_id,
  117                                      das_apidef.DHCP_NETS,
  118                                      self.fmt)
  119         return self._request_list(path, expected_code=expected_code,
  120                                   admin_context=admin_context)
  121 
  122     def _list_l3_agents_hosting_router(self, router_id,
  123                                        expected_code=exc.HTTPOk.code,
  124                                        admin_context=True):
  125         path = "/routers/%s/%s.%s" % (router_id,
  126                                       l3agentscheduler.L3_AGENTS,
  127                                       self.fmt)
  128         return self._request_list(path, expected_code=expected_code,
  129                                   admin_context=admin_context)
  130 
  131     def _list_dhcp_agents_hosting_network(self, network_id,
  132                                           expected_code=exc.HTTPOk.code,
  133                                           admin_context=True):
  134         path = "/networks/%s/%s.%s" % (network_id,
  135                                        das_apidef.DHCP_AGENTS,
  136                                        self.fmt)
  137         return self._request_list(path, expected_code=expected_code,
  138                                   admin_context=admin_context)
  139 
  140     def _add_router_to_l3_agent(self, id, router_id,
  141                                 expected_code=exc.HTTPCreated.code,
  142                                 admin_context=True):
  143         path = "/agents/%s/%s.%s" % (id,
  144                                      l3agentscheduler.L3_ROUTERS,
  145                                      self.fmt)
  146         req = self._path_create_request(path,
  147                                         {'router_id': router_id},
  148                                         admin_context=admin_context)
  149         res = req.get_response(self.ext_api)
  150         self.assertEqual(expected_code, res.status_int)
  151 
  152     def _add_network_to_dhcp_agent(self, id, network_id,
  153                                    expected_code=exc.HTTPCreated.code,
  154                                    admin_context=True):
  155         path = "/agents/%s/%s.%s" % (id,
  156                                      das_apidef.DHCP_NETS,
  157                                      self.fmt)
  158         req = self._path_create_request(path,
  159                                         {'network_id': network_id},
  160                                         admin_context=admin_context)
  161         res = req.get_response(self.ext_api)
  162         self.assertEqual(expected_code, res.status_int)
  163 
  164     def _remove_network_from_dhcp_agent(self, id, network_id,
  165                                         expected_code=exc.HTTPNoContent.code,
  166                                         admin_context=True):
  167         path = "/agents/%s/%s/%s.%s" % (id,
  168                                         das_apidef.DHCP_NETS,
  169                                         network_id,
  170                                         self.fmt)
  171         req = self._path_delete_request(path,
  172                                         admin_context=admin_context)
  173         res = req.get_response(self.ext_api)
  174         self.assertEqual(expected_code, res.status_int)
  175 
  176     def _remove_router_from_l3_agent(self, id, router_id,
  177                                      expected_code=exc.HTTPNoContent.code,
  178                                      admin_context=True):
  179         path = "/agents/%s/%s/%s.%s" % (id,
  180                                         l3agentscheduler.L3_ROUTERS,
  181                                         router_id,
  182                                         self.fmt)
  183         req = self._path_delete_request(path, admin_context=admin_context)
  184         res = req.get_response(self.ext_api)
  185         self.assertEqual(expected_code, res.status_int)
  186 
  187     def _assert_notify(self, notifications, expected_event_type):
  188         event_types = [event['event_type'] for event in notifications]
  189         self.assertIn(expected_event_type, event_types)
  190 
  191     def test_agent_registration_bad_timestamp(self):
  192         callback = agents_db.AgentExtRpcCallback()
  193         delta_time = datetime.datetime.now() - datetime.timedelta(days=1)
  194         str_time = delta_time.strftime('%Y-%m-%dT%H:%M:%S.%f')
  195         callback.report_state(
  196             self.adminContext,
  197             agent_state={
  198                 'agent_state': helpers._get_dhcp_agent_dict(DHCP_HOSTA)},
  199             time=str_time)
  200 
  201     def test_agent_registration_invalid_timestamp_allowed(self):
  202         callback = agents_db.AgentExtRpcCallback()
  203         utc_time = datetime.datetime.utcnow()
  204         delta_time = utc_time - datetime.timedelta(seconds=10)
  205         str_time = delta_time.strftime('%Y-%m-%dT%H:%M:%S.%f')
  206         callback.report_state(
  207             self.adminContext,
  208             agent_state={
  209                 'agent_state': helpers._get_dhcp_agent_dict(DHCP_HOSTA)},
  210             time=str_time)
  211 
  212     def _disable_agent(self, agent_id, admin_state_up=False):
  213         new_agent = {}
  214         new_agent['agent'] = {}
  215         new_agent['agent']['admin_state_up'] = admin_state_up
  216         self._update('agents', agent_id, new_agent)
  217 
  218     def _get_agent_id(self, agent_type, host):
  219         agents = self._list_agents()
  220         for agent_data in agents['agents']:
  221             if (agent_data['agent_type'] == agent_type and
  222                     agent_data['host'] == host):
  223                 return agent_data['id']
  224 
  225 
  226 class OvsAgentSchedulerTestCaseBase(test_l3.L3NatTestCaseMixin,
  227                                     test_agent.AgentDBTestMixIn,
  228                                     AgentSchedulerTestMixIn,
  229                                     test_plugin.NeutronDbPluginV2TestCase):
  230     fmt = 'json'
  231     l3_plugin = ('neutron.tests.unit.extensions.test_l3.'
  232                  'TestL3NatAgentSchedulingServicePlugin')
  233 
  234     def setUp(self):
  235         if self.l3_plugin:
  236             service_plugins = {
  237                 'l3_plugin_name': self.l3_plugin,
  238                 'flavors_plugin_name': 'neutron.services.flavors.'
  239                                        'flavors_plugin.FlavorsPlugin'
  240             }
  241         else:
  242             service_plugins = None
  243         # NOTE(ivasilevskaya) mocking this way allows some control over mocked
  244         # client like further method mocking with asserting calls
  245         self.client_mock = mock.MagicMock(name="mocked client")
  246         mock.patch.object(
  247             n_rpc, 'get_client').start().return_value = self.client_mock
  248         super(OvsAgentSchedulerTestCaseBase, self).setUp(
  249             'ml2', service_plugins=service_plugins)
  250         mock.patch.object(
  251             self.plugin, 'filter_hosts_with_network_access',
  252             side_effect=lambda context, network_id, hosts: hosts).start()
  253         ext_mgr = extensions.PluginAwareExtensionManager.get_instance()
  254         self.ext_api = test_extensions.setup_extensions_middleware(ext_mgr)
  255         self.adminContext = context.get_admin_context()
  256         self.l3plugin = directory.get_plugin(plugin_constants.L3)
  257         self.l3_notify_p = mock.patch(
  258             'neutron.extensions.l3agentscheduler.notify')
  259         self.patched_l3_notify = self.l3_notify_p.start()
  260         self.l3_periodic_p = mock.patch('neutron.db.l3_agentschedulers_db.'
  261                                         'L3AgentSchedulerDbMixin.'
  262                                         'add_periodic_l3_agent_status_check')
  263         self.patched_l3_periodic = self.l3_periodic_p.start()
  264         self.dhcp_notify_p = mock.patch(
  265             'neutron.extensions.dhcpagentscheduler.notify')
  266         self.patched_dhcp_notify = self.dhcp_notify_p.start()
  267 
  268 
  269 class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase):
  270 
  271     def test_report_states(self):
  272         self._register_agent_states()
  273         agents = self._list_agents()
  274         self.assertEqual(4, len(agents['agents']))
  275 
  276     def test_list_router_ids_on_host_no_l3_agent(self):
  277         l3_rpc_cb = l3_rpc.L3RpcCallback()
  278         self.assertEqual(
  279             [],
  280             l3_rpc_cb.get_router_ids(self.adminContext, host="fake host"))
  281 
  282     def test_network_scheduling_on_network_creation(self):
  283         self._register_agent_states()
  284         with self.network() as net:
  285             dhcp_agents = self._list_dhcp_agents_hosting_network(
  286                 net['network']['id'])
  287         self.assertEqual(0, len(dhcp_agents['agents']))
  288 
  289     def test_network_auto_schedule_with_disabled(self):
  290         cfg.CONF.set_override('allow_overlapping_ips', True)
  291         with self.subnet(), self.subnet():
  292             dhcp_rpc_cb = dhcp_rpc.DhcpRpcCallback()
  293             self._register_agent_states()
  294             hosta_id = self._get_agent_id(constants.AGENT_TYPE_DHCP,
  295                                           DHCP_HOSTA)
  296             hostc_id = self._get_agent_id(constants.AGENT_TYPE_DHCP,
  297                                           DHCP_HOSTC)
  298             self._disable_agent(hosta_id)
  299             dhcp_rpc_cb.get_active_networks_info(
  300                 self.adminContext, host=DHCP_HOSTA)
  301             # second agent will host all the networks since first is disabled.
  302             dhcp_rpc_cb.get_active_networks_info(
  303                 self.adminContext, host=DHCP_HOSTC)
  304             networks = self._list_networks_hosted_by_dhcp_agent(hostc_id)
  305             num_hostc_nets = len(networks['networks'])
  306             networks = self._list_networks_hosted_by_dhcp_agent(hosta_id)
  307             num_hosta_nets = len(networks['networks'])
  308         self.assertEqual(0, num_hosta_nets)
  309         self.assertEqual(2, num_hostc_nets)
  310 
  311     def test_network_auto_schedule_with_no_dhcp(self):
  312         cfg.CONF.set_override('allow_overlapping_ips', True)
  313         with self.subnet(enable_dhcp=False), self.subnet(enable_dhcp=False):
  314             dhcp_rpc_cb = dhcp_rpc.DhcpRpcCallback()
  315             self._register_agent_states()
  316             hosta_id = self._get_agent_id(constants.AGENT_TYPE_DHCP,
  317                                           DHCP_HOSTA)
  318             hostc_id = self._get_agent_id(constants.AGENT_TYPE_DHCP,
  319                                           DHCP_HOSTC)
  320             self._disable_agent(hosta_id)
  321             dhcp_rpc_cb.get_active_networks_info(
  322                 self.adminContext, host=DHCP_HOSTA)
  323             dhcp_rpc_cb.get_active_networks_info(
  324                 self.adminContext, host=DHCP_HOSTC)
  325             networks = self._list_networks_hosted_by_dhcp_agent(hostc_id)
  326             num_hostc_nets = len(networks['networks'])
  327             networks = self._list_networks_hosted_by_dhcp_agent(hosta_id)
  328             num_hosta_nets = len(networks['networks'])
  329         self.assertEqual(0, num_hosta_nets)
  330         self.assertEqual(0, num_hostc_nets)
  331 
  332     def test_network_auto_schedule_with_multiple_agents(self):
  333         cfg.CONF.set_override('dhcp_agents_per_network', 2)
  334         cfg.CONF.set_override('allow_overlapping_ips', True)
  335         with self.subnet(), self.subnet():
  336             dhcp_rpc_cb = dhcp_rpc.DhcpRpcCallback()
  337             self._register_agent_states()
  338             hosta_id = self._get_agent_id(constants.AGENT_TYPE_DHCP,
  339                                           DHCP_HOSTA)
  340             hostc_id = self._get_agent_id(constants.AGENT_TYPE_DHCP,
  341                                           DHCP_HOSTC)
  342             dhcp_rpc_cb.get_active_networks_info(
  343                 self.adminContext, host=DHCP_HOSTA)
  344             dhcp_rpc_cb.get_active_networks_info(
  345                 self.adminContext, host=DHCP_HOSTC)
  346             networks = self._list_networks_hosted_by_dhcp_agent(hostc_id)
  347             num_hostc_nets = len(networks['networks'])
  348             networks = self._list_networks_hosted_by_dhcp_agent(hosta_id)
  349             num_hosta_nets = len(networks['networks'])
  350         self.assertEqual(2, num_hosta_nets)
  351         self.assertEqual(2, num_hostc_nets)
  352 
  353     def test_network_auto_schedule_restart_dhcp_agent(self):
  354         cfg.CONF.set_override('dhcp_agents_per_network', 2)
  355         with self.subnet() as sub1:
  356             dhcp_rpc_cb = dhcp_rpc.DhcpRpcCallback()
  357             self._register_agent_states()
  358             dhcp_rpc_cb.get_active_networks_info(
  359                 self.adminContext, host=DHCP_HOSTA)
  360             dhcp_rpc_cb.get_active_networks_info(
  361                 self.adminContext, host=DHCP_HOSTA)
  362             dhcp_agents = self._list_dhcp_agents_hosting_network(
  363                 sub1['subnet']['network_id'])
  364         self.assertEqual(1, len(dhcp_agents['agents']))
  365 
  366     def test_network_auto_schedule_with_hosted(self):
  367         # one agent hosts all the networks, other hosts none
  368         cfg.CONF.set_override('allow_overlapping_ips', True)
  369         with self.subnet() as sub1, self.subnet():
  370             dhcp_rpc_cb = dhcp_rpc.DhcpRpcCallback()
  371             self._register_agent_states()
  372             dhcp_rpc_cb.get_active_networks_info(
  373                 self.adminContext, host=DHCP_HOSTA)
  374             # second agent will not host the network since first has got it.
  375             dhcp_rpc_cb.get_active_networks_info(
  376                 self.adminContext, host=DHCP_HOSTC)
  377             dhcp_agents = self._list_dhcp_agents_hosting_network(
  378                 sub1['subnet']['network_id'])
  379             hosta_id = self._get_agent_id(constants.AGENT_TYPE_DHCP,
  380                                           DHCP_HOSTA)
  381             hostc_id = self._get_agent_id(constants.AGENT_TYPE_DHCP,
  382                                           DHCP_HOSTC)
  383             hosta_nets = self._list_networks_hosted_by_dhcp_agent(hosta_id)
  384             num_hosta_nets = len(hosta_nets['networks'])
  385             hostc_nets = self._list_networks_hosted_by_dhcp_agent(hostc_id)
  386             num_hostc_nets = len(hostc_nets['networks'])
  387 
  388         self.assertEqual(2, num_hosta_nets)
  389         self.assertEqual(0, num_hostc_nets)
  390         self.assertEqual(1, len(dhcp_agents['agents']))
  391         self.assertEqual(DHCP_HOSTA, dhcp_agents['agents'][0]['host'])
  392 
  393     def test_network_auto_schedule_with_hosted_2(self):
  394         # one agent hosts one network
  395         dhcp_rpc_cb = dhcp_rpc.DhcpRpcCallback()
  396         cfg.CONF.set_override('allow_overlapping_ips', True)
  397         with self.subnet() as sub1:
  398             helpers.register_dhcp_agent(DHCP_HOSTA)
  399             dhcp_rpc_cb.get_active_networks_info(
  400                 self.adminContext, host=DHCP_HOSTA)
  401             hosta_id = self._get_agent_id(constants.AGENT_TYPE_DHCP,
  402                                           DHCP_HOSTA)
  403             self._disable_agent(hosta_id, admin_state_up=False)
  404             with self.subnet() as sub2:
  405                 helpers.register_dhcp_agent(DHCP_HOSTC)
  406                 dhcp_rpc_cb.get_active_networks_info(self.adminContext,
  407                                                      host=DHCP_HOSTC)
  408                 dhcp_agents_1 = self._list_dhcp_agents_hosting_network(
  409                     sub1['subnet']['network_id'])
  410                 dhcp_agents_2 = self._list_dhcp_agents_hosting_network(
  411                     sub2['subnet']['network_id'])
  412                 hosta_nets = self._list_networks_hosted_by_dhcp_agent(hosta_id)
  413                 num_hosta_nets = len(hosta_nets['networks'])
  414                 hostc_id = self._get_agent_id(
  415                     constants.AGENT_TYPE_DHCP,
  416                     DHCP_HOSTC)
  417                 hostc_nets = self._list_networks_hosted_by_dhcp_agent(hostc_id)
  418                 num_hostc_nets = len(hostc_nets['networks'])
  419 
  420         self.assertEqual(1, num_hosta_nets)
  421         self.assertEqual(1, num_hostc_nets)
  422         self.assertEqual(1, len(dhcp_agents_1['agents']))
  423         self.assertEqual(1, len(dhcp_agents_2['agents']))
  424         self.assertEqual(DHCP_HOSTA, dhcp_agents_1['agents'][0]['host'])
  425         self.assertEqual(DHCP_HOSTC, dhcp_agents_2['agents'][0]['host'])
  426 
  427     def test_network_scheduling_on_port_creation(self):
  428         with self.subnet() as subnet:
  429             dhcp_agents = self._list_dhcp_agents_hosting_network(
  430                 subnet['subnet']['network_id'])
  431             result0 = len(dhcp_agents['agents'])
  432             self._register_agent_states()
  433             with self.port(subnet=subnet,
  434                            device_owner=DEVICE_OWNER_COMPUTE) as port:
  435                 dhcp_agents = self._list_dhcp_agents_hosting_network(
  436                     port['port']['network_id'])
  437                 result1 = len(dhcp_agents['agents'])
  438         self.assertEqual(0, result0)
  439         self.assertEqual(1, result1)
  440 
  441     def test_network_ha_scheduling_on_port_creation(self):
  442         cfg.CONF.set_override('dhcp_agents_per_network', 2)
  443         with self.subnet() as subnet:
  444             dhcp_agents = self._list_dhcp_agents_hosting_network(
  445                 subnet['subnet']['network_id'])
  446             result0 = len(dhcp_agents['agents'])
  447             self._register_agent_states()
  448             with self.port(subnet=subnet,
  449                            device_owner=DEVICE_OWNER_COMPUTE) as port:
  450                 dhcp_agents = self._list_dhcp_agents_hosting_network(
  451                     port['port']['network_id'])
  452                 result1 = len(dhcp_agents['agents'])
  453         self.assertEqual(0, result0)
  454         self.assertEqual(2, result1)
  455 
  456     def test_network_ha_scheduling_on_port_creation_with_new_agent(self):
  457         cfg.CONF.set_override('dhcp_agents_per_network', 3)
  458         with self.subnet() as subnet:
  459             dhcp_agents = self._list_dhcp_agents_hosting_network(
  460                 subnet['subnet']['network_id'])
  461             result0 = len(dhcp_agents['agents'])
  462             self._register_agent_states()
  463             with self.port(subnet=subnet,
  464                            device_owner=DEVICE_OWNER_COMPUTE) as port:
  465                 dhcp_agents = self._list_dhcp_agents_hosting_network(
  466                     port['port']['network_id'])
  467                 result1 = len(dhcp_agents['agents'])
  468             helpers.register_dhcp_agent('host1')
  469             with self.port(subnet=subnet,
  470                            device_owner=DEVICE_OWNER_COMPUTE) as port:
  471                 dhcp_agents = self._list_dhcp_agents_hosting_network(
  472                     port['port']['network_id'])
  473                 result2 = len(dhcp_agents['agents'])
  474         self.assertEqual(0, result0)
  475         self.assertEqual(2, result1)
  476         self.assertEqual(3, result2)
  477 
  478     def test_network_scheduler_with_disabled_agent(self):
  479         helpers.register_dhcp_agent(DHCP_HOSTA)
  480         with self.port() as port1:
  481             dhcp_agents = self._list_dhcp_agents_hosting_network(
  482                 port1['port']['network_id'])
  483         self._delete('ports', port1['port']['id'])
  484         self._delete('networks', port1['port']['network_id'])
  485         self.assertEqual(1, len(dhcp_agents['agents']))
  486         agents = self._list_agents()
  487         self._disable_agent(agents['agents'][0]['id'])
  488         with self.port() as port2:
  489             dhcp_agents = self._list_dhcp_agents_hosting_network(
  490                 port2['port']['network_id'])
  491         self._delete('ports', port2['port']['id'])
  492         self.assertEqual(0, len(dhcp_agents['agents']))
  493 
  494     def test_is_eligible_agent(self):
  495         agent_startup = ('neutron.db.agentschedulers_db.'
  496                          'DhcpAgentSchedulerDbMixin.agent_starting_up')
  497         is_eligible_agent = ('neutron.db.agentschedulers_db.'
  498                              'AgentSchedulerDbMixin.is_eligible_agent')
  499         dhcp_mixin = agentschedulers_db.DhcpAgentSchedulerDbMixin()
  500         with mock.patch(agent_startup) as startup,\
  501                 mock.patch(is_eligible_agent) as elig:
  502             tests = [(True, True),
  503                      (True, False),
  504                      (False, True),
  505                      (False, False)]
  506             for rv1, rv2 in tests:
  507                 startup.return_value = rv1
  508                 elig.return_value = rv2
  509                 self.assertEqual(rv1 or rv2,
  510                                  dhcp_mixin.is_eligible_agent(None,
  511                                                               None, None))
  512 
  513     def test_network_scheduler_with_down_agent(self):
  514         helpers.register_dhcp_agent(DHCP_HOSTA)
  515         eligible_agent_str = ('neutron.db.agentschedulers_db.'
  516                               'DhcpAgentSchedulerDbMixin.is_eligible_agent')
  517         with mock.patch(eligible_agent_str) as eligible_agent:
  518             eligible_agent.return_value = True
  519             with self.port() as port:
  520                 dhcp_agents = self._list_dhcp_agents_hosting_network(
  521                     port['port']['network_id'])
  522             self._delete('ports', port['port']['id'])
  523             self._delete('networks', port['port']['network_id'])
  524             self.assertEqual(1, len(dhcp_agents['agents']))
  525 
  526         with mock.patch(eligible_agent_str) as eligible_agent:
  527             eligible_agent.return_value = False
  528             with self.port() as port:
  529                 dhcp_agents = self._list_dhcp_agents_hosting_network(
  530                     port['port']['network_id'])
  531             self._delete('ports', port['port']['id'])
  532             self.assertEqual(0, len(dhcp_agents['agents']))
  533 
  534     def test_network_scheduler_with_hosted_network(self):
  535         plugin = directory.get_plugin()
  536         helpers.register_dhcp_agent(DHCP_HOSTA)
  537         with self.port() as port1:
  538             dhcp_agents = self._list_dhcp_agents_hosting_network(
  539                 port1['port']['network_id'])
  540             self.assertEqual(1, len(dhcp_agents['agents']))
  541         with mock.patch.object(plugin,
  542                                'get_dhcp_agents_hosting_networks',
  543                                autospec=True) as mock_hosting_agents:
  544 
  545             mock_hosting_agents.return_value = plugin.get_agent_objects(
  546                 self.adminContext)
  547             with self.network('test') as net1:
  548                 pass
  549             with self.subnet(network=net1,
  550                              cidr='10.0.1.0/24') as subnet1:
  551                 pass
  552             with self.port(subnet=subnet1) as port2:
  553                 pass
  554         dhcp_agents = self._list_dhcp_agents_hosting_network(
  555             port2['port']['network_id'])
  556         self.assertEqual(0, len(dhcp_agents['agents']))
  557 
  558     def test_network_policy(self):
  559         with self.network() as net1:
  560             self._register_agent_states()
  561             hosta_id = self._get_agent_id(constants.AGENT_TYPE_DHCP,
  562                                           DHCP_HOSTA)
  563             self._list_networks_hosted_by_dhcp_agent(
  564                 hosta_id, expected_code=exc.HTTPForbidden.code,
  565                 admin_context=False)
  566             self._add_network_to_dhcp_agent(
  567                 hosta_id, net1['network']['id'],
  568                 expected_code=exc.HTTPForbidden.code,
  569                 admin_context=False)
  570             self._add_network_to_dhcp_agent(hosta_id,
  571                                             net1['network']['id'])
  572             self._remove_network_from_dhcp_agent(
  573                 hosta_id, net1['network']['id'],
  574                 expected_code=exc.HTTPForbidden.code,
  575                 admin_context=False)
  576             self._list_dhcp_agents_hosting_network(
  577                 net1['network']['id'],
  578                 expected_code=exc.HTTPForbidden.code,
  579                 admin_context=False)
  580 
  581     def _test_network_add_to_dhcp_agent(self, admin_state_up=True):
  582         with self.network() as net1:
  583             self._register_agent_states()
  584             hosta_id = self._get_agent_id(constants.AGENT_TYPE_DHCP,
  585                                           DHCP_HOSTA)
  586             if not admin_state_up:
  587                 self._set_agent_admin_state_up(DHCP_HOSTA, False)
  588             num_before_add = len(
  589                 self._list_networks_hosted_by_dhcp_agent(
  590                     hosta_id)['networks'])
  591             self._add_network_to_dhcp_agent(hosta_id,
  592                                             net1['network']['id'])
  593             num_after_add = len(
  594                 self._list_networks_hosted_by_dhcp_agent(
  595                     hosta_id)['networks'])
  596         self.assertEqual(0, num_before_add)
  597         self.assertEqual(1, num_after_add)
  598 
  599     def test_network_add_to_dhcp_agent(self):
  600         self._test_network_add_to_dhcp_agent()
  601 
  602     def test_network_add_to_dhcp_agent_with_admin_state_down(self):
  603         cfg.CONF.set_override(
  604             'enable_services_on_agents_with_admin_state_down', True)
  605         self._test_network_add_to_dhcp_agent(admin_state_up=False)
  606 
  607     def _test_network_remove_from_dhcp_agent(self,
  608                                              concurrent_port_delete=False):
  609         agent = helpers.register_dhcp_agent(DHCP_HOSTA)
  610         hosta_id = agent.id
  611         with self.port(device_owner=constants.DEVICE_OWNER_DHCP,
  612                        host=DHCP_HOSTA) as port1:
  613             num_before_remove = len(
  614                 self._list_networks_hosted_by_dhcp_agent(
  615                     hosta_id)['networks'])
  616             if concurrent_port_delete:
  617                 plugin = directory.get_plugin()
  618                 # Return a foo port to emulate the port not found scenario
  619                 # caused by a concurrent port deletion during unscheduling
  620                 port = {'id': 'foo_port_id', 'device_id': 'foo_device_id'}
  621                 mock.patch.object(plugin, 'get_ports',
  622                                   return_value=[port]).start()
  623             self._remove_network_from_dhcp_agent(hosta_id,
  624                                                  port1['port']['network_id'])
  625             num_after_remove = len(
  626                 self._list_networks_hosted_by_dhcp_agent(
  627                     hosta_id)['networks'])
  628         self.assertEqual(1, num_before_remove)
  629         self.assertEqual(0, num_after_remove)
  630 
  631     def test_network_remove_from_dhcp_agent(self):
  632         self._test_network_remove_from_dhcp_agent()
  633 
  634     def test_network_remove_from_dhcp_agent_on_concurrent_port_delete(self):
  635         self._test_network_remove_from_dhcp_agent(concurrent_port_delete=True)
  636 
  637     def test_list_active_networks_on_not_registered_yet_dhcp_agent(self):
  638         plugin = directory.get_plugin()
  639         nets = plugin.list_active_networks_on_active_dhcp_agent(
  640             self.adminContext, host=DHCP_HOSTA)
  641         self.assertEqual([], nets)
  642 
  643     def test_reserved_port_after_network_remove_from_dhcp_agent(self):
  644         helpers.register_dhcp_agent(DHCP_HOSTA)
  645         hosta_id = self._get_agent_id(constants.AGENT_TYPE_DHCP,
  646                                       DHCP_HOSTA)
  647         with self.port(device_owner=constants.DEVICE_OWNER_DHCP,
  648                        host=DHCP_HOSTA) as port1:
  649             self._remove_network_from_dhcp_agent(hosta_id,
  650                                                  port1['port']['network_id'])
  651             port_res = self._list_ports(
  652                 'json',
  653                 200,
  654                 network_id=port1['port']['network_id'])
  655             port_list = self.deserialize('json', port_res)
  656             self.assertEqual(port_list['ports'][0]['device_id'],
  657                              constants.DEVICE_ID_RESERVED_DHCP_PORT)
  658 
  659     def _test_get_active_networks_from_admin_state_down_agent(self,
  660                                                               keep_services):
  661         if keep_services:
  662             cfg.CONF.set_override(
  663                 'enable_services_on_agents_with_admin_state_down', True)
  664         helpers.register_dhcp_agent(DHCP_HOSTA)
  665         dhcp_rpc_cb = dhcp_rpc.DhcpRpcCallback()
  666         with self.port():
  667             nets = dhcp_rpc_cb.get_active_networks_info(self.adminContext,
  668                                                         host=DHCP_HOSTA)
  669             self.assertEqual(1, len(nets))
  670             self._set_agent_admin_state_up(DHCP_HOSTA, False)
  671             nets = dhcp_rpc_cb.get_active_networks_info(self.adminContext,
  672                                                         host=DHCP_HOSTA)
  673             if keep_services:
  674                 self.assertEqual(1, len(nets))
  675             else:
  676                 self.assertEqual(0, len(nets))
  677 
  678     def test_dhcp_agent_keep_services_off(self):
  679         self._test_get_active_networks_from_admin_state_down_agent(False)
  680 
  681     def test_dhcp_agent_keep_services_on(self):
  682         self._test_get_active_networks_from_admin_state_down_agent(True)
  683 
  684     def _take_down_agent_and_run_reschedule(self, host):
  685         # take down the agent on host A and ensure B is alive
  686         self.adminContext.session.begin(subtransactions=True)
  687         query = self.adminContext.session.query(agent_model.Agent)
  688         agt = query.filter_by(host=host).first()
  689         agt.heartbeat_timestamp = (
  690             agt.heartbeat_timestamp - datetime.timedelta(hours=1))
  691         self.adminContext.session.commit()
  692 
  693         plugin = directory.get_plugin(plugin_constants.L3)
  694         plugin.reschedule_routers_from_down_agents()
  695 
  696     def _set_agent_admin_state_up(self, host, state):
  697         self.adminContext.session.begin(subtransactions=True)
  698         query = self.adminContext.session.query(agent_model.Agent)
  699         agt_db = query.filter_by(host=host).first()
  700         agt_db.admin_state_up = state
  701         self.adminContext.session.commit()
  702 
  703     def test_router_rescheduler_catches_rpc_db_and_reschedule_exceptions(self):
  704         with self.router():
  705             l3_rpc_cb = l3_rpc.L3RpcCallback()
  706             self._register_agent_states()
  707             # schedule the router to host A
  708             l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
  709 
  710             plugin = directory.get_plugin(plugin_constants.L3)
  711             mock.patch.object(
  712                 plugin, 'reschedule_router',
  713                 side_effect=[
  714                     db_exc.DBError(), oslo_messaging.RemoteError(),
  715                     l3agentscheduler.RouterReschedulingFailed(router_id='f',
  716                                                               agent_id='f'),
  717                     ValueError('this raises'),
  718                     Exception()
  719                 ]).start()
  720             self._take_down_agent_and_run_reschedule(L3_HOSTA)  # DBError
  721             self._take_down_agent_and_run_reschedule(L3_HOSTA)  # RemoteError
  722             self._take_down_agent_and_run_reschedule(L3_HOSTA)  # schedule err
  723             self._take_down_agent_and_run_reschedule(L3_HOSTA)  # Value error
  724             self._take_down_agent_and_run_reschedule(L3_HOSTA)  # Exception
  725 
  726     def test_router_rescheduler_catches_exceptions_on_fetching_bindings(self):
  727         with mock.patch('neutron_lib.context.get_admin_context') as get_ctx:
  728             mock_ctx = mock.Mock()
  729             get_ctx.return_value = mock_ctx
  730             mock_ctx.session.query.side_effect = db_exc.DBError()
  731             plugin = directory.get_plugin(plugin_constants.L3)
  732             # check that no exception is raised
  733             plugin.reschedule_routers_from_down_agents()
  734 
  735     def test_router_rescheduler_iterates_after_reschedule_failure(self):
  736         plugin = directory.get_plugin(plugin_constants.L3)
  737         l3_rpc_cb = l3_rpc.L3RpcCallback()
  738         self._register_agent_states()
  739         with self.router() as r1, self.router() as r2:
  740             # schedule the routers to host A
  741             l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
  742 
  743             rs_mock = mock.patch.object(
  744                 plugin, 'reschedule_router',
  745                 side_effect=l3agentscheduler.RouterReschedulingFailed(
  746                     router_id='f', agent_id='f'),
  747             ).start()
  748             self._take_down_agent_and_run_reschedule(L3_HOSTA)
  749             # make sure both had a reschedule attempt even though first failed
  750             rs_mock.assert_has_calls([mock.call(mock.ANY, r1['router']['id']),
  751                                       mock.call(mock.ANY, r2['router']['id'])],
  752                                      any_order=True)
  753 
  754     def test_router_is_not_rescheduled_from_alive_agent(self):
  755         with self.router():
  756             l3_rpc_cb = l3_rpc.L3RpcCallback()
  757             self._register_agent_states()
  758 
  759             # schedule the router to host A
  760             l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
  761             with mock.patch('neutron.db.l3_agentschedulers_db.'
  762                             'L3AgentSchedulerDbMixin.reschedule_router') as rr:
  763                 # take down some unrelated agent and run reschedule check
  764                 self._take_down_agent_and_run_reschedule(DHCP_HOSTC)
  765                 self.assertFalse(rr.called)
  766 
  767     def test_router_is_not_rescheduled_if_agent_is_back_online(self):
  768         plugin = directory.get_plugin(plugin_constants.L3)
  769         l3_rpc_cb = l3_rpc.L3RpcCallback()
  770         agent = helpers.register_l3_agent(host=L3_HOSTA)
  771         with self.router(),\
  772                 self.router(),\
  773                 mock.patch.object(plugin, 'reschedule_router') as rs_mock,\
  774                 mock.patch.object(plugin, '_get_agent') as get_agent_mock:
  775 
  776             # schedule the routers to the agent
  777             l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
  778             self._take_down_agent_and_run_reschedule(L3_HOSTA)
  779             # since _get_agent is mocked it will return Mock object and
  780             # agent.is_active will return true, so no rescheduling will be done
  781             self.assertFalse(rs_mock.called)
  782             # should be called only once as for second router alive agent id
  783             # will be in cache
  784             get_agent_mock.assert_called_once_with(mock.ANY, agent['id'])
  785 
  786     def test_router_reschedule_from_dead_agent(self):
  787         with self.router():
  788             l3_rpc_cb = l3_rpc.L3RpcCallback()
  789             self._register_agent_states()
  790 
  791             # schedule the router to host A
  792             ret_a = l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
  793             self._take_down_agent_and_run_reschedule(L3_HOSTA)
  794 
  795             # B should now pick up the router
  796             ret_b = l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTB)
  797         self.assertEqual(ret_b, ret_a)
  798 
  799     def test_router_no_reschedule_from_dead_admin_down_agent(self):
  800         with self.router() as r:
  801             l3_rpc_cb = l3_rpc.L3RpcCallback()
  802             self._register_agent_states()
  803 
  804             # schedule the router to host A
  805             l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
  806             self._set_agent_admin_state_up(L3_HOSTA, False)
  807             self._take_down_agent_and_run_reschedule(L3_HOSTA)
  808 
  809             # A should still have it even though it was inactive due to the
  810             # admin_state being down
  811             bindings = rb_obj.RouterL3AgentBinding.get_objects(
  812                     self.adminContext, router_id=r['router']['id'])
  813             binding = bindings.pop() if bindings else None
  814             l3_agent = ag_obj.Agent.get_objects(
  815                 self.adminContext, id=binding.l3_agent_id)
  816             self.assertEqual(l3_agent[0].host, L3_HOSTA)
  817 
  818             # B should not pick up the router
  819             ret_b = l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTB)
  820             self.assertFalse(ret_b)
  821 
  822     def test_router_reschedule_succeeded_after_failed_notification(self):
  823         l3_rpc_cb = l3_rpc.L3RpcCallback()
  824         self._register_agent_states()
  825         with self.router() as router:
  826             # schedule the router to host A
  827             l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
  828             ctxt_mock = mock.MagicMock()
  829             call_mock = mock.MagicMock(
  830                 side_effect=[oslo_messaging.MessagingTimeout, None])
  831             ctxt_mock.call = call_mock
  832             self.client_mock.prepare = mock.MagicMock(return_value=ctxt_mock)
  833             self._take_down_agent_and_run_reschedule(L3_HOSTA)
  834             self.assertEqual(2, call_mock.call_count)
  835             # make sure router was rescheduled even when first attempt
  836             # failed to notify l3 agent
  837             l3_agents = self._list_l3_agents_hosting_router(
  838                 router['router']['id'])['agents']
  839             self.assertEqual(1, len(l3_agents))
  840             self.assertEqual(L3_HOSTB, l3_agents[0]['host'])
  841 
  842     def test_router_reschedule_failed_notification_all_attempts(self):
  843         l3_rpc_cb = l3_rpc.L3RpcCallback()
  844         self._register_agent_states()
  845         with self.router() as router:
  846             # schedule the router to host A
  847             l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
  848             # mock client.prepare and context.call
  849             ctxt_mock = mock.MagicMock()
  850             call_mock = mock.MagicMock(
  851                 side_effect=oslo_messaging.MessagingTimeout)
  852             ctxt_mock.call = call_mock
  853             self.client_mock.prepare = mock.MagicMock(return_value=ctxt_mock)
  854             # perform operations
  855             self._take_down_agent_and_run_reschedule(L3_HOSTA)
  856             self.assertEqual(
  857                 l3_rpc_agent_api.AGENT_NOTIFY_MAX_ATTEMPTS,
  858                 call_mock.call_count)
  859             l3_agents = self._list_l3_agents_hosting_router(
  860                 router['router']['id'])['agents']
  861             self.assertEqual(0, len(l3_agents))
  862 
  863     def test_router_reschedule_no_remove_if_agent_has_dvr_service_ports(self):
  864         l3_notifier = self.l3plugin.agent_notifiers[constants.AGENT_TYPE_L3]
  865         agent_a = helpers.register_l3_agent(
  866             host=L3_HOSTA, agent_mode=constants.L3_AGENT_MODE_DVR_SNAT)
  867         agent_b = helpers.register_l3_agent(
  868             host=L3_HOSTB, agent_mode=constants.L3_AGENT_MODE_DVR_SNAT)
  869         with self.subnet() as s, \
  870                 mock.patch.object(l3_notifier.client, 'prepare',
  871                     return_value=l3_notifier.client) as mock_prepare, \
  872                 mock.patch.object(l3_notifier.client, 'cast') as mock_cast, \
  873                 mock.patch.object(l3_notifier.client, 'call'):
  874             net_id = s['subnet']['network_id']
  875             self._set_net_external(net_id)
  876             router = {'name': 'router1',
  877                       'external_gateway_info': {'network_id': net_id},
  878                       'tenant_id': 'tenant_id',
  879                       'admin_state_up': True,
  880                       'distributed': True}
  881             r = self.l3plugin.create_router(self.adminContext,
  882                                             {'router': router})
  883 
  884             # schedule the dvr to one of the agents
  885             self.l3plugin.schedule_router(self.adminContext, r['id'])
  886             l3agents = self.l3plugin.list_l3_agents_hosting_router(
  887                     self.adminContext, r['id'])
  888             agent = l3agents['agents'][0]
  889             # emulating dvr serviceable ports exist on the host
  890             with mock.patch.object(
  891                     self.l3plugin, '_check_dvr_serviceable_ports_on_host') \
  892                     as ports_exist:
  893                 ports_exist.return_value = True
  894                 # reschedule the dvr to one of the other agent
  895                 candidate_agent = (agent_b if agent['host'] == L3_HOSTA
  896                                    else agent_a)
  897                 self.l3plugin.reschedule_router(self.adminContext, r['id'],
  898                         candidates=[candidate_agent])
  899                 # make sure dvr serviceable ports are checked when rescheduling
  900                 self.assertTrue(ports_exist.called)
  901 
  902             # make sure sending update instead of removing for dvr
  903             mock_prepare.assert_called_with(server=candidate_agent['host'])
  904             mock_cast.assert_called_with(
  905                     mock.ANY, 'routers_updated',
  906                     routers=[r['id']])
  907 
  908             # make sure the rescheduling completes
  909             l3agents = self.l3plugin.list_l3_agents_hosting_router(
  910                     self.adminContext, r['id'])
  911             self.assertEqual(1, len(l3agents['agents']))
  912             new_agent_host = l3agents['agents'][0]['host']
  913             self.assertNotEqual(agent['host'], new_agent_host)
  914 
  915     def test_router_auto_schedule_with_invalid_router(self):
  916         with self.router() as router:
  917             l3_rpc_cb = l3_rpc.L3RpcCallback()
  918             self._register_agent_states()
  919         self._delete('routers', router['router']['id'])
  920 
  921         # deleted router
  922         ret_a = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA,
  923                                        router_ids=[router['router']['id']])
  924         self.assertFalse(ret_a)
  925         # non-existent router
  926         ret_a = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA,
  927                                        router_ids=[uuidutils.generate_uuid()])
  928         self.assertFalse(ret_a)
  929 
  930     def test_router_auto_schedule_with_hosted(self):
  931         with self.router() as router:
  932             l3_rpc_cb = l3_rpc.L3RpcCallback()
  933             self._register_agent_states()
  934             ret_a = l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
  935             ret_b = l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTB)
  936             l3_agents = self._list_l3_agents_hosting_router(
  937                 router['router']['id'])
  938             self.assertEqual(1, len(ret_a))
  939             self.assertIn(router['router']['id'], ret_a)
  940             self.assertFalse(len(ret_b))
  941         self.assertEqual(1, len(l3_agents['agents']))
  942         self.assertEqual(L3_HOSTA, l3_agents['agents'][0]['host'])
  943 
  944     def test_router_auto_schedule_restart_l3_agent(self):
  945         with self.router():
  946             l3_rpc_cb = l3_rpc.L3RpcCallback()
  947             self._register_agent_states()
  948             l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
  949             l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
  950 
  951     def test_router_auto_schedule_with_hosted_2(self):
  952         # one agent hosts one router
  953         l3_rpc_cb = l3_rpc.L3RpcCallback()
  954         with self.router() as router1:
  955             hosta_id = helpers.register_l3_agent(host=L3_HOSTA).id
  956             l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
  957             self._disable_agent(hosta_id, admin_state_up=False)
  958             with self.router() as router2:
  959                 hostb_id = helpers.register_l3_agent(host=L3_HOSTB).id
  960                 l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTB)
  961                 l3_agents_1 = self._list_l3_agents_hosting_router(
  962                     router1['router']['id'])
  963                 l3_agents_2 = self._list_l3_agents_hosting_router(
  964                     router2['router']['id'])
  965                 hosta_routers = self._list_routers_hosted_by_l3_agent(hosta_id)
  966                 num_hosta_routers = len(hosta_routers['routers'])
  967                 hostb_routers = self._list_routers_hosted_by_l3_agent(hostb_id)
  968                 num_hostb_routers = len(hostb_routers['routers'])
  969 
  970         self.assertEqual(1, num_hosta_routers)
  971         self.assertEqual(1, num_hostb_routers)
  972         self.assertEqual(1, len(l3_agents_1['agents']))
  973         self.assertEqual(1, len(l3_agents_2['agents']))
  974         self.assertEqual(L3_HOSTA, l3_agents_1['agents'][0]['host'])
  975         self.assertEqual(L3_HOSTB, l3_agents_2['agents'][0]['host'])
  976 
  977     def test_router_auto_schedule_with_disabled(self):
  978         with self.router(), self.router():
  979             l3_rpc_cb = l3_rpc.L3RpcCallback()
  980             self._register_agent_states()
  981             hosta_id = self._get_agent_id(constants.AGENT_TYPE_L3,
  982                                           L3_HOSTA)
  983             hostb_id = self._get_agent_id(constants.AGENT_TYPE_L3,
  984                                           L3_HOSTB)
  985             self._disable_agent(hosta_id)
  986             # first agent will not host router since it is disabled
  987             l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
  988             # second agent will host all the routers since first is disabled.
  989             l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTB)
  990             hostb_routers = self._list_routers_hosted_by_l3_agent(hostb_id)
  991             num_hostb_routers = len(hostb_routers['routers'])
  992             hosta_routers = self._list_routers_hosted_by_l3_agent(hosta_id)
  993             num_hosta_routers = len(hosta_routers['routers'])
  994         self.assertEqual(2, num_hostb_routers)
  995         self.assertEqual(0, num_hosta_routers)
  996 
  997     def test_rpc_sync_routers(self):
  998         l3_rpc_cb = l3_rpc.L3RpcCallback()
  999         self._register_agent_states()
 1000 
 1001         # No routers
 1002         ret_a = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA)
 1003         self.assertEqual(0, len(ret_a))
 1004 
 1005         with self.router() as v1, self.router() as v2, self.router() as v3:
 1006             routers = (v1, v2, v3)
 1007             router_ids = [r['router']['id'] for r in routers]
 1008 
 1009             # auto schedule routers first
 1010             l3_rpc_cb.get_router_ids(self.adminContext, host=L3_HOSTA)
 1011             # Get all routers
 1012             ret_a = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA)
 1013             self.assertEqual(3, len(ret_a))
 1014             self.assertEqual(set(router_ids), set([r['id'] for r in ret_a]))
 1015 
 1016             # Get all routers (router_ids=None)
 1017             ret_a = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA,
 1018                                            router_ids=None)
 1019             self.assertEqual(3, len(ret_a))
 1020             self.assertEqual(set(router_ids), set([r['id'] for r in ret_a]))
 1021 
 1022             # Get router2 only
 1023             ret_a = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA,
 1024                                            router_ids=[router_ids[1]])
 1025             self.assertEqual(1, len(ret_a))
 1026             self.assertIn(router_ids[1], [r['id'] for r in ret_a])
 1027 
 1028             # Get router1 and router3
 1029             ret_a = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA,
 1030                                            router_ids=[router_ids[0],
 1031                                                        router_ids[2]])
 1032             self.assertEqual(2, len(ret_a))
 1033             self.assertIn(router_ids[0], [r['id'] for r in ret_a])
 1034             self.assertIn(router_ids[2], [r['id'] for r in ret_a])
 1035 
 1036     def test_sync_router(self):
 1037         l3_rpc_cb = l3_rpc.L3RpcCallback()
 1038         self._register_agent_states()
 1039         hosta_id = self._get_agent_id(constants.AGENT_TYPE_L3, L3_HOSTA)
 1040 
 1041         with self.router() as r1:
 1042             ret_a = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA,
 1043                                            router_ids=[r1['router']['id']])
 1044             # Not return router to agent if the router is not bound to it.
 1045             self.assertEqual([], ret_a)
 1046             host_routers = self._list_routers_hosted_by_l3_agent(hosta_id)
 1047             # No router will be auto scheduled.
 1048             self.assertEqual(0, len(host_routers['routers']))
 1049 
 1050     def test_sync_dvr_router(self):
 1051         l3_rpc_cb = l3_rpc.L3RpcCallback()
 1052         dvr_agents = self._register_dvr_agents()
 1053 
 1054         with self.router() as r1, \
 1055                 mock.patch.object(self.l3plugin, 'get_subnet_ids_on_router',
 1056                                   return_value=['fake_subnet_id']), \
 1057                 mock.patch.object(self.l3plugin,
 1058                                   '_check_dvr_serviceable_ports_on_host',
 1059                                   return_value=True):
 1060             for l3_agent in dvr_agents:
 1061                 host = l3_agent['host']
 1062                 ret_a = l3_rpc_cb.sync_routers(self.adminContext, host=host,
 1063                                                router_ids=[r1['router']['id']])
 1064                 router_ids = [r['id'] for r in ret_a]
 1065                 # Return router to agent if there is dvr service port in agent.
 1066                 self.assertIn(r1['router']['id'], router_ids)
 1067                 host_routers = self._list_routers_hosted_by_l3_agent(
 1068                     l3_agent['id'])
 1069                 # No router will be auto scheduled.
 1070                 self.assertEqual(0, len(host_routers['routers']))
 1071 
 1072     def test_router_without_l3_agents(self):
 1073         with self.subnet() as s:
 1074             self._set_net_external(s['subnet']['network_id'])
 1075             data = {'router': {'tenant_id': uuidutils.generate_uuid()}}
 1076             data['router']['name'] = 'router1'
 1077             data['router']['external_gateway_info'] = {
 1078                 'network_id': s['subnet']['network_id']}
 1079             router_req = self.new_create_request('routers', data, self.fmt)
 1080             res = router_req.get_response(self.ext_api)
 1081             router = self.deserialize(self.fmt, res)
 1082             l3agents = (
 1083                 self.l3plugin.get_l3_agents_hosting_routers(
 1084                     self.adminContext, [router['router']['id']]))
 1085             self._delete('routers', router['router']['id'])
 1086         self.assertEqual(0, len(l3agents))
 1087 
 1088     def test_dvr_router_scheduling_to_only_dvr_snat_agent(self):
 1089         self._register_dvr_agents()
 1090         with self.subnet() as s:
 1091             net_id = s['subnet']['network_id']
 1092             self._set_net_external(net_id)
 1093 
 1094             router = {'name': 'router1',
 1095                       'external_gateway_info': {'network_id': net_id},
 1096                       'tenant_id': 'tenant_id',
 1097                       'admin_state_up': True,
 1098                       'distributed': True}
 1099             r = self.l3plugin.create_router(self.adminContext,
 1100                                             {'router': router})
 1101             with mock.patch.object(
 1102                     self.l3plugin,
 1103                     '_check_dvr_serviceable_ports_on_host') as ports_exist:
 1104                 # emulating dvr serviceable ports exist on compute node
 1105                 ports_exist.return_value = True
 1106                 self.l3plugin.schedule_router(
 1107                     self.adminContext, r['id'])
 1108 
 1109         l3agents = self._list_l3_agents_hosting_router(r['id'])
 1110         self.assertEqual(1, len(l3agents['agents']))
 1111         agent = l3agents['agents'][0]
 1112         self.assertEqual('dvr_snat',
 1113                          agent['configurations']['agent_mode'])
 1114 
 1115     def test_dvr_router_csnat_rescheduling(self):
 1116         helpers.register_l3_agent(
 1117             host=L3_HOSTA, agent_mode=constants.L3_AGENT_MODE_DVR_SNAT)
 1118         helpers.register_l3_agent(
 1119             host=L3_HOSTB, agent_mode=constants.L3_AGENT_MODE_DVR_SNAT)
 1120         with self.subnet() as s:
 1121             net_id = s['subnet']['network_id']
 1122             self._set_net_external(net_id)
 1123 
 1124             router = {'name': 'router1',
 1125                       'external_gateway_info': {'network_id': net_id},
 1126                       'tenant_id': 'tenant_id',
 1127                       'admin_state_up': True,
 1128                       'distributed': True}
 1129             r = self.l3plugin.create_router(self.adminContext,
 1130                                             {'router': router})
 1131             self.l3plugin.schedule_router(
 1132                     self.adminContext, r['id'])
 1133             l3agents = self._list_l3_agents_hosting_router(r['id'])
 1134             self.assertEqual(1, len(l3agents['agents']))
 1135             agent_host = l3agents['agents'][0]['host']
 1136             self._take_down_agent_and_run_reschedule(agent_host)
 1137             l3agents = self._list_l3_agents_hosting_router(r['id'])
 1138             self.assertEqual(1, len(l3agents['agents']))
 1139             new_agent_host = l3agents['agents'][0]['host']
 1140             self.assertNotEqual(agent_host, new_agent_host)
 1141 
 1142     def test_dvr_router_manual_rescheduling(self):
 1143         helpers.register_l3_agent(
 1144             host=L3_HOSTA, agent_mode=constants.L3_AGENT_MODE_DVR_SNAT)
 1145         helpers.register_l3_agent(
 1146             host=L3_HOSTB, agent_mode=constants.L3_AGENT_MODE_DVR_SNAT)
 1147         with self.subnet() as s:
 1148             net_id = s['subnet']['network_id']
 1149             self._set_net_external(net_id)
 1150 
 1151             router = {'name': 'router1',
 1152                       'external_gateway_info': {'network_id': net_id},
 1153                       'tenant_id': 'tenant_id',
 1154                       'admin_state_up': True,
 1155                       'distributed': True}
 1156             r = self.l3plugin.create_router(self.adminContext,
 1157                                             {'router': router})
 1158             self.l3plugin.schedule_router(
 1159                     self.adminContext, r['id'])
 1160             l3agents = self.l3plugin.list_l3_agents_hosting_router(
 1161                 self.adminContext, r['id'])
 1162             self.assertEqual(1, len(l3agents['agents']))
 1163             agent = l3agents['agents'][0]
 1164             # NOTE: Removing the router from the l3_agent will
 1165             # remove all the namespace since there is no other
 1166             # serviceable ports in the node that requires it.
 1167             self.l3plugin.remove_router_from_l3_agent(
 1168                 self.adminContext, agent['id'], r['id'])
 1169 
 1170             l3agents = self.l3plugin.list_l3_agents_hosting_router(
 1171                 self.adminContext, r['id'])
 1172             self.assertEqual(0, len(l3agents['agents']))
 1173 
 1174             self.l3plugin.add_router_to_l3_agent(
 1175                 self.adminContext, agent['id'], r['id'])
 1176 
 1177             l3agents = self.l3plugin.list_l3_agents_hosting_router(
 1178                 self.adminContext, r['id'])
 1179             self.assertEqual(1, len(l3agents['agents']))
 1180             new_agent = l3agents['agents'][0]
 1181             self.assertEqual(agent['id'], new_agent['id'])
 1182 
 1183     def test_router_sync_data(self):
 1184         with self.subnet() as s1,\
 1185                 self.subnet(cidr='10.0.2.0/24') as s2,\
 1186                 self.subnet(cidr='10.0.3.0/24') as s3:
 1187             self._register_agent_states()
 1188             self._set_net_external(s1['subnet']['network_id'])
 1189             data = {'router': {'tenant_id': uuidutils.generate_uuid()}}
 1190             data['router']['name'] = 'router1'
 1191             data['router']['external_gateway_info'] = {
 1192                 'network_id': s1['subnet']['network_id']}
 1193             router_req = self.new_create_request('routers', data, self.fmt)
 1194             res = router_req.get_response(self.ext_api)
 1195             router = self.deserialize(self.fmt, res)
 1196             self._router_interface_action('add',
 1197                                           router['router']['id'],
 1198                                           s2['subnet']['id'],
 1199                                           None)
 1200             self._router_interface_action('add',
 1201                                           router['router']['id'],
 1202                                           s3['subnet']['id'],
 1203                                           None)
 1204             l3agents = self._list_l3_agents_hosting_router(
 1205                 router['router']['id'])
 1206             self.assertEqual(1, len(l3agents['agents']))
 1207             agents = self._list_agents()
 1208             another_l3_agent_id = None
 1209             another_l3_agent_host = None
 1210             default = l3agents['agents'][0]['id']
 1211             for com in agents['agents']:
 1212                 if (com['id'] != default and
 1213                         com['agent_type'] == constants.AGENT_TYPE_L3):
 1214                     another_l3_agent_id = com['id']
 1215                     another_l3_agent_host = com['host']
 1216                     break
 1217             self.assertIsNotNone(another_l3_agent_id)
 1218             self._add_router_to_l3_agent(another_l3_agent_id,
 1219                                          router['router']['id'],
 1220                                          expected_code=exc.HTTPConflict.code)
 1221             self._remove_router_from_l3_agent(default,
 1222                                               router['router']['id'])
 1223             self._add_router_to_l3_agent(another_l3_agent_id,
 1224                                          router['router']['id'])
 1225             l3agents = self._list_l3_agents_hosting_router(
 1226                 router['router']['id'])
 1227             self.assertEqual(another_l3_agent_host,
 1228                              l3agents['agents'][0]['host'])
 1229             self._remove_router_from_l3_agent(another_l3_agent_id,
 1230                                               router['router']['id'])
 1231             self._router_interface_action('remove',
 1232                                           router['router']['id'],
 1233                                           s2['subnet']['id'],
 1234                                           None)
 1235             l3agents = self._list_l3_agents_hosting_router(
 1236                 router['router']['id'])
 1237             self.assertEqual(1,
 1238                              len(l3agents['agents']))
 1239             self._router_interface_action('remove',
 1240                                           router['router']['id'],
 1241                                           s3['subnet']['id'],
 1242                                           None)
 1243             self._delete('routers', router['router']['id'])
 1244 
 1245     def _test_router_add_to_l3_agent(self, admin_state_up=True):
 1246         with self.router() as router1:
 1247             self._register_agent_states()
 1248             hosta_id = self._get_agent_id(constants.AGENT_TYPE_L3,
 1249                                           L3_HOSTA)
 1250             if not admin_state_up:
 1251                 self._set_agent_admin_state_up(L3_HOSTA, False)
 1252             num_before_add = len(
 1253                 self._list_routers_hosted_by_l3_agent(
 1254                     hosta_id)['routers'])
 1255             self._add_router_to_l3_agent(hosta_id,
 1256                                          router1['router']['id'])
 1257             hostb_id = self._get_agent_id(constants.AGENT_TYPE_L3,
 1258                                           L3_HOSTB)
 1259             self._add_router_to_l3_agent(hostb_id,
 1260                                          router1['router']['id'],
 1261                                          expected_code=exc.HTTPConflict.code)
 1262             num_after_add = len(
 1263                 self._list_routers_hosted_by_l3_agent(
 1264                     hosta_id)['routers'])
 1265         self.assertEqual(0, num_before_add)
 1266         self.assertEqual(1, num_after_add)
 1267 
 1268     def test_router_add_to_l3_agent(self):
 1269         self._test_router_add_to_l3_agent()
 1270 
 1271     def test_router_add_to_l3_agent_with_admin_state_down(self):
 1272         cfg.CONF.set_override(
 1273             'enable_services_on_agents_with_admin_state_down', True)
 1274         self._test_router_add_to_l3_agent(admin_state_up=False)
 1275 
 1276     def test_router_add_to_l3_agent_two_times(self):
 1277         with self.router() as router1:
 1278             self._register_agent_states()
 1279             hosta_id = self._get_agent_id(constants.AGENT_TYPE_L3,
 1280                                           L3_HOSTA)
 1281             self._add_router_to_l3_agent(hosta_id,
 1282                                          router1['router']['id'])
 1283             # scheduling twice on the same agent is fine
 1284             self._add_router_to_l3_agent(hosta_id,
 1285                                          router1['router']['id'])
 1286 
 1287     def test_router_add_to_two_l3_agents(self):
 1288         with self.router() as router1:
 1289             self._register_agent_states()
 1290             hosta_id = self._get_agent_id(constants.AGENT_TYPE_L3,
 1291                                           L3_HOSTA)
 1292             hostb_id = self._get_agent_id(constants.AGENT_TYPE_L3,
 1293                                           L3_HOSTB)
 1294             self._add_router_to_l3_agent(hosta_id,
 1295                                          router1['router']['id'])
 1296             self._add_router_to_l3_agent(hostb_id,
 1297                                          router1['router']['id'],
 1298                                          expected_code=exc.HTTPConflict.code)
 1299 
 1300     def test_router_policy(self):
 1301         with self.router() as router1:
 1302             self._register_agent_states()
 1303             hosta_id = self._get_agent_id(constants.AGENT_TYPE_L3,
 1304                                           L3_HOSTA)
 1305             self._list_routers_hosted_by_l3_agent(
 1306                 hosta_id, expected_code=exc.HTTPForbidden.code,
 1307                 admin_context=False)
 1308             self._add_router_to_l3_agent(
 1309                 hosta_id, router1['router']['id'],
 1310                 expected_code=exc.HTTPForbidden.code,
 1311                 admin_context=False)
 1312             self._add_router_to_l3_agent(
 1313                 hosta_id, router1['router']['id'])
 1314             self._remove_router_from_l3_agent(
 1315                 hosta_id, router1['router']['id'],
 1316                 expected_code=exc.HTTPForbidden.code,
 1317                 admin_context=False)
 1318             self._list_l3_agents_hosting_router(
 1319                 router1['router']['id'],
 1320                 expected_code=exc.HTTPForbidden.code,
 1321                 admin_context=False)
 1322 
 1323     def _test_sync_routers_from_admin_state_down_agent(self, keep_services):
 1324         if keep_services:
 1325             cfg.CONF.set_override(
 1326                 'enable_services_on_agents_with_admin_state_down', True)
 1327         l3_rpc_cb = l3_rpc.L3RpcCallback()
 1328         self._register_agent_states()
 1329         hosta_id = self._get_agent_id(constants.AGENT_TYPE_L3, L3_HOSTA)
 1330         with self.router() as router:
 1331             self._add_router_to_l3_agent(hosta_id,
 1332                                          router['router']['id'])
 1333             routers = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA)
 1334             self.assertEqual(1, len(routers))
 1335             self._set_agent_admin_state_up(L3_HOSTA, False)
 1336             routers = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA)
 1337             if keep_services:
 1338                 self.assertEqual(1, len(routers))
 1339             else:
 1340                 self.assertEqual(0, len(routers))
 1341 
 1342     def test_l3_agent_keep_services_off(self):
 1343         self._test_sync_routers_from_admin_state_down_agent(False)
 1344 
 1345     def test_l3_agent_keep_services_on(self):
 1346         self._test_sync_routers_from_admin_state_down_agent(True)
 1347 
 1348     def test_list_routers_hosted_by_l3_agent_with_invalid_agent(self):
 1349         invalid_agentid = 'non_existing_agent'
 1350         self._list_routers_hosted_by_l3_agent(invalid_agentid,
 1351                                               exc.HTTPNotFound.code)
 1352 
 1353     def test_list_networks_hosted_by_dhcp_agent_with_invalid_agent(self):
 1354         invalid_agentid = 'non_existing_agent'
 1355         self._list_networks_hosted_by_dhcp_agent(invalid_agentid,
 1356                                                  exc.HTTPNotFound.code)
 1357 
 1358 
 1359 class OvsDhcpAgentNotifierTestCase(test_agent.AgentDBTestMixIn,
 1360                                    AgentSchedulerTestMixIn,
 1361                                    test_plugin.NeutronDbPluginV2TestCase):
 1362     def setUp(self):
 1363         super(OvsDhcpAgentNotifierTestCase, self).setUp('ml2')
 1364         mock.patch.object(
 1365             self.plugin, 'filter_hosts_with_network_access',
 1366             side_effect=lambda context, network_id, hosts: hosts).start()
 1367         plugin = directory.get_plugin()
 1368         self.dhcp_notifier = plugin.agent_notifiers[constants.AGENT_TYPE_DHCP]
 1369         self.dhcp_notifier_cast = mock.patch(
 1370             'neutron.api.rpc.agentnotifiers.dhcp_rpc_agent_api.'
 1371             'DhcpAgentNotifyAPI._cast_message').start()
 1372         ext_mgr = extensions.PluginAwareExtensionManager.get_instance()
 1373         self.ext_api = test_extensions.setup_extensions_middleware(ext_mgr)
 1374         self.adminContext = context.get_admin_context()
 1375         fake_notifier.reset()
 1376 
 1377     def test_network_add_to_dhcp_agent_notification(self):
 1378         with self.network() as net1:
 1379             network_id = net1['network']['id']
 1380             self._register_agent_states()
 1381             hosta_id = self._get_agent_id(constants.AGENT_TYPE_DHCP,
 1382                                           DHCP_HOSTA)
 1383             self._add_network_to_dhcp_agent(hosta_id,
 1384                                             network_id)
 1385         self.dhcp_notifier_cast.assert_called_with(
 1386                 mock.ANY, 'network_create_end',
 1387                 {'network': {'id': network_id},
 1388                  'priority': dhcp_rpc_agent_api.PRIORITY_NETWORK_CREATE},
 1389                 DHCP_HOSTA)
 1390         notifications = fake_notifier.NOTIFICATIONS
 1391         expected_event_type = 'dhcp_agent.network.add'
 1392         self._assert_notify(notifications, expected_event_type)
 1393 
 1394     def test_network_remove_from_dhcp_agent_notification(self):
 1395         with self.network() as net1:
 1396             network_id = net1['network']['id']
 1397             self._register_agent_states()
 1398             hosta_id = self._get_agent_id(constants.AGENT_TYPE_DHCP,
 1399                                           DHCP_HOSTA)
 1400             self._add_network_to_dhcp_agent(hosta_id,
 1401                                             network_id)
 1402 
 1403         self._remove_network_from_dhcp_agent(hosta_id,
 1404                                              network_id)
 1405         self.dhcp_notifier_cast.assert_called_with(
 1406                 mock.ANY, 'network_delete_end',
 1407                 {'network_id': network_id,
 1408                  'priority': dhcp_rpc_agent_api.PRIORITY_NETWORK_DELETE},
 1409                 DHCP_HOSTA)
 1410         notifications = fake_notifier.NOTIFICATIONS
 1411         expected_event_type = 'dhcp_agent.network.remove'
 1412         self._assert_notify(notifications, expected_event_type)
 1413 
 1414     def test_agent_updated_dhcp_agent_notification(self):
 1415         self._register_agent_states()
 1416         hosta_id = self._get_agent_id(constants.AGENT_TYPE_DHCP,
 1417                                       DHCP_HOSTA)
 1418         self._disable_agent(hosta_id, admin_state_up=False)
 1419 
 1420         self.dhcp_notifier_cast.assert_called_with(
 1421                 mock.ANY, 'agent_updated',
 1422                 {'admin_state_up': False}, DHCP_HOSTA)
 1423 
 1424     def _api_network_port_create(
 1425             self, hosts, gateway=constants.ATTR_NOT_SPECIFIED, owner=None):
 1426         for host in hosts:
 1427             helpers.register_dhcp_agent(host)
 1428         with self.network() as net1:
 1429             with self.subnet(network=net1,
 1430                              gateway_ip=gateway) as subnet1:
 1431                 if owner:
 1432                     with self.port(subnet=subnet1,
 1433                                    device_owner=owner) as port:
 1434                         return [net1, subnet1, port]
 1435                 else:
 1436                     with self.port(subnet=subnet1) as port:
 1437                         return [net1, subnet1, port]
 1438 
 1439     def _network_port_create(self, *args, **kwargs):
 1440         net, sub, port = self._api_network_port_create(*args, **kwargs)
 1441 
 1442         dhcp_notifier = self.plugin.agent_notifiers[constants.AGENT_TYPE_DHCP]
 1443         if (not hasattr(dhcp_notifier, 'uses_native_notifications') or
 1444             not all(dhcp_notifier.uses_native_notifications[r]['create']
 1445                     for r in ('port', 'subnet', 'network'))):
 1446             return net, sub, port
 1447         # since plugin has native dhcp notifications, the payloads will be the
 1448         # same as the getter outputs
 1449         ctx = context.get_admin_context()
 1450         net['network'] = self.plugin.get_network(ctx, net['network']['id'])
 1451         sub['subnet'] = self.plugin.get_subnet(ctx, sub['subnet']['id'])
 1452         sub['priority'] = dhcp_rpc_agent_api.PRIORITY_SUBNET_UPDATE
 1453         port['port'] = self.plugin.get_port(ctx, port['port']['id'])
 1454         return net, sub, port
 1455 
 1456     def _notification_mocks(self, hosts, net, subnet, port, port_priority):
 1457         host_calls = {}
 1458         for host in hosts:
 1459             expected_calls = [
 1460                 mock.call(
 1461                     mock.ANY,
 1462                     'network_create_end',
 1463                     {'priority': dhcp_rpc_agent_api.PRIORITY_NETWORK_CREATE,
 1464                      'network': {'id': net['network']['id']}},
 1465                     host),
 1466                 mock.call(
 1467                     mock.ANY,
 1468                     'subnet_create_end',
 1469                     subnet,
 1470                     host, 'dhcp_agent'),
 1471                 mock.call(
 1472                     mock.ANY,
 1473                     'port_create_end',
 1474                     {'port': port['port'],
 1475                      'priority': port_priority},
 1476                     host, 'dhcp_agent')]
 1477             host_calls[host] = expected_calls
 1478         return host_calls
 1479 
 1480     def test_network_port_create_notification(self):
 1481         hosts = [DHCP_HOSTA]
 1482         net, subnet, port = self._network_port_create(hosts)
 1483         expected_calls = self._notification_mocks(
 1484             hosts, net, subnet, port,
 1485             dhcp_rpc_agent_api.PRIORITY_PORT_CREATE_HIGH)
 1486         self.assertEqual(
 1487             expected_calls[DHCP_HOSTA], self.dhcp_notifier_cast.call_args_list)
 1488 
 1489     def test_network_ha_port_create_notification(self):
 1490         cfg.CONF.set_override('dhcp_agents_per_network', 3)
 1491         hosts = [DHCP_HOSTA, DHCP_HOSTC, DHCP_HOSTD]
 1492         net, subnet, port = self._network_port_create(hosts)
 1493         for host_call in self.dhcp_notifier_cast.call_args_list:
 1494             if ("'priority': " + str(
 1495                     dhcp_rpc_agent_api.PRIORITY_PORT_CREATE_HIGH)
 1496                     in str(host_call)):
 1497                 if DHCP_HOSTA in str(host_call):
 1498                     expected_high_calls = self._notification_mocks(
 1499                         [DHCP_HOSTA], net, subnet, port,
 1500                         dhcp_rpc_agent_api.PRIORITY_PORT_CREATE_HIGH)
 1501                     high_host = DHCP_HOSTA
 1502                     hosts.pop(0)
 1503                 elif DHCP_HOSTC in str(host_call):
 1504                     expected_high_calls = self._notification_mocks(
 1505                         [DHCP_HOSTC], net, subnet, port,
 1506                         dhcp_rpc_agent_api.PRIORITY_PORT_CREATE_HIGH)
 1507                     high_host = DHCP_HOSTC
 1508                     hosts.pop(1)
 1509                 elif DHCP_HOSTD in str(host_call):
 1510                     expected_high_calls = self._notification_mocks(
 1511                         [DHCP_HOSTD], net, subnet, port,
 1512                         dhcp_rpc_agent_api.PRIORITY_PORT_CREATE_HIGH)
 1513                     high_host = DHCP_HOSTD
 1514                     hosts.pop(2)
 1515         expected_low_calls = self._notification_mocks(
 1516             hosts, net, subnet, port,
 1517             dhcp_rpc_agent_api.PRIORITY_PORT_CREATE_LOW)
 1518         for expected in expected_high_calls[high_host]:
 1519             self.assertIn(expected, self.dhcp_notifier_cast.call_args_list)
 1520         for host, low_expecteds in expected_low_calls.items():
 1521             for expected in low_expecteds:
 1522                 self.assertIn(expected, self.dhcp_notifier_cast.call_args_list)
 1523 
 1524     def _is_schedule_network_called(self, device_id):
 1525         dhcp_notifier_schedule = mock.patch(
 1526             'neutron.api.rpc.agentnotifiers.dhcp_rpc_agent_api.'
 1527             'DhcpAgentNotifyAPI._schedule_network').start()
 1528         plugin = directory.get_plugin()
 1529         with self.subnet() as subnet,\
 1530                 self.port(subnet=subnet, device_id=device_id),\
 1531                 mock.patch.object(plugin,
 1532                                   'get_dhcp_agents_hosting_networks',
 1533                                   return_value=[]):
 1534             return dhcp_notifier_schedule.call_count > 1
 1535 
 1536     def test_reserved_dhcp_port_creation(self):
 1537         device_id = constants.DEVICE_ID_RESERVED_DHCP_PORT
 1538         self.assertFalse(self._is_schedule_network_called(device_id))
 1539 
 1540     def test_unreserved_dhcp_port_creation(self):
 1541         device_id = 'not_reserved'
 1542         self.assertTrue(self._is_schedule_network_called(device_id))
 1543 
 1544 
 1545 class OvsL3AgentNotifierTestCase(test_l3.L3NatTestCaseMixin,
 1546                                  test_agent.AgentDBTestMixIn,
 1547                                  AgentSchedulerTestMixIn,
 1548                                  test_plugin.NeutronDbPluginV2TestCase):
 1549     l3_plugin = ('neutron.tests.unit.extensions.test_l3.'
 1550                  'TestL3NatAgentSchedulingServicePlugin')
 1551 
 1552     def setUp(self):
 1553         self.dhcp_notifier_cls_p = mock.patch(
 1554             'neutron.api.rpc.agentnotifiers.dhcp_rpc_agent_api.'
 1555             'DhcpAgentNotifyAPI')
 1556         self.dhcp_notifier = mock.Mock(name='dhcp_notifier')
 1557         self.dhcp_notifier_cls = self.dhcp_notifier_cls_p.start()
 1558         self.dhcp_notifier_cls.return_value = self.dhcp_notifier
 1559 
 1560         if self.l3_plugin:
 1561             service_plugins = {
 1562                 'l3_plugin_name': self.l3_plugin,
 1563                 'flavors_plugin_name': 'neutron.services.flavors.'
 1564                                        'flavors_plugin.FlavorsPlugin'
 1565             }
 1566         else:
 1567             service_plugins = None
 1568         super(OvsL3AgentNotifierTestCase, self).setUp(
 1569             'ml2', service_plugins=service_plugins)
 1570         ext_mgr = extensions.PluginAwareExtensionManager.get_instance()
 1571         self.ext_api = test_extensions.setup_extensions_middleware(ext_mgr)
 1572         self.adminContext = context.get_admin_context()
 1573         fake_notifier.reset()
 1574 
 1575     def test_router_add_to_l3_agent_notification(self):
 1576         l3_plugin = directory.get_plugin(plugin_constants.L3)
 1577         l3_notifier = l3_plugin.agent_notifiers[constants.AGENT_TYPE_L3]
 1578         with mock.patch.object(
 1579             l3_notifier.client,
 1580             'prepare',
 1581             return_value=l3_notifier.client) as mock_prepare,\
 1582                 mock.patch.object(l3_notifier.client, 'call') as mock_call,\
 1583                 self.router() as router1:
 1584             self._register_agent_states()
 1585             hosta_id = self._get_agent_id(constants.AGENT_TYPE_L3,
 1586                                           L3_HOSTA)
 1587             self._add_router_to_l3_agent(hosta_id,
 1588                                          router1['router']['id'])
 1589             routers = [router1['router']['id']]
 1590             mock_prepare.assert_called_with(server='hosta')
 1591             mock_call.assert_called_with(
 1592                 mock.ANY, 'router_added_to_agent', payload=routers)
 1593             notifications = fake_notifier.NOTIFICATIONS
 1594             expected_event_type = 'l3_agent.router.add'
 1595             self._assert_notify(notifications, expected_event_type)
 1596 
 1597     def test_router_remove_from_l3_agent_notification(self):
 1598         l3_plugin = directory.get_plugin(plugin_constants.L3)
 1599         l3_notifier = l3_plugin.agent_notifiers[constants.AGENT_TYPE_L3]
 1600         with mock.patch.object(
 1601             l3_notifier.client,
 1602             'prepare',
 1603             return_value=l3_notifier.client) as mock_prepare,\
 1604                 mock.patch.object(l3_notifier.client, 'cast') as mock_cast,\
 1605                 mock.patch.object(l3_notifier.client, 'call'),\
 1606                 self.router() as router1:
 1607             self._register_agent_states()
 1608             hosta_id = self._get_agent_id(constants.AGENT_TYPE_L3,
 1609                                           L3_HOSTA)
 1610             self._add_router_to_l3_agent(hosta_id,
 1611                                          router1['router']['id'])
 1612             self._remove_router_from_l3_agent(hosta_id,
 1613                                               router1['router']['id'])
 1614             mock_prepare.assert_called_with(server='hosta')
 1615             mock_cast.assert_called_with(
 1616                     mock.ANY, 'router_removed_from_agent',
 1617                     payload={'router_id': router1['router']['id']})
 1618             notifications = fake_notifier.NOTIFICATIONS
 1619             expected_event_type = 'l3_agent.router.remove'
 1620             self._assert_notify(notifications, expected_event_type)
 1621 
 1622     def test_agent_updated_l3_agent_notification(self):
 1623         l3_plugin = directory.get_plugin(plugin_constants.L3)
 1624         l3_notifier = l3_plugin.agent_notifiers[constants.AGENT_TYPE_L3]
 1625         with mock.patch.object(
 1626             l3_notifier.client,
 1627             'prepare',
 1628             return_value=l3_notifier.client) as mock_prepare,\
 1629                 mock.patch.object(l3_notifier.client, 'cast') as mock_cast:
 1630             agent_id = helpers.register_l3_agent(L3_HOSTA).id
 1631             self._disable_agent(agent_id, admin_state_up=False)
 1632 
 1633             mock_prepare.assert_called_with(server=L3_HOSTA)
 1634 
 1635             mock_cast.assert_called_with(
 1636                 mock.ANY, 'agent_updated', payload={'admin_state_up': False})