Merge "Move get_volume_stats impl to the base volume driver"

This commit is contained in:
Zuul 2020-07-01 20:21:35 +00:00 committed by Gerrit Code Review
commit 61709c5449
34 changed files with 43 additions and 332 deletions

View File

@ -60,6 +60,9 @@ class VolumeDriverCore(base.CinderInterface):
information from the driver instance related to information about the
driver, available and used space, and driver/backend capabilities.
stats are stored in 'self._stats' field, which could be updated in
'_update_volume_stats' method.
It returns a dict with the following required fields:
* volume_backend_name

View File

@ -281,6 +281,8 @@ class FakeConfiguration(object):
self.retries = retries
self.volume_backend_name = volume_backend_name
self.config_group = volume_backend_name
self.filter_function = None
self.goodness_function = None
self.san_is_local = False
if replication_device:
self.replication_device = replication_device

View File

@ -207,18 +207,22 @@ class PowerMaxFCTest(test.TestCase):
def test_get_volume_stats(self):
with mock.patch.object(
self.driver, 'update_volume_stats') as mock_update:
# no refresh
self.driver.get_volume_stats()
mock_update.assert_not_called()
self.driver, '_update_volume_stats') as mock_update:
# with refresh
self.driver.get_volume_stats(True)
# set fake stats
self.driver._stats['driver_version'] = self.driver.VERSION
# no refresh
self.driver.get_volume_stats()
mock_update.assert_called_once_with()
def test_update_volume_stats(self):
with mock.patch.object(self.common, 'update_volume_stats',
return_value={}) as mock_update:
self.driver.update_volume_stats()
self.driver._update_volume_stats()
mock_update.assert_called_once_with()
def test_check_for_setup_error(self):

View File

@ -246,18 +246,14 @@ class PowerMaxISCSITest(test.TestCase):
def test_get_volume_stats(self):
with mock.patch.object(
self.driver, 'update_volume_stats') as mock_update:
# no refresh
self.driver.get_volume_stats()
mock_update.assert_not_called()
# with refresh
self.driver, '_update_volume_stats') as mock_update:
self.driver.get_volume_stats(True)
mock_update.assert_called_once_with()
def test_update_volume_stats(self):
with mock.patch.object(self.common, 'update_volume_stats',
return_value={}) as mock_update:
self.driver.update_volume_stats()
self.driver.get_volume_stats()
mock_update.assert_called_once_with()
def test_check_for_setup_error(self):

View File

@ -1014,14 +1014,6 @@ class RSDDriverTestCase(test_driver.BaseDriverTestCase):
self.rsd_client.delete_vol_or_snap.assert_called()
self.assertEqual(2, self.rsd_client.delete_vol_or_snap.call_count)
def test_get_volume_stats(self):
ret_tuple = (25.0, 60.0, 35.0, 6)
self.rsd_client.get_stats = mock.Mock(return_value=ret_tuple)
stats = self.volume.driver.get_volume_stats()
self.assertEqual({}, stats)
def test_get_volume_stats_refresh(self):
ret_tuple = (25.0, 60.0, 35.0, 6)
self.rsd_client.get_stats = mock.Mock(return_value=ret_tuple)

View File

@ -630,14 +630,14 @@ class BaseVD(object):
return False
def get_volume_stats(self, refresh=False):
"""Return the current state of the volume service.
"""Get volume stats.
If 'refresh' is True, run the update first.
For replication the following state should be reported:
replication = True (None or false disables replication)
If 'refresh' is True, run update the stats first.
"""
return
if not self._stats or refresh:
self._update_volume_stats()
return self._stats
def get_prefixed_property(self, property):
"""Return prefixed property name
@ -2780,16 +2780,6 @@ class ISCSIDriver(VolumeDriver):
def terminate_connection(self, volume, connector, **kwargs):
pass
def get_volume_stats(self, refresh=False):
"""Get volume stats.
If 'refresh' is True, run update the stats first.
"""
if refresh:
self._update_volume_stats()
return self._stats
def _update_volume_stats(self):
"""Retrieve stats info from volume group."""
@ -2935,16 +2925,6 @@ class FibreChannelDriver(VolumeDriver):
{'setting': setting})
raise exception.InvalidConnectorException(missing=setting)
def get_volume_stats(self, refresh=False):
"""Get volume stats.
If 'refresh' is True, run update the stats first.
"""
if refresh:
self._update_volume_stats()
return self._stats
def _update_volume_stats(self):
"""Retrieve stats info from volume group."""

