diff options
| author | Julien Danjou <julien.danjou@enovance.com> | 2011-12-14 18:10:24 +0100 |
|---|---|---|
| committer | Julien Danjou <julien.danjou@enovance.com> | 2012-01-03 17:51:52 +0100 |
| commit | 77269f1720e71f916407ddafdd31f2fcfe49569d (patch) | |
| tree | 06d6b9b33f854c6bc0d8789c249267f23612429c | |
| parent | ea21fe69655ae441eb9660e0579046355f6db4c1 (diff) | |
| download | nova-77269f1720e71f916407ddafdd31f2fcfe49569d.tar.gz nova-77269f1720e71f916407ddafdd31f2fcfe49569d.tar.xz nova-77269f1720e71f916407ddafdd31f2fcfe49569d.zip | |
libvirt: implements boot from ISO images
This allows to boot correctly ISO images. We just set the device type in the
XML template to 'cdrom' if the image is in ISO format, and the bus type to
IDE so it has maximum compatibility.
This implements the blueprint support-kvm-boot-from-iso.
Change-Id: I4d1ea52a17f6f24e944b10020d54aaec9e86c95c
Signed-off-by: Julien Danjou <julien.danjou@enovance.com>
| -rw-r--r-- | nova/tests/test_libvirt.py | 29 | ||||
| -rw-r--r-- | nova/virt/libvirt.xml.template | 30 | ||||
| -rw-r--r-- | nova/virt/libvirt/connection.py | 18 |
3 files changed, 55 insertions, 22 deletions
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index 92a14ee2a..15b7f7259 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -347,12 +347,12 @@ class LibvirtConnTestCase(test.TestCase): result = conn._prepare_xml_info(instance_ref, _fake_network_info(self.stubs, 1), - False) + None, False) self.assertTrue(len(result['nics']) == 1) result = conn._prepare_xml_info(instance_ref, _fake_network_info(self.stubs, 2), - False) + None, False) self.assertTrue(len(result['nics']) == 2) def test_xml_and_uri_no_ramdisk_no_kernel(self): @@ -394,6 +394,14 @@ class LibvirtConnTestCase(test.TestCase): instance_data = dict(self.test_instance) self._check_xml_and_disk_prefix(instance_data) + def test_xml_disk_bus_virtio(self): + self._check_xml_and_disk_bus({"disk_format": "raw"}, + "disk", "virtio") + + def test_xml_disk_bus_ide(self): + self._check_xml_and_disk_bus({"disk_format": "iso"}, + "cdrom", "ide") + @test.skip_if(missing_libvirt(), "Test requires libvirt") def test_snapshot_in_ami_format(self): self.flags(image_service='nova.image.fake.FakeImageService') @@ -555,7 +563,7 @@ class LibvirtConnTestCase(test.TestCase): network_info = _fake_network_info(self.stubs, 2) conn = connection.LibvirtConnection(True) instance_ref = db.instance_create(self.context, instance_data) - xml = conn.to_xml(instance_ref, network_info, False) + xml = conn.to_xml(instance_ref, network_info, None, False) tree = xml_to_tree(xml) interfaces = tree.findall("./devices/interface") self.assertEquals(len(interfaces), 2) @@ -627,6 +635,19 @@ class LibvirtConnTestCase(test.TestCase): '%s != %s failed check %d' % (check(tree), expected_result, i)) + def _check_xml_and_disk_bus(self, image_meta, device_type, bus): + user_context = context.RequestContext(self.user_id, self.project_id) + instance_ref = db.instance_create(user_context, self.test_instance) + network_info = _fake_network_info(self.stubs, 1) + + xml = connection.LibvirtConnection(True).to_xml(instance_ref, + network_info, + image_meta) + tree = xml_to_tree(xml) + self.assertEqual(tree.find('./devices/disk').get('device'), + device_type) + self.assertEqual(tree.find('./devices/disk/target').get('bus'), bus) + def _check_xml_and_uri(self, instance, expect_ramdisk, expect_kernel, rescue=False): user_context = context.RequestContext(self.user_id, self.project_id) @@ -708,7 +729,7 @@ class LibvirtConnTestCase(test.TestCase): self.assertEquals(conn.uri, expected_uri) network_info = _fake_network_info(self.stubs, 1) - xml = conn.to_xml(instance_ref, network_info, rescue) + xml = conn.to_xml(instance_ref, network_info, None, rescue) tree = xml_to_tree(xml) for i, (check, expected_result) in enumerate(checks): self.assertEqual(check(tree), diff --git a/nova/virt/libvirt.xml.template b/nova/virt/libvirt.xml.template index 2a01f32b7..8cf361ef7 100644 --- a/nova/virt/libvirt.xml.template +++ b/nova/virt/libvirt.xml.template @@ -3,23 +3,29 @@ <memory>${memory_kb}</memory> <os> #if $type == 'lxc' - #set $disk_bus = '' <type>exe</type> <init>/sbin/init</init> #else if $type == 'uml' - #set $disk_bus = 'uml' + #set $root_disk_bus = 'uml' + #set $ephemeral_disk_bus = 'uml' <type>uml</type> <kernel>/usr/bin/linux</kernel> #set $root_device_name = $getVar('root_device_name', '/dev/ubda') <root>${root_device_name}</root> #else #if $type == 'xen' - #set $disk_bus = 'scsi' + #set $root_disk_bus = 'scsi' + #set $ephemeral_disk_bus = 'scsi' <type>linux</type> #set $root_device_name = $getVar('root_device_name', '/dev/xvda') <root>${root_device_name}</root> #else - #set $disk_bus = 'virtio' + #set $ephemeral_disk_bus = 'virtio' + #if $root_device_type == 'cdrom' + #set $root_disk_bus = 'ide' + #else + #set $root_disk_bus = 'virtio' + #end if <type>hvm</type> #end if #if $getVar('rescue', False) @@ -58,40 +64,40 @@ <disk type='file'> <driver type='${driver_type}'/> <source file='${basepath}/disk.rescue'/> - <target dev='${disk_prefix}a' bus='${disk_bus}'/> + <target dev='${disk_prefix}a' bus='${ephemeral_disk_bus}'/> </disk> <disk type='file'> <driver type='${driver_type}'/> <source file='${basepath}/disk'/> - <target dev='${disk_prefix}b' bus='${disk_bus}'/> + <target dev='${disk_prefix}b' bus='${ephemeral_disk_bus}'/> </disk> #else #if not ($getVar('ebs_root', False)) - <disk type='file'> + <disk type='file' device='${root_device_type}'> <driver type='${driver_type}'/> <source file='${basepath}/disk'/> - <target dev='${root_device}' bus='${disk_bus}'/> + <target dev='${root_device}' bus='${root_disk_bus}'/> </disk> #end if #if $getVar('local_device', False) <disk type='file'> <driver type='${driver_type}'/> <source file='${basepath}/disk.local'/> - <target dev='${local_device}' bus='${disk_bus}'/> + <target dev='${local_device}' bus='${ephemeral_disk_bus}'/> </disk> #end if #for $eph in $ephemerals <disk type='block'> <driver type='${driver_type}'/> <source dev='${basepath}/${eph.device_path}'/> - <target dev='${eph.device}' bus='${disk_bus}'/> + <target dev='${eph.device}' bus='${ephemeral_disk_bus}'/> </disk> #end for #if $getVar('swap_device', False) <disk type='file'> <driver type='${driver_type}'/> <source file='${basepath}/disk.swap'/> - <target dev='${swap_device}' bus='${disk_bus}'/> + <target dev='${swap_device}' bus='${ephemeral_disk_bus}'/> </disk> #end if #for $vol in $volumes @@ -102,7 +108,7 @@ <disk type='file'> <driver type='raw' /> <source file='${basepath}/disk.config' /> - <target dev='${disk_prefix}z' bus='${disk_bus}' /> + <target dev='${disk_prefix}z' bus='${ephemeral_disk_bus}' /> </disk> #end if #end if diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py index 8a6fa7c16..010e2726f 100644 --- a/nova/virt/libvirt/connection.py +++ b/nova/virt/libvirt/connection.py @@ -629,7 +629,7 @@ class LibvirtConnection(driver.ComputeDriver): 'unrescue.xml') libvirt_utils.write_to_file(unrescue_xml_path, unrescue_xml) - xml = self.to_xml(instance, network_info, rescue=True) + xml = self.to_xml(instance, network_info, image_meta, rescue=True) rescue_images = { 'image_id': FLAGS.rescue_image_id or instance['image_ref'], 'kernel_id': FLAGS.rescue_kernel_id or instance['kernel_id'], @@ -671,7 +671,7 @@ class LibvirtConnection(driver.ComputeDriver): @exception.wrap_exception() def spawn(self, context, instance, image_meta, network_info, block_device_info=None): - xml = self.to_xml(instance, network_info, False, + xml = self.to_xml(instance, network_info, image_meta, False, block_device_info=block_device_info) self.firewall_driver.setup_basic_filtering(instance, network_info) self.firewall_driver.prepare_instance_filter(instance, network_info) @@ -1086,7 +1086,7 @@ class LibvirtConnection(driver.ComputeDriver): LOG.debug(_("block_device_list %s"), block_device_list) return block_device.strip_dev(mount_device) in block_device_list - def _prepare_xml_info(self, instance, network_info, rescue, + def _prepare_xml_info(self, instance, network_info, image_meta, rescue, block_device_info=None): block_device_mapping = driver.block_device_info_get_mapping( block_device_info) @@ -1103,6 +1103,11 @@ class LibvirtConnection(driver.ComputeDriver): else: driver_type = 'raw' + if image_meta and image_meta.get('disk_format') == 'iso': + root_device_type = 'cdrom' + else: + root_device_type = 'disk' + volumes = [] for vol in block_device_mapping: connection_info = vol['connection_info'] @@ -1139,6 +1144,7 @@ class LibvirtConnection(driver.ComputeDriver): 'rescue': rescue, 'disk_prefix': self._disk_prefix, 'driver_type': driver_type, + 'root_device_type': root_device_type, 'vif_type': FLAGS.libvirt_vif_type, 'nics': nics, 'ebs_root': ebs_root, @@ -1194,12 +1200,12 @@ class LibvirtConnection(driver.ComputeDriver): xml_info['disk'] = xml_info['basepath'] + "/disk" return xml_info - def to_xml(self, instance, network_info, rescue=False, + def to_xml(self, instance, network_info, image_meta=None, rescue=False, block_device_info=None): # TODO(termie): cache? LOG.debug(_('instance %s: starting toXML method'), instance['name']) - xml_info = self._prepare_xml_info(instance, network_info, rescue, - block_device_info) + xml_info = self._prepare_xml_info(instance, network_info, image_meta, + rescue, block_device_info) xml = str(Template(self.libvirt_xml, searchList=[xml_info])) LOG.debug(_('instance %s: finished toXML method'), instance['name']) return xml |
