Adding VIF Driver to support Mellanox Plugin

blueprint mellanox-vif-driver

DocImpact

Change-Id: Ic98db496a3e175c9dee98657609a66934c41d557
This commit is contained in:
Itzik Brown 2013-07-01 17:13:44 +03:00
parent 2be50f0f3f
commit 87e6697906
8 changed files with 122 additions and 1 deletions

View File

@ -42,6 +42,9 @@ ivs-ctl: CommandFilter, ivs-ctl, root
# nova/virt/libvirt/vif.py: 'ifc_ctl', ...
ifc_ctl: CommandFilter, /opt/pg/bin/0/ifc_ctl, root
# nova/virt/libvirt/vif.py: 'ebrctl', ...
ebrctl: CommandFilter, ebrctl, root
# nova/network/linux_net.py: 'ebtables', '-D' ...
# nova/network/linux_net.py: 'ebtables', '-I' ...
ebtables: CommandFilter, ebtables, root

View File

@ -36,6 +36,7 @@ VIF_TYPE_IOVISOR = 'iovisor'
VIF_TYPE_BRIDGE = 'bridge'
VIF_TYPE_802_QBG = '802.1qbg'
VIF_TYPE_802_QBH = '802.1qbh'
VIF_TYPE_MLNX_DIRECT = 'mlnx_direct'
VIF_TYPE_OTHER = 'other'
# Constant for max length of network interface names

View File

@ -928,6 +928,12 @@ class API(base.Base):
tenant_id=net['tenant_id']
)
network['subnets'] = subnets
port_profile = port.get('binding:profile')
if port_profile:
physical_network = port_profile.get('physical_network')
if physical_network:
network['physical_network'] = physical_network
if should_create_bridge is not None:
network['should_create_bridge'] = should_create_bridge
return network, ovs_interfaceid

View File

@ -191,6 +191,7 @@ class FlatNetworkTestCase(test.TestCase):
'ip_v6': '2001:db8:0:1::%x' % nid,
'netmask': '255.255.255.0',
'netmask_v6': 64,
'physical_network': None,
}
network = vif['network']
@ -229,7 +230,9 @@ class FlatNetworkTestCase(test.TestCase):
ip=net_v4['ips'][i]['address'],
ip_v6=net_v6['ips'][i]['address'],
netmask=str(net_v4.as_netaddr().netmask),
netmask_v6=net_v6.as_netaddr()._prefixlen)
netmask_v6=net_v6.as_netaddr()._prefixlen,
physical_network=
network.get_meta('physical_network', None))
self.assertThat(vif_dict, matchers.DictMatches(check))

View File

@ -767,6 +767,22 @@ class LibvirtConfigGuestInterfaceTest(LibvirtConfigBaseTest):
<virtualport type="802.1Qbh"/>
</interface>""")
def test_config_direct(self):
obj = config.LibvirtConfigGuestInterface()
obj.net_type = "direct"
obj.mac_addr = "DE:AD:BE:EF:CA:FE"
obj.model = "virtio"
obj.source_dev = "eth0"
obj.source_mode = "passthrough"
xml = obj.to_xml()
self.assertXmlEqual(xml, """
<interface type="direct">
<mac address="DE:AD:BE:EF:CA:FE"/>
<model type="virtio"/>
<source dev="eth0" mode="passthrough"/>
</interface>""")
class LibvirtConfigGuestTest(LibvirtConfigBaseTest):

View File

@ -157,6 +157,19 @@ class LibvirtVifTestCase(test.TestCase):
typeidversion="1",
instanceid="ddd-eee-fff"))
network_mlnx = network_model.Network(id='network-id-xxx-yyy-zzz',
label=None,
bridge=None,
subnets=[subnet_bridge_4,
subnet_bridge_6],
interface='eth0')
vif_mlnx = network_model.VIF(id='vif-xxx-yyy-zzz',
address='ca:fe:de:ad:be:ef',
network=network_mlnx,
type=network_model.VIF_TYPE_MLNX_DIRECT,
devname='tap-xxx-yyy-zzz')
instance = {
'name': 'instance-name',
'uuid': 'instance-uuid'
@ -488,6 +501,19 @@ class LibvirtVifTestCase(test.TestCase):
self.vif_ivs,
br_want)
def test_mlnx_direct_vif_driver(self):
d = vif.LibvirtGenericVIFDriver(self._get_conn())
xml = self._get_instance_xml(d,
self.vif_mlnx)
node = self._get_node(xml)
self.assertEqual(node.get("type"), "direct")
self._assertTypeEquals(node, "direct", "source",
"dev", "eth-xxx-yyy-zzz")
self._assertTypeEquals(node, "direct", "source",
"mode", "passthrough")
self._assertMacEquals(node, self.vif_mlnx)
self._assertModel(xml, "virtio")
def test_generic_8021qbh_driver(self):
d = vif.LibvirtGenericVIFDriver(self._get_conn())
xml = self._get_instance_xml(d, self.vif_8021qbh)

View File

@ -106,6 +106,17 @@ def set_vif_host_backend_802qbh_config(conf, devname, profileid,
conf.target_dev = tapname
def set_vif_host_backend_direct_config(conf, devname):
"""Populate a LibvirtConfigGuestInterface instance
with direct Interface.
"""
conf.net_type = "direct"
conf.source_mode = "passthrough"
conf.source_dev = devname
conf.model = "virtio"
def set_vif_bandwidth_config(conf, inst_type):
"""Config vif inbound/outbound bandwidth limit. parameters are
set in instance_type_extra_specs table, key is in the format

