libvirt: virtuozzo instance rescue mode support

Adapt "nova rescue" code to support Virtuozzo ploop disks.
In rescue mode we use static mount point /mnt/rescue for original filesystem.
As far as ploop disks are in fact directories
we use rmtree function to delete rescue disks in unrescue procedure.

Implements: blueprint virtuozzo-rescue-support
Change-Id: I07b9e3a8b726635294395b0292fc3592a1b0f918
This commit is contained in:
Mikhail Feoktistov 2015-08-27 14:48:27 +03:00 committed by Maxim Nestratov
parent 5ff36af47f
commit d60d70598e
4 changed files with 67 additions and 14 deletions

View File

@ -359,8 +359,8 @@ driver-impl-libvirt-xen=complete
driver-impl-vmware=complete driver-impl-vmware=complete
driver-impl-hyperv=complete driver-impl-hyperv=complete
driver-impl-ironic=missing driver-impl-ironic=missing
driver-impl-libvirt-vz-vm=missing driver-impl-libvirt-vz-vm=complete
driver-impl-libvirt-vz-ct=missing driver-impl-libvirt-vz-ct=complete
[operation.resize] [operation.resize]
title=Resize instance title=Resize instance

View File

@ -14229,7 +14229,13 @@ class LibvirtConnTestCase(test.NoDBTestCase):
self.assertIsInstance(cfg.devices[5], self.assertIsInstance(cfg.devices[5],
vconfig.LibvirtConfigGuestVideo) vconfig.LibvirtConfigGuestVideo)
def test_get_guest_config_parallels_ct_rescue(self):
self._test_get_guest_config_parallels_ct(rescue=True)
def test_get_guest_config_parallels_ct(self): def test_get_guest_config_parallels_ct(self):
self._test_get_guest_config_parallels_ct(rescue=False)
def _test_get_guest_config_parallels_ct(self, rescue=False):
self.flags(virt_type='parallels', group='libvirt') self.flags(virt_type='parallels', group='libvirt')
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
ct_instance = self.test_instance.copy() ct_instance = self.test_instance.copy()
@ -14237,9 +14243,15 @@ class LibvirtConnTestCase(test.NoDBTestCase):
instance_ref = objects.Instance(**ct_instance) instance_ref = objects.Instance(**ct_instance)
image_meta = objects.ImageMeta.from_dict(self.test_image_meta) image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
if rescue:
rescue_data = ct_instance
else:
rescue_data = None
cfg = drvr._get_guest_config(instance_ref, cfg = drvr._get_guest_config(instance_ref,
_fake_network_info(self, 1), _fake_network_info(self, 1),
image_meta, {'mapping': {'disk': {}}}) image_meta, {'mapping': {'disk': {}}},
rescue_data)
self.assertEqual("parallels", cfg.virt_type) self.assertEqual("parallels", cfg.virt_type)
self.assertEqual(instance_ref["uuid"], cfg.uuid) self.assertEqual(instance_ref["uuid"], cfg.uuid)
self.assertEqual(2 * units.Mi, cfg.memory) self.assertEqual(2 * units.Mi, cfg.memory)
@ -14247,18 +14259,31 @@ class LibvirtConnTestCase(test.NoDBTestCase):
self.assertEqual(vm_mode.EXE, cfg.os_type) self.assertEqual(vm_mode.EXE, cfg.os_type)
self.assertEqual("/sbin/init", cfg.os_init_path) self.assertEqual("/sbin/init", cfg.os_init_path)
self.assertIsNone(cfg.os_root) self.assertIsNone(cfg.os_root)
if rescue:
self.assertEqual(5, len(cfg.devices))
else:
self.assertEqual(4, len(cfg.devices)) self.assertEqual(4, len(cfg.devices))
self.assertIsInstance(cfg.devices[0], self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestFilesys) vconfig.LibvirtConfigGuestFilesys)
fs = cfg.devices[0]
device_index = 0
fs = cfg.devices[device_index]
self.assertEqual(fs.source_type, "file") self.assertEqual(fs.source_type, "file")
self.assertEqual(fs.driver_type, "ploop") self.assertEqual(fs.driver_type, "ploop")
self.assertEqual(fs.target_dir, "/") self.assertEqual(fs.target_dir, "/")
self.assertIsInstance(cfg.devices[1],
if rescue:
device_index = 1
fs = cfg.devices[device_index]
self.assertEqual(fs.source_type, "file")
self.assertEqual(fs.driver_type, "ploop")
self.assertEqual(fs.target_dir, "/mnt/rescue")
self.assertIsInstance(cfg.devices[device_index + 1],
vconfig.LibvirtConfigGuestInterface) vconfig.LibvirtConfigGuestInterface)
self.assertIsInstance(cfg.devices[2], self.assertIsInstance(cfg.devices[device_index + 2],
vconfig.LibvirtConfigGuestGraphics) vconfig.LibvirtConfigGuestGraphics)
self.assertIsInstance(cfg.devices[3], self.assertIsInstance(cfg.devices[device_index + 3],
vconfig.LibvirtConfigGuestVideo) vconfig.LibvirtConfigGuestVideo)
def _test_get_guest_config_parallels_volume(self, vmmode, devices): def _test_get_guest_config_parallels_volume(self, vmmode, devices):
@ -15900,6 +15925,13 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
unrescue_xml_path = os.path.join('/path', 'unrescue.xml') unrescue_xml_path = os.path.join('/path', 'unrescue.xml')
xml_path = os.path.join('/path', 'libvirt.xml') xml_path = os.path.join('/path', 'libvirt.xml')
rescue_file = os.path.join('/path', 'rescue.file') rescue_file = os.path.join('/path', 'rescue.file')
rescue_dir = os.path.join('/path', 'rescue.dir')
def isdir_sideeffect(*args, **kwargs):
if args[0] == '/path/rescue.file':
return False
if args[0] == '/path/rescue.dir':
return True
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
with test.nested( with test.nested(
@ -15907,12 +15939,17 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
mock.patch.object(drvr, '_destroy'), mock.patch.object(drvr, '_destroy'),
mock.patch.object(drvr, '_create_domain'), mock.patch.object(drvr, '_create_domain'),
mock.patch.object(libvirt_utils, 'file_delete'), mock.patch.object(libvirt_utils, 'file_delete'),
mock.patch.object(shutil, 'rmtree'),
mock.patch.object(os.path, "isdir",
side_effect=isdir_sideeffect),
mock.patch.object(drvr, '_lvm_disks', mock.patch.object(drvr, '_lvm_disks',
return_value=['lvm.rescue']), return_value=['lvm.rescue']),
mock.patch.object(lvm, 'remove_volumes'), mock.patch.object(lvm, 'remove_volumes'),
mock.patch.object(glob, 'iglob', return_value=[rescue_file]) mock.patch.object(glob, 'iglob',
return_value=[rescue_file, rescue_dir])
) as (mock_write, mock_destroy, mock_create, mock_del, ) as (mock_write, mock_destroy, mock_create, mock_del,
mock_lvm_disks, mock_remove_volumes, mock_glob): mock_rmtree, mock_isdir, mock_lvm_disks,
mock_remove_volumes, mock_glob):
drvr.unrescue(instance, None) drvr.unrescue(instance, None)
mock_write.assert_called_once_with(xml_path, "fake_unrescue_xml") mock_write.assert_called_once_with(xml_path, "fake_unrescue_xml")
mock_destroy.assert_called_once_with(instance) mock_destroy.assert_called_once_with(instance)
@ -15921,6 +15958,8 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
self.assertEqual(2, mock_del.call_count) self.assertEqual(2, mock_del.call_count)
self.assertEqual(unrescue_xml_path, self.assertEqual(unrescue_xml_path,
mock_del.call_args_list[0][0][0]) mock_del.call_args_list[0][0][0])
self.assertEqual(1, mock_rmtree.call_count)
self.assertEqual(rescue_dir, mock_rmtree.call_args_list[0][0][0])
self.assertEqual(rescue_file, mock_del.call_args_list[1][0][0]) self.assertEqual(rescue_file, mock_del.call_args_list[1][0][0])
mock_remove_volumes.assert_called_once_with(['lvm.rescue']) mock_remove_volumes.assert_called_once_with(['lvm.rescue'])

