Skip to content

Commit

Permalink
Convert from using FLAGS directly in SF driver.
Browse files Browse the repository at this point in the history
In order for the Filter scheduler to be used to it's
full advantage Cinder drivers need to move away from
using FLAGS directly and switch to appending their
specific options to self.configuration.

This patch converts the driver and updates tests.

Fixes bug: 1131553

Change-Id: Id1a7c583894ac368bdcc61facc6f72300db320c7
  • Loading branch information
j-griffith committed Feb 28, 2013
1 parent b3aa798 commit d346346
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 32 deletions.
36 changes: 23 additions & 13 deletions cinder/tests/test_solidfire.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
# under the License.

import mox
from mox import IgnoreArg
from mox import IsA
from mox import stubout


from cinder import exception
from cinder.openstack.common import log as logging
Expand All @@ -35,6 +39,12 @@ def create_configuration():

class SolidFireVolumeTestCase(test.TestCase):
def setUp(self):
self._mox = mox.Mox()
self.configuration = mox.MockObject(conf.Configuration)
self.configuration.sf_allow_tenant_qos = True
self.configuration.san_is_local = True
self.configuration.sf_emulate_512 = True

super(SolidFireVolumeTestCase, self).setUp()
self.stubs.Set(SolidFire, '_issue_api_request',
self.fake_issue_api_request)
Expand Down Expand Up @@ -135,7 +145,7 @@ def test_create_with_qos_type(self):
'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66',
'volume_type_id': 'fast'}

sfv = SolidFire(configuration=create_configuration())
sfv = SolidFire(configuration=self.configuration)
model_update = sfv.create_volume(testvol)
self.assertNotEqual(model_update, None)

Expand All @@ -147,7 +157,7 @@ def test_create_volume(self):
'size': 1,
'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66',
'volume_type_id': None}
sfv = SolidFire(configuration=create_configuration())
sfv = SolidFire(configuration=self.configuration)
model_update = sfv.create_volume(testvol)
self.assertNotEqual(model_update, None)

Expand All @@ -164,7 +174,7 @@ def test_create_volume_with_qos(self):
'metadata': [preset_qos],
'volume_type_id': None}

sfv = SolidFire(configuration=create_configuration())
sfv = SolidFire(configuration=self.configuration)
model_update = sfv.create_volume(testvol)
self.assertNotEqual(model_update, None)

Expand All @@ -179,36 +189,36 @@ def test_create_volume_fails(self):
'name': 'testvol',
'size': 1,
'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
sfv = SolidFire(configuration=create_configuration())
sfv = SolidFire(configuration=self.configuration)
try:
sfv.create_volume(testvol)
self.fail("Should have thrown Error")
except Exception:
pass

def test_create_sfaccount(self):
sfv = SolidFire(configuration=create_configuration())
sfv = SolidFire(configuration=self.configuration)
self.stubs.Set(SolidFire, '_issue_api_request',
self.fake_issue_api_request)
account = sfv._create_sfaccount('project-id')
self.assertNotEqual(account, None)

def test_create_sfaccount_fails(self):
sfv = SolidFire(configuration=create_configuration())
sfv = SolidFire(configuration=self.configuration)
self.stubs.Set(SolidFire, '_issue_api_request',
self.fake_issue_api_request_fails)
account = sfv._create_sfaccount('project-id')
self.assertEqual(account, None)

def test_get_sfaccount_by_name(self):
sfv = SolidFire(configuration=create_configuration())
sfv = SolidFire(configuration=self.configuration)
self.stubs.Set(SolidFire, '_issue_api_request',
self.fake_issue_api_request)
account = sfv._get_sfaccount_by_name('some-name')
self.assertNotEqual(account, None)

def test_get_sfaccount_by_name_fails(self):
sfv = SolidFire(configuration=create_configuration())
sfv = SolidFire(configuration=self.configuration)
self.stubs.Set(SolidFire, '_issue_api_request',
self.fake_issue_api_request_fails)
account = sfv._get_sfaccount_by_name('some-name')
Expand All @@ -221,7 +231,7 @@ def test_delete_volume(self):
'name': 'test_volume',
'size': 1,
'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
sfv = SolidFire(configuration=create_configuration())
sfv = SolidFire(configuration=self.configuration)
sfv.delete_volume(testvol)

def test_delete_volume_fails_no_volume(self):
Expand All @@ -231,7 +241,7 @@ def test_delete_volume_fails_no_volume(self):
'name': 'no-name',
'size': 1,
'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
sfv = SolidFire(configuration=create_configuration())
sfv = SolidFire(configuration=self.configuration)
try:
sfv.delete_volume(testvol)
self.fail("Should have thrown Error")
Expand All @@ -249,15 +259,15 @@ def test_delete_volume_fails_account_lookup(self):
'name': 'no-name',
'size': 1,
'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
sfv = SolidFire(configuration=create_configuration())
sfv = SolidFire(configuration=self.configuration)
self.assertRaises(exception.SfAccountNotFound,
sfv.delete_volume,
testvol)

def test_get_cluster_info(self):
self.stubs.Set(SolidFire, '_issue_api_request',
self.fake_issue_api_request)
sfv = SolidFire(configuration=create_configuration())
sfv = SolidFire(configuration=self.configuration)
sfv._get_cluster_info()

