Merge "Fix linuxbridge RPC message format"

This commit is contained in:
Jenkins 2013-05-16 06:06:39 +00:00 committed by Gerrit Code Review
commit 97ea776f29
8 changed files with 176 additions and 41 deletions

View File

@ -58,6 +58,12 @@ reconnect_interval = 2
# Agent's polling interval in seconds
polling_interval = 2
# (BoolOpt) Enable server RPC compatibility with old (pre-havana)
# agents.
#
# Default: rpc_support_old_agents = True
# Example: rpc_support_old_agents = False
[SECURITYGROUP]
# Firewall driver for realizing quantum security group function
firewall_driver = quantum.agent.linux.iptables_firewall.IptablesFirewallDriver

View File

@ -253,21 +253,26 @@ class LinuxBridgeManager:
return bridge_name
def ensure_physical_in_bridge(self, network_id,
network_type,
physical_network,
vlan_id):
segmentation_id):
physical_interface = self.interface_mappings.get(physical_network)
if not physical_interface:
LOG.error(_("No mapping for physical network %s"),
physical_network)
return
if int(vlan_id) == lconst.FLAT_VLAN_ID:
if network_type == lconst.TYPE_FLAT:
return self.ensure_flat_bridge(network_id, physical_interface)
else:
elif network_type == lconst.TYPE_VLAN:
return self.ensure_vlan_bridge(network_id, physical_interface,
vlan_id)
segmentation_id)
else:
LOG.error(_("Unknown network_type %(network_type)s for network "
"%(network_id)s."), {network_type: network_type,
network_id: network_id})
def add_tap_interface(self, network_id, physical_network, vlan_id,
tap_device_name):
def add_tap_interface(self, network_id, network_type, physical_network,
segmentation_id, tap_device_name):
"""Add tap interface.
If a VIF has been plugged into a network, this function will
@ -279,11 +284,12 @@ class LinuxBridgeManager:
return False
bridge_name = self.get_bridge_name(network_id)
if int(vlan_id) == lconst.LOCAL_VLAN_ID:
if network_type == lconst.TYPE_LOCAL:
self.ensure_local_bridge(network_id)
elif not self.ensure_physical_in_bridge(network_id,
network_type,
physical_network,
vlan_id):
segmentation_id):
return False
# Check if device needs to be added to bridge
@ -305,11 +311,11 @@ class LinuxBridgeManager:
LOG.debug(msg)
return True
def add_interface(self, network_id, physical_network, vlan_id,
port_id):
def add_interface(self, network_id, network_type, physical_network,
segmentation_id, port_id):
tap_device_name = self.get_tap_device_name(port_id)
return self.add_tap_interface(network_id,
physical_network, vlan_id,
return self.add_tap_interface(network_id, network_type,
physical_network, segmentation_id,
tap_device_name)
def delete_vlan_bridge(self, bridge_name):
@ -433,12 +439,20 @@ class LinuxBridgeRpcCallbacks(sg_rpc.SecurityGroupAgentRpcCallbackMixin):
self.sg_agent.refresh_firewall()
if port['admin_state_up']:
vlan_id = kwargs.get('vlan_id')
network_type = kwargs.get('network_type')
if network_type:
segmentation_id = kwargs.get('segmentation_id')
else:
# compatibility with pre-Havana RPC vlan_id encoding
vlan_id = kwargs.get('vlan_id')
(network_type,
segmentation_id) = lconst.interpret_vlan_id(vlan_id)
physical_network = kwargs.get('physical_network')
# create the networking for the port
self.agent.br_mgr.add_interface(port['network_id'],
network_type,
physical_network,
vlan_id,
segmentation_id,
port['id'])
# update plugin about port status
self.agent.plugin_rpc.update_device_up(self.context,
@ -569,9 +583,18 @@ class LinuxBridgeQuantumAgentRPC(sg_rpc.SecurityGroupAgentRpcMixin):
{'device': device, 'details': details})
if details['admin_state_up']:
# create the networking for the port
network_type = details.get('network_type')
if network_type:
segmentation_id = details.get('segmentation_id')
else:
# compatibility with pre-Havana RPC vlan_id encoding
vlan_id = details.get('vlan_id')
(network_type,
segmentation_id) = lconst.interpret_vlan_id(vlan_id)
self.br_mgr.add_interface(details['network_id'],
network_type,
details['physical_network'],
details['vlan_id'],
segmentation_id,
details['port_id'])
else:
self.remove_port_binding(details['network_id'],

View File

@ -46,6 +46,9 @@ agent_opts = [
cfg.IntOpt('polling_interval', default=2,
help=_("The number of seconds the agent will wait between "
"polling for local device changes.")),
#TODO(rkukura): Change default to False before havana rc1
cfg.BoolOpt('rpc_support_old_agents', default=True,
help=_("Enable server RPC compatibility with old agents")),
]

View File

@ -25,3 +25,16 @@ TYPE_FLAT = 'flat'
TYPE_VLAN = 'vlan'
TYPE_LOCAL = 'local'
TYPE_NONE = 'none'
# TODO(rkukura): Eventually remove this function, which provides
# temporary backward compatibility with pre-Havana RPC and DB vlan_id
# encoding.
def interpret_vlan_id(vlan_id):
"""Return (network_type, segmentation_id) tuple for encoded vlan_id."""
if vlan_id == LOCAL_VLAN_ID:
return (TYPE_LOCAL, None)
elif vlan_id == FLAT_VLAN_ID:
return (TYPE_FLAT, None)
else:
return (TYPE_VLAN, vlan_id)

View File

@ -86,12 +86,17 @@ class LinuxBridgeRpcCallbacks(dhcp_rpc_base.DhcpRpcCallbackMixin,
if port:
binding = db.get_network_binding(db_api.get_session(),
port['network_id'])
(network_type,
segmentation_id) = constants.interpret_vlan_id(binding.vlan_id)
entry = {'device': device,
'network_type': network_type,
'physical_network': binding.physical_network,
'vlan_id': binding.vlan_id,
'segmentation_id': segmentation_id,
'network_id': port['network_id'],
'port_id': port['id'],
'admin_state_up': port['admin_state_up']}
if cfg.CONF.AGENT.rpc_support_old_agents:
entry['vlan_id'] = binding.vlan_id
new_status = (q_const.PORT_STATUS_ACTIVE if port['admin_state_up']
else q_const.PORT_STATUS_DOWN)
if port['status'] != new_status:
@ -165,11 +170,15 @@ class AgentNotifierApi(proxy.RpcProxy,
topic=self.topic_network_delete)
def port_update(self, context, port, physical_network, vlan_id):
self.fanout_cast(context,
self.make_msg('port_update',
port=port,
physical_network=physical_network,
vlan_id=vlan_id),
network_type, segmentation_id = constants.interpret_vlan_id(vlan_id)
kwargs = {'port': port,
'network_type': network_type,
'physical_network': physical_network,
'segmentation_id': segmentation_id}
if cfg.CONF.AGENT.rpc_support_old_agents:
kwargs['vlan_id'] = vlan_id
msg = self.make_msg('port_update', **kwargs)
self.fanout_cast(context, msg,
topic=self.topic_port_update)

View File

@ -24,6 +24,8 @@ class ConfigurationTest(base.BaseTestCase):
def test_defaults(self):
self.assertEqual(2,
cfg.CONF.AGENT.polling_interval)
self.assertEqual(True,
cfg.CONF.AGENT.rpc_support_old_agents)
self.assertEqual('sudo',
cfg.CONF.AGENT.root_helper)
self.assertEqual('local',

View File

@ -41,6 +41,7 @@ class TestLinuxBridge(base.BaseTestCase):
def test_ensure_physical_in_bridge_invalid(self):
result = self.linux_bridge.ensure_physical_in_bridge('network_id',
lconst.TYPE_VLAN,
'physnetx',
7)
self.assertFalse(result)
@ -49,14 +50,14 @@ class TestLinuxBridge(base.BaseTestCase):
with mock.patch.object(self.linux_bridge,
'ensure_flat_bridge') as flat_bridge_func:
self.linux_bridge.ensure_physical_in_bridge(
'network_id', 'physnet1', lconst.FLAT_VLAN_ID)
'network_id', lconst.TYPE_FLAT, 'physnet1', None)
self.assertTrue(flat_bridge_func.called)
def test_ensure_physical_in_bridge_vlan(self):
with mock.patch.object(self.linux_bridge,
'ensure_vlan_bridge') as vlan_bridge_func:
self.linux_bridge.ensure_physical_in_bridge(
'network_id', 'physnet1', 7)
'network_id', lconst.TYPE_VLAN, 'physnet1', 7)
self.assertTrue(vlan_bridge_func.called)
@ -338,16 +339,19 @@ class TestLinuxBridgeManager(base.BaseTestCase):
def test_ensure_physical_in_bridge(self):
self.assertFalse(
self.lbm.ensure_physical_in_bridge("123", "phys", "1")
self.lbm.ensure_physical_in_bridge("123", lconst.TYPE_VLAN,
"phys", "1")
)
with mock.patch.object(self.lbm, "ensure_flat_bridge") as flbr_fn:
self.assertTrue(
self.lbm.ensure_physical_in_bridge("123", "physnet1", "-1")
self.lbm.ensure_physical_in_bridge("123", lconst.TYPE_FLAT,
"physnet1", None)
)
self.assertTrue(flbr_fn.called)
with mock.patch.object(self.lbm, "ensure_vlan_bridge") as vlbr_fn:
self.assertTrue(
self.lbm.ensure_physical_in_bridge("123", "physnet1", "1")
self.lbm.ensure_physical_in_bridge("123", lconst.TYPE_VLAN,
"physnet1", "1")
)
self.assertTrue(vlbr_fn.called)
@ -355,7 +359,8 @@ class TestLinuxBridgeManager(base.BaseTestCase):
with mock.patch.object(self.lbm, "device_exists") as de_fn:
de_fn.return_value = False
self.assertFalse(
self.lbm.add_tap_interface("123", "physnet1", "1", "tap1")
self.lbm.add_tap_interface("123", lconst.TYPE_VLAN,
"physnet1", "1", "tap1")
)
de_fn.return_value = True
@ -366,25 +371,33 @@ class TestLinuxBridgeManager(base.BaseTestCase):
) as (en_fn, exec_fn, get_br):
exec_fn.return_value = False
get_br.return_value = True
self.assertTrue(self.lbm.add_tap_interface("123", "physnet1",
"-2", "tap1"))
self.assertTrue(self.lbm.add_tap_interface("123",
lconst.TYPE_LOCAL,
"physnet1", None,
"tap1"))
en_fn.assert_called_with("123")
get_br.return_value = False
exec_fn.return_value = True
self.assertFalse(self.lbm.add_tap_interface("123", "physnet1",
"-2", "tap1"))
self.assertFalse(self.lbm.add_tap_interface("123",
lconst.TYPE_LOCAL,
"physnet1", None,
"tap1"))
with mock.patch.object(self.lbm,
"ensure_physical_in_bridge") as ens_fn:
ens_fn.return_value = False
self.assertFalse(self.lbm.add_tap_interface("123", "physnet1",
"1", "tap1"))
self.assertFalse(self.lbm.add_tap_interface("123",
lconst.TYPE_VLAN,
"physnet1", "1",
"tap1"))
def test_add_interface(self):
with mock.patch.object(self.lbm, "add_tap_interface") as add_tap:
self.lbm.add_interface("123", "physnet-1", "1", "234")
add_tap.assert_called_with("123", "physnet-1", "1", "tap234")
self.lbm.add_interface("123", lconst.TYPE_VLAN, "physnet-1",
"1", "234")
add_tap.assert_called_with("123", lconst.TYPE_VLAN, "physnet-1",
"1", "tap234")
def test_delete_vlan_bridge(self):
with contextlib.nested(
@ -508,9 +521,47 @@ class TestLinuxBridgeRpcCallbacks(base.BaseTestCase):
self.lb_rpc.port_update("unused_context", port=port,
vlan_id="1", physical_network="physnet1")
self.assertFalse(reffw_fn.called)
addif_fn.assert_called_with(port["network_id"],
addif_fn.assert_called_with(port["network_id"], lconst.TYPE_VLAN,
"physnet1", "1", port["id"])
self.lb_rpc.port_update("unused_context", port=port,
network_type=lconst.TYPE_VLAN,
segmentation_id="2",
physical_network="physnet1")
self.assertFalse(reffw_fn.called)
addif_fn.assert_called_with(port["network_id"], lconst.TYPE_VLAN,
"physnet1", "2", port["id"])
self.lb_rpc.port_update("unused_context", port=port,
vlan_id=lconst.FLAT_VLAN_ID,
physical_network="physnet1")
self.assertFalse(reffw_fn.called)
addif_fn.assert_called_with(port["network_id"], lconst.TYPE_FLAT,
"physnet1", None, port["id"])
self.lb_rpc.port_update("unused_context", port=port,
network_type=lconst.TYPE_FLAT,
segmentation_id=None,
physical_network="physnet1")
self.assertFalse(reffw_fn.called)
addif_fn.assert_called_with(port["network_id"], lconst.TYPE_FLAT,
"physnet1", None, port["id"])
self.lb_rpc.port_update("unused_context", port=port,
vlan_id=lconst.LOCAL_VLAN_ID,
physical_network=None)
self.assertFalse(reffw_fn.called)
addif_fn.assert_called_with(port["network_id"], lconst.TYPE_LOCAL,
None, None, port["id"])
self.lb_rpc.port_update("unused_context", port=port,
network_type=lconst.TYPE_LOCAL,
segmentation_id=None,
physical_network=None)
self.assertFalse(reffw_fn.called)
addif_fn.assert_called_with(port["network_id"], lconst.TYPE_LOCAL,
None, None, port["id"])
port["admin_state_up"] = False
port["security_groups"] = True
getbr_fn.return_value = "br0"

View File

@ -18,6 +18,7 @@
Unit Tests for linuxbridge rpc
"""
from oslo.config import cfg
import stubout
from quantum.agent import rpc as agent_rpc
@ -29,11 +30,12 @@ from quantum.tests import base
class rpcApiTestCase(base.BaseTestCase):
def _test_lb_api(self, rpcapi, topic, method, rpc_method, **kwargs):
def _test_lb_api(self, rpcapi, topic, method, rpc_method,
expected_msg=None, **kwargs):
ctxt = context.RequestContext('fake_user', 'fake_project')
expected_retval = 'foo' if method == 'call' else None
expected_msg = rpcapi.make_msg(method, **kwargs)
if not expected_msg:
expected_msg = rpcapi.make_msg(method, **kwargs)
expected_msg['version'] = rpcapi.BASE_RPC_API_VERSION
if rpc_method == 'cast' and method == 'run_instance':
kwargs['call'] = False
@ -52,11 +54,11 @@ class rpcApiTestCase(base.BaseTestCase):
retval = getattr(rpcapi, method)(ctxt, **kwargs)
self.assertEqual(retval, expected_retval)
self.assertEqual(expected_retval, retval)
expected_args = [ctxt, topic, expected_msg]
for arg, expected_arg in zip(self.fake_args, expected_args):
self.assertEqual(arg, expected_arg)
self.assertEqual(expected_arg, arg)
def test_delete_network(self):
rpcapi = plb.AgentNotifierApi(topics.AGENT)
@ -68,12 +70,38 @@ class rpcApiTestCase(base.BaseTestCase):
network_id='fake_request_spec')
def test_port_update(self):
cfg.CONF.set_override('rpc_support_old_agents', False, 'AGENT')
rpcapi = plb.AgentNotifierApi(topics.AGENT)
expected_msg = rpcapi.make_msg('port_update',
port='fake_port',
network_type='vlan',
physical_network='fake_net',
segmentation_id='fake_vlan_id')
self._test_lb_api(rpcapi,
topics.get_topic_name(topics.AGENT,
topics.PORT,
topics.UPDATE),
'port_update', rpc_method='fanout_cast',
expected_msg=expected_msg,
port='fake_port',
physical_network='fake_net',
vlan_id='fake_vlan_id')
def test_port_update_old_agent(self):
cfg.CONF.set_override('rpc_support_old_agents', True, 'AGENT')
rpcapi = plb.AgentNotifierApi(topics.AGENT)
expected_msg = rpcapi.make_msg('port_update',
port='fake_port',
network_type='vlan',
physical_network='fake_net',
segmentation_id='fake_vlan_id',
vlan_id='fake_vlan_id')
self._test_lb_api(rpcapi,
topics.get_topic_name(topics.AGENT,
topics.PORT,
topics.UPDATE),
'port_update', rpc_method='fanout_cast',
expected_msg=expected_msg,
port='fake_port',
physical_network='fake_net',
vlan_id='fake_vlan_id')