]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
LVM Thin Provisioning auto-detect
authorEric Harney <eharney@redhat.com>
Mon, 16 Jun 2014 19:43:51 +0000 (15:43 -0400)
committerEric Harney <eharney@redhat.com>
Wed, 12 Aug 2015 14:45:08 +0000 (10:45 -0400)
Add the ability to set lvm_type=auto, which will
enable thin provisioning if the system supports it,
and the configured volume group either:
a) has a pool LV with the expected name or
b) has no LVs

This, along with thin-provisioning accounting, will
give a path to move toward thin LVM as the default.

DocImpact: new value 'auto' for option 'lvm_type'

Partial-Bug: #1472803

Change-Id: Idfc1cd749bfd7aec659ab8e80629cc506cd9797a

cinder/tests/unit/test_volume.py
cinder/volume/drivers/lvm.py

index 824a55775050f154c408bdb6a8001b8e9be40c28..693d964ce7d3db002f9651ad0934935b93e1d39e 100644 (file)
@@ -6343,6 +6343,85 @@ class LVMVolumeDriverTestCase(DriverTestCase):
                                          execute=lvm_driver._execute,
                                          sparse=True)
 
+    @mock.patch.object(cinder.volume.utils, 'get_all_volume_groups',
+                       return_value=[{'name': 'cinder-volumes'}])
+    @mock.patch('cinder.brick.local_dev.lvm.LVM.update_volume_group_info')
+    @mock.patch('cinder.brick.local_dev.lvm.LVM.get_all_physical_volumes')
+    @mock.patch('cinder.brick.local_dev.lvm.LVM.supports_thin_provisioning',
+                return_value=True)
+    def test_lvm_type_auto_thin_pool_exists(self, *_unused_mocks):
+        configuration = conf.Configuration(fake_opt, 'fake_group')
+        configuration.lvm_type = 'auto'
+
+        vg_obj = fake_lvm.FakeBrickLVM('cinder-volumes',
+                                       False,
+                                       None,
+                                       'default')
+
+        lvm_driver = lvm.LVMVolumeDriver(configuration=configuration,
+                                         vg_obj=vg_obj)
+
+        lvm_driver.check_for_setup_error()
+
+        self.assertEqual('thin', lvm_driver.configuration.lvm_type)
+
+    @mock.patch.object(cinder.volume.utils, 'get_all_volume_groups',
+                       return_value=[{'name': 'cinder-volumes'}])
+    @mock.patch.object(cinder.brick.local_dev.lvm.LVM, 'get_volumes',
+                       return_value=[])
+    @mock.patch('cinder.brick.local_dev.lvm.LVM.update_volume_group_info')
+    @mock.patch('cinder.brick.local_dev.lvm.LVM.get_all_physical_volumes')
+    @mock.patch('cinder.brick.local_dev.lvm.LVM.supports_thin_provisioning',
+                return_value=True)
+    def test_lvm_type_auto_no_lvs(self, *_unused_mocks):
+        configuration = conf.Configuration(fake_opt, 'fake_group')
+        configuration.lvm_type = 'auto'
+
+        vg_obj = fake_lvm.FakeBrickLVM('cinder-volumes',
+                                       False,
+                                       None,
+                                       'default')
+
+        lvm_driver = lvm.LVMVolumeDriver(configuration=configuration,
+                                         vg_obj=vg_obj)
+
+        lvm_driver.check_for_setup_error()
+
+        self.assertEqual('thin', lvm_driver.configuration.lvm_type)
+
+    @mock.patch.object(cinder.volume.utils, 'get_all_volume_groups',
+                       return_value=[{'name': 'cinder-volumes'}])
+    @mock.patch('cinder.brick.local_dev.lvm.LVM.update_volume_group_info')
+    @mock.patch('cinder.brick.local_dev.lvm.LVM.get_all_physical_volumes')
+    @mock.patch('cinder.brick.local_dev.lvm.LVM.supports_thin_provisioning',
+                return_value=False)
+    def test_lvm_type_auto_no_thin_support(self, *_unused_mocks):
+        configuration = conf.Configuration(fake_opt, 'fake_group')
+        configuration.lvm_type = 'auto'
+
+        lvm_driver = lvm.LVMVolumeDriver(configuration=configuration)
+
+        lvm_driver.check_for_setup_error()
+
+        self.assertEqual('default', lvm_driver.configuration.lvm_type)
+
+    @mock.patch.object(cinder.volume.utils, 'get_all_volume_groups',
+                       return_value=[{'name': 'cinder-volumes'}])
+    @mock.patch('cinder.brick.local_dev.lvm.LVM.update_volume_group_info')
+    @mock.patch('cinder.brick.local_dev.lvm.LVM.get_all_physical_volumes')
+    @mock.patch('cinder.brick.local_dev.lvm.LVM.get_volume')
+    @mock.patch('cinder.brick.local_dev.lvm.LVM.supports_thin_provisioning',
+                return_value=False)
+    def test_lvm_type_auto_no_thin_pool(self, *_unused_mocks):
+        configuration = conf.Configuration(fake_opt, 'fake_group')
+        configuration.lvm_type = 'auto'
+
+        lvm_driver = lvm.LVMVolumeDriver(configuration=configuration)
+
+        lvm_driver.check_for_setup_error()
+
+        self.assertEqual('default', lvm_driver.configuration.lvm_type)
+
 
 class ISCSITestCase(DriverTestCase):
     """Test Case for ISCSIDriver"""
