diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index 86dd43fb59c..5e53598231c 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -6870,20 +6870,14 @@ def test_live_migration_copy_disk_paths(self, mock_xml): "_live_migration_copy_disk_paths") def test_live_migration_data_gb_plain(self, mock_paths): drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) - dom = fakelibvirt.Domain(drvr._get_connection(), "", False) - guest = libvirt_guest.Guest(dom) instance = objects.Instance(**self.test_instance) - data_gb = drvr._live_migration_data_gb(instance, guest, False) + data_gb = drvr._live_migration_data_gb(instance, []) self.assertEqual(2, data_gb) self.assertEqual(0, mock_paths.call_count) - @mock.patch.object(libvirt_driver.LibvirtDriver, - "_live_migration_copy_disk_paths") - def test_live_migration_data_gb_block(self, mock_paths): + def test_live_migration_data_gb_block(self): drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) - dom = fakelibvirt.Domain(drvr._get_connection(), "", False) - guest = libvirt_guest.Guest(dom) instance = objects.Instance(**self.test_instance) def fake_stat(path): @@ -6902,15 +6896,14 @@ def st_size(self): else: raise Exception("Should not be reached") - mock_paths.return_value = ["/var/lib/nova/instance/123/disk.root", - "/dev/mapper/somevol"] + disk_paths = ["/var/lib/nova/instance/123/disk.root", + "/dev/mapper/somevol"] with mock.patch.object(os, "stat") as mock_stat: mock_stat.side_effect = fake_stat - data_gb = drvr._live_migration_data_gb(instance, guest, True) + data_gb = drvr._live_migration_data_gb(instance, disk_paths) # Expecting 2 GB for RAM, plus 10 GB for disk.root # and 1.5 GB rounded to 2 GB for somevol, so 14 GB self.assertEqual(14, data_gb) - self.assertEqual(1, mock_paths.call_count) EXPECT_SUCCESS = 1 EXPECT_FAILURE = 2 @@ -6978,7 +6971,8 @@ def fake_time(): False, migrate_data, dom, - finish_event) + finish_event, + []) if expect_result == self.EXPECT_SUCCESS: self.assertFalse(fake_recover_method.called, @@ -7239,14 +7233,18 @@ def test_live_migration_downtime_steps(self): @mock.patch.object(libvirt_driver.LibvirtDriver, "_live_migration_monitor") @mock.patch.object(host.Host, "get_guest") @mock.patch.object(fakelibvirt.Connection, "_mark_running") - def test_live_migration_main(self, mock_running, mock_guest, - mock_monitor, mock_thread): + @mock.patch.object(libvirt_driver.LibvirtDriver, + "_live_migration_copy_disk_paths") + def test_live_migration_main(self, mock_copy_disk_path, mock_running, + mock_guest, mock_monitor, mock_thread): drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) instance = objects.Instance(**self.test_instance) dom = fakelibvirt.Domain(drvr._get_connection(), "demo", True) guest = libvirt_guest.Guest(dom) migrate_data = {} + disk_paths = ['/dev/vda', '/dev/vdb'] + mock_copy_disk_path.return_value = disk_paths mock_guest.return_value = guest @@ -7257,7 +7255,7 @@ def fake_recover(): pass drvr._live_migration(self.context, instance, "fakehost", - fake_post, fake_recover, False, + fake_post, fake_recover, True, migrate_data) class AnyEventletEvent(object): @@ -7266,12 +7264,12 @@ def __eq__(self, other): mock_thread.assert_called_once_with( drvr._live_migration_operation, - self.context, instance, "fakehost", False, + self.context, instance, "fakehost", True, migrate_data, dom) mock_monitor.assert_called_once_with( self.context, instance, guest, "fakehost", - fake_post, fake_recover, False, - migrate_data, dom, AnyEventletEvent()) + fake_post, fake_recover, True, + migrate_data, dom, AnyEventletEvent(), disk_paths) def _do_test_create_images_and_backing(self, disk_type): drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 797c4846c9e..4a782e59195 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -5828,12 +5828,12 @@ def _live_migration_copy_disk_paths(self, guest): disks.append(dev.source_path) return disks - def _live_migration_data_gb(self, instance, guest, block_migration): + def _live_migration_data_gb(self, instance, disk_paths): '''Calculate total amount of data to be transferred :param instance: the nova.objects.Instance being migrated - :param guest: the Guest being migrated - :param block_migration: true if block migration is requested + :param disk_paths: list of disk paths that are being migrated + with instance Calculates the total amount of data that needs to be transferred during the live migration. The actual @@ -5849,12 +5849,8 @@ def _live_migration_data_gb(self, instance, guest, block_migration): if ram_gb < 2: ram_gb = 2 - if not block_migration: - return ram_gb - - paths = self._live_migration_copy_disk_paths(guest) disk_gb = 0 - for path in paths: + for path in disk_paths: try: size = os.stat(path).st_size size_gb = (size / units.Gi) @@ -5872,9 +5868,9 @@ def _live_migration_data_gb(self, instance, guest, block_migration): def _live_migration_monitor(self, context, instance, guest, dest, post_method, recover_method, block_migration, - migrate_data, dom, finish_event): - data_gb = self._live_migration_data_gb(instance, guest, - block_migration) + migrate_data, dom, finish_event, + disk_paths): + data_gb = self._live_migration_data_gb(instance, disk_paths) downtime_steps = list(self._migration_downtime_steps(data_gb)) completion_timeout = int( CONF.libvirt.live_migration_completion_timeout * data_gb) @@ -6087,6 +6083,11 @@ def _live_migration(self, context, instance, dest, post_method, guest = self._host.get_guest(instance) + disk_paths = [] + if block_migration: + disk_paths = self._live_migration_copy_disk_paths( + context, instance, guest) + # TODO(sahid): We are converting all calls from a # virDomain object to use nova.virt.libvirt.Guest. # We should be able to remove dom at the end. @@ -6114,7 +6115,7 @@ def thread_finished(thread, event): self._live_migration_monitor(context, instance, guest, dest, post_method, recover_method, block_migration, migrate_data, - dom, finish_event) + dom, finish_event, disk_paths) except Exception as ex: LOG.warn(_LW("Error monitoring migration: %(ex)s"), {"ex": ex}, instance=instance, exc_info=True)