def test_clear_volume_shred_not_clear_size(self): CONF.volume_clear = 'shred' CONF.volume_clear_size = None clear_cmd = ['shred', '-n3', "volume_path"] self.mox.StubOutWithMock(utils, "execute") utils.execute(*clear_cmd, run_as_root=True) self.mox.ReplayAll() volume_utils.clear_volume(1024, "volume_path")
def test_clear_volume_shred(self): CONF.volume_clear = "shred" CONF.volume_clear_size = 1 clear_cmd = ["shred", "-n3", "-s1MiB", "volume_path"] self.mox.StubOutWithMock(utils, "execute") utils.execute(*clear_cmd, run_as_root=True) self.mox.ReplayAll() volume_utils.clear_volume(1024, "volume_path")
def test_clear_volume_zero_and_shred(self): CONF.volume_clear = 'zero' CONF.volume_clear_size = 1 clear_cmd = ['shred', '-n0', '-z', '-s1MiB', "volume_path"] self.mox.StubOutWithMock(utils, "execute") utils.execute(*clear_cmd, run_as_root=True) self.mox.ReplayAll() volume_utils.clear_volume(1024, "volume_path")
def test_clear_volume_zero(self): CONF.volume_clear = 'zero' CONF.volume_clear_size = 1 self.mox.StubOutWithMock(volume_utils, 'copy_volume') volume_utils.copy_volume("/dev/zero", "volume_path", 1, CONF.volume_dd_blocksize, sync=True, execute=utils.execute) self.mox.ReplayAll() volume_utils.clear_volume(1024, "volume_path")
def test_clear_volume_zero(self): CONF.volume_clear = "zero" CONF.volume_clear_size = 1 CONF.volume_clear_ionice = None self.mox.StubOutWithMock(volume_utils, "copy_volume") volume_utils.copy_volume( "/dev/zero", "volume_path", 1, CONF.volume_dd_blocksize, sync=True, ionice=None, execute=utils.execute ) self.mox.ReplayAll() volume_utils.clear_volume(1024, "volume_path")
def delete_volume(self, volume): """Deletes a logical volume.""" dev_path = self.local_path(volume) if not dev_path or dev_path not in \ self.configuration.available_devices: return if os.path.exists(dev_path) and \ self.configuration.volume_clear != 'none': volutils.clear_volume( self._get_device_size(dev_path), dev_path, volume_clear=self.configuration.volume_clear, volume_clear_size=self.configuration.volume_clear_size)
def test_delete_volume_path_exist(self): TEST_VOLUME1 = {'provider_location': '1 2 3 /dev/loop1'} self.mox.StubOutWithMock(self.drv, 'local_path') path = self.drv.local_path(TEST_VOLUME1).AndReturn('/dev/loop1') self.mox.StubOutWithMock(os.path, 'exists') os.path.exists(path).AndReturn(True) self.mox.StubOutWithMock(volutils, 'clear_volume') self.mox.StubOutWithMock(self.drv, '_get_device_size') size = self.drv._get_device_size(path).AndReturn(1024) volutils.clear_volume(size, path, volume_clear=mox.IgnoreArg(), volume_clear_size=mox.IgnoreArg()) self.mox.ReplayAll() self.drv.delete_volume(TEST_VOLUME1)
def test_clear_volume_lvm_snap(self): self.stubs.Set(os.path, "exists", lambda x: True) CONF.volume_clear = "zero" CONF.volume_clear_size = 0 uuid = "00000000-0000-0000-0000-90ed32cdeed3" name = "snapshot-" + uuid mangle_name = "_" + re.sub(r"-", r"--", name) vol_path = "/dev/mapper/cinder--volumes-%s-cow" % mangle_name def fake_copy_volume(srcstr, deststr, size, blocksize, **kwargs): self.assertEqual(deststr, vol_path) return True self.stubs.Set(volume_utils, "copy_volume", fake_copy_volume) volume_utils.clear_volume(123, vol_path)
def test_clear_volume_shred_not_clear_size(self, mock_conf, mock_exec): mock_conf.volume_clear = "shred" mock_conf.volume_clear_size = None mock_conf.volume_clear_ionice = None output = volume_utils.clear_volume(1024, "volume_path") self.assertIsNone(output) mock_exec.assert_called_once_with("shred", "-n3", "volume_path", run_as_root=True)
def test_clear_volume_lvm_snap(self): self.stubs.Set(os.path, 'exists', lambda x: True) CONF.volume_clear = 'zero' CONF.volume_clear_size = 0 uuid = '00000000-0000-0000-0000-90ed32cdeed3' name = 'snapshot-' + uuid mangle_name = '_' + re.sub(r'-', r'--', name) vol_path = '/dev/mapper/cinder--volumes-%s-cow' % mangle_name def fake_copy_volume(srcstr, deststr, size, blocksize, **kwargs): self.assertEqual(deststr, vol_path) return True self.stubs.Set(volume_utils, 'copy_volume', fake_copy_volume) volume_utils.clear_volume(123, vol_path)
def test_delete_volume_path_exist(self, _clear_volume, _exists): TEST_VOLUME1 = {'provider_location': '1 2 3 /dev/loop1'} with mock.patch.object(self.drv, 'local_path', return_value='/dev/loop1') as lp_mocked: with mock.patch.object(self.drv, '_get_device_size', return_value=1024) as gds_mocked: volutils.clear_volume(gds_mocked, lp_mocked) self.drv.delete_volume(TEST_VOLUME1) lp_mocked.assert_called_once_with(TEST_VOLUME1) gds_mocked.assert_called_once_with('/dev/loop1') self.assertTrue(_exists.called) self.assertTrue(_clear_volume.called)
def test_delete_snapshot(self, _clear_volume, _exists): TEST_SNAP = obj_snap.Snapshot(volume_id=fake.VOLUME_ID, provider_location='/dev/loop1', status=fields.SnapshotStatus.AVAILABLE) with mock.patch.object(self.drv, 'local_path', return_value='/dev/loop1') as lp_mocked: with mock.patch.object(self.drv, '_get_devices_sizes', return_value={'/dev/loop1': 1}) as \ gds_mocked: volutils.clear_volume(gds_mocked, lp_mocked) self.drv.delete_snapshot(TEST_SNAP) lp_mocked.assert_called_once_with(TEST_SNAP) gds_mocked.assert_called_once_with(['/dev/loop1']) self.assertTrue(_exists.called) self.assertTrue(_clear_volume.called)
def test_clear_volume_shred(self, mock_conf, mock_exec): mock_conf.volume_clear = 'shred' mock_conf.volume_clear_size = 1 mock_conf.volume_clear_ionice = None output = volume_utils.clear_volume(1024, 'volume_path') self.assertIsNone(output) mock_exec.assert_called_once_with( 'shred', '-n3', '-s1MiB', "volume_path", run_as_root=True)
def test_clear_volume_conf(self, mock_conf, mock_copy): mock_conf.volume_clear = 'zero' mock_conf.volume_clear_size = 0 mock_conf.volume_dd_blocksize = '1M' mock_conf.volume_clear_ionice = '-c3' output = volume_utils.clear_volume(1024, 'volume_path') self.assertIsNone(output) mock_copy.assert_called_once_with('/dev/zero', 'volume_path', 1024, '1M', sync=True, execute=utils.execute, ionice='-c3')
def _delete_volume(self, volume, is_snapshot=False): """Deletes a logical volume.""" # zero out old volumes to prevent data leaking between users # TODO(ja): reclaiming space should be done lazy and low priority if not self.configuration.lvm_type == 'thin' and \ self.configuration.volume_clear != 'none': if is_snapshot: # if the volume to be cleared is a snapshot of another volume # we need to clear out the volume using the -cow instead of the # directly volume path. We need to skip this if we are using # thin provisioned LVs. # bug# lp1191812 dev_path = self.local_path(volume) + "-cow" else: dev_path = self.local_path(volume) # TODO(jdg): Maybe we could optimize this for snaps by looking at # the cow table and only overwriting what's necessary? # for now we're still skipping on snaps due to hang issue if not os.path.exists(dev_path): msg = (_('Volume device file path %s does not exist.') % dev_path) LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) size_in_g = volume.get('size', volume.get('volume_size', None)) if size_in_g is None: msg = (_("Size for volume: %s not found, " "cannot secure delete.") % volume['id']) LOG.error(msg) raise exception.InvalidParameterValue(msg) vol_size = size_in_g * 1024 volutils.clear_volume( vol_size, dev_path, volume_clear=self.configuration.volume_clear, volume_clear_size=self.configuration.volume_clear_size) name = volume['name'] if is_snapshot: name = self._escape_snapshot(volume['name']) self.vg.delete(name)
def _clear_block_device(self, device): """Deletes a block device.""" dev_path = self.local_path(device) if not dev_path or dev_path not in \ self.configuration.available_devices: return if os.path.exists(dev_path) and \ self.configuration.volume_clear != 'none': dev_size = self._get_devices_sizes([dev_path]) volutils.clear_volume( dev_size[dev_path], dev_path, volume_clear=self.configuration.volume_clear, volume_clear_size=self.configuration.volume_clear_size) else: LOG.warning(_LW("The device %s won't be cleared."), device) if device.status == "error_deleting": msg = _("Failed to delete device.") LOG.error(msg, resource=device) raise exception.VolumeDriverException(msg)
def test_clear_volume_shred(self, mock_conf, mock_exec): # 'shred' now uses 'dd'. Remove this test when # support for 'volume_clear=shred' is removed. mock_conf.volume_clear = 'shred' mock_conf.volume_clear_size = 1 mock_conf.volume_clear_ionice = None mock_conf.volume_dd_blocksize = '1M' output = volume_utils.clear_volume(1024, 'volume_path') self.assertIsNone(output) mock_exec.assert_called_with( 'dd', 'if=/dev/zero', 'of=volume_path', 'count=1048576', 'bs=1M', 'iflag=count_bytes', 'oflag=direct', run_as_root=True)
def test_clear_volume_args(self, mock_conf, mock_copy): mock_conf.volume_clear = 'shred' mock_conf.volume_clear_size = 0 mock_conf.volume_dd_blocksize = '1M' mock_conf.volume_clear_ionice = '-c3' output = volume_utils.clear_volume(1024, 'volume_path', 'zero', 1, '-c0') self.assertIsNone(output) mock_copy.assert_called_once_with('/dev/zero', 'volume_path', 1, '1M', sync=True, execute=utils.execute, ionice='-c0', throttle=None, sparse=False)
def test_delete_volume_path_exist(self, _clear_volume, _exists): TEST_VOLUME = obj_volume.Volume(name_id=fake.VOLUME_NAME_ID, size=1, provider_location='/dev/loop1', display_name='vol1', status='available') with mock.patch.object(self.drv, 'local_path', return_value='/dev/loop1') as lp_mocked: with mock.patch.object(self.drv, '_get_devices_sizes', return_value={'/dev/loop1': 1}) as \ gds_mocked: volutils.clear_volume(gds_mocked, lp_mocked) self.drv.delete_volume(TEST_VOLUME) lp_mocked.assert_called_once_with(TEST_VOLUME) gds_mocked.assert_called_once_with(['/dev/loop1']) self.assertTrue(_exists.called) self.assertTrue(_clear_volume.called)
def _clear_volume(self, volume, is_snapshot=False): # zero out old volumes to prevent data leaking between users # TODO(ja): reclaiming space should be done lazy and low priority if is_snapshot: # if the volume to be cleared is a snapshot of another volume # we need to clear out the volume using the -cow instead of the # directly volume path. We need to skip this if we are using # thin provisioned LVs. # bug# lp1191812 dev_path = self.local_path(volume) + "-cow" else: dev_path = self.local_path(volume) # TODO(jdg): Maybe we could optimize this for snaps by looking at # the cow table and only overwriting what's necessary? # for now we're still skipping on snaps due to hang issue if not os.path.exists(dev_path): msg = (_('Volume device file path %s does not exist.') % dev_path) LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) size_in_g = (volume.get('volume_size') if is_snapshot else volume.get('size')) if size_in_g is None: msg = (_("Size for volume: %s not found, cannot secure delete.") % volume['id']) LOG.error(msg) raise exception.InvalidParameterValue(msg) # clear_volume expects sizes in MiB, we store integer GiB # be sure to convert before passing in vol_sz_in_meg = size_in_g * units.Ki volutils.clear_volume( vol_sz_in_meg, dev_path, volume_clear=self.configuration.volume_clear, volume_clear_size=self.configuration.volume_clear_size)
def test_clear_volume_shred(self, mock_conf, mock_exec): # 'shred' now uses 'dd'. Remove this test when # support for 'volume_clear=shred' is removed. mock_conf.volume_clear = 'shred' mock_conf.volume_clear_size = 1 mock_conf.volume_clear_ionice = None mock_conf.volume_dd_blocksize = '1M' output = volume_utils.clear_volume(1024, 'volume_path') self.assertIsNone(output) mock_exec.assert_called_with('dd', 'if=/dev/zero', 'of=volume_path', 'count=1', 'bs=1M', 'oflag=direct', run_as_root=True)
def test_clear_volume_args(self, mock_conf, mock_copy): mock_conf.volume_clear = "shred" mock_conf.volume_clear_size = 0 mock_conf.volume_dd_blocksize = "1M" mock_conf.volume_clear_ionice = "-c3" output = volume_utils.clear_volume(1024, "volume_path", "zero", 1, "-c0") self.assertIsNone(output) mock_copy.assert_called_once_with( "/dev/zero", "volume_path", 1, "1M", sync=True, execute=utils.execute, ionice="-c0", throttle=None, sparse=False, )