libvirt: sync time on resumed from suspend instances
Time is not being synchronized for migrated or resumed from suspend instances as guest.resume() method is not being called on these operations. Calling sync_guest_time directly in the resume method as well as in finish_migration. Resolves-Bug: #1636565 Change-Id: Ie140bc0912e6b312d3fcbee7e9650a81076eda4d
This commit is contained in:
parent
f23646d2cb
commit
cd1af7abdd
|
@ -11617,9 +11617,12 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
return_value='fake_pci_devs'),
|
||||
mock.patch.object(utils, 'get_image_from_system_metadata'),
|
||||
mock.patch.object(blockinfo, 'get_disk_info'),
|
||||
mock.patch.object(guest, 'sync_guest_time'),
|
||||
mock.patch.object(drvr, '_wait_for_running',
|
||||
side_effect=loopingcall.LoopingCallDone()),
|
||||
) as (_get_existing_domain_xml, _create_domain_and_network,
|
||||
_attach_pci_devices, get_instance_pci_devs, get_image_metadata,
|
||||
get_disk_info):
|
||||
get_disk_info, mock_sync_time, mock_wait):
|
||||
get_image_metadata.return_value = {'bar': 234}
|
||||
|
||||
disk_info = {'foo': 123}
|
||||
|
@ -11634,6 +11637,7 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
instance, network_info, disk_info,
|
||||
block_device_info=block_device_info,
|
||||
vifs_already_plugged=True)])
|
||||
self.assertTrue(mock_sync_time.called)
|
||||
_attach_pci_devices.assert_has_calls([mock.call(guest,
|
||||
'fake_pci_devs')])
|
||||
|
||||
|
@ -15603,6 +15607,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
|
|||
self.fake_create_domain_called = True
|
||||
self.assertEqual(powered_on, power_on)
|
||||
self.assertTrue(vifs_already_plugged)
|
||||
return libvirt_guest.Guest('fake_dom')
|
||||
|
||||
def fake_enable_hairpin():
|
||||
pass
|
||||
|
@ -15678,10 +15683,16 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
|
|||
resize_instance, self.fake_disk_resize_called)
|
||||
|
||||
def test_finish_migration_resize(self):
|
||||
self._test_finish_migration(True, resize_instance=True)
|
||||
with mock.patch('nova.virt.libvirt.guest.Guest.sync_guest_time'
|
||||
) as mock_guest_time:
|
||||
self._test_finish_migration(True, resize_instance=True)
|
||||
self.assertTrue(mock_guest_time.called)
|
||||
|
||||
def test_finish_migration_power_on(self):
|
||||
self._test_finish_migration(True)
|
||||
with mock.patch('nova.virt.libvirt.guest.Guest.sync_guest_time'
|
||||
) as mock_guest_time:
|
||||
self._test_finish_migration(True)
|
||||
self.assertTrue(mock_guest_time.called)
|
||||
|
||||
def test_finish_migration_power_off(self):
|
||||
self._test_finish_migration(False)
|
||||
|
|
|
@ -139,7 +139,7 @@ class GuestTestCase(test.NoDBTestCase):
|
|||
@mock.patch('time.time', return_value=1234567890.125)
|
||||
def test_time_sync_no_errors(self, time_mock):
|
||||
self.domain.setTime.side_effect = fakelibvirt.libvirtError('error')
|
||||
self.guest.resume()
|
||||
self.guest.sync_guest_time()
|
||||
self.domain.setTime.assert_called_once_with(time={
|
||||
'nseconds': 125000000,
|
||||
'seconds': 1234567890})
|
||||
|
|
|
@ -2345,7 +2345,9 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
|
||||
def unpause(self, instance):
|
||||
"""Unpause paused VM instance."""
|
||||
self._host.get_guest(instance).resume()
|
||||
guest = self._host.get_guest(instance)
|
||||
guest.resume()
|
||||
guest.sync_guest_time()
|
||||
|
||||
def _clean_shutdown(self, instance, timeout, retry_interval):
|
||||
"""Attempt to shutdown the instance gracefully.
|
||||
|
@ -2478,6 +2480,10 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
self._attach_pci_devices(guest,
|
||||
pci_manager.get_instance_pci_devs(instance))
|
||||
self._attach_sriov_ports(context, instance, guest, network_info)
|
||||
timer = loopingcall.FixedIntervalLoopingCall(self._wait_for_running,
|
||||
instance)
|
||||
timer.start(interval=0.5).wait()
|
||||
guest.sync_guest_time()
|
||||
|
||||
def resume_state_on_host_boot(self, context, instance, network_info,
|
||||
block_device_info=None):
|
||||
|
@ -7264,7 +7270,8 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
# and the status change in the port might go undetected by the neutron
|
||||
# L2 agent (or neutron server) so neutron may not know that the VIF was
|
||||
# unplugged in the first place and never send an event.
|
||||
self._create_domain_and_network(context, xml, instance, network_info,
|
||||
guest = self._create_domain_and_network(context, xml, instance,
|
||||
network_info,
|
||||
block_disk_info,
|
||||
block_device_info=block_device_info,
|
||||
power_on=power_on,
|
||||
|
@ -7276,6 +7283,9 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
instance)
|
||||
timer.start(interval=0.5).wait()
|
||||
|
||||
# Sync guest time after migration.
|
||||
guest.sync_guest_time()
|
||||
|
||||
LOG.debug("finish_migration finished successfully.", instance=instance)
|
||||
|
||||
def _cleanup_failed_migration(self, inst_base):
|
||||
|
|
|
@ -145,7 +145,7 @@ class Guest(object):
|
|||
"""Stops a running guest."""
|
||||
self._domain.destroy()
|
||||
|
||||
def _sync_guest_time(self):
|
||||
def sync_guest_time(self):
|
||||
"""Try to set VM time to the current value. This is typically useful
|
||||
when clock wasn't running on the VM for some time (e.g. during
|
||||
suspension or migration), especially if the time delay exceeds NTP
|
||||
|
@ -190,9 +190,8 @@ class Guest(object):
|
|||
self._domain.injectNMI()
|
||||
|
||||
def resume(self):
|
||||
"""Resumes a suspended guest."""
|
||||
"""Resumes a paused guest."""
|
||||
self._domain.resume()
|
||||
self._sync_guest_time()
|
||||
|
||||
def enable_hairpin(self):
|
||||
"""Enables hairpin mode for this guest."""
|
||||
|
|
Loading…
Reference in New Issue