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:
Daniel P. Berrange 2013-01-07 17:17:39 +00:00
parent fab8af583b
commit 1c07735f8e
5 changed files with 87 additions and 31 deletions

View File

@ -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)

View File

@ -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

View File

@ -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))

View File

@ -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'])

View File

@ -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