diff --git a/devops/driver/libvirt/libvirt_driver.py b/devops/driver/libvirt/libvirt_driver.py index 3ab3c952..fe10fefc 100644 --- a/devops/driver/libvirt/libvirt_driver.py +++ b/devops/driver/libvirt/libvirt_driver.py @@ -14,6 +14,7 @@ from __future__ import division import datetime +import itertools import os from time import sleep import xml.etree.ElementTree as ET @@ -121,6 +122,8 @@ class Snapshot(object): class DevopsDriver(object): + _device_name_generators = {} + def __init__(self, connection_string="qemu:///system", storage_pool_name="default", @@ -274,7 +277,7 @@ class DevopsDriver(object): else: raise - @retry() + @retry(delay=3) def network_define(self, network): """Define network @@ -1071,3 +1074,42 @@ class DevopsDriver(object): else: logger.warning("Can't close tray: no cdrom devices " "found for Node {!r}".format(node.name)) + + def get_allocated_device_names(self): + """Get list of existing bridge names and network devices + + :rtype : List + """ + names = [] + + # Local Network Devices + for dev in self.conn.listAllDevices(): + xml = ET.fromstring(dev.XMLDesc()) + name_el = xml.find('./capability/interface') + if name_el is None: + continue + name = name_el.text + names.append(name) + + # Network Bridges + for net in self.conn.listAllNetworks(): + names.append(net.bridgeName()) + + return names + + def get_available_device_name(self, prefix): + """Get available name for bridge + + :type prefix: str + :rtype : String + """ + allocated_names = self.get_allocated_device_names() + if prefix not in self._device_name_generators: + self._device_name_generators[prefix] = ( + '{}{}'.format(prefix, i) for i in itertools.count()) + all_names = self._device_name_generators[prefix] + + for name in all_names: + if name in allocated_names: + continue + return name diff --git a/devops/driver/libvirt/libvirt_xml_builder.py b/devops/driver/libvirt/libvirt_xml_builder.py index ac0b6007..b8d64782 100644 --- a/devops/driver/libvirt/libvirt_xml_builder.py +++ b/devops/driver/libvirt/libvirt_xml_builder.py @@ -51,8 +51,9 @@ class LibvirtXMLBuilder(object): stp_val = 'off' if self.driver.stp: stp_val = 'on' - # bridge_name will be generated by libvirt with prefix 'virbr' + network_xml.bridge( + name=self.driver.get_available_device_name(br_prefix), stp=stp_val, delay="0") if network.forward is not None: diff --git a/devops/tests/test_libvirt_xml_builder.py b/devops/tests/test_libvirt_xml_builder.py index 48ba637e..39f18445 100644 --- a/devops/tests/test_libvirt_xml_builder.py +++ b/devops/tests/test_libvirt_xml_builder.py @@ -28,7 +28,8 @@ class BaseTestXMLBuilder(TestCase): def setUp(self): # TODO(prmtl): make it fuzzy self.volume_path = "volume_path_mock" - self.xml_builder = LibvirtXMLBuilder(mock.Mock()) + self.driver_mock = mock.Mock() + self.xml_builder = LibvirtXMLBuilder(self.driver_mock) self.xml_builder.driver.volume_path = mock.Mock( return_value=self.volume_path ) @@ -104,12 +105,15 @@ class TestNetworkXml(BaseTestXMLBuilder): self.net.has_dhcp_server = False def test_net_name_bridge_name(self): + self.driver_mock.get_available_device_name.return_value = 'fuelbr0' xml = self.xml_builder.build_network_xml(self.net) self.assertXMLIn( '{0}_{1}' ''.format(self.net.environment.name, self.net.name), xml) - self.assertXMLIn('', xml) + self.assertXMLIn('', xml) + self.driver_mock.get_available_device_name.assert_called_once_with( + 'fuelbr') def test_forward(self): self.net.forward = "nat"