From d346346f77cd2cafebb7e73910ad77aae6f1c9fc Mon Sep 17 00:00:00 2001
From: john-griffith <john.griffith@solidfire.com>
Date: Thu, 21 Feb 2013 22:06:26 -0700
Subject: [PATCH] Convert from using FLAGS directly in SF driver.

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
---
 cinder/tests/test_solidfire.py     | 36 ++++++++++++-------
 cinder/volume/drivers/solidfire.py | 57 ++++++++++++++++++++----------
 2 files changed, 61 insertions(+), 32 deletions(-)

diff --git a/cinder/tests/test_solidfire.py b/cinder/tests/test_solidfire.py
index a32b7b998..40dfa419a 100644
--- a/cinder/tests/test_solidfire.py
+++ b/cinder/tests/test_solidfire.py
@@ -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
@@ -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)
@@ -135,7 +145,7 @@ class SolidFireVolumeTestCase(test.TestCase):
                    '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)
 
@@ -147,7 +157,7 @@ class SolidFireVolumeTestCase(test.TestCase):
                    '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)
 
@@ -164,7 +174,7 @@ class SolidFireVolumeTestCase(test.TestCase):
                    '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)
 
@@ -179,7 +189,7 @@ class SolidFireVolumeTestCase(test.TestCase):
                    '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")
@@ -187,28 +197,28 @@ class SolidFireVolumeTestCase(test.TestCase):
             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')
@@ -221,7 +231,7 @@ class SolidFireVolumeTestCase(test.TestCase):
                    '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):
@@ -231,7 +241,7 @@ class SolidFireVolumeTestCase(test.TestCase):
                    '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")
@@ -249,7 +259,7 @@ class SolidFireVolumeTestCase(test.TestCase):
                    '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)
@@ -257,7 +267,7 @@ class SolidFireVolumeTestCase(test.TestCase):
     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):
@@ -267,6 +277,6 @@ class SolidFireVolumeTestCase(test.TestCase):
                        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)
diff --git a/cinder/volume/drivers/solidfire.py b/cinder/volume/drivers/solidfire.py
index 54e3ad627..0b7966cbf 100644
--- a/cinder/volume/drivers/solidfire.py
+++ b/cinder/volume/drivers/solidfire.py
@@ -29,7 +29,6 @@ from oslo.config import cfg
 
 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
@@ -46,9 +45,6 @@ sf_opts = [
                 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.
@@ -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):
@@ -94,12 +91,12 @@ class SolidFire(SanISCSIDriver):
                                    '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)
@@ -160,10 +157,12 @@ class SolidFire(SanISCSIDriver):
                     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)
@@ -257,12 +256,24 @@ class SolidFire(SanISCSIDriver):
         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
@@ -409,7 +420,7 @@ class SolidFire(SanISCSIDriver):
         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)
 
@@ -427,7 +438,7 @@ class SolidFire(SanISCSIDriver):
                   '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}
 
@@ -453,6 +464,13 @@ class SolidFire(SanISCSIDriver):
         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)
@@ -546,8 +564,9 @@ class SolidFire(SanISCSIDriver):
         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']
-- 
2.45.2