Fix nova evacuate issues for RBD
For RBD scenario, there are some issues in Nova code
now against evacuate function:
1. Based on current implementation, nova evacuate and
nova rebuild are sharing some code. When user enables
the on_shared_storage option for nova evacuate, nova
will check if the instance path is accessible. For
the RBD scenario, the volume(block) is shared between
different hosts, though the path isn't shared at the
filesystem level. This patch fixes this issue and adds
test cases for that.
2. Missing the 'recreate' parameter for rebuild method.
Though the libvirt driver doesn't implement rebuild
method(only Ironic driver implements it), but we really
need to set 'recreate' in kwargs so it gets passed to
_rebuild_default_impl so we don't call driver.destroy
on evacuate for shared filesystem/block storage cases.
It is fixed in this patch and test case is added as well.
Closes-Bug: 1249319
Closes-Bug: 1340411
Change-Id: Idc8c45b055e986cf85730235d5d25777632ad1c1
(cherry picked from commit 91d3272b97
)
This commit is contained in:
parent
b86bcb9358
commit
7920cfdab2
|
@ -2803,7 +2803,8 @@ class ComputeManager(manager.Manager):
|
|||
attach_block_devices=self._prep_block_device,
|
||||
block_device_info=block_device_info,
|
||||
network_info=network_info,
|
||||
preserve_ephemeral=preserve_ephemeral)
|
||||
preserve_ephemeral=preserve_ephemeral,
|
||||
recreate=recreate)
|
||||
try:
|
||||
self.driver.rebuild(**kwargs)
|
||||
except NotImplementedError:
|
||||
|
|
|
@ -1974,6 +1974,50 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
|
|||
|
||||
do_test()
|
||||
|
||||
def test_rebuild_default_impl(self):
|
||||
def _detach(context, bdms):
|
||||
pass
|
||||
|
||||
def _attach(context, instance, bdms, do_check_attach=True):
|
||||
return {'block_device_mapping': 'shared_block_storage'}
|
||||
|
||||
def _spawn(context, instance, image_meta, injected_files,
|
||||
admin_password, network_info=None, block_device_info=None):
|
||||
self.assertEqual(block_device_info['block_device_mapping'],
|
||||
'shared_block_storage')
|
||||
|
||||
with contextlib.nested(
|
||||
mock.patch.object(self.compute.driver, 'destroy',
|
||||
return_value=None),
|
||||
mock.patch.object(self.compute.driver, 'spawn',
|
||||
side_effect=_spawn),
|
||||
mock.patch.object(objects.Instance, 'save',
|
||||
return_value=None)
|
||||
) as(
|
||||
mock_destroy,
|
||||
mock_spawn,
|
||||
mock_save
|
||||
):
|
||||
instance = fake_instance.fake_instance_obj(self.context)
|
||||
instance.task_state = task_states.REBUILDING
|
||||
instance.save(expected_task_state=[task_states.REBUILDING])
|
||||
self.compute._rebuild_default_impl(self.context,
|
||||
instance,
|
||||
None,
|
||||
[],
|
||||
admin_password='new_pass',
|
||||
bdms=[],
|
||||
detach_block_devices=_detach,
|
||||
attach_block_devices=_attach,
|
||||
network_info=None,
|
||||
recreate=True,
|
||||
block_device_info=None,
|
||||
preserve_ephemeral=False)
|
||||
|
||||
self.assertFalse(mock_destroy.called)
|
||||
self.assertTrue(mock_save.called)
|
||||
self.assertTrue(mock_spawn.called)
|
||||
|
||||
|
||||
class ComputeManagerBuildInstanceTestCase(test.NoDBTestCase):
|
||||
def setUp(self):
|
||||
|
|
|
@ -12428,6 +12428,17 @@ class LibvirtDriverTestCase(test.TestCase):
|
|||
vconfig.LibvirtConfigGuestGIDMap,
|
||||
1, 20000, 10)
|
||||
|
||||
def test_instance_on_disk(self):
|
||||
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
||||
instance = objects.Instance(uuid='fake-uuid', id=1)
|
||||
self.assertFalse(conn.instance_on_disk(instance))
|
||||
|
||||
def test_instance_on_disk_rbd(self):
|
||||
self.flags(images_type='rbd', group='libvirt')
|
||||
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
||||
instance = objects.Instance(uuid='fake-uuid', id=1)
|
||||
self.assertTrue(conn.instance_on_disk(instance))
|
||||
|
||||
|
||||
class LibvirtVolumeUsageTestCase(test.TestCase):
|
||||
"""Test for LibvirtDriver.get_all_volume_usage."""
|
||||
|
|
|
@ -6220,7 +6220,13 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
# ensure directories exist and are writable
|
||||
instance_path = libvirt_utils.get_instance_path(instance)
|
||||
LOG.debug('Checking instance files accessibility %s', instance_path)
|
||||
return os.access(instance_path, os.W_OK)
|
||||
shared_instance_path = os.access(instance_path, os.W_OK)
|
||||
# NOTE(flwang): For shared block storage scenario, the file system is
|
||||
# not really shared by the two hosts, but the volume of evacuated
|
||||
# instance is reachable.
|
||||
shared_block_storage = (self.image_backend.backend().
|
||||
is_shared_block_storage())
|
||||
return shared_instance_path or shared_block_storage
|
||||
|
||||
def inject_network_info(self, instance, nw_info):
|
||||
self.firewall_driver.setup_basic_filtering(instance, nw_info)
|
||||
|
|
Loading…
Reference in New Issue