def test_get_cluster_info_fail(self):
Expand All @@ -267,6 +277,6 @@ def test_get_cluster_info_fail(self):
self.fake_update_cluster_status)
self.stubs.Set(SolidFire, '_issue_api_request',
self.fake_issue_api_request_fails)
sfv = SolidFire(configuration=create_configuration())
sfv = SolidFire(configuration=self.configuration)
self.assertRaises(exception.SolidFireAPIException,
sfv._get_cluster_info)
57 changes: 38 additions & 19 deletions cinder/volume/drivers/solidfire.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@

from cinder import context
from cinder import exception
from cinder import flags
from cinder.openstack.common import log as logging
from cinder.volume.drivers.san.san import SanISCSIDriver
from cinder.volume import volume_types
Expand All @@ -46,9 +45,6 @@
default=False,
help='Allow tenants to specify QOS on create'), ]

FLAGS = flags.FLAGS
FLAGS.register_opts(sf_opts)


class SolidFire(SanISCSIDriver):
"""OpenStack driver to enable SolidFire cluster.
Expand Down Expand Up @@ -76,10 +72,11 @@ class SolidFire(SanISCSIDriver):
sf_qos_keys = ['minIOPS', 'maxIOPS', 'burstIOPS']
cluster_stats = {}

GB = math.pow(10, 9)
GB = math.pow(2, 30)

def __init__(self, *args, **kwargs):
super(SolidFire, self).__init__(*args, **kwargs)
self.configuration.append_config_values(sf_opts)
self._update_cluster_status()

def _issue_api_request(self, method_name, params):
Expand All @@ -94,12 +91,12 @@ def _issue_api_request(self, method_name, params):
'xMaxClonesPerVolumeExceeded',
'xMaxSnapshotsPerNodeExceeded',
'xMaxClonesPerNodeExceeded']
host = FLAGS.san_ip
host = self.configuration.san_ip
# For now 443 is the only port our server accepts requests on
port = 443

cluster_admin = FLAGS.san_login
cluster_password = FLAGS.san_password
cluster_admin = self.configuration.san_login
cluster_password = self.configuration.san_password

# NOTE(jdg): We're wrapping a retry loop for a know XDB issue
# Shows up in very high request rates (ie create 1000 volumes)
Expand Down Expand Up @@ -160,10 +157,12 @@ def _issue_api_request(self, method_name, params):
time.sleep(5)
# Don't decrement the retry count for this one
elif 'xDBVersionMismatch' in data['error']['name']:
LOG.debug(_('Detected xDBVersionMismatch, '
LOG.warning(_('Detected xDBVersionMismatch, '
'retry %s of 5') % (5 - retry_count))
time.sleep(1)
retry_count -= 1
elif 'xUnknownAccount' in data['error']['name']:
retry_count = 0
else:
msg = _("API response: %s") % data
raise exception.SolidFireAPIException(msg)
Expand Down Expand Up @@ -257,12 +256,24 @@ def _get_model_info(self, sfaccount, sf_volume_id):
iscsi_portal = cluster_info['clusterInfo']['svip'] + ':3260'
chap_secret = sfaccount['targetSecret']

volume_list = self._get_volumes_by_sfaccount(sfaccount['accountID'])
iqn = None
for v in volume_list:
if v['volumeID'] == sf_volume_id:
iqn = v['iqn']
break
found_volume = False
iteration_count = 0
while not found_volume and iteration_count < 10:
volume_list = self._get_volumes_by_sfaccount(
sfaccount['accountID'])
iqn = None
for v in volume_list:
if v['volumeID'] == sf_volume_id:
iqn = v['iqn']
found_volume = True
break
time.sleep(2)
iteration_count += 1

if not found_volume:
LOG.error(_('Failed to retrieve volume SolidFire-'
'ID: %s in get_by_account!') % sf_volume_id)
raise exception.VolumeNotFound(volume_id=uuid)

model_update = {}
# NOTE(john-griffith): SF volumes are always at lun 0
Expand Down Expand Up @@ -409,7 +420,7 @@ def create_volume(self, volume):
attributes = {}
qos = {}

if (FLAGS.sf_allow_tenant_qos and
if (self.configuration.sf_allow_tenant_qos and
volume.get('volume_metadata')is not None):
qos = self._set_qos_presets(volume)

Expand All @@ -427,7 +438,7 @@ def create_volume(self, volume):
'accountID': None,
'sliceCount': slice_count,
'totalSize': int(volume['size'] * self.GB),
'enable512e': FLAGS.sf_emulate_512,
'enable512e': self.configuration.sf_emulate_512,
'attributes': attributes,
'qos': qos}

Expand All @@ -453,6 +464,13 @@ def delete_volume(self, volume):
LOG.debug(_("Enter SolidFire delete_volume..."))

sfaccount = self._get_sfaccount(volume['project_id'])
if sfaccount is None:
LOG.error(_("Account for Volume ID %s was not found on "
"the SolidFire Cluster!") % volume['id'])
LOG.error(_("This usually means the volume was never "
"succesfully created."))
return

params = {'accountID': sfaccount['accountID']}

sf_vol = self._get_sf_volume(volume['id'], params)
Expand Down Expand Up @@ -546,8 +564,9 @@ def _update_cluster_status(self):
data["storage_protocol"] = 'iSCSI'

data['total_capacity_gb'] = results['maxProvisionedSpace']
data['free_capacity_gb'] = free_capacity
data['reserved_percentage'] = FLAGS.reserved_percentage

data['free_capacity_gb'] = float(free_capacity)
data['reserved_percentage'] = 0
data['QoS_support'] = True
data['compression_percent'] =\
results['compressionPercent']
Expand Down

0 comments on commit d346346

Please sign in to comment.