From 66a7f044f5143feaf7046cebafea3df3ea95e04b Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Wed, 16 Jan 2013 12:38:23 +0000 Subject: Allow disk driver to be chosen per image This allows for an image in glance to be annotated with a property describing the required disk / cdrom bus type. eg # glance image-update \ --property disk_bus=ide \ --property cdrom_bus=ide \ f16-x86_64-openstack-sda Valid bus values vary per the libvirt_type setting: qemu/kvm: 'virtio', 'scsi', 'ide', 'usb' xen: 'xen', 'ide' uml: 'uml' Requesting an unsupported disk bus will cause the guest instance to fail to launch. DocImpact Blueprint: libvirt-custom-hardware Change-Id: Ibc20b843ceccf374eae246384a3f246cc1c52a28 Signed-off-by: Daniel P. Berrange --- nova/tests/test_libvirt_blockinfo.py | 31 +++++++++++++++++++++++++++++++ nova/virt/libvirt/blockinfo.py | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/nova/tests/test_libvirt_blockinfo.py b/nova/tests/test_libvirt_blockinfo.py index 23f846324..e8d548399 100644 --- a/nova/tests/test_libvirt_blockinfo.py +++ b/nova/tests/test_libvirt_blockinfo.py @@ -18,6 +18,7 @@ from nova import block_device from nova import context from nova import db +from nova import exception from nova import test import nova.tests.image.fake from nova.virt.libvirt import blockinfo @@ -394,3 +395,33 @@ class LibvirtBlockInfoTest(test.TestCase): 'root': {'bus': 'virtio', 'dev': 'vdf', 'type': 'disk'} } self.assertEqual(mapping, expect) + + def test_get_disk_bus(self): + bus = blockinfo.get_disk_bus_for_device_type('kvm') + self.assertEqual(bus, 'virtio') + + bus = blockinfo.get_disk_bus_for_device_type('kvm', + device_type='cdrom') + self.assertEqual(bus, 'ide') + + image_meta = {'properties': {'disk_bus': 'scsi'}} + bus = blockinfo.get_disk_bus_for_device_type('kvm', + image_meta) + self.assertEqual(bus, 'scsi') + + image_meta = {'properties': {'disk_bus': 'usb', + 'cdrom_bus': 'scsi'}} + bus = blockinfo.get_disk_bus_for_device_type('kvm', + image_meta, + device_type='cdrom') + self.assertEqual(bus, 'scsi') + + bus = blockinfo.get_disk_bus_for_device_type('kvm', + image_meta) + self.assertEqual(bus, 'usb') + + image_meta = {'properties': {'disk_bus': 'xen'}} + self.assertRaises(exception.NovaException, + blockinfo.get_disk_bus_for_device_type, + 'kvm', + image_meta) diff --git a/nova/virt/libvirt/blockinfo.py b/nova/virt/libvirt/blockinfo.py index 844ae4a1b..fc4a7dbfb 100644 --- a/nova/virt/libvirt/blockinfo.py +++ b/nova/virt/libvirt/blockinfo.py @@ -166,7 +166,24 @@ def find_disk_dev_for_disk_bus(mapping, bus, last_device=False): dev_prefix) -def get_disk_bus_for_device_type(virt_type, device_type="disk"): +def is_disk_bus_valid_for_virt(virt_type, disk_bus): + valid_bus = { + 'qemu': ['virtio', 'scsi', 'ide', 'usb'], + 'kvm': ['virtio', 'scsi', 'ide', 'usb'], + 'xen': ['xen', 'ide'], + 'uml': ['uml'], + } + + if virt_type not in valid_bus: + raise exception.NovaException( + _("Unsupported virt type %s") % virt_type) + + return disk_bus in valid_bus[virt_type] + + +def get_disk_bus_for_device_type(virt_type, + image_meta=None, + device_type="disk"): """Determine the best disk bus to use for a device type. Considering the currently configured virtualization @@ -177,6 +194,18 @@ def get_disk_bus_for_device_type(virt_type, device_type="disk"): Returns the disk_bus, or returns None if the device type is not supported for this virtualization""" + # Prefer a disk bus set against the image first of all + if image_meta: + key = device_type + "_bus" + disk_bus = image_meta.get('properties', {}).get(key) + if disk_bus is not None: + if not is_disk_bus_valid_for_virt(virt_type, disk_bus): + raise exception.NovaException( + _("Disk bus %(disk_bus)s is not valid for %(virt)s") % + {'disk_bus': disk_bus, 'virt': virt_type}) + return disk_bus + + # Otherwise pick a hypervisor default disk bus if virt_type == "uml": if device_type == "disk": return "uml" @@ -375,8 +404,8 @@ def get_disk_info(virt_type, instance, block_device_info=None, Returns the disk mapping disk.""" - disk_bus = get_disk_bus_for_device_type(virt_type, "disk") - cdrom_bus = get_disk_bus_for_device_type(virt_type, "cdrom") + disk_bus = get_disk_bus_for_device_type(virt_type, image_meta, "disk") + cdrom_bus = get_disk_bus_for_device_type(virt_type, image_meta, "cdrom") mapping = get_disk_mapping(virt_type, instance, disk_bus, cdrom_bus, block_device_info, -- cgit