View File

@ -2600,6 +2600,9 @@ class LibvirtDriver(driver.ComputeDriver):
libvirt_utils.file_delete(unrescue_xml_path) libvirt_utils.file_delete(unrescue_xml_path)
rescue_files = os.path.join(instance_dir, "*.rescue") rescue_files = os.path.join(instance_dir, "*.rescue")
for rescue_file in glob.iglob(rescue_files): for rescue_file in glob.iglob(rescue_files):
if os.path.isdir(rescue_file):
shutil.rmtree(rescue_file)
else:
libvirt_utils.file_delete(rescue_file) libvirt_utils.file_delete(rescue_file)
# cleanup rescue volume # cleanup rescue volume
lvm.remove_volumes([lvmdisk for lvmdisk in self._lvm_disks(instance) lvm.remove_volumes([lvmdisk for lvmdisk in self._lvm_disks(instance)
@ -3433,6 +3436,14 @@ class LibvirtDriver(driver.ComputeDriver):
libvirt_utils.get_instance_path(instance), 'rootfs') libvirt_utils.get_instance_path(instance), 'rootfs')
devices.append(fs) devices.append(fs)
elif os_type == vm_mode.EXE and CONF.libvirt.virt_type == "parallels": elif os_type == vm_mode.EXE and CONF.libvirt.virt_type == "parallels":
if rescue:
fsrescue = self._get_guest_fs_config(instance, "disk.rescue")
devices.append(fsrescue)
fsos = self._get_guest_fs_config(instance, "disk")
fsos.target_dir = "/mnt/rescue"
devices.append(fsos)
else:
if 'disk' in disk_mapping: if 'disk' in disk_mapping:
fs = self._get_guest_fs_config(instance, "disk") fs = self._get_guest_fs_config(instance, "disk")
devices.append(fs) devices.append(fs)

View File

@ -0,0 +1,3 @@
---
features:
- Virtuozzo instances with ploop disks now support the rescue operation