Skip to content

Commit

Permalink
Fix ability to add custom volume_backend_name
Browse files Browse the repository at this point in the history
This patch fixes the ability to set the volume_backend_name
for each driver.   The original bug was filed against LeftHand
and 3PAR, but several drivers exhibited a fixed backend name.

Fixes: bug #1175222
       bug #1172286

Change-Id: I4197f99bebd6ca8e4969795ae6edb537bc066c90
(cherry picked from commit 54a2ee4)
  • Loading branch information
hemna authored and j-griffith committed May 7, 2013
1 parent 79b9582 commit 995a310
Show file tree
Hide file tree
Showing 13 changed files with 115 additions and 65 deletions.
16 changes: 14 additions & 2 deletions cinder/tests/test_hp3par.py
Expand Up @@ -492,9 +492,15 @@ def test_create_cloned_volume(self):

def test_get_volume_stats(self):
self.flags(lock_path=self.tempdir)

def fake_safe_get(*args):
return "HP3PARFCDriver"

self.stubs.Set(self.driver.configuration, 'safe_get', fake_safe_get)
stats = self.driver.get_volume_stats(True)
self.assertEquals(stats['storage_protocol'], 'FC')
self.assertEquals(stats['volume_backend_name'], 'HP3PARFCDriver')
self.assertEquals(stats['total_capacity_gb'], 'infinite')
self.assertEquals(stats['free_capacity_gb'], 'infinite')


class TestHP3PARISCSIDriver(HP3PARBaseDriver, test.TestCase):
Expand Down Expand Up @@ -631,6 +637,12 @@ def test_create_cloned_volume(self):

def test_get_volume_stats(self):
self.flags(lock_path=self.tempdir)

def fake_safe_get(*args):
return "HP3PARFCDriver"

self.stubs.Set(self.driver.configuration, 'safe_get', fake_safe_get)
stats = self.driver.get_volume_stats(True)
self.assertEquals(stats['storage_protocol'], 'iSCSI')
self.assertEquals(stats['volume_backend_name'], 'HP3PARISCSIDriver')
self.assertEquals(stats['total_capacity_gb'], 'infinite')
self.assertEquals(stats['free_capacity_gb'], 'infinite')
10 changes: 10 additions & 0 deletions cinder/tests/test_rbd.py
Expand Up @@ -153,7 +153,12 @@ def test_copy_image_volume_tmp(self):
def test_update_volume_stats(self):
def fake_stats(*args):
return RADOS_DF_OUT, ''

def fake_safe_get(*args):
return "RBD"

