Merge "Move network schedule to first port creation."

This commit is contained in:
Jenkins 2013-03-02 07:55:45 +00:00 committed by Gerrit Code Review
commit 3c8703913e
7 changed files with 169 additions and 59 deletions

View File

@ -62,6 +62,19 @@ class DhcpAgentNotifyAPI(proxy.RpcProxy):
plugin = manager.QuantumManager.get_plugin() plugin = manager.QuantumManager.get_plugin()
if (method != 'network_delete_end' and utils.is_extension_supported( if (method != 'network_delete_end' and utils.is_extension_supported(
plugin, constants.AGENT_SCHEDULER_EXT_ALIAS)): plugin, constants.AGENT_SCHEDULER_EXT_ALIAS)):
if method == 'port_create_end':
# we don't schedule when we create network
# because we want to give admin a chance to
# schedule network manually by API
adminContext = (context if context.is_admin else
context.elevated())
network = plugin.get_network(adminContext, network_id)
chosen_agent = plugin.schedule_network(adminContext, network)
if chosen_agent:
self._notification_host(
context, 'network_create_end',
{'network': {'id': network_id}},
chosen_agent['host'])
for (host, topic) in self._get_dhcp_agents(context, network_id): for (host, topic) in self._get_dhcp_agents(context, network_id):
self.cast( self.cast(
context, self.make_msg(method, context, self.make_msg(method,

View File

@ -292,12 +292,13 @@ class AgentSchedulerDbMixin(agentscheduler.AgentSchedulerPluginBase):
else: else:
return {'agents': []} return {'agents': []}
def schedule_network(self, context, request_network, created_network): def schedule_network(self, context, created_network):
if self.network_scheduler: if self.network_scheduler:
result = self.network_scheduler.schedule( chosen_agent = self.network_scheduler.schedule(
self, context, request_network, created_network) self, context, created_network)
if not result: if not chosen_agent:
LOG.warn(_('Fail scheduling network %s'), created_network) LOG.warn(_('Fail scheduling network %s'), created_network)
return chosen_agent
def auto_schedule_networks(self, context, host): def auto_schedule_networks(self, context, host):
if self.network_scheduler: if self.network_scheduler:

View File

@ -956,7 +956,7 @@ class NvpPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
net_binding) net_binding)
self._extend_network_port_security_dict(context, new_net) self._extend_network_port_security_dict(context, new_net)
self._extend_network_dict_l3(context, new_net) self._extend_network_dict_l3(context, new_net)
self.schedule_network(context, network['network'], new_net) self.schedule_network(context, new_net)
return new_net return new_net
def delete_network(self, context, id): def delete_network(self, context, id):
@ -1351,7 +1351,7 @@ class NvpPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
self._extend_port_dict_security_group(context, port_data) self._extend_port_dict_security_group(context, port_data)
self._extend_port_qos_queue(context, port_data) self._extend_port_qos_queue(context, port_data)
net = self.get_network(context, port_data['network_id']) net = self.get_network(context, port_data['network_id'])
self.schedule_network(context, None, net) self.schedule_network(context, net)
return port_data return port_data
def update_port(self, context, id, port): def update_port(self, context, id, port):

View File

@ -497,7 +497,6 @@ class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
self._extend_network_dict_l3(context, net) self._extend_network_dict_l3(context, net)
# note - exception will rollback entire transaction # note - exception will rollback entire transaction
LOG.debug(_("Created network: %s"), net['id']) LOG.debug(_("Created network: %s"), net['id'])
self.schedule_network(context, network['network'], net)
return net return net
def update_network(self, context, id, network): def update_network(self, context, id, network):
@ -578,8 +577,6 @@ class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
else: else:
self.notifier.security_groups_member_updated( self.notifier.security_groups_member_updated(
context, port.get(ext_sg.SECURITYGROUPS)) context, port.get(ext_sg.SECURITYGROUPS))
net = self.get_network(context, port['network_id'])
self.schedule_network(context, None, net)
return self._extend_port_dict_binding(context, port) return self._extend_port_dict_binding(context, port)
def get_port(self, context, id, fields=None): def get_port(self, context, id, fields=None):

View File

@ -35,7 +35,7 @@ class ChanceScheduler(object):
More sophisticated scheduler (similar to filter scheduler in nova?) More sophisticated scheduler (similar to filter scheduler in nova?)
can be introduced later.""" can be introduced later."""
def schedule(self, plugin, context, request_network, network): def schedule(self, plugin, context, network):
"""Schedule the network to an active DHCP agent if there """Schedule the network to an active DHCP agent if there
is no active DHCP agent hosting it. is no active DHCP agent hosting it.
""" """
@ -47,21 +47,21 @@ class ChanceScheduler(object):
if dhcp_agents: if dhcp_agents:
LOG.debug(_('Network %s is hosted already'), LOG.debug(_('Network %s is hosted already'),
network['id']) network['id'])
return False return
enabled_dhcp_agents = plugin.get_agents_db( enabled_dhcp_agents = plugin.get_agents_db(
context, filters={ context, filters={
'agent_type': [constants.AGENT_TYPE_DHCP], 'agent_type': [constants.AGENT_TYPE_DHCP],
'admin_state_up': [True]}) 'admin_state_up': [True]})
if not enabled_dhcp_agents: if not enabled_dhcp_agents:
LOG.warn(_('No enabled DHCP agents')) LOG.warn(_('No enabled DHCP agents'))
return False return
active_dhcp_agents = [enabled_dhcp_agent for enabled_dhcp_agent in active_dhcp_agents = [enabled_dhcp_agent for enabled_dhcp_agent in
enabled_dhcp_agents if not enabled_dhcp_agents if not
agents_db.AgentDbMixin.is_agent_down( agents_db.AgentDbMixin.is_agent_down(
enabled_dhcp_agent['heartbeat_timestamp'])] enabled_dhcp_agent['heartbeat_timestamp'])]
if not active_dhcp_agents: if not active_dhcp_agents:
LOG.warn(_('No active DHCP agents')) LOG.warn(_('No active DHCP agents'))
return False return
chosen_agent = random.choice(active_dhcp_agents) chosen_agent = random.choice(active_dhcp_agents)
binding = agentschedulers_db.NetworkDhcpAgentBinding() binding = agentschedulers_db.NetworkDhcpAgentBinding()
binding.dhcp_agent = chosen_agent binding.dhcp_agent = chosen_agent
@ -71,7 +71,7 @@ class ChanceScheduler(object):
'DHCP agent %(agent_id)s'), 'DHCP agent %(agent_id)s'),
{'network_id': network['id'], {'network_id': network['id'],
'agent_id': chosen_agent['id']}) 'agent_id': chosen_agent['id']})
return True return chosen_agent
def auto_schedule_networks(self, plugin, context, host): def auto_schedule_networks(self, plugin, context, host):
"""Schedule non-hosted networks to the DHCP agent on """Schedule non-hosted networks to the DHCP agent on

