Merge "Libvirt: Support ovs plug in vhostuser vif"

This commit is contained in:
Jenkins 2015-02-18 13:44:24 +00:00 committed by Gerrit Code Review
commit 8a6c418e13
7 changed files with 134 additions and 12 deletions

View File

@ -1366,6 +1366,10 @@ def delete_ovs_vif_port(bridge, dev):
delete_net_dev(dev)
def ovs_set_vhostuser_port_type(dev):
_ovs_vsctl(['--', 'set', 'Interface', dev, 'type=dpdkvhostuser'])
def create_ivs_vif_port(dev, iface_id, mac, instance_id):
utils.execute('ivs-ctl', 'add-port',
dev, run_as_root=True)

View File

@ -59,8 +59,11 @@ VIF_DETAILS_VLAN = 'vlan'
# Sets mode on vhost-user socket, valid values are 'client'
# and 'server'
VIF_DETAILS_VHOSTUSER_MODE = 'vhostuser_mode'
# Location of the directory to store vhost-user sockets
VIF_DETAILS_VHOSTUSER_DIR = 'vhostuser_sock_dir'
# vhost-user socket path
VIF_DETAILS_VHOSTUSER_SOCKET = 'vhostuser_socket'
# Specifies whether vhost-user socket should be plugged
# into ovs bridge. Valid values are True and False
VIF_DETAILS_VHOSTUSER_OVS_PLUG = 'vhostuser_ovs_plug'
# Define supported virtual NIC types. VNIC_TYPE_DIRECT and VNIC_TYPE_MACVTAP
# are used for SR-IOV ports

View File

@ -1373,6 +1373,7 @@ class API(base_api.NetworkAPI):
# Network model metadata
should_create_bridge = None
vif_type = port.get('binding:vif_type')
port_details = port.get('binding:vif_details')
# TODO(berrange) Neutron should pass the bridge name
# in another binding metadata field
if vif_type == network_model.VIF_TYPE_OVS:
@ -1385,6 +1386,11 @@ class API(base_api.NetworkAPI):
# The name of the DVS port group will contain the neutron
# network id
bridge = port['network_id']
elif (vif_type == network_model.VIF_TYPE_VHOSTUSER and
port_details.get(network_model.VIF_DETAILS_VHOSTUSER_OVS_PLUG,
False)):
bridge = CONF.neutron.ovs_bridge
ovs_interfaceid = port['id']
# Prune the bridge name if necessary. For the DVS this is not done
# as the bridge is a '<network-name>-<network-UUID>'.

View File

@ -1267,3 +1267,13 @@ class LinuxNetworkTestCase(test.NoDBTestCase):
self.driver._exec_ebtables('fake')
self.assertEqual(2, len(executes))
self.mox.UnsetStubs()
def test_ovs_set_vhostuser_type(self):
calls = [
mock.call('ovs-vsctl', '--timeout=120', '--', 'set',
'Interface', 'fake-dev', 'type=dpdkvhostuser',
run_as_root=True)
]
with mock.patch.object(utils, 'execute', return_value=('', '')) as ex:
linux_net.ovs_set_vhostuser_port_type('fake-dev')
ex.assert_has_calls(calls)

View File

