def test_get_volume_stats(self, _mock_get_version, mock_vgs, mock_pvs, mock_get_volumes): self.volume.driver.vg = brick_lvm.LVM('cinder-volumes', 'sudo') self.volume.driver._update_volume_stats() stats = self.volume.driver._stats self.assertEqual(float('5.52'), stats['pools'][0]['total_capacity_gb']) self.assertEqual(float('0.52'), stats['pools'][0]['free_capacity_gb']) self.assertEqual(float('5.0'), stats['pools'][0]['provisioned_capacity_gb']) self.assertEqual(int('1'), stats['pools'][0]['total_volumes']) self.assertFalse(stats['sparse_copy_volume']) # Check value of sparse_copy_volume for thin enabled case. # This value is set in check_for_setup_error. self.configuration = conf.Configuration(None) self.configuration.lvm_type = 'thin' self.configuration.target_helper = 'lioadm' vg_obj = fake_lvm.FakeBrickLVM('cinder-volumes', False, None, 'default') lvm_driver = lvm.LVMVolumeDriver(configuration=self.configuration, db=db, vg_obj=vg_obj) lvm_driver.check_for_setup_error() lvm_driver.vg = brick_lvm.LVM('cinder-volumes', 'sudo') lvm_driver._update_volume_stats() stats = lvm_driver._stats self.assertTrue(stats['sparse_copy_volume'])
def test_check_for_setup_error(self, _mock_get_version, vgs): vg_obj = fake_lvm.FakeBrickLVM('cinder-volumes', False, None, 'auto') configuration = conf.Configuration(fake_opt, 'fake_group') lvm_driver = lvm.LVMVolumeDriver(configuration=configuration, vg_obj=vg_obj, db=db) lvm_driver.delete_snapshot = mock.Mock() volume = tests_utils.create_volume(self.context, host=socket.gethostname()) volume_id = volume['id'] backup = {} backup['volume_id'] = volume_id backup['user_id'] = fake.USER_ID backup['project_id'] = fake.PROJECT_ID backup['host'] = socket.gethostname() backup['availability_zone'] = '1' backup['display_name'] = 'test_check_for_setup_error' backup['display_description'] = 'test_check_for_setup_error' backup['container'] = 'fake' backup['status'] = fields.BackupStatus.CREATING backup['fail_reason'] = '' backup['service'] = 'fake' backup['parent_id'] = None backup['size'] = 5 * 1024 * 1024 backup['object_count'] = 22 db.backup_create(self.context, backup) lvm_driver.check_for_setup_error()
def test_create_volume_from_snapshot_sparse(self): self.configuration.lvm_type = 'thin' lvm_driver = lvm.LVMVolumeDriver(configuration=self.configuration, db=db) with mock.patch.object(lvm_driver, 'vg'), \ mock.patch.object(lvm_driver, '_create_volume'), \ mock.patch.object(volutils, 'copy_volume') as mock_copy: # Test case for thin LVM lvm_driver._sparse_copy_volume = True src_volume = tests_utils.create_volume(self.context) snapshot_ref = tests_utils.create_snapshot(self.context, src_volume['id']) dst_volume = tests_utils.create_volume(self.context) lvm_driver.create_volume_from_snapshot(dst_volume, snapshot_ref) volume_path = lvm_driver.local_path(dst_volume) snapshot_path = lvm_driver.local_path(snapshot_ref) volume_size = 1024 block_size = '1M' mock_copy.assert_called_with(snapshot_path, volume_path, volume_size, block_size, execute=lvm_driver._execute, sparse=True)
def test_snapshot_over_subscription(self, _mock_get_version, mock_vgs, mock_pvs, mock_get_volumes): self.configuration.lvm_type = 'thin' self.configuration.max_over_subscription_ratio = 1 lvm_driver = lvm.LVMVolumeDriver(configuration=self.configuration, db=db) # Test case for thin LVM lvm_driver._sparse_copy_volume = True lvm_driver.vg = brick_lvm.LVM('cinder-volumes', 'sudo') volume_size = 5 with mock.patch.object(self.volume.driver, '_create_volume'), \ mock.patch.object(lvm_driver.vg, 'get_volume', return_value={'name': 'fake_lv', 'size': volume_size}), \ mock.patch.object(lvm_driver.vg, 'create_lv_snapshot'): lvm_driver.vg.vg_size = 10 lvm_driver.vg.vg_provisioned_capacity = 8 fake_volume = tests_utils.create_volume( self.context, size=volume_size) fake_snapshot = tests_utils.create_snapshot( self.context, fake_volume['id']) self.assertRaises(exception.LVMThinPoolCapacityError, lvm_driver.create_snapshot, fake_snapshot)
def test_get_volume_stats(self, _mock_get_version): def _fake_get_all_physical_volumes(obj, root_helper, vg_name): return [{}] @staticmethod def _fake_get_all_volume_groups(root_helper, vg_name=None): return [{'name': 'cinder-volumes', 'size': '5.52', 'available': '0.52', 'lv_count': '2', 'uuid': 'vR1JU3-FAKE-C4A9-PQFh-Mctm-9FwA-Xwzc1m'}] def _fake_get_volumes(obj, lv_name=None): return [{'vg': 'fake_vg', 'name': 'fake_vol', 'size': '1000'}] self.stubs.Set(brick_lvm.LVM, 'get_all_volume_groups', _fake_get_all_volume_groups) self.stubs.Set(brick_lvm.LVM, 'get_all_physical_volumes', _fake_get_all_physical_volumes) self.stubs.Set(brick_lvm.LVM, 'get_volumes', _fake_get_volumes) self.volume.driver.vg = brick_lvm.LVM('cinder-volumes', 'sudo') self.volume.driver._update_volume_stats() stats = self.volume.driver._stats self.assertEqual( float('5.52'), stats['pools'][0]['total_capacity_gb']) self.assertEqual( float('0.52'), stats['pools'][0]['free_capacity_gb']) self.assertEqual( float('5.0'), stats['pools'][0]['provisioned_capacity_gb']) self.assertEqual( int('1'), stats['pools'][0]['total_volumes']) self.assertFalse(stats['sparse_copy_volume']) # Check value of sparse_copy_volume for thin enabled case. # This value is set in check_for_setup_error. self.configuration = conf.Configuration(None) self.configuration.lvm_type = 'thin' vg_obj = fake_lvm.FakeBrickLVM('cinder-volumes', False, None, 'default') lvm_driver = lvm.LVMVolumeDriver(configuration=self.configuration, db=db, vg_obj=vg_obj) lvm_driver.check_for_setup_error() lvm_driver.vg = brick_lvm.LVM('cinder-volumes', 'sudo') lvm_driver._update_volume_stats() stats = lvm_driver._stats self.assertTrue(stats['sparse_copy_volume'])
def test_delete_volume_invalid_parameter(self, _mock_create_export, mock_exists): self.configuration.volume_clear = 'zero' self.configuration.volume_clear_size = 0 lvm_driver = lvm.LVMVolumeDriver(configuration=self.configuration, db=db) # Test volume without 'size' field and 'volume_size' field self.assertRaises(exception.InvalidParameterValue, lvm_driver._delete_volume, self.FAKE_VOLUME)
def test_lvm_type_auto_no_thin_pool(self, *_unused_mocks): configuration = conf.Configuration(fake_opt, 'fake_group') configuration.lvm_type = 'auto' lvm_driver = lvm.LVMVolumeDriver(configuration=configuration) lvm_driver.check_for_setup_error() self.assertEqual('default', lvm_driver.configuration.lvm_type)
def test_multiattach_terminate_connection(self): # Ensure that target_driver.terminate_connection is only called when a # single active volume attachment remains per host for each volume. host1_connector = {'ip': '10.0.0.2', 'host': 'fakehost1', 'initiator': 'iqn.2012-07.org.fake:01'} host2_connector = {'ip': '10.0.0.3', 'host': 'fakehost2', 'initiator': 'iqn.2012-07.org.fake:02'} host1_attachment1 = fake_volume.volume_attachment_ovo( self.context) host1_attachment1.connector = host1_connector host1_attachment2 = fake_volume.volume_attachment_ovo( self.context) host1_attachment2.connector = host1_connector host2_attachment = fake_volume.volume_attachment_ovo(self.context) host2_attachment.connector = host2_connector # Create a multiattach volume object with two active attachments on # host1 and another single attachment on host2. vol = fake_volume.fake_volume_obj(self.context) vol.multiattach = True vol.volume_attachment.objects.append(host1_attachment1) vol.volume_attachment.objects.append(host1_attachment2) vol.volume_attachment.objects.append(host2_attachment) self.configuration = conf.Configuration(None) vg_obj = fake_lvm.FakeBrickLVM('cinder-volumes', False, None, 'default') lvm_driver = lvm.LVMVolumeDriver(configuration=self.configuration, db=db, vg_obj=vg_obj) with mock.patch.object(lvm_driver.target_driver, 'terminate_connection') as mock_term_conn: # Verify that terminate_connection is not called against host1 when # there are multiple active attachments against that host. self.assertTrue(lvm_driver.terminate_connection(vol, host1_connector)) mock_term_conn.assert_not_called() # Verify that terminate_connection is called against either host # when only one active attachment per host is present. vol.volume_attachment.objects.remove(host1_attachment1) self.assertTrue(lvm_driver.terminate_connection(vol, host1_connector)) self.assertTrue(lvm_driver.terminate_connection(vol, host2_connector)) mock_term_conn.assert_has_calls([mock.call(vol, host1_connector), mock.call(vol, host2_connector)])
def test_delete_volume_bad_path(self, _mock_create_export, mock_exists): self.configuration.volume_clear = 'zero' self.configuration.volume_clear_size = 0 self.configuration.volume_type = 'default' volume = dict(self.FAKE_VOLUME, size=1) lvm_driver = lvm.LVMVolumeDriver(configuration=self.configuration, db=db) self.assertRaises(exception.VolumeBackendAPIException, lvm_driver._delete_volume, volume)
def test_revert_thin_snapshot(self): configuration = conf.Configuration(fake_opt, 'fake_group') configuration.lvm_type = 'thin' lvm_driver = lvm.LVMVolumeDriver(configuration=configuration, db=db) fake_volume = tests_utils.create_volume(self.context, display_name='fake_volume') fake_snapshot = tests_utils.create_snapshot(self.context, fake_volume.id) self.assertRaises(NotImplementedError, lvm_driver.revert_to_snapshot, self.context, fake_volume, fake_snapshot)
def test_lvm_type_auto_no_lvs(self, *_unused_mocks): configuration = conf.Configuration(fake_opt, 'fake_group') configuration.lvm_type = 'auto' vg_obj = fake_lvm.FakeBrickLVM('cinder-volumes', False, None, 'default') lvm_driver = lvm.LVMVolumeDriver(configuration=configuration, vg_obj=vg_obj) lvm_driver.check_for_setup_error() self.assertEqual('thin', lvm_driver.configuration.lvm_type)
def test_delete_volume_invalid_parameter(self, _mock_create_export): self.configuration.volume_clear = 'zero' self.configuration.volume_clear_size = 0 lvm_driver = lvm.LVMVolumeDriver(configuration=self.configuration, db=db) self.mox.StubOutWithMock(os.path, 'exists') os.path.exists(mox.IgnoreArg()).AndReturn(True) self.mox.ReplayAll() # Test volume without 'size' field and 'volume_size' field self.assertRaises(exception.InvalidParameterValue, lvm_driver._delete_volume, self.FAKE_VOLUME)
def test_lvm_max_over_subscription_ratio(self, global_value, lvm_value, expected_value): configuration = conf.Configuration(fake_opt, 'fake_group') configuration.max_over_subscription_ratio = global_value configuration.lvm_max_over_subscription_ratio = lvm_value fake_vg = mock.Mock( fake_lvm.FakeBrickLVM('cinder-volumes', False, None, 'default')) lvm_driver = lvm.LVMVolumeDriver(configuration=configuration, vg_obj=fake_vg, db=db) self.assertEqual(expected_value, lvm_driver.configuration.max_over_subscription_ratio)
def test_lvm_migrate_volume_proceed_with_thin(self): hostname = socket.gethostname() capabilities = { 'location_info': 'LVMVolumeDriver:%s:' 'cinder-volumes-2:default:0' % hostname } host = {'capabilities': capabilities} vol = {'name': 'testvol', 'id': 1, 'size': 2, 'status': 'available'} def fake_execute(*args, **kwargs): pass def get_all_volume_groups(): # NOTE(flaper87) Return just the destination # host to test the check of dest VG existence. return [{'name': 'cinder-volumes-2'}] def _fake_get_all_physical_volumes(obj, root_helper, vg_name): return [{}] self.configuration.lvm_type = 'thin' lvm_driver = lvm.LVMVolumeDriver(configuration=self.configuration, db=db) with mock.patch.object(brick_lvm.LVM, 'get_all_physical_volumes', return_value = [{}]), \ mock.patch.object(lvm_driver, '_execute') \ as mock_execute, \ mock.patch.object(volutils, 'copy_volume') as mock_copy, \ mock.patch.object(volutils, 'get_all_volume_groups', side_effect = get_all_volume_groups), \ mock.patch.object(lvm_driver, '_delete_volume'): lvm_driver.vg = fake_lvm.FakeBrickLVM('cinder-volumes', False, None, 'default') lvm_driver._sparse_copy_volume = True mock_execute.return_value = ("mock_outs", "mock_errs") moved, model_update = \ lvm_driver.migrate_volume(self.context, vol, host) self.assertTrue(moved) self.assertIsNone(model_update) mock_copy.assert_called_once_with( '/dev/mapper/cinder--volumes-testvol', '/dev/mapper/cinder--volumes--2-testvol', 2048, '1M', execute=mock_execute, sparse=True)
def test_create_volume_from_snapshot_sparse(self): self.configuration.lvm_type = 'thin' lvm_driver = lvm.LVMVolumeDriver(configuration=self.configuration, db=db) with mock.patch.object(lvm_driver, 'vg'): # Test case for thin LVM lvm_driver._sparse_copy_volume = True src_volume = tests_utils.create_volume(self.context) snapshot_ref = tests_utils.create_snapshot(self.context, src_volume['id']) dst_volume = tests_utils.create_volume(self.context) lvm_driver.create_volume_from_snapshot(dst_volume, snapshot_ref)
def test_delete_volume_bad_path(self, _mock_create_export): self.configuration.volume_clear = 'zero' self.configuration.volume_clear_size = 0 self.configuration.volume_type = 'default' volume = dict(self.FAKE_VOLUME, size=1) lvm_driver = lvm.LVMVolumeDriver(configuration=self.configuration, db=db) self.mox.StubOutWithMock(os.path, 'exists') os.path.exists(mox.IgnoreArg()).AndReturn(False) self.mox.ReplayAll() self.assertRaises(exception.VolumeBackendAPIException, lvm_driver._delete_volume, volume)
def test_delete_volume_thinlvm_snap(self, _mock_create_export, mock_copy, mock_clear): vg_obj = fake_lvm.FakeBrickLVM('cinder-volumes', False, None, 'default') self.configuration.volume_clear = 'zero' self.configuration.volume_clear_size = 0 self.configuration.lvm_type = 'thin' self.configuration.target_helper = 'tgtadm' lvm_driver = lvm.LVMVolumeDriver(configuration=self.configuration, vg_obj=vg_obj, db=db) uuid = '00000000-0000-0000-0000-c3aa7ee01536' fake_snapshot = {'name': 'volume-' + uuid, 'id': uuid, 'size': 123} lvm_driver._delete_volume(fake_snapshot, is_snapshot=True)
def test_create_cloned_volume_by_thin_snapshot(self, mock_extend): self.configuration.lvm_type = 'thin' fake_vg = mock.Mock(fake_lvm.FakeBrickLVM('cinder-volumes', False, None, 'default')) lvm_driver = lvm.LVMVolumeDriver(configuration=self.configuration, vg_obj=fake_vg, db=db) fake_volume = tests_utils.create_volume(self.context, size=1) fake_new_volume = tests_utils.create_volume(self.context, size=2) lvm_driver.create_cloned_volume(fake_new_volume, fake_volume) fake_vg.create_lv_snapshot.assert_called_once_with( fake_new_volume['name'], fake_volume['name'], 'thin') mock_extend.assert_called_once_with(fake_new_volume, 2) fake_vg.activate_lv.assert_called_once_with( fake_new_volume['name'], is_snapshot=True, permanent=True)
def test_create_volume_from_snapshot_sparse_extend(self): self.configuration.lvm_type = 'thin' lvm_driver = lvm.LVMVolumeDriver(configuration=self.configuration, db=db) with mock.patch.object(lvm_driver, 'vg'), \ mock.patch.object(lvm_driver, 'extend_volume') as mock_extend: # Test case for thin LVM lvm_driver._sparse_copy_volume = True src_volume = tests_utils.create_volume(self.context) snapshot_ref = tests_utils.create_snapshot(self.context, src_volume['id']) dst_volume = tests_utils.create_volume(self.context) dst_volume['size'] = snapshot_ref['volume_size'] + 1 lvm_driver.create_volume_from_snapshot(dst_volume, snapshot_ref) mock_extend.assert_called_with(dst_volume, dst_volume['size'])
def test_delete_volume_thinlvm_snap(self, _mock_create_export): self.configuration.volume_clear = 'zero' self.configuration.volume_clear_size = 0 self.configuration.lvm_type = 'thin' self.configuration.iscsi_helper = 'tgtadm' lvm_driver = lvm.LVMVolumeDriver(configuration=self.configuration, vg_obj=mox.MockAnything(), db=db) # Ensures that copy_volume is not called for ThinLVM self.mox.StubOutWithMock(volutils, 'copy_volume') self.mox.StubOutWithMock(volutils, 'clear_volume') self.mox.StubOutWithMock(lvm_driver, '_execute') self.mox.ReplayAll() uuid = '00000000-0000-0000-0000-c3aa7ee01536' fake_snapshot = {'name': 'volume-' + uuid, 'id': uuid, 'size': 123} lvm_driver._delete_volume(fake_snapshot, is_snapshot=True)
def test_do_setup_clean_temporary_dir(self): vg_obj = fake_lvm.FakeBrickLVM('cinder-volumes', False, None, 'default') self.configuration.volume_clear = 'zero' self.configuration.volume_clear_size = 0 self.configuration.lvm_type = 'thin' self.configuration.iscsi_helper = 'tgtadm' lvm_driver = lvm.LVMVolumeDriver(configuration=self.configuration, vg_obj=vg_obj, db=db) tmp_files = ['tmpFileA', 'tmpFileB'] with mock.patch('os.path.exists', return_value=True) \ as mock_path_exists, \ mock.patch('os.listdir', return_value=tmp_files), \ mock.patch('os.remove') as mock_remove: lvm_driver.do_setup('context') mock_path_exists.assert_called_once_with( CONF.image_conversion_dir) self.assertEqual(mock_remove.call_count, len(tmp_files)) calls = [args for args, kwargs in mock_remove.call_args_list] for f in tmp_files: self.assertIn((os.path.join(CONF.image_conversion_dir, f),), calls)