self.stubs.Set(self.driver, '_execute', fake_stats)
self.stubs.Set(self.driver.configuration, 'safe_get', fake_safe_get)
expected = dict(
volume_backend_name='RBD',
vendor_name='Open Source',
Expand All @@ -168,7 +173,12 @@ def fake_stats(*args):
def test_update_volume_stats_error(self):
def fake_exc(*args):
raise exception.ProcessExecutionError()

def fake_safe_get(*args):
return "RBD"

self.stubs.Set(self.driver, '_execute', fake_exc)
self.stubs.Set(self.driver.configuration, 'safe_get', fake_safe_get)
expected = dict(
volume_backend_name='RBD',
vendor_name='Open Source',
Expand Down
8 changes: 5 additions & 3 deletions cinder/volume/drivers/coraid.py
Expand Up @@ -400,13 +400,15 @@ def initialize_connection(self, volume, connector):

def get_volume_stats(self, refresh=False):
"""Return Volume Stats."""
return {'driver_version': '1.0',
data = {'driver_version': '1.0',
'free_capacity_gb': 'unknown',
'reserved_percentage': 0,
'storage_protocol': 'aoe',
'total_capacity_gb': 'unknown',
'vendor_name': 'Coraid',
'volume_backend_name': 'EtherCloud ESM'}
'vendor_name': 'Coraid'}
backend_name = self.configuration.safe_get('volume_backend_name')
data['volume_backend_name'] = backend_name or 'EtherCloud ESM'
return data

def local_path(self, volume):
pass
Expand Down
3 changes: 2 additions & 1 deletion cinder/volume/drivers/emc/emc_smis_iscsi.py
Expand Up @@ -240,6 +240,7 @@ def update_volume_status(self):
"""Retrieve status info from volume group."""
LOG.debug(_("Updating volume status"))
data = self.common.update_volume_status()
data['volume_backend_name'] = 'EMCSMISISCSIDriver'
backend_name = self.configuration.safe_get('volume_backend_name')
data['volume_backend_name'] = backend_name or 'EMCSMISISCSIDriver'
data['storage_protocol'] = 'iSCSI'
self._stats = data
3 changes: 2 additions & 1 deletion cinder/volume/drivers/huawei/huawei_iscsi.py
Expand Up @@ -1393,7 +1393,8 @@ def _update_volume_status(self):

LOG.debug(_("Updating volume status"))
data = {}
data['volume_backend_name'] = 'HuaweiISCSIDriver'
backend_name = self.configuration.safe_get('volume_backend_name')
data["volume_backend_name"] = backend_name or 'HuaweiISCSIDriver'
data['vendor_name'] = 'Huawei'
data['driver_version'] = '1.0'
data['storage_protocol'] = 'iSCSI'
Expand Down
5 changes: 4 additions & 1 deletion cinder/volume/drivers/nexenta/volume.py
Expand Up @@ -316,7 +316,10 @@ def _update_volume_status(self):

LOG.debug(_("Updating volume status"))
data = {}
data["volume_backend_name"] = self.__class__.__name__
backend_name = self.__class__.__name__
if self.configuration:
backend_name = self.configuration.safe_get('volume_backend_name')
data["volume_backend_name"] = backend_name or self.__class__.__name__
data["vendor_name"] = 'Nexenta'
data["driver_version"] = VERSION
data["storage_protocol"] = 'iSCSI'
Expand Down
23 changes: 11 additions & 12 deletions cinder/volume/drivers/rbd.py
Expand Up @@ -54,14 +54,7 @@ class RBDDriver(driver.VolumeDriver):
def __init__(self, *args, **kwargs):
super(RBDDriver, self).__init__(*args, **kwargs)
self.configuration.append_config_values(rbd_opts)
self._stats = dict(
volume_backend_name='RBD',
vendor_name='Open Source',
driver_version=VERSION,
storage_protocol='ceph',
total_capacity_gb='unknown',
free_capacity_gb='unknown',
reserved_percentage=0)
self._stats = {}

def check_for_setup_error(self):
"""Returns an error if prerequisites aren't met"""
Expand All @@ -73,9 +66,15 @@ def check_for_setup_error(self):
raise exception.VolumeBackendAPIException(data=exception_message)

def _update_volume_stats(self):
stats = dict(
total_capacity_gb='unknown',
free_capacity_gb='unknown')
stats = {'vendor_name': 'Open Source',
'driver_version': VERSION,
'storage_protocol': 'ceph',
'total_capacity_gb': 'unknown',
'free_capacity_gb': 'unknown',
'reserved_percentage': 0}
backend_name = self.configuration.safe_get('volume_backend_name')
stats['volume_backend_name'] = backend_name or 'RBD'

try:
stdout, _err = self._execute('rados', 'df', '--format', 'json')
new_stats = json.loads(stdout)
Expand All @@ -86,7 +85,7 @@ def _update_volume_stats(self):
except exception.ProcessExecutionError:
# just log and return unknown capacities
LOG.exception(_('error refreshing volume stats'))
self._stats.update(stats)
self._stats = stats

def get_volume_stats(self, refresh=False):
"""Return the current state of the volume service. If 'refresh' is
Expand Down
58 changes: 34 additions & 24 deletions cinder/volume/drivers/san/hp/hp_3par_common.py
Expand Up @@ -95,13 +95,7 @@

class HP3PARCommon():

stats = {'driver_version': '1.0',
'free_capacity_gb': 'unknown',
'reserved_percentage': 0,
'storage_protocol': None,
'total_capacity_gb': 'unknown',
'vendor_name': 'Hewlett-Packard',
'volume_backend_name': None}
stats = {}

# Valid values for volume type extra specs
# The first value in the list is the default value
Expand Down Expand Up @@ -417,26 +411,42 @@ def get_volume_stats(self, refresh, client):
const = 0.0009765625

if refresh:
try:
cpg = client.getCPG(self.config.hp3par_cpg)
if 'limitMiB' not in cpg['SDGrowth']:
total_capacity = 'infinite'
free_capacity = 'infinite'
else:
total_capacity = int(cpg['SDGrowth']['limitMiB'] * const)
free_capacity = int((cpg['SDGrowth']['limitMiB'] -
cpg['UsrUsage']['usedMiB']) * const)

self.stats['total_capacity_gb'] = total_capacity
self.stats['free_capacity_gb'] = free_capacity
except hpexceptions.HTTPNotFound:
err = (_("CPG (%s) doesn't exist on array")
% self.config.hp3par_cpg)
LOG.error(err)
raise exception.InvalidInput(reason=err)
self._update_volume_stats(client)

return self.stats

def _update_volume_stats(self, client):

# storage_protocol and volume_backend_name are
# set in the child classes
stats = {'driver_version': '1.0',
'free_capacity_gb': 'unknown',
'reserved_percentage': 0,
'storage_protocol': None,
'total_capacity_gb': 'unknown',
'vendor_name': 'Hewlett-Packard',
'volume_backend_name': None}

try:
cpg = client.getCPG(self.config.hp3par_cpg)
if 'limitMiB' not in cpg['SDGrowth']:
total_capacity = 'infinite'
free_capacity = 'infinite'
else:
total_capacity = int(cpg['SDGrowth']['limitMiB'] * const)
free_capacity = int((cpg['SDGrowth']['limitMiB'] -
cpg['UsrUsage']['usedMiB']) * const)

stats['total_capacity_gb'] = total_capacity
stats['free_capacity_gb'] = free_capacity
except hpexceptions.HTTPNotFound:
err = (_("CPG (%s) doesn't exist on array")
% self.config.hp3par_cpg)
LOG.error(err)
raise exception.InvalidInput(reason=err)

self.stats = stats

def create_vlun(self, volume, host, client):
"""
In order to export a volume on a 3PAR box, we have to
Expand Down
3 changes: 2 additions & 1 deletion cinder/volume/drivers/san/hp/hp_3par_fc.py
Expand Up @@ -76,7 +76,8 @@ def _create_client(self):
def get_volume_stats(self, refresh):
stats = self.common.get_volume_stats(refresh, self.client)
stats['storage_protocol'] = 'FC'
stats['volume_backend_name'] = 'HP3PARFCDriver'
backend_name = self.configuration.safe_get('volume_backend_name')
stats['volume_backend_name'] = backend_name or self.__class__.__name__
return stats

def do_setup(self, context):
Expand Down
3 changes: 2 additions & 1 deletion cinder/volume/drivers/san/hp/hp_3par_iscsi.py
Expand Up @@ -75,7 +75,8 @@ def _create_client(self):
def get_volume_stats(self, refresh):
stats = self.common.get_volume_stats(refresh, self.client)
stats['storage_protocol'] = 'iSCSI'
stats['volume_backend_name'] = 'HP3PARISCSIDriver'
backend_name = self.configuration.safe_get('volume_backend_name')
stats['volume_backend_name'] = backend_name or self.__class__.__name__
return stats

def do_setup(self, context):
Expand Down
3 changes: 2 additions & 1 deletion cinder/volume/drivers/scality.py
Expand Up @@ -223,14 +223,15 @@ def get_volume_stats(self, refresh=False):
If 'refresh' is True, run the update first.
"""
stats = {
'volume_backend_name': 'Scality_SOFS',
'vendor_name': 'Scality',
'driver_version': '1.0',
'storage_protocol': 'scality',
'total_capacity_gb': 'infinite',
'free_capacity_gb': 'infinite',
'reserved_percentage': 0,
}
backend_name = self.configuration.safe_get('volume_backend_name')
stats['volume_backend_name'] = backend_name or 'Scality_SOFS'
return stats

def copy_image_to_volume(self, context, volume, image_service, image_id):
Expand Down
26 changes: 16 additions & 10 deletions cinder/volume/drivers/sheepdog.py
Expand Up @@ -33,16 +33,8 @@ class SheepdogDriver(driver.VolumeDriver):

def __init__(self, *args, **kwargs):
super(SheepdogDriver, self).__init__(*args, **kwargs)
self._stats = dict(
volume_backend_name='sheepdog',
vendor_name='Open Source',
dirver_version='1.0',
storage_protocol='sheepdog',
total_capacity_gb='unknown',
free_capacity_gb='unknown',
reserved_percentage=0,
QoS_support=False)
self.stats_pattern = re.compile(r'[\w\s%]*Total\s(\d+)\s(\d+)*')
self._stats = {}

def check_for_setup_error(self):
"""Returns an error if prerequisites aren't met"""
Expand Down Expand Up @@ -118,6 +110,19 @@ def terminate_connection(self, volume, connector, **kwargs):

def _update_volume_stats(self):
stats = {}

backend_name = "sheepdog"
if self.configuration:
backend_name = self.configuration.safe_get('volume_backend_name')
stats["volume_backend_name"] = backend_name or 'sheepdog'
stats['vendor_name'] = 'Open Source'
stats['dirver_version'] = '1.0'
stats['storage_protocol'] = 'sheepdog'
stats['total_capacity_gb'] = 'unknown'
stats['free_capacity_gb'] = 'unknown'
stats['reserved_percentage'] = 0
stats['QoS_support'] = False

try:
stdout, _err = self._execute('collie', 'node', 'info', '-r')
m = self.stats_pattern.match(stdout)
Expand All @@ -127,7 +132,8 @@ def _update_volume_stats(self):
stats['free_capacity_gb'] = (total - used) / (1024 ** 3)
except exception.ProcessExecutionError:
LOG.exception(_('error refreshing volume stats'))
self._stats.update(stats)

self._stats = stats

def get_volume_stats(self, refresh=False):
if refresh:
Expand Down
19 changes: 11 additions & 8 deletions cinder/volume/drivers/xenapi/sm.py
Expand Up @@ -245,14 +245,17 @@ def _use_glance_plugin_to_upload_volume(self, context, volume,

def get_volume_stats(self, refresh=False):
if refresh or not self._stats:
self._stats = dict(
volume_backend_name='XenAPINFS',
vendor_name='Open Source',
driver_version='1.0',
storage_protocol='xensm',
total_capacity_gb='unknown',
free_capacity_gb='unknown',
reserved_percentage=0)
data = {}

backend_name = self.configuration.safe_get('volume_backend_name')
data["volume_backend_name"] = backend_name or 'XenAPINFS',
data['vendor_name'] = 'Open Source',
data['driver_version'] = '1.0'
data['storage_protocol'] = 'xensm'
data['total_capacity_gb'] = 'unknown'
data['free_capacity_gb'] = 'unknown'
data['reserved_percentage'] = 0
self._stats = data

return self._stats

Expand Down

0 comments on commit 995a310

Please sign in to comment.