Libvirt: Added suffix to configdrive_path required for rescue

It was observed that during nova rescue, nova failed to create
a rescue disk for disk.config. The reason being that .rescue
suffix was missing from the configdrive path. It was working
till Havana but the functionality broke in Icehouse. This commit
fixes the suffix problem.

Unittests have been added to verify following scenarios:
    1. Make sure that .rescue disks are created when not using
        config drive
    2. Make sure that .rescue disks are created when using
        config drive

Closes-Bug: #1334024

Change-Id: I87449ffddd047cb84b7b881757ea4c29927b95da
This commit is contained in:
Shraddha Pandhe 2014-06-25 20:56:33 +00:00
parent b16db2bdca
commit 0d781d41fe
3 changed files with 171 additions and 4 deletions

View File

@ -56,3 +56,18 @@ class Backend(object):
#NOTE(bfilippov): this is done in favor for
# snapshot tests in test_libvirt.LibvirtConnTestCase
return imagebackend.Backend(True).snapshot(path, image_type)
class Raw(imagebackend.Image):
# NOTE(spandhe) Added for test_rescue and test_rescue_config_drive
def __init__(self, instance=None, disk_name=None, path=None):
pass
def _get_driver_format(self):
pass
def correct_format(self):
pass
def create_image(self, prepare_template, base, size, *args, **kwargs):
pass

View File