View File

@ -124,18 +124,18 @@ class ChanceScheduler(object):
' by L3 agent %(agent_id)s'), ' by L3 agent %(agent_id)s'),
{'router_id': sync_router['id'], {'router_id': sync_router['id'],
'agent_id': l3_agents[0]['id']}) 'agent_id': l3_agents[0]['id']})
return False return
active_l3_agents = plugin.get_l3_agents(context, active=True) active_l3_agents = plugin.get_l3_agents(context, active=True)
if not active_l3_agents: if not active_l3_agents:
LOG.warn(_('No active L3 agents')) LOG.warn(_('No active L3 agents'))
return False return
candidates = plugin.get_l3_agent_candidates(sync_router, candidates = plugin.get_l3_agent_candidates(sync_router,
active_l3_agents) active_l3_agents)
if not candidates: if not candidates:
LOG.warn(_('No L3 agents can host the router %s'), LOG.warn(_('No L3 agents can host the router %s'),
sync_router['id']) sync_router['id'])
return False return
chosen_agent = random.choice(candidates) chosen_agent = random.choice(candidates)
binding = agentschedulers_db.RouterL3AgentBinding() binding = agentschedulers_db.RouterL3AgentBinding()
@ -146,4 +146,4 @@ class ChanceScheduler(object):
'L3 agent %(agent_id)s'), 'L3 agent %(agent_id)s'),
{'router_id': sync_router['id'], {'router_id': sync_router['id'],
'agent_id': chosen_agent['id']}) 'agent_id': chosen_agent['id']})
return True return chosen_agent

View File