View File

@ -54,6 +54,7 @@ CONF.import_opt('use_ipv6', 'nova.netconf')
# Since libvirt 0.9.11, <interface type='bridge'>
# supports OpenVSwitch natively.
LIBVIRT_OVS_VPORT_VERSION = 9011
DEV_PREFIX_ETH = 'eth'
def is_vif_model_valid_for_virt(virt_type, vif_model):
@ -94,6 +95,10 @@ class LibvirtBaseVIFDriver(object):
return vif['devname']
return ("nic" + vif['id'])[:network_model.NIC_NAME_LEN]
def get_vif_devname_with_prefix(self, vif, prefix):
devname = self.get_vif_devname(vif)
return prefix + devname[3:]
def get_config(self, instance, vif, image_meta, inst_type):
conf = vconfig.LibvirtConfigGuestInterface()
# Default to letting libvirt / the hypervisor choose the model
@ -296,6 +301,17 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver):
return conf
def get_config_mlnx_direct(self, instance, vif, image_meta,
inst_type):
conf = super(LibvirtGenericVIFDriver,
self).get_config(instance, vif,
image_meta, inst_type)
devname = self.get_vif_devname_with_prefix(vif, DEV_PREFIX_ETH)
designer.set_vif_host_backend_direct_config(conf, devname)
return conf
def get_config(self, instance, vif, image_meta, inst_type):
vif_type = vif['type']
@ -338,6 +354,11 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver):
vif,
image_meta,
inst_type)
elif vif_type == network_model.VIF_TYPE_MLNX_DIRECT:
return self.get_config_mlnx_direct(instance,
vif,
image_meta,
inst_type)
else:
raise exception.NovaException(
_("Unexpected vif_type=%s") % vif_type)
@ -465,6 +486,23 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver):
else:
self.plug_ivs_ethernet(instance, vif)
def plug_mlnx_direct(self, instance, vif):
super(LibvirtGenericVIFDriver,
self).plug(instance, vif)
network = vif['network']
vnic_mac = vif['address']
device_id = instance['uuid']
fabric = network['meta']['physical_network']
dev_name = self.get_vif_devname_with_prefix(vif, DEV_PREFIX_ETH)
try:
utils.execute('ebrctl', 'add-port', vnic_mac, device_id, fabric,
network_model.VIF_TYPE_MLNX_DIRECT, dev_name,
run_as_root=True)
except processutils.ProcessExecutionError:
LOG.exception(_("Failed while plugging vif"), instance=instance)
def plug_802qbg(self, instance, vif):
super(LibvirtGenericVIFDriver,
self).plug(instance, vif)
@ -521,6 +559,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver):
self.plug_ivs(instance, vif)
elif vif_type == network_model.VIF_TYPE_IOVISOR:
self.plug_iovisor(instance, vif)
elif vif_type == network_model.VIF_TYPE_MLNX_DIRECT:
self.plug_mlnx_direct(instance, vif)
else:
raise exception.NovaException(
_("Unexpected vif_type=%s") % vif_type)
@ -614,6 +654,19 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver):
else:
self.unplug_ivs_ethernet(instance, vif)
def unplug_mlnx_direct(self, instance, vif):
super(LibvirtGenericVIFDriver,
self).unplug(instance, vif)
network = vif['network']
vnic_mac = vif['address']
fabric = network['meta']['physical_network']
try:
utils.execute('ebrctl', 'del-port', fabric,
vnic_mac, run_as_root=True)
except processutils.ProcessExecutionError:
LOG.exception(_("Failed while unplugging vif"), instance=instance)
def unplug_802qbg(self, instance, vif):
super(LibvirtGenericVIFDriver,
self).unplug(instance, vif)
@ -667,6 +720,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver):
self.unplug_ivs(instance, vif)
elif vif_type == network_model.VIF_TYPE_IOVISOR:
self.unplug_iovisor(instance, vif)
elif vif_type == network_model.VIF_TYPE_MLNX_DIRECT:
self.unplug_mlnx_direct(instance, vif)
else:
raise exception.NovaException(
_("Unexpected vif_type=%s") % vif_type)