@ -32,6 +32,7 @@ from oslo.config import cfg
from xml.dom import minidom
from nova.api.ec2 import cloud
from nova.api.metadata import base as instance_metadata
from nova.compute import flavors
from nova.compute import manager
from nova.compute import power_state
@ -61,6 +62,7 @@ from nova.tests import fake_network
import nova.tests.image.fake
from nova.tests import matchers
from nova.tests.objects import test_pci_device
from nova.tests.virt.libvirt import fake_imagebackend
from nova.tests.virt.libvirt import fake_libvirt_utils
from nova.tests.virt.libvirt import fakelibvirt
from nova import utils
@ -5199,7 +5201,7 @@ class LibvirtConnTestCase(test.TestCase):
).AndReturn(instance)
self.mox.StubOutWithMock(driver, "block_device_info_get_mapping")
driver.block_device_info_get_mapping(vol
).AndReturn(vol['block_device_mapping'])
).AndReturn(vol['block_device_mapping'])
self.mox.StubOutWithMock(libvirt_driver.LibvirtDriver,
"volume_driver_method")
if volume_fail:
@ -9281,6 +9283,156 @@ class LibvirtDriverTestCase(test.TestCase):
'detach_interface', power_state.SHUTDOWN,
expected_flags=(libvirt.VIR_DOMAIN_AFFECT_CONFIG))
def test_rescue(self):
instance = self._create_instance()
instance.config_drive = False
dummyxml = ("<domain type='kvm'><name>instance-0000000a</name>"
"<devices>"
"<disk type='file'><driver name='qemu' type='raw'/>"
"<source file='/test/disk'/>"
"<target dev='vda' bus='virtio'/></disk>"
"<disk type='file'><driver name='qemu' type='qcow2'/>"
"<source file='/test/disk.local'/>"
"<target dev='vdb' bus='virtio'/></disk>"
"</devices></domain>")
network_info = _fake_network_info(self.stubs, 1)
self.mox.StubOutWithMock(self.libvirtconnection,
'_get_existing_domain_xml')
self.mox.StubOutWithMock(libvirt_utils, 'write_to_file')
self.mox.StubOutWithMock(imagebackend.Backend, 'image')
self.mox.StubOutWithMock(imagebackend.Image, 'cache')
self.mox.StubOutWithMock(self.libvirtconnection, '_get_guest_xml')
self.mox.StubOutWithMock(self.libvirtconnection, '_destroy')
self.mox.StubOutWithMock(self.libvirtconnection, '_create_domain')
self.libvirtconnection._get_existing_domain_xml(mox.IgnoreArg(),
mox.IgnoreArg()).MultipleTimes().AndReturn(dummyxml)
libvirt_utils.write_to_file(mox.IgnoreArg(), mox.IgnoreArg())
libvirt_utils.write_to_file(mox.IgnoreArg(), mox.IgnoreArg(),
mox.IgnoreArg())
imagebackend.Backend.image(instance, 'kernel.rescue', 'raw'
).AndReturn(fake_imagebackend.Raw())
imagebackend.Backend.image(instance, 'ramdisk.rescue', 'raw'
).AndReturn(fake_imagebackend.Raw())
imagebackend.Backend.image(instance, 'disk.rescue', 'default'
).AndReturn(fake_imagebackend.Raw())
imagebackend.Image.cache(context=mox.IgnoreArg(),
fetch_func=mox.IgnoreArg(),
filename=mox.IgnoreArg(),
image_id=mox.IgnoreArg(),
project_id=mox.IgnoreArg(),
user_id=mox.IgnoreArg()).MultipleTimes()
imagebackend.Image.cache(context=mox.IgnoreArg(),
fetch_func=mox.IgnoreArg(),
filename=mox.IgnoreArg(),
image_id=mox.IgnoreArg(),
project_id=mox.IgnoreArg(),
size=None, user_id=mox.IgnoreArg())
image_meta = {'id': 'fake', 'name': 'fake'}
self.libvirtconnection._get_guest_xml(mox.IgnoreArg(), instance,
network_info, mox.IgnoreArg(),
image_meta, rescue=mox.IgnoreArg(),
write_to_disk=mox.IgnoreArg()
).AndReturn(dummyxml)
self.libvirtconnection._destroy(instance)
self.libvirtconnection._create_domain(mox.IgnoreArg())
self.mox.ReplayAll()
rescue_password = 'fake_password'
self.libvirtconnection.rescue(self.context, instance,
network_info, image_meta, rescue_password)
self.mox.VerifyAll()
def test_rescue_config_drive(self):
instance = self._create_instance()
uuid = instance.uuid
configdrive_path = uuid + '/disk.config.rescue'
dummyxml = ("<domain type='kvm'><name>instance-0000000a</name>"
"<devices>"
"<disk type='file'><driver name='qemu' type='raw'/>"
"<source file='/test/disk'/>"
"<target dev='vda' bus='virtio'/></disk>"
"<disk type='file'><driver name='qemu' type='qcow2'/>"
"<source file='/test/disk.local'/>"
"<target dev='vdb' bus='virtio'/></disk>"
"</devices></domain>")
network_info = _fake_network_info(self.stubs, 1)
self.mox.StubOutWithMock(self.libvirtconnection,
'_get_existing_domain_xml')
self.mox.StubOutWithMock(libvirt_utils, 'write_to_file')
self.mox.StubOutWithMock(imagebackend.Backend, 'image')
self.mox.StubOutWithMock(imagebackend.Image, 'cache')
self.mox.StubOutWithMock(instance_metadata.InstanceMetadata,
'__init__')
self.mox.StubOutWithMock(configdrive, 'ConfigDriveBuilder')
self.mox.StubOutWithMock(configdrive.ConfigDriveBuilder, 'make_drive')
self.mox.StubOutWithMock(self.libvirtconnection, '_get_guest_xml')
self.mox.StubOutWithMock(self.libvirtconnection, '_destroy')
self.mox.StubOutWithMock(self.libvirtconnection, '_create_domain')
self.libvirtconnection._get_existing_domain_xml(mox.IgnoreArg(),
mox.IgnoreArg()).MultipleTimes().AndReturn(dummyxml)
libvirt_utils.write_to_file(mox.IgnoreArg(), mox.IgnoreArg())
libvirt_utils.write_to_file(mox.IgnoreArg(), mox.IgnoreArg(),
mox.IgnoreArg())
imagebackend.Backend.image(instance, 'kernel.rescue', 'raw'
).AndReturn(fake_imagebackend.Raw())
imagebackend.Backend.image(instance, 'ramdisk.rescue', 'raw'
).AndReturn(fake_imagebackend.Raw())
imagebackend.Backend.image(instance, 'disk.rescue', 'default'
).AndReturn(fake_imagebackend.Raw())
imagebackend.Image.cache(context=mox.IgnoreArg(),
fetch_func=mox.IgnoreArg(),
filename=mox.IgnoreArg(),
image_id=mox.IgnoreArg(),
project_id=mox.IgnoreArg(),
user_id=mox.IgnoreArg()).MultipleTimes()
imagebackend.Image.cache(context=mox.IgnoreArg(),
fetch_func=mox.IgnoreArg(),
filename=mox.IgnoreArg(),
image_id=mox.IgnoreArg(),
project_id=mox.IgnoreArg(),
size=None, user_id=mox.IgnoreArg())
instance_metadata.InstanceMetadata.__init__(mox.IgnoreArg(),
content=mox.IgnoreArg(),
extra_md=mox.IgnoreArg(),
network_info=mox.IgnoreArg())
cdb = self.mox.CreateMockAnything()
m = configdrive.ConfigDriveBuilder(instance_md=mox.IgnoreArg())
m.AndReturn(cdb)
# __enter__ and __exit__ are required by "with"
cdb.__enter__().AndReturn(cdb)
cdb.make_drive(mox.Regex(configdrive_path))
cdb.__exit__(mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()
).AndReturn(None)
image_meta = {'id': 'fake', 'name': 'fake'}
self.libvirtconnection._get_guest_xml(mox.IgnoreArg(), instance,
network_info, mox.IgnoreArg(),
image_meta, rescue=mox.IgnoreArg(),
write_to_disk=mox.IgnoreArg()
).AndReturn(dummyxml)
self.libvirtconnection._destroy(instance)
self.libvirtconnection._create_domain(mox.IgnoreArg())
self.mox.ReplayAll()
rescue_password = 'fake_password'
self.libvirtconnection.rescue(self.context, instance, network_info,
image_meta, rescue_password)
self.mox.VerifyAll()
class LibvirtVolumeUsageTestCase(test.TestCase):
"""Test for LibvirtDriver.get_all_volume_usage."""

View File

@ -2457,9 +2457,9 @@ class LibvirtDriver(driver.ComputeDriver):
'console.log')
@staticmethod
def _get_disk_config_path(instance):
def _get_disk_config_path(instance, suffix=''):
return os.path.join(libvirt_utils.get_instance_path(instance),
'disk.config')
'disk.config' + suffix)
def _chown_console_log_for_instance(self, instance):
console_log = self._get_console_log_path(instance)
@ -2682,7 +2682,7 @@ class LibvirtDriver(driver.ComputeDriver):
inst_md = instance_metadata.InstanceMetadata(instance,
content=files, extra_md=extra_md, network_info=network_info)
with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
configdrive_path = self._get_disk_config_path(instance)
configdrive_path = self._get_disk_config_path(instance, suffix)
LOG.info(_LI('Creating config drive at %(path)s'),
{'path': configdrive_path}, instance=instance)