Merge two fake drivers into the one FakeLoggingVolumeDriver

Two different fake drivers for unit-tests look confusing. We are able to
test anything we want with only one fake driver.

Current LoggingVolumeDriver doesn't actually log anything. It just
stores all drivers actions in a list.

Now, we can add real logging to FakeLoggingVolumeDriver and use it both
for unit and functional tests.

It's a first patch in a series for unit tests refactoring. More manager
and LVM driver tests will be proposed in a following patches.

Change-Id: I383bcdb531c7d52c0fdbb6875de73f1274a92854
This commit is contained in:
Ivan Kolodyazhny 2016-08-01 13:39:24 +03:00
parent cda4dc9704
commit f5fa8c73f0
7 changed files with 91 additions and 195 deletions

View File

@ -23,11 +23,16 @@ from cinder.volume.drivers import lvm
from cinder.zonemanager import utils as fczm_utils
class FakeISCSIDriver(lvm.LVMVolumeDriver):
# TODO(e0ne): add logging to FakeLoggingVolumeDriver and remove this one.
# TODO(e0ne): inherit from driver.VolumeDriver and fix unit-tests
class FakeLoggingVolumeDriver(lvm.LVMVolumeDriver):
"""Logs calls instead of executing."""
def __init__(self, *args, **kwargs):
super(FakeISCSIDriver, self).__init__(execute=self.fake_execute,
*args, **kwargs)
super(FakeLoggingVolumeDriver, self).__init__(
execute=self.fake_execute, *args, **kwargs)
self.backend_name = 'fake'
self.protocol = 'fake'
self.vg = fake_lvm.FakeBrickLVM('cinder-volumes', False,
None, 'default',
self.fake_execute)
@ -39,6 +44,36 @@ class FakeISCSIDriver(lvm.LVMVolumeDriver):
def create_volume(self, volume):
pass
def delete_volume(self, volume):
pass
def create_snapshot(self, snapshot):
pass
def delete_snapshot(self, snapshot):
pass
def ensure_export(self, context, volume):
pass
def create_export(self, context, volume, connector):
pass
def remove_export(self, context, volume):
pass
def create_export_snapshot(self, context, snapshot):
pass
def remove_export_snapshot(self, context, snapshot):
pass
def terminate_connection_snapshot(self, snapshot, connector):
pass
def create_cloned_volume(self, volume, src_vol):
pass
def initialize_connection(self, volume, connector):
# NOTE(thangp): There are several places in the core cinder code where
# the volume passed through is a dict and not an oslo_versionedobject.
@ -68,19 +103,25 @@ class FakeISCSIDriver(lvm.LVMVolumeDriver):
def terminate_connection(self, volume, connector, **kwargs):
pass
def _update_pools_and_stats(self, data):
fake_pool = {}
fake_pool.update(dict(
pool_name=data["volume_backend_name"],
total_capacity_gb='infinite',
free_capacity_gb='infinite',
provisioned_capacity_gb=0,
reserved_percentage=100,
QoS_support=False,
filter_function=self.get_filter_function(),
goodness_function=self.get_goodness_function()
))
data["pools"].append(fake_pool)
def _update_volume_stats(self):
data = {'volume_backend_name': self.backend_name,
'vendor_name': 'Open Source',
'driver_version': self.VERSION,
'storage_protocol': self.protocol,
'pools': []}
fake_pool = {'pool_name': data['volume_backend_name'],
'total_capacity_gb': 'infinite',
'free_capacity_gb': 'infinite',
'provisioned_capacity_gb': 0,
'reserved_percentage': 100,
'QoS_support': False,
'filter_function': self.get_filter_function(),
'goodness_function': self.get_goodness_function(),
'consistencygroup_support': False,
'replication_enabled': False}
data['pools'].append(fake_pool)
self._stats = data
@staticmethod
@ -89,7 +130,7 @@ class FakeISCSIDriver(lvm.LVMVolumeDriver):
return (None, None)
class FakeISERDriver(FakeISCSIDriver):
class FakeISERDriver(FakeLoggingVolumeDriver):
def __init__(self, *args, **kwargs):
super(FakeISERDriver, self).__init__(execute=self.fake_execute,
*args, **kwargs)
@ -137,99 +178,6 @@ class FakeFibreChannelDriver(driver.FibreChannelDriver):
}}
class LoggingVolumeDriver(driver.VolumeDriver):
"""Logs and records calls, for unit tests."""
def check_for_setup_error(self):
pass
def create_volume(self, volume):
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):
raise NotImplementedError()
def ensure_export(self, context, volume):
self.log_action('ensure_export', volume)
def create_export(self, context, volume):
self.log_action('create_export', volume)
def remove_export(self, context, volume):
self.log_action('remove_export', volume)
def initialize_connection(self, volume, connector):
self.log_action('initialize_connection', volume)
def terminate_connection(self, volume, connector):
self.log_action('terminate_connection', volume)
def create_export_snapshot(self, context, snapshot):
self.log_action('create_export_snapshot', snapshot)
def remove_export_snapshot(self, context, snapshot):
self.log_action('remove_export_snapshot', snapshot)
def initialize_connection_snapshot(self, snapshot, connector):
self.log_action('initialize_connection_snapshot', snapshot)
def terminate_connection_snapshot(self, snapshot, connector):
self.log_action('terminate_connection_snapshot', snapshot)
def create_cloned_volume(self, volume, src_vol):
self.log_action('create_cloned_volume', volume)
_LOGS = []
@staticmethod
def clear_logs():
LoggingVolumeDriver._LOGS = []
@staticmethod
def log_action(action, parameters):
"""Logs the command."""
log_dictionary = {}
if parameters:
log_dictionary = dict(parameters)
log_dictionary['action'] = action
LoggingVolumeDriver._LOGS.append(log_dictionary)
@staticmethod
def all_logs():
return LoggingVolumeDriver._LOGS
@staticmethod
def logs_like(action, **kwargs):
matches = []
for entry in LoggingVolumeDriver._LOGS:
if entry['action'] != action:
continue
match = True
for k, v in kwargs.items():
if entry.get(k) != v:
match = False
break
if match:
matches.append(entry)
return matches
def get_volume_stats(self, refresh=False):
return {
'volume_backend_name': self.configuration.safe_get(
'volume_backend_name'),
'vendor_name': 'LoggingVolumeDriver',
'total_capacity_gb': 'infinite',
'free_capacity_gb': 'infinite',
}
class FakeGateDriver(lvm.LVMVolumeDriver):
"""Class designation for FakeGateDriver.

View File

@ -15,7 +15,6 @@ import mock
import uuid
from cinder import quota
from cinder.tests import fake_driver
from cinder.tests.functional.api import client
from cinder.tests.functional import functional_helpers
@ -26,7 +25,6 @@ class NestedQuotasTest(functional_helpers._FunctionalTestBase):
def setUp(self):
super(NestedQuotasTest, self).setUp()
self.api.create_type(self._vol_type_name)
fake_driver.LoggingVolumeDriver.clear_logs()
self._create_project_hierarchy()
# Need to mock out Keystone so the functional tests don't require other
# services
@ -54,7 +52,7 @@ class NestedQuotasTest(functional_helpers._FunctionalTestBase):
def _get_flags(self):
f = super(NestedQuotasTest, self)._get_flags()
f['volume_driver'] = \
'cinder.tests.fake_driver.LoggingVolumeDriver'
'cinder.tests.fake_driver.FakeLoggingVolumeDriver'
f['default_volume_type'] = self._vol_type_name
return f

View File

@ -13,7 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
from cinder.tests import fake_driver
from cinder.tests.functional import functional_helpers
@ -23,12 +22,11 @@ class VolumesTest(functional_helpers._FunctionalTestBase):
def setUp(self):
super(VolumesTest, self).setUp()
self.api.create_type(self._vol_type_name)
fake_driver.LoggingVolumeDriver.clear_logs()
def _get_flags(self):
f = super(VolumesTest, self)._get_flags()
f['volume_driver'] = \
'cinder.tests.fake_driver.LoggingVolumeDriver'
'cinder.tests.fake_driver.FakeLoggingVolumeDriver'
f['default_volume_type'] = self._vol_type_name
return f
@ -75,18 +73,6 @@ class VolumesTest(functional_helpers._FunctionalTestBase):
# Should be gone
self.assertFalse(found_volume)
# Exactly one volume should have been created and deleted
for action_type in ['create_volume', 'delete_volume']:
actions = fake_driver.LoggingVolumeDriver.logs_like(
action_type, id=created_volume_id)
self.assertEqual(1, len(actions))
action = actions[0]
self.assertEqual(created_volume_id, action['id'])
self.assertEqual('nova', action['availability_zone'])
if action_type == 'create_volume':
self.assertEqual(1, action['size'])
def test_create_volume_with_metadata(self):
"""Creates a volume with metadata."""

View File

@ -206,11 +206,11 @@ class BaseBackupTest(test.TestCase):
class BackupTestCase(BaseBackupTest):
"""Test Case for backups."""
@mock.patch.object(cinder.tests.fake_driver.FakeISCSIDriver,
@mock.patch.object(cinder.tests.fake_driver.FakeLoggingVolumeDriver,
'set_initialized')
@mock.patch.object(cinder.tests.fake_driver.FakeISCSIDriver,
@mock.patch.object(cinder.tests.fake_driver.FakeLoggingVolumeDriver,
'do_setup')
@mock.patch.object(cinder.tests.fake_driver.FakeISCSIDriver,
@mock.patch.object(cinder.tests.fake_driver.FakeLoggingVolumeDriver,
'check_for_setup_error')
@mock.patch('cinder.context.get_admin_context')
def test_init_host(self, mock_get_admin_context, mock_check, mock_setup,
@ -676,7 +676,7 @@ class BackupTestCase(BaseBackupTest):
self.assertEqual(fields.BackupStatus.AVAILABLE, backup['status'])
self.assertEqual(vol_size, backup['size'])
@mock.patch.object(fake_driver.FakeISCSIDriver, 'create_snapshot')
@mock.patch.object(fake_driver.FakeLoggingVolumeDriver, 'create_snapshot')
def test_create_temp_snapshot(self, mock_create_snapshot):
volume_manager = importutils.import_object(CONF.volume_manager)
volume_manager.driver.set_initialized()
@ -693,7 +693,8 @@ class BackupTestCase(BaseBackupTest):
self.assertEqual('available', temp_snap['status'])
self.assertEqual('fake_provider_id', temp_snap['provider_id'])
@mock.patch.object(fake_driver.FakeISCSIDriver, 'create_cloned_volume')
@mock.patch.object(fake_driver.FakeLoggingVolumeDriver,
'create_cloned_volume')
def test_create_temp_cloned_volume(self, mock_create_cloned_volume):
volume_manager = importutils.import_object(CONF.volume_manager)
volume_manager.driver.set_initialized()
@ -710,7 +711,7 @@ class BackupTestCase(BaseBackupTest):
self.assertEqual('available', temp_vol['status'])
self.assertEqual('fake_provider_id', temp_vol['provider_id'])
@mock.patch.object(fake_driver.FakeISCSIDriver,
@mock.patch.object(fake_driver.FakeLoggingVolumeDriver,
'create_volume_from_snapshot')
def test_create_temp_volume_from_snapshot(self, mock_create_vol_from_snap):
volume_manager = importutils.import_object(CONF.volume_manager)

View File

@ -34,7 +34,7 @@ def_vol_type = 'fake_vol_type'
def set_defaults(conf):
conf.set_default('default_volume_type', def_vol_type)
conf.set_default('volume_driver',
'cinder.tests.fake_driver.FakeISCSIDriver')
'cinder.tests.fake_driver.FakeLoggingVolumeDriver')
conf.set_default('iscsi_helper', 'fake')
conf.set_default('rpc_backend', 'cinder.openstack.common.rpc.impl_fake')
conf.set_default('connection', 'sqlite://', group='database')

View File

@ -405,7 +405,8 @@ class VolumeTestCase(BaseVolumeTestCase):
# to be volume_backend_name or None
vol0.refresh()
self.assertEqual(volutils.append_host(CONF.host, 'LVM'), vol0.host)
expected_host = volutils.append_host(CONF.host, 'fake')
self.assertEqual(expected_host, vol0.host)
self.volume.delete_volume(self.context, vol0.id, volume=vol0)
self.volume.delete_volume(self.context, vol1.id, volume=vol1)
self.volume.delete_volume(self.context, vol2.id, volume=vol2)
@ -2236,7 +2237,7 @@ class VolumeTestCase(BaseVolumeTestCase):
with mock.patch.object(cinder.volume.volume_types,
'get_volume_type_qos_specs') as type_qos, \
mock.patch.object(cinder.tests.fake_driver.FakeISCSIDriver,
mock.patch.object(cinder.tests.fake_driver.FakeLoggingVolumeDriver,
'initialize_connection') as driver_init:
type_qos.return_value = dict(qos_specs=qos_values)
driver_init.return_value = {'data': {}}
@ -2266,7 +2267,7 @@ class VolumeTestCase(BaseVolumeTestCase):
volume=fake_volume_obj)
self.assertIsNone(conn_info['data']['qos_specs'])
@mock.patch.object(fake_driver.FakeISCSIDriver, 'create_export')
@mock.patch.object(fake_driver.FakeLoggingVolumeDriver, 'create_export')
def test_initialize_connection_export_failure(self,
_mock_create_export):
"""Test exception path for create_export failure."""
@ -3548,15 +3549,6 @@ class VolumeTestCase(BaseVolumeTestCase):
self.assertEqual(fields.SnapshotStatus.AVAILABLE, snapshot_ref.status)
self.mox.UnsetStubs()
self.assertRaises(exception.VolumeBackendAPIException,
self.volume.delete_snapshot,
self.context,
snapshot)
self.assertRaises(exception.VolumeBackendAPIException,
self.volume.delete_volume,
self.context,
volume_id,
volume=volume)
@mock.patch('cinder.volume.drivers.lvm.LVMVolumeDriver.'
'create_cloned_volume')
@ -3702,9 +3694,6 @@ class VolumeTestCase(BaseVolumeTestCase):
image_info.virtual_size = '1073741824'
mock_qemu_info.return_value = image_info
# We want to test BaseVD copy_image_to_volume and since FakeISCSIDriver
# inherits from LVM it overwrites it, so we'll mock it to use the
# BaseVD implementation.
unbound_copy_method = cinder.volume.driver.BaseVD.copy_image_to_volume
bound_copy_method = unbound_copy_method.__get__(self.volume.driver)
with mock.patch.object(self.volume.driver, 'copy_image_to_volume',
@ -4466,7 +4455,7 @@ class VolumeTestCase(BaseVolumeTestCase):
volume,
cascade=True)
@mock.patch.object(fake_driver.FakeISCSIDriver, 'get_volume_stats')
@mock.patch.object(fake_driver.FakeLoggingVolumeDriver, 'get_volume_stats')
@mock.patch.object(driver.BaseVD, '_init_vendor_properties')
def test_get_capabilities(self, mock_init_vendor, mock_get_volume_stats):
stats = {
@ -4543,7 +4532,7 @@ class VolumeTestCase(BaseVolumeTestCase):
self.assertEqual(expected, capabilities)
self.assertTrue(mock_get_volume_stats.called)
@mock.patch.object(fake_driver.FakeISCSIDriver, 'get_volume_stats')
@mock.patch.object(fake_driver.FakeLoggingVolumeDriver, 'get_volume_stats')
@mock.patch.object(driver.BaseVD, '_init_vendor_properties')
@mock.patch.object(driver.BaseVD, '_init_standard_capabilities')
def test_get_capabilities_prefix_error(self, mock_init_standard,
@ -4583,7 +4572,7 @@ class VolumeTestCase(BaseVolumeTestCase):
discover)
self.assertEqual(expected, capabilities['properties'])
@mock.patch.object(fake_driver.FakeISCSIDriver, 'get_volume_stats')
@mock.patch.object(fake_driver.FakeLoggingVolumeDriver, 'get_volume_stats')
@mock.patch.object(driver.BaseVD, '_init_vendor_properties')
@mock.patch.object(driver.BaseVD, '_init_standard_capabilities')
def test_get_capabilities_fail_override(self, mock_init_standard,
@ -5767,7 +5756,8 @@ class CopyVolumeToImageTestCase(BaseVolumeTestCase):
@mock.patch.object(QUOTAS, 'reserve')
@mock.patch.object(QUOTAS, 'commit')
@mock.patch.object(vol_manager.VolumeManager, 'create_volume')
@mock.patch.object(fake_driver.FakeISCSIDriver, 'copy_volume_to_image')
@mock.patch.object(fake_driver.FakeLoggingVolumeDriver,
'copy_volume_to_image')
def _test_copy_volume_to_image_with_image_volume(
self, mock_copy, mock_create, mock_quota_commit,
mock_quota_reserve):
@ -6029,7 +6019,7 @@ class DriverTestCase(test.TestCase):
@ddt.ddt
class GenericVolumeDriverTestCase(DriverTestCase):
"""Test case for VolumeDriver."""
driver_name = "cinder.tests.fake_driver.LoggingVolumeDriver"
driver_name = "cinder.tests.fake_driver.FakeLoggingVolumeDriver"
@mock.patch.object(utils, 'temporary_chown')
@mock.patch('six.moves.builtins.open')
@ -6111,24 +6101,23 @@ class GenericVolumeDriverTestCase(DriverTestCase):
self.volume.driver._attach_volume = mock.MagicMock()
self.volume.driver._detach_volume = mock.MagicMock()
self.volume.driver.terminate_connection = mock.MagicMock()
self.volume.driver._create_temp_cloned_volume = mock.MagicMock()
self.volume.driver._delete_temp_volume = mock.MagicMock()
self.volume.driver._create_temp_snapshot = mock.MagicMock()
self.volume.driver._delete_temp_snapshot = mock.MagicMock()
mock_volume_get.return_value = vol
self.volume.driver._create_temp_cloned_volume.return_value = temp_vol
self.volume.driver._create_temp_snapshot.return_value = temp_vol
mock_get_connector_properties.return_value = properties
f = mock_file_open.return_value = open('/dev/null', 'rb')
backup_service.backup(backup_obj, f, None)
self.volume.driver._attach_volume.return_value = attach_info, vol
self.volume.driver.backup_volume(self.context, backup_obj,
backup_service)
mock_volume_get.assert_called_with(self.context, vol['id'])
self.volume.driver._create_temp_cloned_volume.assert_called_once_with(
self.volume.driver._create_temp_snapshot.assert_called_once_with(
self.context, vol)
self.volume.driver._delete_temp_volume.assert_called_once_with(
self.volume.driver._delete_temp_snapshot.assert_called_once_with(
self.context, temp_vol)
@mock.patch.object(utils, 'temporary_chown')
@ -6144,7 +6133,6 @@ class GenericVolumeDriverTestCase(DriverTestCase):
backup = {'volume_id': vol['id'], 'id': 'backup-for-%s' % vol['id']}
properties = {}
attach_info = {'device': {'path': dev_null}}
root_helper = 'sudo cinder-rootwrap /etc/cinder/rootwrap.conf'
volume_file = mock.MagicMock()
mock_open.return_value.__enter__.return_value = volume_file
@ -6159,36 +6147,11 @@ class GenericVolumeDriverTestCase(DriverTestCase):
True)
backup_service = mock.MagicMock()
for i in (1, 2):
self.volume.driver.restore_backup(self.context, backup, vol,
backup_service)
mock_get_connector_properties.assert_called_with(root_helper,
CONF.my_ip,
False, False)
self.volume.driver._attach_volume.assert_called_with(
self.context, vol, properties)
self.assertEqual(i, self.volume.driver._attach_volume.call_count)
self.volume.driver._detach_volume.assert_called_with(
self.context, attach_info, vol, properties)
self.assertEqual(i, self.volume.driver._detach_volume.call_count)
self.volume.driver.secure_file_operations_enabled.\
assert_called_with()
self.assertEqual(
i,
self.volume.driver.secure_file_operations_enabled.call_count
)
mock_temporary_chown.assert_called_once_with(dev_null)
mock_open.assert_called_with(dev_null, 'wb')
self.assertEqual(i, mock_open.call_count)
backup_service.restore.assert_called_with(backup, vol['id'],
volume_file)
self.assertEqual(i, backup_service.restore.call_count)
self.volume.driver.restore_backup(self.context, backup, vol,
backup_service)
backup_service.restore.assert_called_with(backup, vol['id'],
volume_file)
self.assertEqual(1, backup_service.restore.call_count)
def test_get_backup_device_available(self):
vol = tests_utils.create_volume(self.context)

View File

@ -46,7 +46,7 @@ class LVMVolumeDriverTestCase(test_volume.DriverTestCase):
'id': 'test1'}
@mock.patch.object(os.path, 'exists', return_value=True)
@mock.patch.object(fake_driver.FakeISCSIDriver, 'create_export')
@mock.patch.object(fake_driver.FakeLoggingVolumeDriver, 'create_export')
def test_delete_volume_invalid_parameter(self, _mock_create_export,
mock_exists):
self.configuration.volume_clear = 'zero'
@ -59,7 +59,7 @@ class LVMVolumeDriverTestCase(test_volume.DriverTestCase):
self.FAKE_VOLUME)
@mock.patch.object(os.path, 'exists', return_value=False)
@mock.patch.object(fake_driver.FakeISCSIDriver, 'create_export')
@mock.patch.object(fake_driver.FakeLoggingVolumeDriver, 'create_export')
def test_delete_volume_bad_path(self, _mock_create_export, mock_exists):
self.configuration.volume_clear = 'zero'
self.configuration.volume_clear_size = 0
@ -74,7 +74,7 @@ class LVMVolumeDriverTestCase(test_volume.DriverTestCase):
@mock.patch.object(volutils, 'clear_volume')
@mock.patch.object(volutils, 'copy_volume')
@mock.patch.object(fake_driver.FakeISCSIDriver, 'create_export')
@mock.patch.object(fake_driver.FakeLoggingVolumeDriver, 'create_export')
def test_delete_volume_thinlvm_snap(self, _mock_create_export,
mock_copy, mock_clear):
vg_obj = fake_lvm.FakeBrickLVM('cinder-volumes',