Merge "libvirt: Re-initialise volumes, encryptors, and vifs on hard reboot" into stable/ocata

This commit is contained in:
Zuul 2018-02-05 17:44:27 +00:00 committed by Gerrit Code Review
commit 475f352327
4 changed files with 24 additions and 21 deletions

View File

@ -11614,15 +11614,14 @@ class LibvirtConnTestCase(test.NoDBTestCase):
mock_hard_reboot.assert_called_once_with(self.context,
instance, [], None)
@mock.patch('nova.virt.libvirt.LibvirtDriver._undefine_domain')
@mock.patch('nova.virt.libvirt.LibvirtDriver.get_info')
@mock.patch('nova.virt.libvirt.LibvirtDriver._create_domain_and_network')
@mock.patch('nova.virt.libvirt.LibvirtDriver._get_guest_xml')
@mock.patch('nova.virt.libvirt.LibvirtDriver._get_instance_disk_info')
@mock.patch('nova.virt.libvirt.LibvirtDriver._destroy')
@mock.patch('nova.virt.libvirt.LibvirtDriver.destroy')
def test_hard_reboot(self, mock_destroy, mock_get_disk_info,
mock_get_guest_xml, mock_create_domain_and_network,
mock_get_info, mock_undefine):
mock_get_info):
self.context.auth_token = True # any non-None value will suffice
instance = objects.Instance(**self.test_instance)
network_info = _fake_network_info(self, 1)
@ -11670,8 +11669,9 @@ class LibvirtConnTestCase(test.NoDBTestCase):
for name in ('disk', 'disk.local'):
self.assertTrue(disks[name].cache.called)
mock_destroy.assert_called_once_with(instance)
mock_undefine.assert_called_once_with(instance)
mock_destroy.assert_called_once_with(self.context, instance,
network_info, destroy_disks=False,
block_device_info=block_device_info)
# Check the structure of disk_info passed to
# _create_domain_and_network, but we don't care about any of the values
@ -11686,8 +11686,7 @@ class LibvirtConnTestCase(test.NoDBTestCase):
}
mock_create_domain_and_network.assert_called_once_with(self.context,
dummyxml, instance, network_info, mock_disk_info,
block_device_info=block_device_info,
reboot=True, vifs_already_plugged=True)
block_device_info=block_device_info)
@mock.patch('oslo_utils.fileutils.ensure_tree')
@mock.patch('oslo_service.loopingcall.FixedIntervalLoopingCall')

View File

@ -163,7 +163,7 @@ class LuksEncryptorTestCase(test_cryptsetup.CryptsetupEncryptorTestCase):
mock_execute.assert_has_calls([
mock.call('cryptsetup', 'luksClose', self.dev_name,
attempts=3, run_as_root=True, check_exit_code=True),
attempts=3, run_as_root=True, check_exit_code=[0, 4]),
])
self.assertEqual(1, mock_execute.call_count)
@ -173,7 +173,7 @@ class LuksEncryptorTestCase(test_cryptsetup.CryptsetupEncryptorTestCase):
mock_execute.assert_has_calls([
mock.call('cryptsetup', 'luksClose', self.dev_name,
attempts=3, run_as_root=True, check_exit_code=True),
attempts=3, run_as_root=True, check_exit_code=[0, 4]),
])
self.assertEqual(1, mock_execute.call_count)
@ -217,7 +217,7 @@ class LuksEncryptorTestCase(test_cryptsetup.CryptsetupEncryptorTestCase):
self.dev_name, process_input=fake_key_mangled,
run_as_root=True, check_exit_code=True),
mock.call('cryptsetup', 'luksClose', self.dev_name,
run_as_root=True, check_exit_code=True, attempts=3),
run_as_root=True, check_exit_code=[0, 4], attempts=3),
mock.call('cryptsetup', 'luksAddKey', self.dev_path,
process_input=''.join([fake_key_mangled,
'\n', fake_key,
@ -227,7 +227,7 @@ class LuksEncryptorTestCase(test_cryptsetup.CryptsetupEncryptorTestCase):
self.dev_name, process_input=fake_key,
run_as_root=True, check_exit_code=True),
mock.call('cryptsetup', 'luksClose', self.dev_name,
run_as_root=True, check_exit_code=True, attempts=3),
run_as_root=True, check_exit_code=[0, 4], attempts=3),
mock.call('cryptsetup', 'luksRemoveKey', self.dev_path,
process_input=fake_key_mangled, run_as_root=True,
check_exit_code=True),

View File

@ -2433,12 +2433,15 @@ class LibvirtDriver(driver.ComputeDriver):
re-creates the domain to ensure the reboot happens, as the guest
OS cannot ignore this action.
"""
self._destroy(instance)
# Domain XML will be redefined so we can safely undefine it
# from libvirt. This ensure that such process as create serial
# console for guest will run smoothly.
self._undefine_domain(instance)
# NOTE(mdbooth): In addition to performing a hard reboot of the domain,
# the hard reboot operation is relied upon by operators to be an
# automated attempt to fix as many things as possible about a
# non-functioning instance before resorting to manual intervention.
# With this goal in mind, we tear down all the aspects of an instance
# we can here without losing data. This allows us to re-initialise from
# scratch, and hopefully fix, most aspects of a non-functioning guest.
self.destroy(context, instance, network_info, destroy_disks=False,
block_device_info=block_device_info)
# Convert the system metadata to image metadata
# NOTE(mdbooth): This is a workaround for stateless Nova compute
@ -2474,9 +2477,7 @@ class LibvirtDriver(driver.ComputeDriver):
# start the instance.
self._create_domain_and_network(context, xml, instance, network_info,
disk_info,
block_device_info=block_device_info,
reboot=True,
vifs_already_plugged=True)
block_device_info=block_device_info)
self._prepare_pci_devices_for_use(
pci_manager.get_instance_pci_devs(instance, 'all'))

View File

@ -163,6 +163,9 @@ class LuksEncryptor(cryptsetup.CryptsetupEncryptor):
def _close_volume(self, **kwargs):
"""Closes the device (effectively removes the dm-crypt mapping)."""
LOG.debug("closing encrypted volume %s", self.dev_path)
# cryptsetup returns 4 when attempting to destroy a non-active
# luks device. We are going to ignore this error code to avoid raising
# an exception while detaching an already detached volume.
utils.execute('cryptsetup', 'luksClose', self.dev_name,
run_as_root=True, check_exit_code=True,
run_as_root=True, check_exit_code=[0, 4],
attempts=3)