Add 'ovs_interfaceid' to nova network VIF model
Instead of relying on the hypervisor VIF drivers to make up the correct 'interfaceid' parameter based on the VIF uuid, explicitly tell them what the ovs interfaceid value should be. Blueprint: libvirt-vif-driver Change-Id: I77bb1bcb8f38c8c6e20e9ccbbbd490b251f32fef Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
parent
fab8af583b
commit
1c07735f8e
|
@ -207,7 +207,7 @@ class Network(Model):
|
|||
class VIF(Model):
|
||||
"""Represents a Virtual Interface in Nova."""
|
||||
def __init__(self, id=None, address=None, network=None, type=None,
|
||||
devname=None, **kwargs):
|
||||
devname=None, ovs_interfaceid=None, **kwargs):
|
||||
super(VIF, self).__init__()
|
||||
|
||||
self['id'] = id
|
||||
|
@ -216,6 +216,8 @@ class VIF(Model):
|
|||
self['type'] = type
|
||||
self['devname'] = devname
|
||||
|
||||
self['ovs_interfaceid'] = ovs_interfaceid
|
||||
|
||||
self._set_meta(kwargs)
|
||||
|
||||
def __eq__(self, other):
|
||||
|
@ -381,6 +383,7 @@ class NetworkInfo(list):
|
|||
'vif_type': vif['type'],
|
||||
'vif_devname': vif.get('devname'),
|
||||
'vif_uuid': vif['id'],
|
||||
'ovs_interfaceid': vif.get('ovs_interfaceid'),
|
||||
'rxtx_cap': vif.get_meta('rxtx_cap', 0),
|
||||
'dns': [get_ip(ip) for ip in subnet_v4['dns']],
|
||||
'ips': [fixed_ip_dict(ip, subnet)
|
||||
|
|
|
@ -661,11 +661,13 @@ class API(base.Base):
|
|||
if fixed_ip.is_in_subnet(subnet)]
|
||||
|
||||
bridge = None
|
||||
ovs_interfaceid = None
|
||||
vif_type = port.get('binding:vif_type')
|
||||
# TODO(berrange) Quantum should pass the bridge name
|
||||
# in another binding metadata field
|
||||
if vif_type == network_model.VIF_TYPE_OVS:
|
||||
bridge = CONF.quantum_ovs_bridge
|
||||
ovs_interfaceid = port['id']
|
||||
elif vif_type == network_model.VIF_TYPE_BRIDGE:
|
||||
bridge = "brq" + port['network_id']
|
||||
|
||||
|
@ -688,6 +690,7 @@ class API(base.Base):
|
|||
address=port['mac_address'],
|
||||
network=network,
|
||||
type=port.get('binding:vif_type'),
|
||||
ovs_interfaceid=ovs_interfaceid,
|
||||
devname=devname))
|
||||
return nw_info
|
||||
|
||||
|
|
|
@ -189,6 +189,7 @@ class FlatNetworkTestCase(test.TestCase):
|
|||
'vif_devname': None,
|
||||
'vif_uuid':
|
||||
'00000000-0000-0000-0000-00000000000000%02d' % nid,
|
||||
'ovs_interfaceid': None,
|
||||
'should_create_vlan': False,
|
||||
'should_create_bridge': False}
|
||||
self.assertThat(info, matchers.DictMatches(check))
|
||||
|
|
|
@ -27,7 +27,7 @@ CONF = cfg.CONF
|
|||
|
||||
class LibvirtVifTestCase(test.TestCase):
|
||||
|
||||
net = {
|
||||
net_bridge = {
|
||||
'cidr': '101.168.1.0/24',
|
||||
'cidr_v6': '101:1db9::/64',
|
||||
'gateway_v6': '101:1db9::1',
|
||||
|
@ -42,15 +42,39 @@ class LibvirtVifTestCase(test.TestCase):
|
|||
'id': 'network-id-xxx-yyy-zzz'
|
||||
}
|
||||
|
||||
mapping = {
|
||||
mapping_bridge = {
|
||||
'mac': 'ca:fe:de:ad:be:ef',
|
||||
'gateway_v6': net['gateway_v6'],
|
||||
'gateway_v6': net_bridge['gateway_v6'],
|
||||
'ips': [{'ip': '101.168.1.9'}],
|
||||
'dhcp_server': '191.168.1.1',
|
||||
'vif_uuid': 'vif-xxx-yyy-zzz',
|
||||
'vif_devname': 'tap-xxx-yyy-zzz'
|
||||
}
|
||||
|
||||
net_ovs = {
|
||||
'cidr': '101.168.1.0/24',
|
||||
'cidr_v6': '101:1db9::/64',
|
||||
'gateway_v6': '101:1db9::1',
|
||||
'netmask_v6': '64',
|
||||
'netmask': '255.255.255.0',
|
||||
'bridge': 'br0',
|
||||
'vlan': 99,
|
||||
'gateway': '101.168.1.1',
|
||||
'broadcast': '101.168.1.255',
|
||||
'dns1': '8.8.8.8',
|
||||
'id': 'network-id-xxx-yyy-zzz'
|
||||
}
|
||||
|
||||
mapping_ovs = {
|
||||
'mac': 'ca:fe:de:ad:be:ef',
|
||||
'gateway_v6': net_ovs['gateway_v6'],
|
||||
'ips': [{'ip': '101.168.1.9'}],
|
||||
'dhcp_server': '191.168.1.1',
|
||||
'vif_uuid': 'vif-xxx-yyy-zzz',
|
||||
'vif_devname': 'tap-xxx-yyy-zzz',
|
||||
'ovs_interfaceid': 'aaa-bbb-ccc',
|
||||
}
|
||||
|
||||
instance = {
|
||||
'name': 'instance-name',
|
||||
'uuid': 'instance-uuid'
|
||||
|
@ -67,7 +91,7 @@ class LibvirtVifTestCase(test.TestCase):
|
|||
|
||||
self.stubs.Set(utils, 'execute', fake_execute)
|
||||
|
||||
def _get_instance_xml(self, driver):
|
||||
def _get_instance_xml(self, driver, net, mapping):
|
||||
conf = vconfig.LibvirtConfigGuest()
|
||||
conf.virt_type = "qemu"
|
||||
conf.name = "fake-name"
|
||||
|
@ -75,7 +99,7 @@ class LibvirtVifTestCase(test.TestCase):
|
|||
conf.memory = 100 * 1024
|
||||
conf.vcpus = 4
|
||||
|
||||
nic = driver.get_config(self.instance, self.net, self.mapping)
|
||||
nic = driver.get_config(self.instance, net, mapping)
|
||||
conf.add_device(nic)
|
||||
return conf.to_xml()
|
||||
|
||||
|
@ -126,7 +150,9 @@ class LibvirtVifTestCase(test.TestCase):
|
|||
libvirt_type='kvm')
|
||||
|
||||
d = vif.LibvirtBridgeDriver()
|
||||
xml = self._get_instance_xml(d)
|
||||
xml = self._get_instance_xml(d,
|
||||
self.net_bridge,
|
||||
self.mapping_bridge)
|
||||
|
||||
doc = etree.fromstring(xml)
|
||||
ret = doc.findall('./devices/interface')
|
||||
|
@ -143,7 +169,9 @@ class LibvirtVifTestCase(test.TestCase):
|
|||
libvirt_type='kvm')
|
||||
|
||||
d = vif.LibvirtBridgeDriver()
|
||||
xml = self._get_instance_xml(d)
|
||||
xml = self._get_instance_xml(d,
|
||||
self.net_bridge,
|
||||
self.mapping_bridge)
|
||||
|
||||
doc = etree.fromstring(xml)
|
||||
ret = doc.findall('./devices/interface')
|
||||
|
@ -160,7 +188,9 @@ class LibvirtVifTestCase(test.TestCase):
|
|||
libvirt_type='qemu')
|
||||
|
||||
d = vif.LibvirtBridgeDriver()
|
||||
xml = self._get_instance_xml(d)
|
||||
xml = self._get_instance_xml(d,
|
||||
self.net_bridge,
|
||||
self.mapping_bridge)
|
||||
|
||||
doc = etree.fromstring(xml)
|
||||
ret = doc.findall('./devices/interface')
|
||||
|
@ -177,7 +207,9 @@ class LibvirtVifTestCase(test.TestCase):
|
|||
libvirt_type='xen')
|
||||
|
||||
d = vif.LibvirtBridgeDriver()
|
||||
xml = self._get_instance_xml(d)
|
||||
xml = self._get_instance_xml(d,
|
||||
self.net_bridge,
|
||||
self.mapping_bridge)
|
||||
|
||||
doc = etree.fromstring(xml)
|
||||
ret = doc.findall('./devices/interface')
|
||||
|
@ -191,7 +223,9 @@ class LibvirtVifTestCase(test.TestCase):
|
|||
|
||||
def test_bridge_driver(self):
|
||||
d = vif.LibvirtBridgeDriver()
|
||||
xml = self._get_instance_xml(d)
|
||||
xml = self._get_instance_xml(d,
|
||||
self.net_bridge,
|
||||
self.mapping_bridge)
|
||||
|
||||
doc = etree.fromstring(xml)
|
||||
ret = doc.findall('./devices/interface')
|
||||
|
@ -199,13 +233,15 @@ class LibvirtVifTestCase(test.TestCase):
|
|||
node = ret[0]
|
||||
self.assertEqual(node.get("type"), "bridge")
|
||||
br_name = node.find("source").get("bridge")
|
||||
self.assertEqual(br_name, self.net['bridge'])
|
||||
self.assertEqual(br_name, self.net_bridge['bridge'])
|
||||
mac = node.find("mac").get("address")
|
||||
self.assertEqual(mac, self.mapping['mac'])
|
||||
self.assertEqual(mac, self.mapping_bridge['mac'])
|
||||
|
||||
def test_ovs_ethernet_driver(self):
|
||||
d = vif.LibvirtOpenVswitchDriver()
|
||||
xml = self._get_instance_xml(d)
|
||||
xml = self._get_instance_xml(d,
|
||||
self.net_ovs,
|
||||
self.mapping_ovs)
|
||||
|
||||
doc = etree.fromstring(xml)
|
||||
ret = doc.findall('./devices/interface')
|
||||
|
@ -215,13 +251,15 @@ class LibvirtVifTestCase(test.TestCase):
|
|||
dev_name = node.find("target").get("dev")
|
||||
self.assertTrue(dev_name.startswith("tap"))
|
||||
mac = node.find("mac").get("address")
|
||||
self.assertEqual(mac, self.mapping['mac'])
|
||||
self.assertEqual(mac, self.mapping_ovs['mac'])
|
||||
script = node.find("script").get("path")
|
||||
self.assertEquals(script, "")
|
||||
|
||||
def test_ovs_virtualport_driver(self):
|
||||
d = vif.LibvirtOpenVswitchVirtualPortDriver()
|
||||
xml = self._get_instance_xml(d)
|
||||
xml = self._get_instance_xml(d,
|
||||
self.net_ovs,
|
||||
self.mapping_ovs)
|
||||
|
||||
doc = etree.fromstring(xml)
|
||||
ret = doc.findall('./devices/interface')
|
||||
|
@ -232,21 +270,24 @@ class LibvirtVifTestCase(test.TestCase):
|
|||
br_name = node.find("source").get("bridge")
|
||||
self.assertEqual(br_name, "br0")
|
||||
mac = node.find("mac").get("address")
|
||||
self.assertEqual(mac, self.mapping['mac'])
|
||||
self.assertEqual(mac, self.mapping_ovs['mac'])
|
||||
vp = node.find("virtualport")
|
||||
self.assertEqual(vp.get("type"), "openvswitch")
|
||||
iface_id_found = False
|
||||
for p_elem in vp.findall("parameters"):
|
||||
iface_id = p_elem.get("interfaceid", None)
|
||||
if iface_id:
|
||||
self.assertEqual(iface_id, self.mapping['vif_uuid'])
|
||||
self.assertEqual(iface_id,
|
||||
self.mapping_ovs['ovs_interfaceid'])
|
||||
iface_id_found = True
|
||||
|
||||
self.assertTrue(iface_id_found)
|
||||
|
||||
def test_quantum_bridge_ethernet_driver(self):
|
||||
d = vif.QuantumLinuxBridgeVIFDriver()
|
||||
xml = self._get_instance_xml(d)
|
||||
xml = self._get_instance_xml(d,
|
||||
self.net_bridge,
|
||||
self.mapping_bridge)
|
||||
|
||||
doc = etree.fromstring(xml)
|
||||
ret = doc.findall('./devices/interface')
|
||||
|
@ -256,13 +297,15 @@ class LibvirtVifTestCase(test.TestCase):
|
|||
dev_name = node.find("target").get("dev")
|
||||
self.assertTrue(dev_name.startswith("tap"))
|
||||
mac = node.find("mac").get("address")
|
||||
self.assertEqual(mac, self.mapping['mac'])
|
||||
self.assertEqual(mac, self.mapping_ovs['mac'])
|
||||
br_name = node.find("source").get("bridge")
|
||||
self.assertEqual(br_name, "br0")
|
||||
|
||||
def test_quantum_hybrid_driver(self):
|
||||
d = vif.LibvirtHybridOVSBridgeDriver()
|
||||
xml = self._get_instance_xml(d)
|
||||
xml = self._get_instance_xml(d,
|
||||
self.net_ovs,
|
||||
self.mapping_ovs)
|
||||
|
||||
doc = etree.fromstring(xml)
|
||||
ret = doc.findall('./devices/interface')
|
||||
|
@ -270,6 +313,6 @@ class LibvirtVifTestCase(test.TestCase):
|
|||
node = ret[0]
|
||||
self.assertEqual(node.get("type"), "bridge")
|
||||
br_name = node.find("source").get("bridge")
|
||||
self.assertEqual(br_name, self.net['bridge'])
|
||||
self.assertEqual(br_name, self.net_ovs['bridge'])
|
||||
mac = node.find("mac").get("address")
|
||||
self.assertEqual(mac, self.mapping['mac'])
|
||||
self.assertEqual(mac, self.mapping_ovs['mac'])
|
||||
|
|
|
@ -150,6 +150,9 @@ class LibvirtOpenVswitchDriver(LibvirtBaseVIFDriver):
|
|||
def get_bridge_name(self, network):
|
||||
return network.get('bridge') or CONF.libvirt_ovs_bridge
|
||||
|
||||
def get_ovs_interfaceid(self, mapping):
|
||||
return mapping.get('ovs_interfaceid') or mapping['vif_uuid']
|
||||
|
||||
def get_config(self, instance, network, mapping):
|
||||
dev = self.get_vif_devname(mapping)
|
||||
|
||||
|
@ -179,7 +182,7 @@ class LibvirtOpenVswitchDriver(LibvirtBaseVIFDriver):
|
|||
|
||||
def plug(self, instance, vif):
|
||||
network, mapping = vif
|
||||
iface_id = mapping['vif_uuid']
|
||||
iface_id = self.get_ovs_interfaceid(mapping)
|
||||
dev = self.get_vif_devname(mapping)
|
||||
if not linux_net.device_exists(dev):
|
||||
# Older version of the command 'ip' from the iproute2 package
|
||||
|
@ -247,9 +250,9 @@ class LibvirtHybridOVSBridgeDriver(LibvirtBridgeDriver,
|
|||
"""
|
||||
|
||||
network, mapping = vif
|
||||
iface_id = mapping['vif_uuid']
|
||||
br_name = self.get_br_name(iface_id)
|
||||
v1_name, v2_name = self.get_veth_pair_names(iface_id)
|
||||
iface_id = self.get_ovs_interfaceid(mapping)
|
||||
br_name = self.get_br_name(mapping['vif_uuid'])
|
||||
v1_name, v2_name = self.get_veth_pair_names(mapping['vif_uuid'])
|
||||
|
||||
if not linux_net.device_exists(br_name):
|
||||
utils.execute('brctl', 'addbr', br_name, run_as_root=True)
|
||||
|
@ -270,9 +273,8 @@ class LibvirtHybridOVSBridgeDriver(LibvirtBridgeDriver,
|
|||
"""
|
||||
try:
|
||||
network, mapping = vif
|
||||
iface_id = mapping['vif_uuid']
|
||||
br_name = self.get_br_name(iface_id)
|
||||
v1_name, v2_name = self.get_veth_pair_names(iface_id)
|
||||
br_name = self.get_br_name(mapping['vif_uuid'])
|
||||
v1_name, v2_name = self.get_veth_pair_names(mapping['vif_uuid'])
|
||||
|
||||
utils.execute('brctl', 'delif', br_name, v1_name, run_as_root=True)
|
||||
utils.execute('ip', 'link', 'set', br_name, 'down',
|
||||
|
@ -291,6 +293,9 @@ class LibvirtOpenVswitchVirtualPortDriver(LibvirtBaseVIFDriver):
|
|||
def get_bridge_name(self, network):
|
||||
return network.get('bridge') or CONF.libvirt_ovs_bridge
|
||||
|
||||
def get_ovs_interfaceid(self, mapping):
|
||||
return mapping.get('ovs_interfaceid') or mapping['vif_uuid']
|
||||
|
||||
def get_config(self, instance, network, mapping):
|
||||
"""Pass data required to create OVS virtual port element."""
|
||||
conf = super(LibvirtOpenVswitchVirtualPortDriver,
|
||||
|
@ -299,7 +304,8 @@ class LibvirtOpenVswitchVirtualPortDriver(LibvirtBaseVIFDriver):
|
|||
mapping)
|
||||
|
||||
designer.set_vif_host_backend_ovs_config(
|
||||
conf, self.get_bridge_name(network), mapping['vif_uuid'],
|
||||
conf, self.get_bridge_name(network),
|
||||
self.get_ovs_interfaceid(mapping),
|
||||
self.get_vif_devname(mapping))
|
||||
|
||||
return conf
|
||||
|
|
Loading…
Reference in New Issue