@ -2412,6 +2412,32 @@ class TestNeutronv2(TestNeutronv2Base):
self.assertEqual('net-id1', net['id'])
self.assertEqual('tenant', net['meta']['tenant_id'])
def test_nw_info_build_network_vhostuser(self):
fake_port = {
'fixed_ips': [{'ip_address': '1.1.1.1'}],
'id': 'port-id',
'network_id': 'net-id',
'binding:vif_type': model.VIF_TYPE_VHOSTUSER,
'binding:vif_details': {
model.VIF_DETAILS_VHOSTUSER_OVS_PLUG: True
}
}
fake_subnets = [model.Subnet(cidr='1.0.0.0/8')]
fake_nets = [{'id': 'net-id', 'name': 'foo', 'tenant_id': 'tenant'}]
api = neutronapi.API()
self.mox.ReplayAll()
neutronapi.get_client('fake')
net, iid = api._nw_info_build_network(fake_port, fake_nets,
fake_subnets)
self.assertEqual(net['subnets'], fake_subnets)
self.assertEqual(net['id'], 'net-id')
self.assertEqual(net['label'], 'foo')
self.assertEqual(net.get_meta('tenant_id'), 'tenant')
self.assertEqual(net.get_meta('injected'), CONF.flat_injected)
self.assertEqual(net['bridge'], CONF.neutron.ovs_bridge)
self.assertNotIn('should_create_bridge', net)
self.assertEqual(iid, 'port-id')
def test_build_network_info_model(self):
api = neutronapi.API()
fake_inst = {'project_id': 'fake', 'uuid': 'uuid',

View File

@ -274,12 +274,25 @@ class LibvirtVifTestCase(test.NoDBTestCase):
type=network_model.VIF_TYPE_IOVISOR,
devname='tap-xxx-yyy-zzz',
ovs_interfaceid=None)
vif_vhostuser = network_model.VIF(id='vif-xxx-yyy-zzz',
address='ca:fe:de:ad:be:ef',
network=network_bridge,
type=network_model.VIF_TYPE_VHOSTUSER,
details = {network_model.VIF_DETAILS_VHOSTUSER_MODE: 'client',
network_model.VIF_DETAILS_VHOSTUSER_DIR: '/tmp'}
network_model.VIF_DETAILS_VHOSTUSER_SOCKET:
'/tmp/vif-xxx-yyy-zzz'}
)
vif_vhostuser_ovs = network_model.VIF(id='vif-xxx-yyy-zzz',
address='ca:fe:de:ad:be:ef',
network=network_bridge,
type=network_model.VIF_TYPE_VHOSTUSER,
details = {network_model.VIF_DETAILS_VHOSTUSER_MODE: 'client',
network_model.VIF_DETAILS_VHOSTUSER_SOCKET:
'/tmp/usv-xxx-yyy-zzz',
network_model.VIF_DETAILS_VHOSTUSER_OVS_PLUG: True},
ovs_interfaceid='aaa-bbb-ccc'
)
vif_vhostuser_no_path = network_model.VIF(id='vif-xxx-yyy-zzz',
@ -1110,3 +1123,50 @@ class LibvirtVifTestCase(test.NoDBTestCase):
self._get_instance_xml,
d,
self.vif_vhostuser_no_path)
def test_vhostuser_driver_ovs(self):
d = vif.LibvirtGenericVIFDriver()
xml = self._get_instance_xml(d,
self.vif_vhostuser_ovs)
node = self._get_node(xml)
self.assertEqual(node.get("type"),
network_model.VIF_TYPE_VHOSTUSER)
self._assertTypeEquals(node, network_model.VIF_TYPE_VHOSTUSER,
"source", "mode", "client")
self._assertTypeEquals(node, network_model.VIF_TYPE_VHOSTUSER,
"source", "path", "/tmp/usv-xxx-yyy-zzz")
self._assertTypeEquals(node, network_model.VIF_TYPE_VHOSTUSER,
"source", "type", "unix")
self._assertMacEquals(node, self.vif_vhostuser_ovs)
self._assertModel(xml, network_model.VIF_MODEL_VIRTIO)
def test_vhostuser_ovs_plug(self):
calls = {
'create_ovs_vif_port': [mock.call('br0',
'usv-xxx-yyy-zzz',
'aaa-bbb-ccc',
'ca:fe:de:ad:be:ef',
'instance-uuid')],
'ovs_set_vhostuser_port_type': [mock.call('usv-xxx-yyy-zzz')]
}
with contextlib.nested(
mock.patch.object(linux_net, 'create_ovs_vif_port'),
mock.patch.object(linux_net, 'ovs_set_vhostuser_port_type')
) as (create_ovs_vif_port, ovs_set_vhostuser_port_type):
d = vif.LibvirtGenericVIFDriver()
d.plug_vhostuser(self.instance, self.vif_vhostuser_ovs)
create_ovs_vif_port.assert_has_calls(calls['create_ovs_vif_port'])
ovs_set_vhostuser_port_type.assert_has_calls(
calls['ovs_set_vhostuser_port_type'])
def test_vhostuser_ovs_unplug(self):
calls = {
'delete_ovs_vif_port': [mock.call('br0', 'usv-xxx-yyy-zzz')]
}
with mock.patch.object(linux_net,
'delete_ovs_vif_port') as delete_port:
d = vif.LibvirtGenericVIFDriver()
d.unplug_vhostuser(None, self.vif_vhostuser_ovs)
delete_port.assert_has_calls(calls['delete_ovs_vif_port'])

View File

@ -337,15 +337,11 @@ class LibvirtGenericVIFDriver(object):
vif_details = vif['details']
mode = vif_details.get(network_model.VIF_DETAILS_VHOSTUSER_MODE,
'server')
path = vif_details.get(network_model.VIF_DETAILS_VHOSTUSER_DIR)
if path is None:
sock_path = vif_details.get(network_model.VIF_DETAILS_VHOSTUSER_SOCKET)
if sock_path is None:
raise exception.VifDetailsMissingVhostuserSockPath(
vif_id=vif['id'])
designer.set_vif_host_backend_vhostuser_config(
conf,
mode,
os.path.join(path, vif['id']))
designer.set_vif_host_backend_vhostuser_config(conf, mode, sock_path)
return conf
def get_config_vrouter(self, instance, vif, image_meta,
@ -540,7 +536,17 @@ class LibvirtGenericVIFDriver(object):
LOG.exception(_LE("Failed while plugging vif"), instance=instance)
def plug_vhostuser(self, instance, vif):
pass
ovs_plug = vif['details'].get(
network_model.VIF_DETAILS_VHOSTUSER_OVS_PLUG,
False)
if ovs_plug:
iface_id = self.get_ovs_interfaceid(vif)
port_name = os.path.basename(
vif['details'][network_model.VIF_DETAILS_VHOSTUSER_SOCKET])
linux_net.create_ovs_vif_port(self.get_bridge_name(vif),
port_name, iface_id, vif['address'],
instance['uuid'])
linux_net.ovs_set_vhostuser_port_type(port_name)
def plug_vrouter(self, instance, vif):
"""Plug into Contrail's network port
@ -736,7 +742,14 @@ class LibvirtGenericVIFDriver(object):
instance=instance)
def unplug_vhostuser(self, instance, vif):
pass
ovs_plug = vif['details'].get(
network_model.VIF_DETAILS_VHOSTUSER_OVS_PLUG,
False)
if ovs_plug:
port_name = os.path.basename(
vif['details'][network_model.VIF_DETAILS_VHOSTUSER_SOCKET])
linux_net.delete_ovs_vif_port(self.get_bridge_name(vif),
port_name)
def unplug_vrouter(self, instance, vif):
"""Unplug Contrail's network port