support a configurable volume wiping method

Add a clear_volume() method that is called from delete_method().
This is only implemented at present for the base LVM driver.
This new clear_volume() method now supports these config vars:

  volume_clear = none, zero, shred
  volume_clear_size = size_in_MiB

'zero' is the default method and unchanged from previously.
'none' is used if security isn't a concern, or there is
  independent volume scrubbing.
'shred' is for more security conscious situations where
an overwrite count is required. Currently this defaults to 3 passes.

size_in_MiB can be used to limit the cleared area to the first
part of the volume, which can greatly speed up the operation,
and can be useful with encrypted volumes for example where
overwritting the encryption keys at the start is sufficient.

Fixes bug: 1022511
Change-Id: I7312678ff5d66156578501483a1b74e2a69e19a0
This commit is contained in:
Pádraig Brady 2012-09-06 16:36:50 +01:00
parent 7905b6b233
commit bb06ebd0f6
4 changed files with 50 additions and 8 deletions

View File

@ -229,9 +229,6 @@ global_opts = [
'and deprecated.'),
cfg.StrOpt('control_exchange',
default='cinder',
help='AMQP exchange to connect to if using RabbitMQ or Qpid'),
cfg.BoolOpt('secure_delete',
default=True,
help='Whether to perform secure delete'), ]
help='AMQP exchange to connect to if using RabbitMQ or Qpid'), ]
FLAGS.register_opts(global_opts)

View File

@ -56,8 +56,12 @@ class LoggingVolumeDriver(driver.VolumeDriver):
self.log_action('create_volume', volume)
def delete_volume(self, volume):
self.clear_volume(volume)
self.log_action('delete_volume', volume)
def clear_volume(self, volume):
self.log_action('clear_volume', volume)
def local_path(self, volume):
print "local_path not implemented"
raise NotImplementedError()

View File

@ -39,6 +39,13 @@ volume_opts = [
cfg.StrOpt('volume_group',
default='cinder-volumes',
help='Name for the VG that will contain exported volumes'),
cfg.StrOpt('volume_clear',
default='zero',
help='Method used to wipe old volumes (valid options are: '
'none, zero, shred)'),
cfg.IntOpt('volume_clear_size',
default=0,
help='Size in MiB to wipe at start of old volumes. 0 => all'),
cfg.IntOpt('lvm_mirrors',
default=0,
help='If set, create lvms with multiple mirrors. Note that '
@ -119,10 +126,8 @@ class LVMVolumeDriver(driver.VolumeDriver):
# zero out old volumes to prevent data leaking between users
# TODO(ja): reclaiming space should be done lazy and low priority
dev_path = self.local_path(volume)
if FLAGS.secure_delete and os.path.exists(dev_path):
LOG.info(_("Performing secure delete on volume: %s")
% volume['id'])
self._copy_volume('/dev/zero', dev_path, size_in_g)
if os.path.exists(dev_path):
self.clear_volume(volume)
self._try_execute('lvremove', '-f', "%s/%s" %
(FLAGS.volume_group,
@ -173,6 +178,38 @@ class LVMVolumeDriver(driver.VolumeDriver):
self._delete_volume(volume, volume['size'])
def clear_volume(self, volume):
"""unprovision old volumes to prevent data leaking between users."""
vol_path = self.local_path(volume)
size_in_g = volume.get('size')
size_in_m = FLAGS.volume_clear_size
if not size_in_g:
return
if FLAGS.volume_clear == 'none':
return
LOG.info(_("Performing secure delete on volume: %s") % volume['id'])
if FLAGS.volume_clear == 'zero':
if size_in_m == 0:
return self._copy_volume('/dev/zero', vol_path, size_in_g)
else:
clear_cmd = ['shred', '-n0', '-z', '-s%dMiB' % size_in_m]
elif FLAGS.volume_clear == 'shred':
clear_cmd = ['shred', '-n3']
if size_in_m:
clear_cmd.append('-s%dMiB' % size_in_m)
else:
LOG.error(_("Error unrecognized volume_clear option: %s"),
FLAGS.volume_clear)
return
clear_cmd.append(vol_path)
self._execute(*clear_cmd, run_as_root=True)
def create_snapshot(self, snapshot):
"""Creates a snapshot."""
orig_lv_name = "%s/%s" % (FLAGS.volume_group, snapshot['volume_name'])

View File

@ -28,6 +28,10 @@ lvdisplay: CommandFilter, /sbin/lvdisplay, root
iscsiadm: CommandFilter, /sbin/iscsiadm, root
iscsiadm_usr: CommandFilter, /usr/bin/iscsiadm, root
# cinder/volume/drivers/lvm.py: 'shred', '-n3'
# cinder/volume/drivers/lvm.py: 'shred', '-n0', '-z', '-s%dMiB'
shred: CommandFilter, /usr/bin/shred, root
#cinder/volume/.py: utils.temporary_chown(path, 0), ...
chown: CommandFilter, /bin/chown, root