components/openstack/nova/patches/10-launchpad-1356552.patch
branchs11u3-sru
changeset 5413 bca6b9853ab7
equal deleted inserted replaced
5412:8566c7ab4a73 5413:bca6b9853ab7
       
     1 commit 42cae28241cd0c213201d036bfbe13fb118e4bee
       
     2 Author: Cyril Roelandt <[email protected]>
       
     3 Date:   Mon Aug 18 17:45:35 2014 +0000
       
     4 
       
     5     libvirt: Make sure volumes are well detected during block migration
       
     6     
       
     7     Current implementation of live migration in libvirt incorrectly includes
       
     8     block devices on shared storage (e.g., NFS) when computing destination
       
     9     storage requirements. Since these volumes are already on shared storage
       
    10     they do not need to be migrated. As a result, migration fails if the
       
    11     amount of free space on the shared drive is less than the size of the
       
    12     volume to be migrated. The problem is addressed by adding a
       
    13     block_device_info parameter to check_can_live_migrate_source() to allow
       
    14     volumes to be filtered correctly when computing migration space
       
    15     requirements.
       
    16     
       
    17     This only fixes the issue on libvirt: it is unclear whether other
       
    18     implementations suffer from the same issue.
       
    19     
       
    20     Thanks to Florent Flament for spotting and fixing an issue while trying out
       
    21     this patch.
       
    22     
       
    23     Co-Authored-By: Florent Flament <[email protected]>
       
    24     Change-Id: Iac7d2cd2a70800fd89864463ca45c030c47411b0
       
    25     Closes-Bug: #1356552
       
    26     (cherry picked from commit 671aa9f8b7ca5274696f83bde0d4822ee431b837)
       
    27 
       
    28 --- nova-2014.2.2/nova/compute/manager.py.~3~	2015-12-01 05:07:52.781465660 -0800
       
    29 +++ nova-2014.2.2/nova/compute/manager.py	2015-12-01 05:07:52.795381628 -0800
       
    30 @@ -4891,8 +4891,11 @@ class ComputeManager(manager.Manager):
       
    31          is_volume_backed = self.compute_api.is_volume_backed_instance(ctxt,
       
    32                                                                        instance)
       
    33          dest_check_data['is_volume_backed'] = is_volume_backed
       
    34 +        block_device_info = self._get_instance_block_device_info(
       
    35 +                            ctxt, instance, refresh_conn_info=True)
       
    36          return self.driver.check_can_live_migrate_source(ctxt, instance,
       
    37 -                                                         dest_check_data)
       
    38 +                                                         dest_check_data,
       
    39 +                                                         block_device_info)
       
    40  
       
    41      @object_compat
       
    42      @wrap_exception()
       
    43 --- nova-2014.2.2/nova/tests/compute/test_compute_mgr.py.~2~	2015-12-01 05:07:52.782691092 -0800
       
    44 +++ nova-2014.2.2/nova/tests/compute/test_compute_mgr.py	2015-12-01 05:07:52.796520248 -0800
       
    45 @@ -1302,13 +1302,19 @@ class ComputeManagerUnitTestCase(test.No
       
    46  
       
    47          self.mox.StubOutWithMock(self.compute.compute_api,
       
    48                                   'is_volume_backed_instance')
       
    49 +        self.mox.StubOutWithMock(self.compute,
       
    50 +                                 '_get_instance_block_device_info')
       
    51          self.mox.StubOutWithMock(self.compute.driver,
       
    52                                   'check_can_live_migrate_source')
       
    53  
       
    54          self.compute.compute_api.is_volume_backed_instance(
       
    55                  self.context, instance).AndReturn(is_volume_backed)
       
    56 +        self.compute._get_instance_block_device_info(
       
    57 +                self.context, instance, refresh_conn_info=True
       
    58 +                ).AndReturn({'block_device_mapping': 'fake'})
       
    59          self.compute.driver.check_can_live_migrate_source(
       
    60 -                self.context, instance, expected_dest_check_data)
       
    61 +                self.context, instance, expected_dest_check_data,
       
    62 +                {'block_device_mapping': 'fake'})
       
    63  
       
    64          self.mox.ReplayAll()
       
    65  
       
    66 diff --git a/nova/tests/virt/libvirt/test_driver.py b/nova/tests/virt/libvirt/test_driver.py
       
    67 index 613943b..c686b88 100644
       
    68 --- a/nova/tests/virt/libvirt/test_driver.py
       
    69 +++ b/nova/tests/virt/libvirt/test_driver.py
       
    70 @@ -5323,7 +5323,7 @@ class LibvirtConnTestCase(test.TestCase):
       
    71          self.mox.StubOutWithMock(conn, "_assert_dest_node_has_enough_disk")
       
    72          conn._assert_dest_node_has_enough_disk(
       
    73              self.context, instance, dest_check_data['disk_available_mb'],
       
    74 -            False)
       
    75 +            False, None)
       
    76  
       
    77          self.mox.ReplayAll()
       
    78          ret = conn.check_can_live_migrate_source(self.context, instance,
       
    79 @@ -5386,8 +5386,9 @@ class LibvirtConnTestCase(test.TestCase):
       
    80                  disk_available_mb=0)
       
    81  
       
    82          self.mox.StubOutWithMock(conn, "get_instance_disk_info")
       
    83 -        conn.get_instance_disk_info(instance["name"]).AndReturn(
       
    84 -                                            '[{"virt_disk_size":2}]')
       
    85 +        conn.get_instance_disk_info(instance["name"],
       
    86 +                                    block_device_info=None).AndReturn(
       
    87 +                                        '[{"virt_disk_size":2}]')
       
    88  
       
    89          self.mox.ReplayAll()
       
    90          self.assertRaises(exception.MigrationError,
       
    91 diff --git a/nova/virt/driver.py b/nova/virt/driver.py
       
    92 index fd483e5..20f4dd1 100644
       
    93 --- a/nova/virt/driver.py
       
    94 +++ b/nova/virt/driver.py
       
    95 @@ -808,7 +808,7 @@ class ComputeDriver(object):
       
    96          raise NotImplementedError()
       
    97  
       
    98      def check_can_live_migrate_source(self, context, instance,
       
    99 -                                      dest_check_data):
       
   100 +                                      dest_check_data, block_device_info=None):
       
   101          """Check if it is possible to execute live migration.
       
   102  
       
   103          This checks if the live migration can succeed, based on the
       
   104 @@ -817,6 +817,7 @@ class ComputeDriver(object):
       
   105          :param context: security context
       
   106          :param instance: nova.db.sqlalchemy.models.Instance
       
   107          :param dest_check_data: result of check_can_live_migrate_destination
       
   108 +        :param block_device_info: result of _get_instance_block_device_info
       
   109          :returns: a dict containing migration info (hypervisor-dependent)
       
   110          """
       
   111          raise NotImplementedError()
       
   112 diff --git a/nova/virt/fake.py b/nova/virt/fake.py
       
   113 index 049c519..fe9ff1c 100644
       
   114 --- a/nova/virt/fake.py
       
   115 +++ b/nova/virt/fake.py
       
   116 @@ -426,7 +426,7 @@ class FakeDriver(driver.ComputeDriver):
       
   117          return {}
       
   118  
       
   119      def check_can_live_migrate_source(self, ctxt, instance_ref,
       
   120 -                                      dest_check_data):
       
   121 +                                      dest_check_data, block_device_info=None):
       
   122          return
       
   123  
       
   124      def finish_migration(self, context, migration, instance, disk_info,
       
   125 diff --git a/nova/virt/hyperv/driver.py b/nova/virt/hyperv/driver.py
       
   126 index 485aa23..fa42130 100644
       
   127 --- a/nova/virt/hyperv/driver.py
       
   128 +++ b/nova/virt/hyperv/driver.py
       
   129 @@ -169,7 +169,7 @@ class HyperVDriver(driver.ComputeDriver):
       
   130              context, dest_check_data)
       
   131  
       
   132      def check_can_live_migrate_source(self, context, instance,
       
   133 -                                      dest_check_data):
       
   134 +                                      dest_check_data, block_device_info=None):
       
   135          return self._livemigrationops.check_can_live_migrate_source(
       
   136              context, instance, dest_check_data)
       
   137  
       
   138 diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py
       
   139 index cec2013..d420f15 100644
       
   140 --- a/nova/virt/libvirt/driver.py
       
   141 +++ b/nova/virt/libvirt/driver.py
       
   142 @@ -5028,7 +5028,8 @@ class LibvirtDriver(driver.ComputeDriver):
       
   143          self._cleanup_shared_storage_test_file(filename)
       
   144  
       
   145      def check_can_live_migrate_source(self, context, instance,
       
   146 -                                      dest_check_data):
       
   147 +                                      dest_check_data,
       
   148 +                                      block_device_info=None):
       
   149          """Check if it is possible to execute live migration.
       
   150  
       
   151          This checks if the live migration can succeed, based on the
       
   152 @@ -5037,6 +5038,7 @@ class LibvirtDriver(driver.ComputeDriver):
       
   153          :param context: security context
       
   154          :param instance: nova.db.sqlalchemy.models.Instance
       
   155          :param dest_check_data: result of check_can_live_migrate_destination
       
   156 +        :param block_device_info: result of _get_instance_block_device_info
       
   157          :returns: a dict containing migration info
       
   158          """
       
   159          # Checking shared storage connectivity
       
   160 @@ -5058,7 +5060,8 @@ class LibvirtDriver(driver.ComputeDriver):
       
   161                  raise exception.InvalidLocalStorage(reason=reason, path=source)
       
   162              self._assert_dest_node_has_enough_disk(context, instance,
       
   163                                      dest_check_data['disk_available_mb'],
       
   164 -                                    dest_check_data['disk_over_commit'])
       
   165 +                                    dest_check_data['disk_over_commit'],
       
   166 +                                    block_device_info)
       
   167  
       
   168          elif not (dest_check_data['is_shared_block_storage'] or
       
   169                    dest_check_data['is_shared_instance_path']):
       
   170 @@ -5106,7 +5109,8 @@ class LibvirtDriver(driver.ComputeDriver):
       
   171          return False
       
   172  
       
   173      def _assert_dest_node_has_enough_disk(self, context, instance,
       
   174 -                                             available_mb, disk_over_commit):
       
   175 +                                             available_mb, disk_over_commit,
       
   176 +                                             block_device_info=None):
       
   177          """Checks if destination has enough disk for block migration."""
       
   178          # Libvirt supports qcow2 disk format,which is usually compressed
       
   179          # on compute nodes.
       
   180 @@ -5122,7 +5126,8 @@ class LibvirtDriver(driver.ComputeDriver):
       
   181          if available_mb:
       
   182              available = available_mb * units.Mi
       
   183  
       
   184 -        ret = self.get_instance_disk_info(instance['name'])
       
   185 +        ret = self.get_instance_disk_info(instance['name'],
       
   186 +                                          block_device_info=block_device_info)
       
   187          disk_infos = jsonutils.loads(ret)
       
   188  
       
   189          necessary = 0
       
   190 --- nova-2014.2.2/nova/virt/xenapi/driver.py.~2~	2015-12-01 05:16:19.562306358 -0800
       
   191 +++ nova-2014.2.2/nova/virt/xenapi/driver.py	2015-12-01 05:16:19.614403555 -0800
       
   192 @@ -501,7 +501,7 @@ class XenAPIDriver(driver.ComputeDriver)
       
   193          pass
       
   194  
       
   195      def check_can_live_migrate_source(self, context, instance,
       
   196 -                                      dest_check_data):
       
   197 +                                      dest_check_data, block_device_info=None):
       
   198          """Check if it is possible to execute live migration.
       
   199  
       
   200          This checks if the live migration can succeed, based on the
       
   201 @@ -511,6 +511,7 @@ class XenAPIDriver(driver.ComputeDriver)
       
   202          :param instance: nova.db.sqlalchemy.models.Instance
       
   203          :param dest_check_data: result of check_can_live_migrate_destination
       
   204                                  includes the block_migration flag
       
   205 +        :param block_device_info: result of _get_instance_block_device_info
       
   206          """
       
   207          return self._vmops.check_can_live_migrate_source(context, instance,
       
   208                                                           dest_check_data)