]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
support a configurable volume wiping method
authorPádraig Brady <pbrady@redhat.com>
Thu, 6 Sep 2012 15:36:50 +0000 (16:36 +0100)
committerPádraig Brady <pbrady@redhat.com>
Tue, 15 Jan 2013 16:26:59 +0000 (16:26 +0000)
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

cinder/flags.py
cinder/tests/fake_driver.py
cinder/volume/drivers/lvm.py
etc/cinder/rootwrap.d/volume.filters

index aae589a329e937e7dbbbe2bb8197bd2c6788d348..9e859d41a9bbf272201628dba07d345b2ca8b150 100644 (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)
index 12cc5366cc5129bff9c2e521577aaf51614efa10..10f791e77b83b351e73cb0ac9a655e04b132901e 100644 (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()
index 14c2b5b3b2e86002263844bf598fa281d31bdf09..1e0c694e537f8fe20493d0f9806f07c8ea45a1cd 100644 (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'])
index 45a1e29cda35edda127d0b8cd8747e1997b41ff3..68a57b1df864345da471a278ac78e6d6c2ea3a72 100644 (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