From 010d4a23b7f25cfa9786cecc35939f667a6812ba Mon Sep 17 00:00:00 2001
From: Cory Stone <corystone@gmail.com>
Date: Mon, 8 Feb 2016 11:22:59 -0600
Subject: [PATCH] Fix dynamic import of CONF.volume_api_class

Modifies the import to actually happen when API() is called instead of
when the module is loaded.

This is necessary because CONF.volume_api_class is always evaluated as
the default value since the config file hadn't been parsed yet when the
module is loaded.

Nova fixed this problem a while ago for the compute driver in
https://review.openstack.org/#/c/14353/.

Change-Id: I4c3d6b4300298ad0ac4e40a7a1a815cbf88bb151
Closes-Bug: #1543219
---
 cinder/tests/unit/api/contrib/test_backups.py   |  4 ++--
 .../unit/api/contrib/test_volume_actions.py     | 17 +++++++++--------
 .../api/contrib/test_volume_host_attribute.py   |  4 ++--
 .../api/contrib/test_volume_image_metadata.py   | 14 +++++++-------
 .../test_volume_migration_status_attribute.py   |  4 ++--
 .../api/contrib/test_volume_tenant_attribute.py |  4 ++--
 .../tests/unit/api/v1/test_snapshot_metadata.py |  2 +-
 .../tests/unit/api/v1/test_volume_metadata.py   |  4 ++--
 .../tests/unit/api/v2/test_snapshot_metadata.py |  2 +-
 .../tests/unit/api/v2/test_volume_metadata.py   |  4 ++--
 cinder/volume/__init__.py                       |  5 ++++-
 11 files changed, 34 insertions(+), 30 deletions(-)

diff --git a/cinder/tests/unit/api/contrib/test_backups.py b/cinder/tests/unit/api/contrib/test_backups.py
index d12017e76..79c87a869 100644
--- a/cinder/tests/unit/api/contrib/test_backups.py
+++ b/cinder/tests/unit/api/contrib/test_backups.py
@@ -1221,7 +1221,7 @@ class BackupsAPITestCase(test.TestCase):
         self.assertEqual("Missing required element 'restore' in request body.",
                          res_dict['badRequest']['message'])
 
-    @mock.patch('cinder.volume.API.create')
+    @mock.patch('cinder.volume.api.API.create')
     def test_restore_backup_volume_id_unspecified(self,
                                                   _mock_volume_api_create):
 
@@ -1248,7 +1248,7 @@ class BackupsAPITestCase(test.TestCase):
         self.assertEqual(202, res.status_int)
         self.assertEqual(backup_id, res_dict['restore']['backup_id'])
 
-    @mock.patch('cinder.volume.API.create')
+    @mock.patch('cinder.volume.api.API.create')
     def test_restore_backup_name_specified(self,
                                            _mock_volume_api_create):
 
diff --git a/cinder/tests/unit/api/contrib/test_volume_actions.py b/cinder/tests/unit/api/contrib/test_volume_actions.py
index 99abddf86..3fc1b2f98 100644
--- a/cinder/tests/unit/api/contrib/test_volume_actions.py
+++ b/cinder/tests/unit/api/contrib/test_volume_actions.py
@@ -52,7 +52,8 @@ class VolumeActionsTest(test.TestCase):
         self.controller = volume_actions.VolumeActionsController()
         self.api_patchers = {}
         for _meth in self._methods:
-            self.api_patchers[_meth] = mock.patch('cinder.volume.API.' + _meth)
+            self.api_patchers[_meth] = mock.patch('cinder.volume.api.API.' +
+                                                  _meth)
             self.api_patchers[_meth].start()
             self.addCleanup(self.api_patchers[_meth].stop)
             self.api_patchers[_meth].return_value = True
@@ -61,11 +62,11 @@ class VolumeActionsTest(test.TestCase):
                   'size': 1, 'migration_status': None,
                   'volume_type_id': 'fake', 'project_id': 'project_id'}
         vol = fake_volume.fake_volume_obj(self.context, **db_vol)
-        self.get_patcher = mock.patch('cinder.volume.API.get')
+        self.get_patcher = mock.patch('cinder.volume.api.API.get')
         self.mock_volume_get = self.get_patcher.start()
         self.addCleanup(self.get_patcher.stop)
         self.mock_volume_get.return_value = vol
