Merge "Libvirt: Support ovs plug in vhostuser vif"
This commit is contained in:
commit
8a6c418e13
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>'.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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'])
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue