File 0001-Make-sure-volumes-are-well-detected.patch of Package openstack-nova-doc

From 19f93a75778bc91b7b1ce1a9a37ab86025c4021b Mon Sep 17 00:00:00 2001
From: Michal Jura <mjura@suse.com>
Date: Wed, 18 Feb 2015 11:45:03 +0100
Subject: [PATCH] libvirt: Make sure volumes are well detected during block
 migration

Current implementation of live migration in libvirt incorrectly includes
block devices on shared storage (e.g., NFS) when computing destination
storage requirements. Since these volumes are already on shared storage
they do not need to be migrated. As a result, migration fails if the
amount of free space on the shared drive is less than the size of the
volume to be migrated. The problem is addressed by adding a
block_device_info parameter to check_can_live_migrate_source() to allow
volumes to be filtered correctly when computing migration space
requirements.

This only fixes the issue on libvirt: it is unclear whether other
implementations suffer from the same issue.

Thanks to Florent Flament for spotting and fixing an issue while trying out
this patch.

Co-Authored-By: Florent Flament <florent.flament@cloudwatt.com>
Change-Id: Iac7d2cd2a70800fd89864463ca45c030c47411b0
Closes-Bug: #1356552
(cherry picked from commit 671aa9f8b7ca5274696f83bde0d4822ee431b837)
---
 nova/compute/manager.py                 |  5 ++++-
 nova/tests/compute/test_compute_mgr.py  |  8 +++++++-
 nova/tests/virt/libvirt/test_libvirt.py |  7 ++++---
 nova/virt/driver.py                     |  3 ++-
 nova/virt/fake.py                       |  2 +-
 nova/virt/hyperv/driver.py              |  2 +-
 nova/virt/libvirt/driver.py             | 13 +++++++++----
 nova/virt/xenapi/driver.py              |  3 ++-
 8 files changed, 30 insertions(+), 13 deletions(-)

Index: nova-2014.1.5.dev3/nova/compute/manager.py
===================================================================
--- nova-2014.1.5.dev3.orig/nova/compute/manager.py
+++ nova-2014.1.5.dev3/nova/compute/manager.py
@@ -4522,8 +4522,11 @@ class ComputeManager(manager.Manager):
         is_volume_backed = self.compute_api.is_volume_backed_instance(ctxt,
                                                                       instance)
         dest_check_data['is_volume_backed'] = is_volume_backed
+        block_device_info = self._get_instance_block_device_info(
+                            ctxt, instance, refresh_conn_info=True)
         return self.driver.check_can_live_migrate_source(ctxt, instance,
-                                                         dest_check_data)
+                                                         dest_check_data,
+                                                         block_device_info)
 
     @object_compat
     @wrap_exception()
Index: nova-2014.1.5.dev3/nova/tests/compute/test_compute_mgr.py
===================================================================
--- nova-2014.1.5.dev3.orig/nova/tests/compute/test_compute_mgr.py
+++ nova-2014.1.5.dev3/nova/tests/compute/test_compute_mgr.py
@@ -955,14 +955,20 @@ class ComputeManagerUnitTestCase(test.No
 
         self.mox.StubOutWithMock(self.compute.compute_api,
                                  'is_volume_backed_instance')
+        self.mox.StubOutWithMock(self.compute,
+                                 '_get_instance_block_device_info')
         self.mox.StubOutWithMock(self.compute.driver,
                                  'check_can_live_migrate_source')
 
         instance_p = obj_base.obj_to_primitive(instance)
         self.compute.compute_api.is_volume_backed_instance(
                 self.context, instance).AndReturn(is_volume_backed)
+        self.compute._get_instance_block_device_info(
+                self.context, instance, refresh_conn_info=True
+                ).AndReturn({'block_device_mapping': 'fake'})
         self.compute.driver.check_can_live_migrate_source(
-                self.context, instance, expected_dest_check_data)
+                self.context, instance, expected_dest_check_data,
+                {'block_device_mapping': 'fake'})
 
         self.mox.ReplayAll()
 
Index: nova-2014.1.5.dev3/nova/tests/virt/libvirt/test_libvirt.py
===================================================================
--- nova-2014.1.5.dev3.orig/nova/tests/virt/libvirt/test_libvirt.py
+++ nova-2014.1.5.dev3/nova/tests/virt/libvirt/test_libvirt.py
@@ -4007,7 +4007,7 @@ class LibvirtConnTestCase(test.TestCase)
         self.mox.StubOutWithMock(conn, "_assert_dest_node_has_enough_disk")
         conn._assert_dest_node_has_enough_disk(
             self.context, instance_ref, dest_check_data['disk_available_mb'],
-            False)
+            False, None)
 
         self.mox.ReplayAll()
         conn.check_can_live_migrate_source(self.context, instance_ref,
@@ -4113,8 +4113,9 @@ class LibvirtConnTestCase(test.TestCase)
         self.mox.StubOutWithMock(conn, "get_instance_disk_info")
         conn.get_instance_disk_info(instance_ref["name"]).AndReturn(
                                             '[{"virt_disk_size":2}]')
-        conn.get_instance_disk_info(instance_ref["name"]).AndReturn(
-                                            '[{"virt_disk_size":2}]')
+        conn.get_instance_disk_info(instance_ref["name"],
+                                    block_device_info=None).AndReturn(
+                                             '[{"virt_disk_size":2}]')
 
         dest_check_data = {"filename": "file",
                            "disk_available_mb": 0,
Index: nova-2014.1.5.dev3/nova/virt/driver.py
===================================================================
--- nova-2014.1.5.dev3.orig/nova/virt/driver.py
+++ nova-2014.1.5.dev3/nova/virt/driver.py
@@ -749,7 +749,7 @@ class ComputeDriver(object):
         raise NotImplementedError()
 
     def check_can_live_migrate_source(self, ctxt, instance_ref,
-                                      dest_check_data):
+                                      dest_check_data, block_device_info=None):
         """Check if it is possible to execute live migration.
 
         This checks if the live migration can succeed, based on the
@@ -758,6 +758,7 @@ class ComputeDriver(object):
         :param context: security context
         :param instance_ref: nova.db.sqlalchemy.models.Instance
         :param dest_check_data: result of check_can_live_migrate_destination
+        :param block_device_info: result of _get_instance_block_device_info
         :returns: a dict containing migration info (hypervisor-dependent)
         """
         raise NotImplementedError()
Index: nova-2014.1.5.dev3/nova/virt/fake.py
===================================================================
--- nova-2014.1.5.dev3.orig/nova/virt/fake.py
+++ nova-2014.1.5.dev3/nova/virt/fake.py
@@ -395,7 +395,7 @@ class FakeDriver(driver.ComputeDriver):
         return {}
 
     def check_can_live_migrate_source(self, ctxt, instance_ref,
-                                      dest_check_data):
+                                      dest_check_data, block_device_info=None):
         return
 
     def finish_migration(self, context, migration, instance, disk_info,
Index: nova-2014.1.5.dev3/nova/virt/hyperv/driver.py
===================================================================
--- nova-2014.1.5.dev3.orig/nova/virt/hyperv/driver.py
+++ nova-2014.1.5.dev3/nova/virt/hyperv/driver.py
@@ -165,7 +165,7 @@ class HyperVDriver(driver.ComputeDriver)
             ctxt, dest_check_data)
 
     def check_can_live_migrate_source(self, ctxt, instance_ref,
-                                      dest_check_data):
+                                      dest_check_data, block_device_info=None):
         return self._livemigrationops.check_can_live_migrate_source(
             ctxt, instance_ref, dest_check_data)
 
Index: nova-2014.1.5.dev3/nova/virt/libvirt/driver.py
===================================================================
--- nova-2014.1.5.dev3.orig/nova/virt/libvirt/driver.py
+++ nova-2014.1.5.dev3/nova/virt/libvirt/driver.py
@@ -4323,7 +4323,8 @@ class LibvirtDriver(driver.ComputeDriver
         self._cleanup_shared_storage_test_file(filename)
 
     def check_can_live_migrate_source(self, context, instance,
-                                      dest_check_data):
+                                      dest_check_data,
+                                      block_device_info=None):
         """Check if it is possible to execute live migration.
 
         This checks if the live migration can succeed, based on the
@@ -4332,6 +4333,7 @@ class LibvirtDriver(driver.ComputeDriver
         :param context: security context
         :param instance: nova.db.sqlalchemy.models.Instance
         :param dest_check_data: result of check_can_live_migrate_destination
+        :param block_device_info: result of _get_instance_block_device_info
         :returns: a dict containing migration info
         """
         # Checking shared storage connectivity
@@ -4352,7 +4354,8 @@ class LibvirtDriver(driver.ComputeDriver
                 raise exception.InvalidLocalStorage(reason=reason, path=source)
             self._assert_dest_node_has_enough_disk(context, instance,
                                     dest_check_data['disk_available_mb'],
-                                    dest_check_data['disk_over_commit'])
+                                    dest_check_data['disk_over_commit'],
+                                    block_device_info)
 
         elif not shared and (not is_volume_backed or has_local_disks):
             reason = _("Live migration can not be used "
@@ -4370,7 +4373,8 @@ class LibvirtDriver(driver.ComputeDriver
         return dest_check_data
 
     def _assert_dest_node_has_enough_disk(self, context, instance,
-                                             available_mb, disk_over_commit):
+                                             available_mb, disk_over_commit,
+                                             block_device_info=None):
         """Checks if destination has enough disk for block migration."""
         # Libvirt supports qcow2 disk format,which is usually compressed
         # on compute nodes.
@@ -4386,7 +4390,8 @@ class LibvirtDriver(driver.ComputeDriver
         if available_mb:
             available = available_mb * units.Mi
 
-        ret = self.get_instance_disk_info(instance['name'])
+        ret = self.get_instance_disk_info(instance['name'],
+                                          block_device_info=block_device_info)
         disk_infos = jsonutils.loads(ret)
 
         necessary = 0
Index: nova-2014.1.5.dev3/nova/virt/xenapi/driver.py
===================================================================
--- nova-2014.1.5.dev3.orig/nova/virt/xenapi/driver.py
+++ nova-2014.1.5.dev3/nova/virt/xenapi/driver.py
@@ -514,7 +514,7 @@ class XenAPIDriver(driver.ComputeDriver)
         pass
 
     def check_can_live_migrate_source(self, ctxt, instance_ref,
-                                      dest_check_data):
+                                      dest_check_data, block_device_info=None):
         """Check if it is possible to execute live migration.
 
         This checks if the live migration can succeed, based on the
@@ -524,6 +524,7 @@ class XenAPIDriver(driver.ComputeDriver)
         :param instance_ref: nova.db.sqlalchemy.models.Instance
         :param dest_check_data: result of check_can_live_migrate_destination
                                 includes the block_migration flag
+        :param block_device_info: result of _get_instance_block_device_info
         """
         return self._vmops.check_can_live_migrate_source(ctxt, instance_ref,
                                                          dest_check_data)
openSUSE Build Service is sponsored by