@ -20,6 +20,7 @@ import mock
from webob import exc from webob import exc
from quantum.api import extensions from quantum.api import extensions
from quantum.api.rpc.agentnotifiers import dhcp_rpc_agent_api
from quantum.common import constants from quantum.common import constants
from quantum import context from quantum import context
from quantum.db import agents_db from quantum.db import agents_db
@ -28,7 +29,6 @@ from quantum.db import l3_rpc_base
from quantum.extensions import agentscheduler from quantum.extensions import agentscheduler
from quantum import manager from quantum import manager
from quantum.openstack.common import uuidutils from quantum.openstack.common import uuidutils
from quantum.plugins.openvswitch.ovs_quantum_plugin import OVSQuantumPluginV2
from quantum.tests.unit import test_agent_ext_plugin from quantum.tests.unit import test_agent_ext_plugin
from quantum.tests.unit.testlib_api import create_request from quantum.tests.unit.testlib_api import create_request
from quantum.tests.unit import test_db_plugin as test_plugin from quantum.tests.unit import test_db_plugin as test_plugin
@ -183,27 +183,20 @@ class AgentSchedulerTestMixIn(object):
return agent['id'] return agent['id']
class AgentSchedulerTestCase(test_l3_plugin.L3NatTestCaseMixin, class OvsAgentSchedulerTestCase(test_l3_plugin.L3NatTestCaseMixin,
test_agent_ext_plugin.AgentDBTestMixIn, test_agent_ext_plugin.AgentDBTestMixIn,
AgentSchedulerTestMixIn, AgentSchedulerTestMixIn,
test_plugin.QuantumDbPluginV2TestCase): test_plugin.QuantumDbPluginV2TestCase):
fmt = 'json' fmt = 'json'
plugin_str = ('quantum.plugins.openvswitch.'
'ovs_quantum_plugin.OVSQuantumPluginV2')
def setUp(self): def setUp(self):
plugin = ('quantum.plugins.openvswitch.' super(OvsAgentSchedulerTestCase, self).setUp(self.plugin_str)
'ovs_quantum_plugin.OVSQuantumPluginV2')
self.dhcp_notifier_cls_p = mock.patch(
'quantum.api.rpc.agentnotifiers.dhcp_rpc_agent_api.'
'DhcpAgentNotifyAPI')
self.dhcp_notifier = mock.Mock(name='dhcp_notifier')
self.dhcp_notifier_cls = self.dhcp_notifier_cls_p.start()
self.dhcp_notifier_cls.return_value = self.dhcp_notifier
super(AgentSchedulerTestCase, self).setUp(plugin)
ext_mgr = extensions.PluginAwareExtensionManager.get_instance() ext_mgr = extensions.PluginAwareExtensionManager.get_instance()
self.ext_api = test_extensions.setup_extensions_middleware(ext_mgr) self.ext_api = test_extensions.setup_extensions_middleware(ext_mgr)
self.adminContext = context.get_admin_context() self.adminContext = context.get_admin_context()
self.agentscheduler_dbMinxin = manager.QuantumManager.get_plugin() self.agentscheduler_dbMinxin = manager.QuantumManager.get_plugin()
self.addCleanup(self.dhcp_notifier_cls_p.stop)
def test_report_states(self): def test_report_states(self):
self._register_agent_states() self._register_agent_states()
@ -215,7 +208,7 @@ class AgentSchedulerTestCase(test_l3_plugin.L3NatTestCaseMixin,
with self.network() as net: with self.network() as net:
dhcp_agents = self._list_dhcp_agents_hosting_network( dhcp_agents = self._list_dhcp_agents_hosting_network(
net['network']['id']) net['network']['id'])
self.assertEqual(1, len(dhcp_agents['agents'])) self.assertEqual(0, len(dhcp_agents['agents']))
def test_network_auto_schedule_with_disabled(self): def test_network_auto_schedule_with_disabled(self):
with contextlib.nested(self.network(), with contextlib.nested(self.network(),
@ -328,15 +321,15 @@ class AgentSchedulerTestCase(test_l3_plugin.L3NatTestCaseMixin,
}, },
'agent_type': constants.AGENT_TYPE_DHCP} 'agent_type': constants.AGENT_TYPE_DHCP}
self._register_one_agent_state(dhcp_hosta) self._register_one_agent_state(dhcp_hosta)
with self.network() as net1: with self.port() as port1:
dhcp_agents = self._list_dhcp_agents_hosting_network( dhcp_agents = self._list_dhcp_agents_hosting_network(
net1['network']['id']) port1['port']['network_id'])
self.assertEqual(1, len(dhcp_agents['agents'])) self.assertEqual(1, len(dhcp_agents['agents']))
agents = self._list_agents() agents = self._list_agents()
self._disable_agent(agents['agents'][0]['id']) self._disable_agent(agents['agents'][0]['id'])
with self.network() as net2: with self.port() as port2:
dhcp_agents = self._list_dhcp_agents_hosting_network( dhcp_agents = self._list_dhcp_agents_hosting_network(
net2['network']['id']) port2['port']['network_id'])
self.assertEqual(0, len(dhcp_agents['agents'])) self.assertEqual(0, len(dhcp_agents['agents']))
def test_network_scheduler_with_down_agent(self): def test_network_scheduler_with_down_agent(self):
@ -352,18 +345,19 @@ class AgentSchedulerTestCase(test_l3_plugin.L3NatTestCaseMixin,
is_agent_down_str = 'quantum.db.agents_db.AgentDbMixin.is_agent_down' is_agent_down_str = 'quantum.db.agents_db.AgentDbMixin.is_agent_down'
with mock.patch(is_agent_down_str) as mock_is_agent_down: with mock.patch(is_agent_down_str) as mock_is_agent_down:
mock_is_agent_down.return_value = False mock_is_agent_down.return_value = False
with self.network() as net: with self.port() as port:
dhcp_agents = self._list_dhcp_agents_hosting_network( dhcp_agents = self._list_dhcp_agents_hosting_network(
net['network']['id']) port['port']['network_id'])
self.assertEqual(1, len(dhcp_agents['agents'])) self.assertEqual(1, len(dhcp_agents['agents']))
with mock.patch(is_agent_down_str) as mock_is_agent_down: with mock.patch(is_agent_down_str) as mock_is_agent_down:
mock_is_agent_down.return_value = True mock_is_agent_down.return_value = True
with self.network() as net: with self.port() as port:
dhcp_agents = self._list_dhcp_agents_hosting_network( dhcp_agents = self._list_dhcp_agents_hosting_network(
net['network']['id']) port['port']['network_id'])
self.assertEqual(0, len(dhcp_agents['agents'])) self.assertEqual(0, len(dhcp_agents['agents']))
def test_network_scheduler_with_hosted_network(self): def test_network_scheduler_with_hosted_network(self):
plugin = manager.QuantumManager.get_plugin()
dhcp_hosta = { dhcp_hosta = {
'binary': 'quantum-dhcp-agent', 'binary': 'quantum-dhcp-agent',
'host': DHCP_HOSTA, 'host': DHCP_HOSTA,
@ -373,20 +367,26 @@ class AgentSchedulerTestCase(test_l3_plugin.L3NatTestCaseMixin,
}, },
'agent_type': constants.AGENT_TYPE_DHCP} 'agent_type': constants.AGENT_TYPE_DHCP}
self._register_one_agent_state(dhcp_hosta) self._register_one_agent_state(dhcp_hosta)
agents = self._list_agents() with self.port() as port1:
with self.network() as net1:
dhcp_agents = self._list_dhcp_agents_hosting_network( dhcp_agents = self._list_dhcp_agents_hosting_network(
net1['network']['id']) port1['port']['network_id'])
self.assertEqual(1, len(dhcp_agents['agents'])) self.assertEqual(1, len(dhcp_agents['agents']))
with mock.patch.object(OVSQuantumPluginV2, with mock.patch.object(plugin,
'get_dhcp_agents_hosting_networks', 'get_dhcp_agents_hosting_networks',
autospec=True) as mock_hosting_agents: autospec=True) as mock_hosting_agents:
mock_hosting_agents.return_value = agents['agents'] mock_hosting_agents.return_value = plugin.get_agents_db(
with self.network(do_delete=False) as net2: self.adminContext)
with self.network('test', do_delete=False) as net1:
pass
with self.subnet(network=net1,
cidr='10.0.1.0/24',
do_delete=False) as subnet1:
pass
with self.port(subnet=subnet1, no_delete=True) as port2:
pass pass
dhcp_agents = self._list_dhcp_agents_hosting_network( dhcp_agents = self._list_dhcp_agents_hosting_network(
net2['network']['id']) port2['port']['network_id'])
self.assertEqual(0, len(dhcp_agents['agents'])) self.assertEqual(0, len(dhcp_agents['agents']))
def test_network_policy(self): def test_network_policy(self):
@ -440,12 +440,12 @@ class AgentSchedulerTestCase(test_l3_plugin.L3NatTestCaseMixin,
self._register_one_agent_state(dhcp_hosta) self._register_one_agent_state(dhcp_hosta)
hosta_id = self._get_agent_id(constants.AGENT_TYPE_DHCP, hosta_id = self._get_agent_id(constants.AGENT_TYPE_DHCP,
DHCP_HOSTA) DHCP_HOSTA)
with self.network() as net1: with self.port() as port1:
num_before_remove = len( num_before_remove = len(
self._list_networks_hosted_by_dhcp_agent( self._list_networks_hosted_by_dhcp_agent(
hosta_id)['networks']) hosta_id)['networks'])
self._remove_network_from_dhcp_agent(hosta_id, self._remove_network_from_dhcp_agent(hosta_id,
net1['network']['id']) port1['port']['network_id'])
num_after_remove = len( num_after_remove = len(
self._list_networks_hosted_by_dhcp_agent( self._list_networks_hosted_by_dhcp_agent(
hosta_id)['networks']) hosta_id)['networks'])
@ -731,20 +731,119 @@ class AgentSchedulerTestCase(test_l3_plugin.L3NatTestCaseMixin,
admin_context=False) admin_context=False)
class L3AgentNotifierTestCase(test_l3_plugin.L3NatTestCaseMixin, class OvsDhcpAgentNotifierTestCase(test_l3_plugin.L3NatTestCaseMixin,
test_agent_ext_plugin.AgentDBTestMixIn, test_agent_ext_plugin.AgentDBTestMixIn,
AgentSchedulerTestMixIn, AgentSchedulerTestMixIn,
test_plugin.QuantumDbPluginV2TestCase): test_plugin.QuantumDbPluginV2TestCase):
def setUp(self): plugin_str = ('quantum.plugins.openvswitch.'
plugin = ('quantum.plugins.openvswitch.'
'ovs_quantum_plugin.OVSQuantumPluginV2') 'ovs_quantum_plugin.OVSQuantumPluginV2')
def setUp(self):
self.dhcp_notifier = dhcp_rpc_agent_api.DhcpAgentNotifyAPI()
self.dhcp_notifier_cls_p = mock.patch(
'quantum.api.rpc.agentnotifiers.dhcp_rpc_agent_api.'
'DhcpAgentNotifyAPI')
self.dhcp_notifier_cls = self.dhcp_notifier_cls_p.start()
self.dhcp_notifier_cls.return_value = self.dhcp_notifier
super(OvsDhcpAgentNotifierTestCase, self).setUp(self.plugin_str)
ext_mgr = extensions.PluginAwareExtensionManager.get_instance()
self.ext_api = test_extensions.setup_extensions_middleware(ext_mgr)
self.adminContext = context.get_admin_context()
self.addCleanup(self.dhcp_notifier_cls_p.stop)
def test_network_add_to_dhcp_agent_notification(self):
with mock.patch.object(self.dhcp_notifier, 'cast') as mock_dhcp:
with self.network() as net1:
network_id = net1['network']['id']
self._register_agent_states()
hosta_id = self._get_agent_id(constants.AGENT_TYPE_DHCP,
DHCP_HOSTA)
self._add_network_to_dhcp_agent(hosta_id,
network_id)
mock_dhcp.assert_called_with(
mock.ANY,
self.dhcp_notifier.make_msg(
'network_create_end',
payload={'network': {'id': network_id}}),
topic='dhcp_agent.' + DHCP_HOSTA)
def test_network_remove_from_dhcp_agent_notification(self):
with self.network(do_delete=False) as net1:
network_id = net1['network']['id']
self._register_agent_states()
hosta_id = self._get_agent_id(constants.AGENT_TYPE_DHCP,
DHCP_HOSTA)
self._add_network_to_dhcp_agent(hosta_id,
network_id)
with mock.patch.object(self.dhcp_notifier, 'cast') as mock_dhcp:
self._remove_network_from_dhcp_agent(hosta_id,
network_id)
mock_dhcp.assert_called_with(
mock.ANY,
self.dhcp_notifier.make_msg(
'network_delete_end',
payload={'network_id': network_id}),
topic='dhcp_agent.' + DHCP_HOSTA)
def test_agent_updated_dhcp_agent_notification(self):
with mock.patch.object(self.dhcp_notifier, 'cast') as mock_dhcp:
self._register_agent_states()
hosta_id = self._get_agent_id(constants.AGENT_TYPE_DHCP,
DHCP_HOSTA)
self._disable_agent(hosta_id, admin_state_up=False)
mock_dhcp.assert_called_with(
mock.ANY, self.dhcp_notifier.make_msg(
'agent_updated',
payload={'admin_state_up': False}),
topic='dhcp_agent.' + DHCP_HOSTA)
def test_network_port_create_notification(self):
dhcp_hosta = {
'binary': 'quantum-dhcp-agent',
'host': DHCP_HOSTA,
'topic': 'dhcp_agent',
'configurations': {'dhcp_driver': 'dhcp_driver',
'use_namespaces': True,
},
'agent_type': constants.AGENT_TYPE_DHCP}
self._register_one_agent_state(dhcp_hosta)
with mock.patch.object(self.dhcp_notifier, 'cast') as mock_dhcp:
with self.network(do_delete=False) as net1:
with self.subnet(network=net1,
do_delete=False) as subnet1:
with self.port(subnet=subnet1, no_delete=True) as port:
network_id = port['port']['network_id']
expected_calls = [
mock.call(
mock.ANY,
self.dhcp_notifier.make_msg(
'network_create_end',
payload={'network': {'id': network_id}}),
topic='dhcp_agent.' + DHCP_HOSTA),
mock.call(
mock.ANY,
self.dhcp_notifier.make_msg(
'port_create_end',
payload={'port': port['port']}),
topic='dhcp_agent.' + DHCP_HOSTA)]
self.assertEqual(mock_dhcp.call_args_list, expected_calls)
class OvsL3AgentNotifierTestCase(test_l3_plugin.L3NatTestCaseMixin,
test_agent_ext_plugin.AgentDBTestMixIn,
AgentSchedulerTestMixIn,
test_plugin.QuantumDbPluginV2TestCase):
plugin_str = ('quantum.plugins.openvswitch.'
'ovs_quantum_plugin.OVSQuantumPluginV2')
def setUp(self):
self.dhcp_notifier_cls_p = mock.patch( self.dhcp_notifier_cls_p = mock.patch(
'quantum.api.rpc.agentnotifiers.dhcp_rpc_agent_api.' 'quantum.api.rpc.agentnotifiers.dhcp_rpc_agent_api.'
'DhcpAgentNotifyAPI') 'DhcpAgentNotifyAPI')
self.dhcp_notifier = mock.Mock(name='dhcp_notifier') self.dhcp_notifier = mock.Mock(name='dhcp_notifier')
self.dhcp_notifier_cls = self.dhcp_notifier_cls_p.start() self.dhcp_notifier_cls = self.dhcp_notifier_cls_p.start()
self.dhcp_notifier_cls.return_value = self.dhcp_notifier self.dhcp_notifier_cls.return_value = self.dhcp_notifier
super(L3AgentNotifierTestCase, self).setUp(plugin) super(OvsL3AgentNotifierTestCase, self).setUp(self.plugin_str)
ext_mgr = extensions.PluginAwareExtensionManager.get_instance() ext_mgr = extensions.PluginAwareExtensionManager.get_instance()
self.ext_api = test_extensions.setup_extensions_middleware(ext_mgr) self.ext_api = test_extensions.setup_extensions_middleware(ext_mgr)
self.adminContext = context.get_admin_context() self.adminContext = context.get_admin_context()
@ -799,5 +898,5 @@ class L3AgentNotifierTestCase(test_l3_plugin.L3NatTestCaseMixin,
topic='l3_agent.hosta') topic='l3_agent.hosta')
class AgentSchedulerTestCaseXML(AgentSchedulerTestCase): class OvsAgentSchedulerTestCaseXML(OvsAgentSchedulerTestCase):
fmt = 'xml' fmt = 'xml'