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:
parent
5ff36af47f
commit
d60d70598e
@ -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
|
||||||
|
@ -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'])
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Virtuozzo instances with ploop disks now support the rescue operation
|
Loading…
Reference in New Issue
Block a user