From 8f1664416abf7aaf8e049ba26ca404ab627b7d57 Mon Sep 17 00:00:00 2001 From: Christoph Thiel Date: Tue, 24 Jul 2012 22:25:12 +0200 Subject: libvirt driver: set driver name consistently Add pick_disk_driver_name to utils, to be able to set driver_name consistently across volume and imagebackend. This is mostly required for xen. Xen requires specifying both the driver name and type attributes when defining disks. E.g. the following disk XML snippet produces incorrect configuration in the xen tools (uname file:/tmp/disk0.qcow2) Including the driver name fixes this produces (uname tap:qcow2:/tmp/disk0.qcow2) Change-Id: Id984e0c431b6fc743a39e6e6f3dc3eb289fbb43a --- nova/tests/test_libvirt.py | 13 +++++++++++++ nova/virt/libvirt/imagebackend.py | 12 ++++++++---- nova/virt/libvirt/utils.py | 25 +++++++++++++++++++++++++ nova/virt/libvirt/volume.py | 9 +++------ 4 files changed, 49 insertions(+), 10 deletions(-) diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index f93c724bc..d4dd92e34 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -3187,6 +3187,19 @@ class LibvirtUtilsTestCase(test.TestCase): self.mox.ReplayAll() libvirt_utils.create_cow_image('/some/path', '/the/new/cow') + def test_pick_disk_driver_name(self): + type_map = {'kvm': ([True, 'qemu'], [False, 'qemu'], [None, 'qemu']), + 'qemu': ([True, 'qemu'], [False, 'qemu'], [None, 'qemu']), + 'xen': ([True, 'phy'], [False, 'tap'], [None, 'tap']), + 'uml': ([True, None], [False, None], [None, None]), + 'lxc': ([True, None], [False, None], [None, None])} + + for (libvirt_type, checks) in type_map.iteritems(): + self.flags(libvirt_type=libvirt_type) + for (is_block_dev, expected_result) in checks: + result = libvirt_utils.pick_disk_driver_name(is_block_dev) + self.assertEquals(result, expected_result) + def test_get_disk_size(self): self.mox.StubOutWithMock(utils, 'execute') utils.execute('qemu-img', diff --git a/nova/virt/libvirt/imagebackend.py b/nova/virt/libvirt/imagebackend.py index bc0489fbd..b564c128a 100644 --- a/nova/virt/libvirt/imagebackend.py +++ b/nova/virt/libvirt/imagebackend.py @@ -50,14 +50,16 @@ FLAGS.register_opts(__imagebackend_opts) class Image(object): __metaclass__ = abc.ABCMeta - def __init__(self, source_type, driver_format): + def __init__(self, source_type, driver_format, is_block_dev=False): """Image initialization. :source_type: block or file :driver_format: raw or qcow2 + :is_block_dev: """ self.source_type = source_type self.driver_format = driver_format + self.is_block_dev = is_block_dev @abc.abstractmethod def create_image(self, prepare_template, base, size, *args, **kwargs): @@ -87,6 +89,8 @@ class Image(object): info.target_dev = disk_dev info.driver_cache = cache_mode info.driver_format = self.driver_format + driver_name = libvirt_utils.pick_disk_driver_name(self.is_block_dev) + info.driver_name = driver_name info.source_path = self.path return info @@ -119,7 +123,7 @@ class Image(object): class Raw(Image): def __init__(self, instance, name): - super(Raw, self).__init__("file", "raw") + super(Raw, self).__init__("file", "raw", is_block_dev=False) self.path = os.path.join(FLAGS.instances_path, instance, name) @@ -143,7 +147,7 @@ class Raw(Image): class Qcow2(Image): def __init__(self, instance, name): - super(Qcow2, self).__init__("file", "qcow2") + super(Qcow2, self).__init__("file", "qcow2", is_block_dev=False) self.path = os.path.join(FLAGS.instances_path, instance, name) @@ -172,7 +176,7 @@ class Lvm(Image): return fname.replace('_', '__') def __init__(self, instance, name): - super(Lvm, self).__init__("block", "raw") + super(Lvm, self).__init__("block", "raw", is_block_dev=True) if not FLAGS.libvirt_images_volume_group: raise RuntimeError(_('You should specify' diff --git a/nova/virt/libvirt/utils.py b/nova/virt/libvirt/utils.py index 7edc76122..88e7097eb 100644 --- a/nova/virt/libvirt/utils.py +++ b/nova/virt/libvirt/utils.py @@ -145,6 +145,31 @@ def remove_logical_volumes(*paths): execute(*lvremove, attempts=3, run_as_root=True) +def pick_disk_driver_name(is_block_dev=False): + """Pick the libvirt primary backend driver name + + If the hypervisor supports multiple backend drivers, then the name + attribute selects the primary backend driver name, while the optional + type attribute provides the sub-type. For example, xen supports a name + of "tap", "tap2", "phy", or "file", with a type of "aio" or "qcow2", + while qemu only supports a name of "qemu", but multiple types including + "raw", "bochs", "qcow2", and "qed". + + :param is_block_dev: + :returns: driver_name or None + """ + if FLAGS.libvirt_type == "xen": + if is_block_dev: + return "phy" + else: + return "tap" + elif FLAGS.libvirt_type in ('kvm', 'qemu'): + return "qemu" + else: + # UML doesn't want a driver_name set + return None + + def get_disk_size(path): """Get the (virtual) size of a disk image diff --git a/nova/virt/libvirt/volume.py b/nova/virt/libvirt/volume.py index f5a346ca7..3c286a901 100644 --- a/nova/virt/libvirt/volume.py +++ b/nova/virt/libvirt/volume.py @@ -25,6 +25,7 @@ from nova import flags from nova.openstack.common import log as logging from nova import utils from nova.virt.libvirt import config +from nova.virt.libvirt import utils as virtutils LOG = logging.getLogger(__name__) FLAGS = flags.FLAGS @@ -36,15 +37,11 @@ class LibvirtVolumeDriver(object): def __init__(self, connection): self.connection = connection - def _pick_volume_driver(self): - hypervisor_type = self.connection.get_hypervisor_type().lower() - return "phy" if hypervisor_type == "xen" else "qemu" - def connect_volume(self, connection_info, mount_device): """Connect the volume. Returns xml for libvirt.""" conf = config.LibvirtConfigGuestDisk() conf.source_type = "block" - conf.driver_name = self._pick_volume_driver() + conf.driver_name = virtutils.pick_disk_driver_name(is_block_dev=True) conf.driver_format = "raw" conf.driver_cache = "none" conf.source_path = connection_info['data']['device_path'] @@ -79,7 +76,7 @@ class LibvirtNetVolumeDriver(LibvirtVolumeDriver): def connect_volume(self, connection_info, mount_device): conf = config.LibvirtConfigGuestDisk() conf.source_type = "network" - conf.driver_name = self._pick_volume_driver() + conf.driver_name = virtutils.pick_disk_driver_name(is_block_dev=False) conf.driver_format = "raw" conf.driver_cache = "none" conf.source_protocol = connection_info['driver_volume_type'] -- cgit