-        self.update_patcher = mock.patch('cinder.volume.API.update')
+        self.update_patcher = mock.patch('cinder.volume.api.API.update')
         self.mock_volume_update = self.update_patcher.start()
         self.addCleanup(self.update_patcher.stop)
         self.mock_volume_update.return_value = vol
@@ -310,7 +311,7 @@ class VolumeActionsTest(test.TestCase):
     def test_begin_detaching(self):
         def fake_begin_detaching(*args, **kwargs):
             return {}
-        self.stubs.Set(volume.API, 'begin_detaching',
+        self.stubs.Set(volume.api.API, 'begin_detaching',
                        fake_begin_detaching)
 
         body = {'os-begin_detaching': {'fake': 'fake'}}
@@ -325,7 +326,7 @@ class VolumeActionsTest(test.TestCase):
     def test_roll_detaching(self):
         def fake_roll_detaching(*args, **kwargs):
             return {}
-        self.stubs.Set(volume.API, 'roll_detaching',
+        self.stubs.Set(volume.api.API, 'roll_detaching',
                        fake_roll_detaching)
 
         body = {'os-roll_detaching': {'fake': 'fake'}}
@@ -340,7 +341,7 @@ class VolumeActionsTest(test.TestCase):
     def test_extend_volume(self):
         def fake_extend_volume(*args, **kwargs):
             return {}
-        self.stubs.Set(volume.API, 'extend',
+        self.stubs.Set(volume.api.API, 'extend',
                        fake_extend_volume)
 
         body = {'os-extend': {'new_size': 5}}
@@ -356,7 +357,7 @@ class VolumeActionsTest(test.TestCase):
         def fake_extend_volume(*args, **kwargs):
             msg = "Volume status must be available"
             raise exception.InvalidVolume(reason=msg)
-        self.stubs.Set(volume.API, 'extend',
+        self.stubs.Set(volume.api.API, 'extend',
                        fake_extend_volume)
 
         body = {'os-extend': {'new_size': 5}}
@@ -371,7 +372,7 @@ class VolumeActionsTest(test.TestCase):
     def test_update_readonly_flag(self):
         def fake_update_readonly_flag(*args, **kwargs):
             return {}
-        self.stubs.Set(volume.API, 'update_readonly_flag',
+        self.stubs.Set(volume.api.API, 'update_readonly_flag',
                        fake_update_readonly_flag)
 
         def make_update_readonly_flag_test(self, readonly, return_code):
diff --git a/cinder/tests/unit/api/contrib/test_volume_host_attribute.py b/cinder/tests/unit/api/contrib/test_volume_host_attribute.py
index e472c9d35..dcc136f06 100644
--- a/cinder/tests/unit/api/contrib/test_volume_host_attribute.py
+++ b/cinder/tests/unit/api/contrib/test_volume_host_attribute.py
@@ -69,8 +69,8 @@ class VolumeHostAttributeTest(test.TestCase):
 
     def setUp(self):
         super(VolumeHostAttributeTest, self).setUp()
-        self.stubs.Set(volume.API, 'get', fake_volume_api_get)
-        self.stubs.Set(volume.API, 'get_all', fake_volume_get_all)
+        self.stubs.Set(volume.api.API, 'get', fake_volume_api_get)
+        self.stubs.Set(volume.api.API, 'get_all', fake_volume_get_all)
         self.stubs.Set(db, 'volume_get', fake_db_volume_get)
 
         self.UUID = uuid.uuid4()
diff --git a/cinder/tests/unit/api/contrib/test_volume_image_metadata.py b/cinder/tests/unit/api/contrib/test_volume_image_metadata.py
index 505150b04..92131dc43 100644
--- a/cinder/tests/unit/api/contrib/test_volume_image_metadata.py
+++ b/cinder/tests/unit/api/contrib/test_volume_image_metadata.py
@@ -100,11 +100,11 @@ class VolumeImageMetadataTest(test.TestCase):
 
     def setUp(self):
         super(VolumeImageMetadataTest, self).setUp()
-        self.stubs.Set(volume.API, 'get', fake_volume_api_get)
-        self.stubs.Set(volume.API, 'get_all', fake_volume_get_all)
-        self.stubs.Set(volume.API, 'get_volume_image_metadata',
+        self.stubs.Set(volume.api.API, 'get', fake_volume_api_get)
+        self.stubs.Set(volume.api.API, 'get_all', fake_volume_get_all)
+        self.stubs.Set(volume.api.API, 'get_volume_image_metadata',
                        fake_get_volume_image_metadata)
-        self.stubs.Set(volume.API, 'get_volumes_image_metadata',
+        self.stubs.Set(volume.api.API, 'get_volumes_image_metadata',
                        fake_get_volumes_image_metadata)
         self.UUID = uuid.uuid4()
         self.controller = (volume_image_metadata.
@@ -164,7 +164,7 @@ class VolumeImageMetadataTest(test.TestCase):
                          self._get_image_metadata_list(res.body)[0])
 
     def test_create_image_metadata(self):
-        self.stubs.Set(volume.API, 'get_volume_image_metadata',
+        self.stubs.Set(volume.api.API, 'get_volume_image_metadata',
                        return_empty_image_metadata)
         self.stubs.Set(db, 'volume_metadata_update',
                        fake_create_volume_metadata)
@@ -183,7 +183,7 @@ class VolumeImageMetadataTest(test.TestCase):
     def test_create_with_keys_case_insensitive(self):
         # If the keys in uppercase_and_lowercase, should return the one
         # which server added
-        self.stubs.Set(volume.API, 'get_volume_image_metadata',
+        self.stubs.Set(volume.api.API, 'get_volume_image_metadata',
                        return_empty_image_metadata)
         self.stubs.Set(db, 'volume_metadata_update',
                        fake_create_volume_metadata)
@@ -218,7 +218,7 @@ class VolumeImageMetadataTest(test.TestCase):
                           self.controller.create, req, 1, None)
 
     def test_create_nonexistent_volume(self):
-        self.stubs.Set(volume.API, 'get', return_volume_nonexistent)
+        self.stubs.Set(volume.api.API, 'get', return_volume_nonexistent)
 
         req = fakes.HTTPRequest.blank('/v2/fake/volumes/1/action')
         req.method = 'POST'
diff --git a/cinder/tests/unit/api/contrib/test_volume_migration_status_attribute.py b/cinder/tests/unit/api/contrib/test_volume_migration_status_attribute.py
index f27257f6b..f7bb69376 100644
--- a/cinder/tests/unit/api/contrib/test_volume_migration_status_attribute.py
+++ b/cinder/tests/unit/api/contrib/test_volume_migration_status_attribute.py
@@ -68,8 +68,8 @@ class VolumeMigStatusAttributeTest(test.TestCase):
 
     def setUp(self):
         super(VolumeMigStatusAttributeTest, self).setUp()
-        self.stubs.Set(volume.API, 'get', fake_volume_api_get)
-        self.stubs.Set(volume.API, 'get_all', fake_volume_get_all)
+        self.stubs.Set(volume.api.API, 'get', fake_volume_api_get)
+        self.stubs.Set(volume.api.API, 'get_all', fake_volume_get_all)
         self.UUID = uuid.uuid4()
 
     def test_get_volume_allowed(self):
diff --git a/cinder/tests/unit/api/contrib/test_volume_tenant_attribute.py b/cinder/tests/unit/api/contrib/test_volume_tenant_attribute.py
index 201af635e..1fc4fe40a 100644
--- a/cinder/tests/unit/api/contrib/test_volume_tenant_attribute.py
+++ b/cinder/tests/unit/api/contrib/test_volume_tenant_attribute.py
@@ -54,8 +54,8 @@ class VolumeTenantAttributeTest(test.TestCase):
 
     def setUp(self):
         super(VolumeTenantAttributeTest, self).setUp()
-        self.stubs.Set(volume.API, 'get', fake_volume_get)
-        self.stubs.Set(volume.API, 'get_all', fake_volume_get_all)
+        self.stubs.Set(volume.api.API, 'get', fake_volume_get)
+        self.stubs.Set(volume.api.API, 'get_all', fake_volume_get_all)
         self.UUID = uuid.uuid4()
 
     def test_get_volume_allowed(self):
diff --git a/cinder/tests/unit/api/v1/test_snapshot_metadata.py b/cinder/tests/unit/api/v1/test_snapshot_metadata.py
index 65604272f..cfcbb39b8 100644
--- a/cinder/tests/unit/api/v1/test_snapshot_metadata.py
+++ b/cinder/tests/unit/api/v1/test_snapshot_metadata.py
@@ -115,7 +115,7 @@ class SnapshotMetaDataTest(test.TestCase):
     def setUp(self):
         super(SnapshotMetaDataTest, self).setUp()
         self.volume_api = cinder.volume.api.API()
-        self.stubs.Set(volume.API, 'get', stub_get)
+        self.stubs.Set(volume.api.API, 'get', stub_get)
         self.stubs.Set(cinder.db, 'snapshot_get', return_snapshot)
 
         self.stubs.Set(self.volume_api, 'update_snapshot_metadata',
diff --git a/cinder/tests/unit/api/v1/test_volume_metadata.py b/cinder/tests/unit/api/v1/test_volume_metadata.py
index 6ef0d6f7d..2b20b9b1d 100644
--- a/cinder/tests/unit/api/v1/test_volume_metadata.py
+++ b/cinder/tests/unit/api/v1/test_volume_metadata.py
@@ -134,7 +134,7 @@ class volumeMetaDataTest(test.TestCase):
     def setUp(self):
         super(volumeMetaDataTest, self).setUp()
         self.volume_api = cinder.volume.api.API()
-        self.stubs.Set(volume.API, 'get', get_volume)
+        self.stubs.Set(volume.api.API, 'get', get_volume)
         self.stubs.Set(cinder.db, 'volume_metadata_get',
                        return_volume_metadata)
         self.stubs.Set(cinder.db, 'service_get_all_by_topic',
@@ -343,7 +343,7 @@ class volumeMetaDataTest(test.TestCase):
                           req, self.req_id, body)
 
     def test_create_nonexistent_volume(self):
-        self.stubs.Set(volume.API, 'get', return_volume_nonexistent)
+        self.stubs.Set(volume.api.API, 'get', return_volume_nonexistent)
         self.stubs.Set(cinder.db, 'volume_metadata_get',
                        return_volume_metadata)
         self.stubs.Set(cinder.db, 'volume_metadata_update',
diff --git a/cinder/tests/unit/api/v2/test_snapshot_metadata.py b/cinder/tests/unit/api/v2/test_snapshot_metadata.py
index 9261b6349..c3676c0f9 100644
--- a/cinder/tests/unit/api/v2/test_snapshot_metadata.py
+++ b/cinder/tests/unit/api/v2/test_snapshot_metadata.py
@@ -116,7 +116,7 @@ class SnapshotMetaDataTest(test.TestCase):
     def setUp(self):
         super(SnapshotMetaDataTest, self).setUp()
         self.volume_api = cinder.volume.api.API()
-        self.stubs.Set(volume.API, 'get', stub_get)
+        self.stubs.Set(volume.api.API, 'get', stub_get)
         self.stubs.Set(cinder.db, 'snapshot_get', return_snapshot)
 
         self.stubs.Set(self.volume_api, 'update_snapshot_metadata',
diff --git a/cinder/tests/unit/api/v2/test_volume_metadata.py b/cinder/tests/unit/api/v2/test_volume_metadata.py
index 27d3a3530..53730fda3 100644
--- a/cinder/tests/unit/api/v2/test_volume_metadata.py
+++ b/cinder/tests/unit/api/v2/test_volume_metadata.py
@@ -127,7 +127,7 @@ class volumeMetaDataTest(test.TestCase):
     def setUp(self):
         super(volumeMetaDataTest, self).setUp()
         self.volume_api = volume_api.API()
-        self.stubs.Set(volume.API, 'get', get_volume)
+        self.stubs.Set(volume.api.API, 'get', get_volume)
         self.stubs.Set(db, 'volume_metadata_get',
                        return_volume_metadata)
         self.stubs.Set(db, 'service_get_all_by_topic',
@@ -378,7 +378,7 @@ class volumeMetaDataTest(test.TestCase):
                           req, self.req_id, body)
 
     def test_create_nonexistent_volume(self):
-        self.stubs.Set(volume.API, 'get', return_volume_nonexistent)
+        self.stubs.Set(volume.api.API, 'get', return_volume_nonexistent)
         self.stubs.Set(db, 'volume_metadata_get',
                        return_volume_metadata)
         self.stubs.Set(db, 'volume_metadata_update',
diff --git a/cinder/volume/__init__.py b/cinder/volume/__init__.py
index 55c98ef3d..91589956c 100644
--- a/cinder/volume/__init__.py
+++ b/cinder/volume/__init__.py
@@ -24,4 +24,7 @@ from cinder.common import config
 
 CONF = config.CONF
 
-API = importutils.import_class(CONF.volume_api_class)
+
+def API(*args, **kwargs):
+    class_name = CONF.volume_api_class
+    return importutils.import_object(class_name, *args, **kwargs)
-- 
2.45.2