Adding VIF Driver to support Mellanox Plugin
blueprint mellanox-vif-driver DocImpact Change-Id: Ic98db496a3e175c9dee98657609a66934c41d557
This commit is contained in:
parent
2be50f0f3f
commit
87e6697906
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
||||
|
@ -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):
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user