Update SolidFire volume driver

Implements blueprint update-solidfire-driver

* Updates driver to reflect changes in the release version of SF API
* Modify SF naming scheme
* Implement snapshot functionality
* Implement setting qos on create via metadata
* Update/Add tests

(cherry picked from cinder commit df5c4ba)

Change-Id: I08f7aac31e9d95f971d297a19c285dfa7151b931
This commit is contained in:
John Griffith
2012-08-13 18:35:35 -06:00
parent 328680da00
commit 49c909bc34

View File

@@ -18,7 +18,7 @@
from nova import exception from nova import exception
from nova.openstack.common import log as logging from nova.openstack.common import log as logging
from nova import test from nova import test
from nova.volume import san from nova.volume.solidfire import SolidFire
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@@ -28,83 +28,104 @@ class SolidFireVolumeTestCase(test.TestCase):
super(SolidFireVolumeTestCase, self).setUp() super(SolidFireVolumeTestCase, self).setUp()
def fake_issue_api_request(obj, method, params): def fake_issue_api_request(obj, method, params):
if method == 'GetClusterInfo': if method is 'GetClusterInfo':
LOG.info('Called Fake GetClusterInfo...') LOG.info('Called Fake GetClusterInfo...')
results = {'result': {'clusterInfo': results = {'result': {'clusterInfo':
{'name': 'fake-cluster', {'name': 'fake-cluster',
'mvip': '1.1.1.1', 'mvip': '1.1.1.1',
'svip': '1.1.1.1', 'svip': '1.1.1.1',
'uniqueID': 'unqid', 'uniqueID': 'unqid',
'repCount': 2, 'repCount': 2,
'attributes': {}}}} 'attributes': {}}}}
return results return results
elif method == 'AddAccount': elif method is 'AddAccount':
LOG.info('Called Fake AddAccount...') LOG.info('Called Fake AddAccount...')
return {'result': {'accountID': 25}, 'id': 1} return {'result': {'accountID': 25}, 'id': 1}
elif method == 'GetAccountByName': elif method is 'GetAccountByName':
LOG.info('Called Fake GetAccountByName...') LOG.info('Called Fake GetAccountByName...')
results = {'result': {'account': { results = {'result': {'account':
'accountID': 25, {'accountID': 25,
'username': params['username'], 'username': params['username'],
'status': 'active', 'status': 'active',
'initiatorSecret': '123456789012', 'initiatorSecret': '123456789012',
'targetSecret': '123456789012', 'targetSecret': '123456789012',
'attributes': {}, 'attributes': {},
'volumes': [6, 7, 20]}}, 'volumes': [6, 7, 20]}},
"id": 1} "id": 1}
return results return results
elif method == 'CreateVolume': elif method is 'CreateVolume':
LOG.info('Called Fake CreateVolume...') LOG.info('Called Fake CreateVolume...')
return {'result': {'volumeID': 5}, 'id': 1} return {'result': {'volumeID': 5}, 'id': 1}
elif method == 'DeleteVolume': elif method is 'DeleteVolume':
LOG.info('Called Fake DeleteVolume...') LOG.info('Called Fake DeleteVolume...')
return {'result': {}, 'id': 1} return {'result': {}, 'id': 1}
elif method == 'ListVolumesForAccount': elif method is 'ListVolumesForAccount':
test_name = 'OS-VOLID-a720b3c0-d1f0-11e1-9b23-0800200c9a66'
LOG.info('Called Fake ListVolumesForAccount...') LOG.info('Called Fake ListVolumesForAccount...')
result = {'result': {'volumes': [{ result = {'result': {
'volumeID': '5', 'volumes': [{'volumeID': 5,
'name': 'test_volume', 'name': test_name,
'accountID': 25, 'accountID': 25,
'sliceCount': 1, 'sliceCount': 1,
'totalSize': 1048576 * 1024, 'totalSize': 1048576 * 1024,
'enable512e': False, 'enable512e': True,
'access': "readWrite", 'access': "readWrite",
'status': "active", 'status': "active",
'attributes':None, 'attributes':None,
'qos':None}]}} 'qos': None,
'iqn': test_name}]}}
return result return result
else: else:
LOG.error('Unimplemented API call in Fake:%s' % method) LOG.error('Crap, unimplemented API call in Fake:%s' % method)
def fake_issue_api_request_fails(obj, method, params): def fake_issue_api_request_fails(obj, method, params):
return {'error': { return {'error': {'code': 000,
'code': 000, 'name': 'DummyError',
'name': 'DummyError', 'message': 'This is a fake error response'},
'message': 'This is a fake error response'}, 'id': 1}
'id': 1}
def fake_volume_get(obj, key, default=None):
return {'qos': 'fast'}
def test_create_volume(self): def test_create_volume(self):
self.stubs.Set(san.SolidFireSanISCSIDriver, '_issue_api_request', self.stubs.Set(SolidFire, '_issue_api_request',
self.fake_issue_api_request) self.fake_issue_api_request)
testvol = {'project_id': 'testprjid', testvol = {'project_id': 'testprjid',
'name': 'testvol', 'name': 'testvol',
'size': 1} 'size': 1,
sfv = san.SolidFireSanISCSIDriver() 'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
sfv = SolidFire()
model_update = sfv.create_volume(testvol)
def test_create_volume_with_qos(self):
preset_qos = {}
preset_qos['qos'] = 'fast'
self.stubs.Set(SolidFire, '_issue_api_request',
self.fake_issue_api_request)
testvol = {'project_id': 'testprjid',
'name': 'testvol',
'size': 1,
'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66',
'metadata': [preset_qos]}
sfv = SolidFire()
model_update = sfv.create_volume(testvol) model_update = sfv.create_volume(testvol)
def test_create_volume_fails(self): def test_create_volume_fails(self):
self.stubs.Set(san.SolidFireSanISCSIDriver, '_issue_api_request', self.stubs.Set(SolidFire, '_issue_api_request',
self.fake_issue_api_request_fails) self.fake_issue_api_request_fails)
testvol = {'project_id': 'testprjid', testvol = {'project_id': 'testprjid',
'name': 'testvol', 'name': 'testvol',
'size': 1} 'size': 1,
sfv = san.SolidFireSanISCSIDriver() 'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
sfv = SolidFire()
try: try:
sfv.create_volume(testvol) sfv.create_volume(testvol)
self.fail("Should have thrown Error") self.fail("Should have thrown Error")
@@ -112,49 +133,51 @@ class SolidFireVolumeTestCase(test.TestCase):
pass pass
def test_create_sfaccount(self): def test_create_sfaccount(self):
sfv = san.SolidFireSanISCSIDriver() sfv = SolidFire()
self.stubs.Set(san.SolidFireSanISCSIDriver, '_issue_api_request', self.stubs.Set(SolidFire, '_issue_api_request',
self.fake_issue_api_request) self.fake_issue_api_request)
account = sfv._create_sfaccount('project-id') account = sfv._create_sfaccount('project-id')
self.assertNotEqual(account, None) self.assertNotEqual(account, None)
def test_create_sfaccount_fails(self): def test_create_sfaccount_fails(self):
sfv = san.SolidFireSanISCSIDriver() sfv = SolidFire()
self.stubs.Set(san.SolidFireSanISCSIDriver, '_issue_api_request', self.stubs.Set(SolidFire, '_issue_api_request',
self.fake_issue_api_request_fails) self.fake_issue_api_request_fails)
account = sfv._create_sfaccount('project-id') account = sfv._create_sfaccount('project-id')
self.assertEqual(account, None) self.assertEqual(account, None)
def test_get_sfaccount_by_name(self): def test_get_sfaccount_by_name(self):
sfv = san.SolidFireSanISCSIDriver() sfv = SolidFire()
self.stubs.Set(san.SolidFireSanISCSIDriver, '_issue_api_request', self.stubs.Set(SolidFire, '_issue_api_request',
self.fake_issue_api_request) self.fake_issue_api_request)
account = sfv._get_sfaccount_by_name('some-name') account = sfv._get_sfaccount_by_name('some-name')
self.assertNotEqual(account, None) self.assertNotEqual(account, None)
def test_get_sfaccount_by_name_fails(self): def test_get_sfaccount_by_name_fails(self):
sfv = san.SolidFireSanISCSIDriver() sfv = SolidFire()
self.stubs.Set(san.SolidFireSanISCSIDriver, '_issue_api_request', self.stubs.Set(SolidFire, '_issue_api_request',
self.fake_issue_api_request_fails) self.fake_issue_api_request_fails)
account = sfv._get_sfaccount_by_name('some-name') account = sfv._get_sfaccount_by_name('some-name')
self.assertEqual(account, None) self.assertEqual(account, None)
def test_delete_volume(self): def test_delete_volume(self):
self.stubs.Set(san.SolidFireSanISCSIDriver, '_issue_api_request', self.stubs.Set(SolidFire, '_issue_api_request',
self.fake_issue_api_request) self.fake_issue_api_request)
testvol = {'project_id': 'testprjid', testvol = {'project_id': 'testprjid',
'name': 'test_volume', 'name': 'test_volume',
'size': 1} 'size': 1,
sfv = san.SolidFireSanISCSIDriver() 'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
sfv = SolidFire()
model_update = sfv.delete_volume(testvol) model_update = sfv.delete_volume(testvol)
def test_delete_volume_fails_no_volume(self): def test_delete_volume_fails_no_volume(self):
self.stubs.Set(san.SolidFireSanISCSIDriver, '_issue_api_request', self.stubs.Set(SolidFire, '_issue_api_request',
self.fake_issue_api_request) self.fake_issue_api_request)
testvol = {'project_id': 'testprjid', testvol = {'project_id': 'testprjid',
'name': 'no-name', 'name': 'no-name',
'size': 1} 'size': 1,
sfv = san.SolidFireSanISCSIDriver() 'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
sfv = SolidFire()
try: try:
model_update = sfv.delete_volume(testvol) model_update = sfv.delete_volume(testvol)
self.fail("Should have thrown Error") self.fail("Should have thrown Error")
@@ -162,25 +185,26 @@ class SolidFireVolumeTestCase(test.TestCase):
pass pass
def test_delete_volume_fails_account_lookup(self): def test_delete_volume_fails_account_lookup(self):
self.stubs.Set(san.SolidFireSanISCSIDriver, '_issue_api_request', self.stubs.Set(SolidFire, '_issue_api_request',
self.fake_issue_api_request) self.fake_issue_api_request_fails)
testvol = {'project_id': 'testprjid', testvol = {'project_id': 'testprjid',
'name': 'no-name', 'name': 'no-name',
'size': 1} 'size': 1,
sfv = san.SolidFireSanISCSIDriver() 'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
self.assertRaises(exception.DuplicateSfVolumeNames, sfv = SolidFire()
self.assertRaises(exception.SfAccountNotFound,
sfv.delete_volume, sfv.delete_volume,
testvol) testvol)
def test_get_cluster_info(self): def test_get_cluster_info(self):
self.stubs.Set(san.SolidFireSanISCSIDriver, '_issue_api_request', self.stubs.Set(SolidFire, '_issue_api_request',
self.fake_issue_api_request) self.fake_issue_api_request)
sfv = san.SolidFireSanISCSIDriver() sfv = SolidFire()
sfv._get_cluster_info() sfv._get_cluster_info()
def test_get_cluster_info_fail(self): def test_get_cluster_info_fail(self):
self.stubs.Set(san.SolidFireSanISCSIDriver, '_issue_api_request', self.stubs.Set(SolidFire, '_issue_api_request',
self.fake_issue_api_request_fails) self.fake_issue_api_request_fails)
sfv = san.SolidFireSanISCSIDriver() sfv = SolidFire()
self.assertRaises(exception.SolidFireAPIException, self.assertRaises(exception.SolidFireAPIException,
sfv._get_cluster_info) sfv._get_cluster_info)