]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Implement LVM thin provisioning support.
authorJohn Griffith <john.griffith@solidfire.com>
Fri, 11 Jan 2013 21:38:23 +0000 (14:38 -0700)
committerjohn-griffith <john.griffith@solidfire.com>
Fri, 25 Jan 2013 17:24:01 +0000 (10:24 -0700)
As of LVM2 version 2.02.89 the ability to do thin provisioning
was made available in LVM, this provides some cool new features
but also addresses some problems with things like terrible
LVM snapshot performance.

Currently the version of LVM in Ubuntu 12.04 does NOT support LVM thin,
however an experimental PPA from brightbox which is a backport from
Quantal has been proposed to Cannonical to be pulled in.  For some
users the experimental PPA is a better option than dealing with some of
the current issues in the standard LVM2 version of Precise (including
the dd hangs on secure delete). See BP for more info.

This change will create the thin pool if it doesn't exist
using pool_size flag, or by default using entire VG space.

Implements BP: implement-lvm-thin-provisioning

Change-Id: I8a30a1283e1992c64e8ac96841ae4a6f82f7018a

cinder/volume/drivers/lvm.py
etc/cinder/cinder.conf.sample
etc/cinder/rootwrap.d/volume.filters

index b3bde19b8f85520ab2b7afa2be8e7615c4920ab0..0fbe1fa82f00242672b11ede832cbdb8c244f996 100644 (file)
@@ -46,6 +46,10 @@ volume_opts = [
     cfg.IntOpt('volume_clear_size',
                default=0,
                help='Size in MiB to wipe at start of old volumes. 0 => all'),
+    cfg.StrOpt('pool_size',
+               default=None,
+               help='Size of thin provisioning pool '
+                    '(None uses entire cinder VG)'),
     cfg.IntOpt('lvm_mirrors',
                default=0,
                help='If set, create lvms with multiple mirrors. Note that '
@@ -492,3 +496,65 @@ class LVMISCSIDriver(LVMVolumeDriver, driver.ISCSIDriver):
 
     def _iscsi_authentication(self, chap, name, password):
         return "%s %s %s" % (chap, name, password)
+
+
+class ThinLVMVolumeDriver(LVMISCSIDriver):
+    """Subclass for thin provisioned LVM's."""
+    def __init__(self, *args, **kwargs):
+        super(ThinLVMVolumeDriver, self).__init__(*args, **kwargs)
+
+    def check_for_setup_error(self):
+        """Returns an error if prerequisites aren't met"""
+        out, err = self._execute('lvs', '--option',
+                                 'name', '--noheadings',
+                                 run_as_root=True)
+        pool_name = "%s-pool" % FLAGS.volume_group
+        if pool_name not in out:
+            if not FLAGS.pool_size:
+                out, err = self._execute('vgs', FLAGS.volume_group,
+                                         '--noheadings', '--options',
+                                         'name,size', run_as_root=True)
+                size = re.sub(r'[\.][\d][\d]', '', out.split()[1])
+            else:
+                size = "%s" % FLAGS.pool_size
+
+            pool_path = '%s/%s' % (FLAGS.volume_group, pool_name)
+            out, err = self._execute('lvcreate', '-T', '-L', size,
+                                     pool_path, run_as_root=True)
+
+    def _do_lvm_snapshot(self, src_lvm_name, dest_vref, is_cinder_snap=True):
+            if is_cinder_snap:
+                new_name = self._escape_snapshot(dest_vref['name'])
+            else:
+                new_name = dest_vref['name']
+
+            self._try_execute('lvcreate', '-s', '-n', new_name,
+                              src_lvm_name, run_as_root=True)
+
+    def create_volume(self, volume):
+        """Creates a logical volume. Can optionally return a Dictionary of
+        changes to the volume object to be persisted."""
+        sizestr = self._sizestr(volume['size'])
+        vg_name = ("%s/%s-pool" % (FLAGS.volume_group, FLAGS.volume_group))
+        self._try_execute('lvcreate', '-T', '-V', sizestr, '-n',
+                          volume['name'], vg_name, run_as_root=True)
+
+    def delete_volume(self, volume):
+        """Deletes a logical volume."""
+        if self._volume_not_present(volume['name']):
+            return True
+        self._try_execute('lvremove', '-f', "%s/%s" %
+                          (FLAGS.volume_group,
+                           self._escape_snapshot(volume['name'])),
+                          run_as_root=True)
+
+    def create_cloned_volume(self, volume, src_vref):
+        """Creates a clone of the specified volume."""
+        LOG.info(_('Creating clone of volume: %s') % src_vref['id'])
+        orig_lv_name = "%s/%s" % (FLAGS.volume_group, src_vref['name'])
+        self._do_lvm_snapshot(orig_lv_name, volume, False)
+
+    def create_snapshot(self, snapshot):
+        """Creates a snapshot of a volume."""
+        orig_lv_name = "%s/%s" % (FLAGS.volume_group, snapshot['volume_name'])
+        self._do_lvm_snapshot(orig_lv_name, snapshot)
index 40b5c34917f85dca09ad21d40bcd6b87084b04c8..54513ca997402f2e8f825951abde13b5a2ff7a8b 100644 (file)
 # Options defined in cinder.scheduler.host_manager
 #
 
+# num_shell_tries=3
+#### (IntOpt) number of times to attempt to run flakey shell commands
+
 # Which filter class names to use for filtering hosts when not
 # specified in the request. (list value)
 #scheduler_default_filters=AvailabilityZoneFilter,CapacityFilter,CapabilitiesFilter
 # value)
 #lvm_mirrors=0
 
+# pool_size=None
+### (strOpt) Size of thin pool to create including suffix (5G),
+###          default is None and uses full size of VG###
+
+
 
 #
 # Options defined in cinder.volume.drivers.netapp
index 68a57b1df864345da471a278ac78e6d6c2ea3a72..c97437ada0fa28300c01e54151a3d7e1cdafef3b 100644 (file)
@@ -49,3 +49,4 @@ df: CommandFilter, /bin/df, root
 truncate: CommandFilter, /usr/bin/truncate, root
 chmod: CommandFilter, /bin/chmod, root
 rm: CommandFilter, /bin/rm, root
+lvs: CommandFilter, /sbin/lvs, root