]> xenbits.xensource.com Git - osstest/openstack-nova.git/commitdiff
libvirt: sync time on resumed from suspend instances
authorVladik Romanovsky <vromanso@redhat.com>
Wed, 19 Oct 2016 16:21:40 +0000 (12:21 -0400)
committerVladik Romanovsky <vromanso@redhat.com>
Fri, 28 Oct 2016 14:01:25 +0000 (10:01 -0400)
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

nova/tests/unit/virt/libvirt/test_driver.py
nova/tests/unit/virt/libvirt/test_guest.py
nova/virt/libvirt/driver.py
nova/virt/libvirt/guest.py

index 653ee7fbe756d0e15c7da642f5b5d5eb80f41a70..026f05fe918cf617212ceda3c2a2d19bb563002d 100644 (file)
@@ -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)
index 0be386a6a873248f1f531d6e953d5c6cc53bccd2..bc62024c3db4b5eec03472b187ecd792106789be 100644 (file)
@@ -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})
index 10bc929a52d6c8d67af6fe431105a7125790b0e0..16444905c2e16920ace42709d7d45dfb172f8745 100644 (file)
@@ -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):
index 22cdfb54dd8a917138c5fcfd8a834763aeb0721c..573d8d033a467d206f0434fa4ed1226e42be5bbf 100644 (file)
@@ -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."""