View File

@ -489,18 +489,7 @@ class PowerMaxFCDriver(san.SanDriver, driver.FibreChannelDriver):
"""
self.common.extend_volume(volume, new_size)
def get_volume_stats(self, refresh=False):
"""Get volume stats.
:param refresh: boolean -- If True, run update the stats first.
:returns: dict -- the stats dict
"""
if refresh:
self.update_volume_stats()
return self._stats
def update_volume_stats(self):
def _update_volume_stats(self):
"""Retrieve stats info from volume group."""
LOG.debug("Updating volume stats")
data = self.common.update_volume_stats()

View File

@ -405,18 +405,7 @@ class PowerMaxISCSIDriver(san.SanISCSIDriver):
"""
self.common.extend_volume(volume, new_size)
def get_volume_stats(self, refresh=False):
"""Get volume stats.
:param refresh: boolean -- If True, run update the stats first.
:returns: dict -- the stats dict
"""
if refresh:
self.update_volume_stats()
return self._stats
def update_volume_stats(self):
def _update_volume_stats(self):
"""Retrieve stats info from volume group."""
LOG.debug("Updating volume stats")
data = self.common.update_volume_stats()

View File

@ -702,21 +702,6 @@ class SCCommonDriver(driver.ManageableVD,
msg = _('Unable to extend volume %s') % volume_name
raise exception.VolumeBackendAPIException(data=msg)
def get_volume_stats(self, refresh=False):
"""Get volume status.
If 'refresh' is True, run update the stats first.
"""
if refresh:
self._update_volume_stats()
# Take this opportunity to report our failover state.
if self.failed_over:
LOG.debug('%(source)s has been failed over to %(dest)s',
{'source': self.backend_name,
'dest': self.active_backend_id})
return self._stats
def _update_volume_stats(self):
"""Retrieve stats info from volume group."""
with self._client.open_connection() as api:
@ -765,6 +750,12 @@ class SCCommonDriver(driver.ManageableVD,
{'total': data['total_capacity_gb'],
'free': data['free_capacity_gb']})
# Take this opportunity to report our failover state.
if self.failed_over:
LOG.debug('%(source)s has been failed over to %(dest)s',
{'source': self.backend_name,
'dest': self.active_backend_id})
def update_migrated_volume(self, ctxt, volume, new_volume,
original_volume_status):
"""Return model update for migrated volume.

View File

@ -226,17 +226,7 @@ class UnityDriver(driver.ManageableVD,
zm_utils.remove_fc_zone(conn_info)
return conn_info
def get_volume_stats(self, refresh=False):
"""Get volume stats.
:param refresh: True to get updated data
"""
if refresh:
self.update_volume_stats()
return self._stats
def update_volume_stats(self):
def _update_volume_stats(self):
"""Retrieve stats info from volume group."""
LOG.debug("Updating volume stats.")
stats = self.adapter.update_volume_stats()

View File

@ -244,17 +244,7 @@ class VNXDriver(driver.ManageableVD,
zm_utils.remove_fc_zone(conn_info)
return conn_info
def get_volume_stats(self, refresh=False):
"""Get volume stats.
:param refresh: True to get updated data
"""
if refresh:
self.update_volume_stats()
return self._stats
def update_volume_stats(self):
def _update_volume_stats(self):
"""Retrieve stats info from volume group."""
LOG.debug("Updating volume stats.")
self._stats = self.adapter.update_volume_stats()

View File

@ -1153,19 +1153,6 @@ class VxFlexOSDriver(driver.VolumeDriver):
return r["dataLayout"] == "FineGranularity"
return False
def get_volume_stats(self, refresh=False):
"""Get volume stats.
If 'refresh' is True, run update the stats first.
:param refresh: update stats or get them from cache
:return: storage backend stats
"""
if refresh:
self._update_volume_stats()
return self._stats
@staticmethod
def _get_volumetype_extraspecs(volume):
specs = {}

View File

@ -638,15 +638,6 @@ class XtremIOVolumeDriver(san.SanDriver):
}
self._stats.update(self.client.get_extra_capabilities())
def get_volume_stats(self, refresh=False):
"""Get volume stats.
If 'refresh' is True, run update the stats first.
"""
if refresh:
self._update_volume_stats()
return self._stats
def manage_existing(self, volume, existing_ref, is_snapshot=False):
"""Manages an existing LV."""
lv_name = existing_ref['source-name']

View File

@ -1187,17 +1187,6 @@ class FlashSystemDriver(san.SanDriver,
LOG.debug('leave: create_cloned_volume: create %(vol)s from %(src)s.',
{'src': src_volume['name'], 'vol': volume['name']})
def get_volume_stats(self, refresh=False):
"""Get volume stats.
If we haven't gotten stats yet or 'refresh' is True,
run update the stats first.
"""
if not self._stats or refresh:
self._update_volume_stats()
return self._stats
def manage_existing(self, volume, existing_ref):
"""Manages an existing vdisk.

View File

@ -838,17 +838,6 @@ class GPFSDriver(driver.CloneableImageVD,
def terminate_connection(self, volume, connector, **kwargs):
pass
def get_volume_stats(self, refresh=False):
"""Get volume stats.
If 'refresh' is True, or stats have never been updated, run update
the stats first.
"""
if not self._stats or refresh:
self._update_volume_stats()
return self._stats
def _update_volume_stats(self):
"""Retrieve stats info from volume group."""
@ -1552,17 +1541,6 @@ class GPFSNFSDriver(GPFSDriver, nfs.NfsDriver, san.SanDriver):
super(GPFSNFSDriver, self).do_setup(context)
self._context = context
def get_volume_stats(self, refresh=False):
"""Get volume stats.
If 'refresh' is True, or stats have never been updated, run update
the stats first.
"""
if not self._stats or refresh:
self._update_volume_stats()
return self._stats
def _update_volume_stats(self):
"""Retrieve stats info from volume group."""

View File

@ -5181,17 +5181,6 @@ class StorwizeSVCCommonDriver(san.SanDriver,
"""Remove the specified volume from Cinder management."""
pass
def get_volume_stats(self, refresh=False):
"""Get volume stats.
If we haven't gotten stats yet or 'refresh' is True,
run update the stats first.
"""
if not self._stats or refresh:
self._update_volume_stats()
return self._stats
@staticmethod
def _get_rccg_name(group, grp_id=None, hyper_grp=False):
group_id = group.id if group else grp_id

View File

@ -457,17 +457,6 @@ class AS13000Driver(san.SanISCSIDriver):
request_type = 'delete'
self._rest.send_rest_api(method=method, request_type=request_type)
@utils.trace
def get_volume_stats(self, refresh=False):
"""Get volume stats.
If we haven't gotten stats yet or 'refresh' is True,
run update the stats first.
"""
if not self._stats or refresh:
self._update_volume_stats()
return self._stats
@utils.trace
def _update_volume_stats(self):
"""Update the backend stats including driver info and pools info."""

View File

@ -1012,17 +1012,6 @@ class InStorageMCSCommonDriver(driver.VolumeDriver, san.SanDriver):
"""Remove the specified volume from Cinder management."""
pass
def get_volume_stats(self, refresh=False):
"""Get volume stats.
If we haven't gotten stats yet or 'refresh' is True,
run update the stats first.
"""
if not self._stats or refresh:
self._update_volume_stats()
return self._stats
# ## Group method ## #
def create_group(self, context, group):
"""Create a group.

View File

@ -581,17 +581,6 @@ class LVMVolumeDriver(driver.VolumeDriver):
image_service):
return None, False
def get_volume_stats(self, refresh=False):
"""Get volume status.
If 'refresh' is True, run update the stats first.
"""
if refresh:
self._update_volume_stats()
return self._stats
def extend_volume(self, volume, new_size):
"""Extend an existing volume's size."""
self.vg.extend_volume(volume['name'],

View File

@ -708,13 +708,6 @@ class MacroSANBaseDriver(driver.VolumeDriver):
pass
@record_request_id
def get_volume_stats(self, refresh=False):
"""Get volume stats."""
if refresh:
self._update_volume_stats()
return self._stats
def _update_volume_stats(self):
data = {}
pool = {}

View File

@ -643,16 +643,6 @@ class NexentaISCSIDriver(driver.ISCSIDriver):
zvol_name = self._get_zvol_name(volume['name'])
self.nms.scsidisk.delete_lu(zvol_name)
def get_volume_stats(self, refresh=False):
"""Get volume stats.
If 'refresh' is True, run update the stats first.
"""
if refresh:
self._update_volume_stats()
return self._stats
def _update_volume_stats(self):
"""Retrieve stats info for NexentaStor appliance."""
LOG.debug('Updating volume stats')

View File

@ -357,16 +357,6 @@ class NexentaISCSIDriver(driver.ISCSIDriver):
'tg': mapping_tg, 'hg': mapping_hg})
return info
def get_volume_stats(self, refresh=False):
"""Get volume stats.
If 'refresh' is True, run update the stats first.
"""
if refresh or not self._stats:
self._update_volume_stats()
return self._stats
def _update_volume_stats(self):
"""Retrieve stats info for NexentaStor appliance."""
LOG.debug('Updating volume backend %(volume_backend_name)s stats',

View File

@ -818,16 +818,6 @@ class NexentaNfsDriver(nfs.NfsDriver):
volume_path = posixpath.join(self.root_path, volume_name)
return '%s@%s' % (volume_path, snapshot_name)
def get_volume_stats(self, refresh=False):
"""Get volume stats.
If 'refresh' is True, update the stats first.
"""
if refresh or not self._stats:
self._update_volume_stats()
return self._stats
def _update_volume_stats(self):
"""Retrieve stats info for NexentaStor Appliance."""
LOG.debug('Updating volume backend %(volume_backend_name)s stats',

View File

@ -1403,16 +1403,6 @@ class DPLCOMMONDriver(driver.CloneableImageVD,
LOG.info('Flexvisor succeeded to delete snapshot %(id)s.',
{'id': snapshot['id']})
def get_volume_stats(self, refresh=False):
"""Get volume stats.
If 'refresh' is True, run update the stats first.
"""
if refresh:
self._update_volume_stats()
return self._stats
def _get_pools(self):
pools = []
qpools = []

View File

@ -730,18 +730,7 @@ class PureBaseVolumeDriver(san.SanDriver):
return not host_still_used
@pure_driver_debug_trace
def get_volume_stats(self, refresh=False):
"""Return the current state of the volume service.
If 'refresh' is True, run the update first.
"""
if refresh:
LOG.debug("Updating volume stats.")
self._update_stats()
return self._stats
def _update_stats(self):
def _update_volume_stats(self):
"""Set self._stats with relevant information."""
current_array = self._get_current_array()

View File

@ -619,15 +619,6 @@ class RBDDriver(driver.CloneableImageVD, driver.MigrateVD,
LOG.exception('error refreshing volume stats')
self._stats = stats
def get_volume_stats(self, refresh=False):
"""Return the current state of the volume service.
If 'refresh' is True, run the update first.
"""
if refresh:
self._update_volume_stats()
return self._stats
def _get_clone_depth(self, client, volume_name, depth=0):
"""Returns the number of ancestral clones of the given volume."""
parent_volume = self.rbd.Image(client.ioctx, volume_name)

View File

@ -606,16 +606,6 @@ class RemoteFSDriver(driver.BaseVD):
"""Disallow connection from connector."""
pass
def get_volume_stats(self, refresh=False):
"""Get volume stats.
If 'refresh' is True, update the stats first.
"""
if refresh or not self._stats:
self._update_volume_stats()
return self._stats
def _update_volume_stats(self):
"""Retrieve stats info from volume group."""

View File

@ -570,6 +570,7 @@ class RSDDriver(driver.VolumeDriver):
volume_name=volume.name,
ignore_non_exist=True)
@utils.trace
def _update_volume_stats(self):
backend_name = (
self.configuration.safe_get('volume_backend_name') or 'RSD')
@ -596,12 +597,6 @@ class RSDDriver(driver.VolumeDriver):
# SinglePool
self._stats['pools'] = [spool]
@utils.trace
def get_volume_stats(self, refresh=False):
if refresh:
self._update_volume_stats()
return self._stats
@utils.trace
def initialize_connection(self, volume, connector, **kwargs):
uuid = connector.get("system uuid")

View File

@ -129,12 +129,6 @@ class SdsBaseDriver(driver.VolumeDriver):
data['pools'].append(pool)
return data
def get_volume_stats(self, refresh=False):
"""Get volume status and reload sandstone config file."""
if refresh:
return self._update_volume_stats(self.pool)
return self._stats
def _raise_exception(self, msg):
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)

View File

@ -233,12 +233,6 @@ class SPDKDriver(driver.VolumeDriver):
self._delete_bdev(volume.name)
def get_volume_stats(self, refresh=False):
if refresh:
self._update_volume_stats()
return self._stats
def create_volume_from_snapshot(self, volume, snapshot):
"""Creates a volume from a snapshot."""

View File

@ -262,12 +262,6 @@ class StorPoolDriver(driver.VolumeDriver):
LOG.error("StorPoolDriver API initialization failed: %s", e)
raise
def get_volume_stats(self, refresh=False):
if refresh:
self._update_volume_stats()
return self._stats
def _update_volume_stats(self):
try:
dl = self._attach.api().disksList()

View File

@ -329,19 +329,13 @@ class VMwareVcVmdkDriver(driver.VolumeDriver):
def check_for_setup_error(self):
pass
def get_volume_stats(self, refresh=False):
"""Obtain status of the volume service.
def _update_volume_stats(self):
if self.configuration.safe_get('vmware_enable_volume_stats'):
self._stats = self._get_volume_stats()
else:
self._stats = self._get_fake_stats()
:param refresh: Whether to get refreshed information
"""
if not self._stats or refresh:
if self.configuration.safe_get('vmware_enable_volume_stats'):
self._stats = self._get_volume_stats(refresh)
else:
self._stats = self._get_fake_stats(refresh)
return self._stats
def _get_fake_stats(self, refresh=False):
def _get_fake_stats(self):
"""Provide fake stats to the scheduler.
:param refresh: Whether to get refreshed information
@ -361,7 +355,7 @@ class VMwareVcVmdkDriver(driver.VolumeDriver):
self._stats = data
return self._stats
def _get_volume_stats(self, refresh=False):
def _get_volume_stats(self):
"""Fetch the stats about the backend.
This can be slow at scale, but allows
@ -395,6 +389,7 @@ class VMwareVcVmdkDriver(driver.VolumeDriver):
break
data['total_capacity_gb'] = round(global_capacity / units.Gi)
data['free_capacity_gb'] = round(global_free / units.Gi)
self._stats = data
return data
def _get_datastore_summaries(self):

View File

@ -722,17 +722,6 @@ class ZadaraVPSAISCSIDriver(driver.ISCSIDriver):
# Detach volume from server
self._detach_vpsa_volume(vpsa_vol=vpsa_vol, vpsa_srv=vpsa_srv)
def get_volume_stats(self, refresh=False):
"""Get volume stats.
If 'refresh' is True, run update the stats first.
"""
if refresh:
self._update_volume_stats()
return self._stats
def _get_servers_attached_to_volume(self, vpsa_vol):
"""Return all servers attached to volume."""
xml_tree = self.vpsa.send_cmd('list_vol_attachments',

View File

@ -14,7 +14,7 @@ fixtures>=3.0.0 # Apache-2.0/BSD
oslotest>=3.2.0 # Apache-2.0
pycodestyle==2.6.0 # MIT License
PyMySQL>=0.7.6 # MIT License
psycopg2>=2.7 # LGPL/ZPL
# psycopg2>=2.7 # LGPL/ZPL
SQLAlchemy-Utils>=0.36.1 # BSD License
testtools>=2.2.0 # MIT
oslo.versionedobjects[fixtures]>=1.31.2 # Apache-2.0