From 6b8ba716d2300add4f3d89b57501aaeee21bf59f Mon Sep 17 00:00:00 2001 From: John Griffith Date: Fri, 11 Jan 2013 14:38:23 -0700 Subject: [PATCH] Implement LVM thin provisioning support. 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 | 66 ++++++++++++++++++++++++++++ etc/cinder/cinder.conf.sample | 8 ++++ etc/cinder/rootwrap.d/volume.filters | 1 + 3 files changed, 75 insertions(+) diff --git a/cinder/volume/drivers/lvm.py b/cinder/volume/drivers/lvm.py index b3bde19b8..0fbe1fa82 100644 --- a/cinder/volume/drivers/lvm.py +++ b/cinder/volume/drivers/lvm.py @@ -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) diff --git a/etc/cinder/cinder.conf.sample b/etc/cinder/cinder.conf.sample index 40b5c3491..54513ca99 100644 --- a/etc/cinder/cinder.conf.sample +++ b/etc/cinder/cinder.conf.sample @@ -618,6 +618,9 @@ # 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 @@ -723,6 +726,11 @@ # 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 diff --git a/etc/cinder/rootwrap.d/volume.filters b/etc/cinder/rootwrap.d/volume.filters index 68a57b1df..c97437ada 100644 --- a/etc/cinder/rootwrap.d/volume.filters +++ b/etc/cinder/rootwrap.d/volume.filters @@ -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 -- 2.45.2