index a78038dfbae94fe931267ba3b7e3e927dcfd324e..e45f30bb6aad61436f4255506aa894c2a098a8d5 100644 (file)
@@ -51,8 +51,9 @@ volume_opts = [
                     'this requires lvm_mirrors + 2 PVs with available space'),
     cfg.StrOpt('lvm_type',
                default='default',
-               choices=['default', 'thin'],
-               help='Type of LVM volumes to deploy'),
+               choices=['default', 'thin', 'auto'],
+               help='Type of LVM volumes to deploy; (default, thin, or auto). '
+                    'Auto defaults to thin if thin is supported.'),
     cfg.StrOpt('lvm_conf_file',
                default='/etc/cinder/lvm.conf',
                help='LVM conf file to use for the LVM driver in Cinder; '
@@ -278,6 +279,26 @@ class LVMVolumeDriver(driver.VolumeDriver):
                        self.configuration.volume_group)
             raise exception.VolumeBackendAPIException(data=message)
 
+        pool_name = "%s-pool" % self.configuration.volume_group
+
+        if self.configuration.lvm_type == 'auto':
+            # Default to thin provisioning if it is supported and
+            # the volume group is empty, or contains a thin pool
+            # for us to use.
+            self.vg.update_volume_group_info()
+
+            self.configuration.lvm_type = 'default'
+
+            if volutils.supports_thin_provisioning():
+                if self.vg.get_volume(pool_name) is not None:
+                    LOG.info(_LI('Enabling LVM thin provisioning by default '
+                                 'because a thin pool exists.'))
+                    self.configuration.lvm_type = 'thin'
+                elif len(self.vg.get_volumes()) == 0:
+                    LOG.info(_LI('Enabling LVM thin provisioning by default '
+                                 'because no LVs exist.'))
+                    self.configuration.lvm_type = 'thin'
+
         if self.configuration.lvm_type == 'thin':
             # Specific checks for using Thin provisioned LV's
             if not volutils.supports_thin_provisioning():
@@ -285,7 +306,6 @@ class LVMVolumeDriver(driver.VolumeDriver):
                             "on this version of LVM.")
                 raise exception.VolumeBackendAPIException(data=message)
 
-            pool_name = "%s-pool" % self.configuration.volume_group
             if self.vg.get_volume(pool_name) is None:
                 try:
                     self.vg.create_thin_pool(pool_name)