From 76df9f313b5cc4b4c08f2634d0eac5b05a23299b Mon Sep 17 00:00:00 2001 From: Andrey Pavlov Date: Thu, 18 Jun 2015 16:19:51 +0300 Subject: [PATCH] Fix doc string definitions Changed """" at start of docstring to """ and changed ''' to """ in docstrings. Docstring standards are here - https://www.python.org/dev/peps/pep-0008/#documentation-strings Closes-Bug: #1466802 Change-Id: I7d03643845b0542deb52aed59edc1543827436ba --- cinder/db/sqlalchemy/api.py | 2 +- cinder/scheduler/driver.py | 4 +- cinder/scheduler/rpcapi.py | 4 +- cinder/tests/unit/api/test_common.py | 24 +- cinder/tests/unit/api/v2/test_volumes.py | 2 +- cinder/tests/unit/integrated/test_xml.py | 2 +- cinder/tests/unit/test_backup.py | 2 +- cinder/tests/unit/test_backup_ceph.py | 22 +- cinder/tests/unit/test_db_api.py | 24 +- cinder/tests/unit/test_dellscapi.py | 8 +- cinder/tests/unit/test_v7000_common.py | 4 +- cinder/tests/unit/test_volume.py | 2 +- .../volume/drivers/netapp/eseries/fakes.py | 6 +- .../drivers/dell/dell_storagecenter_api.py | 286 +++++++++--------- .../drivers/dell/dell_storagecenter_common.py | 70 ++--- .../drivers/dell/dell_storagecenter_fc.py | 14 +- .../drivers/dell/dell_storagecenter_iscsi.py | 6 +- cinder/volume/drivers/eqlx.py | 2 +- cinder/volume/drivers/ibm/storwize_svc/ssh.py | 2 +- cinder/volume/drivers/netapp/common.py | 4 +- cinder/volume/drivers/san/hp/hp_3par_iscsi.py | 2 +- cinder/volume/drivers/srb.py | 12 +- cinder/volume/rpcapi.py | 4 +- 23 files changed, 254 insertions(+), 254 deletions(-) diff --git a/cinder/db/sqlalchemy/api.py b/cinder/db/sqlalchemy/api.py index 87bcb76abf2..5bad367b309 100644 --- a/cinder/db/sqlalchemy/api.py +++ b/cinder/db/sqlalchemy/api.py @@ -1430,7 +1430,7 @@ def volume_get_all_by_group(context, group_id, filters=None): @require_context def volume_get_all_by_project(context, project_id, marker, limit, sort_keys=None, sort_dirs=None, filters=None): - """"Retrieves all volumes in a project. + """Retrieves all volumes in a project. If no sort parameters are specified then the returned volumes are sorted first by the 'created_at' key and then by the 'id' key in descending diff --git a/cinder/scheduler/driver.py b/cinder/scheduler/driver.py index f0db67ca868..6de52e8c7f3 100644 --- a/cinder/scheduler/driver.py +++ b/cinder/scheduler/driver.py @@ -42,10 +42,10 @@ CONF.register_opts(scheduler_driver_opts) def volume_update_db(context, volume_id, host): - '''Set the host and set the scheduled_at field of a volume. + """Set the host and set the scheduled_at field of a volume. :returns: A Volume with the updated fields set properly. - ''' + """ now = timeutils.utcnow() values = {'host': host, 'scheduled_at': now} return db.volume_update(context, volume_id, values) diff --git a/cinder/scheduler/rpcapi.py b/cinder/scheduler/rpcapi.py index b342ef62fed..12dfb0d7a83 100644 --- a/cinder/scheduler/rpcapi.py +++ b/cinder/scheduler/rpcapi.py @@ -28,7 +28,7 @@ CONF = cfg.CONF class SchedulerAPI(object): - '''Client side of the scheduler rpc API. + """Client side of the scheduler rpc API. API version history: @@ -41,7 +41,7 @@ class SchedulerAPI(object): 1.5 - Add manage_existing method 1.6 - Add create_consistencygroup method 1.7 - Add get_active_pools method - ''' + """ RPC_API_VERSION = '1.0' diff --git a/cinder/tests/unit/api/test_common.py b/cinder/tests/unit/api/test_common.py index 71d0a32d7bd..83561380e2c 100644 --- a/cinder/tests/unit/api/test_common.py +++ b/cinder/tests/unit/api/test_common.py @@ -208,34 +208,34 @@ class PaginationParamsTest(test.TestCase): class SortParamUtilsTest(test.TestCase): def test_get_sort_params_defaults(self): - '''Verifies the default sort key and direction.''' + """Verifies the default sort key and direction.""" sort_keys, sort_dirs = common.get_sort_params({}) self.assertEqual(['created_at'], sort_keys) self.assertEqual(['desc'], sort_dirs) def test_get_sort_params_override_defaults(self): - '''Verifies that the defaults can be overriden.''' + """Verifies that the defaults can be overriden.""" sort_keys, sort_dirs = common.get_sort_params({}, default_key='key1', default_dir='dir1') self.assertEqual(['key1'], sort_keys) self.assertEqual(['dir1'], sort_dirs) def test_get_sort_params_single_value_sort_param(self): - '''Verifies a single sort key and direction.''' + """Verifies a single sort key and direction.""" params = {'sort': 'key1:dir1'} sort_keys, sort_dirs = common.get_sort_params(params) self.assertEqual(['key1'], sort_keys) self.assertEqual(['dir1'], sort_dirs) def test_get_sort_params_single_value_old_params(self): - '''Verifies a single sort key and direction.''' + """Verifies a single sort key and direction.""" params = {'sort_key': 'key1', 'sort_dir': 'dir1'} sort_keys, sort_dirs = common.get_sort_params(params) self.assertEqual(['key1'], sort_keys) self.assertEqual(['dir1'], sort_dirs) def test_get_sort_params_single_with_default_sort_param(self): - '''Verifies a single sort value with a default direction.''' + """Verifies a single sort value with a default direction.""" params = {'sort': 'key1'} sort_keys, sort_dirs = common.get_sort_params(params) self.assertEqual(['key1'], sort_keys) @@ -243,7 +243,7 @@ class SortParamUtilsTest(test.TestCase): self.assertEqual(['desc'], sort_dirs) def test_get_sort_params_single_with_default_old_params(self): - '''Verifies a single sort value with a default direction.''' + """Verifies a single sort value with a default direction.""" params = {'sort_key': 'key1'} sort_keys, sort_dirs = common.get_sort_params(params) self.assertEqual(['key1'], sort_keys) @@ -251,14 +251,14 @@ class SortParamUtilsTest(test.TestCase): self.assertEqual(['desc'], sort_dirs) def test_get_sort_params_multiple_values(self): - '''Verifies multiple sort parameter values.''' + """Verifies multiple sort parameter values.""" params = {'sort': 'key1:dir1,key2:dir2,key3:dir3'} sort_keys, sort_dirs = common.get_sort_params(params) self.assertEqual(['key1', 'key2', 'key3'], sort_keys) self.assertEqual(['dir1', 'dir2', 'dir3'], sort_dirs) def test_get_sort_params_multiple_not_all_dirs(self): - '''Verifies multiple sort keys without all directions.''' + """Verifies multiple sort keys without all directions.""" params = {'sort': 'key1:dir1,key2,key3:dir3'} sort_keys, sort_dirs = common.get_sort_params(params) self.assertEqual(['key1', 'key2', 'key3'], sort_keys) @@ -266,7 +266,7 @@ class SortParamUtilsTest(test.TestCase): self.assertEqual(['dir1', 'desc', 'dir3'], sort_dirs) def test_get_sort_params_multiple_override_default_dir(self): - '''Verifies multiple sort keys and overriding default direction.''' + """Verifies multiple sort keys and overriding default direction.""" params = {'sort': 'key1:dir1,key2,key3'} sort_keys, sort_dirs = common.get_sort_params(params, default_dir='foo') @@ -274,7 +274,7 @@ class SortParamUtilsTest(test.TestCase): self.assertEqual(['dir1', 'foo', 'foo'], sort_dirs) def test_get_sort_params_params_modified(self): - '''Verifies that the input sort parameter are modified.''' + """Verifies that the input sort parameter are modified.""" params = {'sort': 'key1:dir1,key2:dir2,key3:dir3'} common.get_sort_params(params) self.assertEqual({}, params) @@ -284,14 +284,14 @@ class SortParamUtilsTest(test.TestCase): self.assertEqual({}, params) def test_get_sort_params_random_spaces(self): - '''Verifies that leading and trailing spaces are removed.''' + """Verifies that leading and trailing spaces are removed.""" params = {'sort': ' key1 : dir1,key2: dir2 , key3 '} sort_keys, sort_dirs = common.get_sort_params(params) self.assertEqual(['key1', 'key2', 'key3'], sort_keys) self.assertEqual(['dir1', 'dir2', 'desc'], sort_dirs) def test_get_params_mix_sort_and_old_params(self): - '''An exception is raised if both types of sorting params are given.''' + """An exception is raised if both types of sorting params are given.""" for params in ({'sort': 'k1', 'sort_key': 'k1'}, {'sort': 'k1', 'sort_dir': 'd1'}, {'sort': 'k1', 'sort_key': 'k1', 'sort_dir': 'd2'}): diff --git a/cinder/tests/unit/api/v2/test_volumes.py b/cinder/tests/unit/api/v2/test_volumes.py index 7943cc824e3..d30f8308d28 100644 --- a/cinder/tests/unit/api/v2/test_volumes.py +++ b/cinder/tests/unit/api/v2/test_volumes.py @@ -1261,7 +1261,7 @@ class VolumeApiTest(test.TestCase): self.stubs.Set(volume_api.API, 'get', stubs.stub_volume_get) def _verify_links(links, url_key): - '''Verify next link and url.''' + """Verify next link and url.""" self.assertEqual(links[0]['rel'], 'next') href_parts = urllib.parse.urlparse(links[0]['href']) self.assertEqual('/v2/fakeproject/%s' % key, href_parts.path) diff --git a/cinder/tests/unit/integrated/test_xml.py b/cinder/tests/unit/integrated/test_xml.py index c238775895b..00ff457b07f 100644 --- a/cinder/tests/unit/integrated/test_xml.py +++ b/cinder/tests/unit/integrated/test_xml.py @@ -24,7 +24,7 @@ LOG = logging.getLogger(__name__) class XmlTests(integrated_helpers._IntegratedTestBase): - """"Some basic XML sanity checks.""" + """Some basic XML sanity checks.""" # FIXME(ja): does cinder need limits? # def test_namespace_limits(self): diff --git a/cinder/tests/unit/test_backup.py b/cinder/tests/unit/test_backup.py index 836d5dd56aa..bb0a7f17af1 100644 --- a/cinder/tests/unit/test_backup.py +++ b/cinder/tests/unit/test_backup.py @@ -522,7 +522,7 @@ class BackupTestCase(BaseBackupTest): self.assertEqual(len(backups), 2) def test_backup_manager_driver_name(self): - """"Test mapping between backup services and backup drivers.""" + """Test mapping between backup services and backup drivers.""" self.override_config('backup_driver', "cinder.backup.services.swift") backup_mgr = \ importutils.import_object(CONF.backup_manager) diff --git a/cinder/tests/unit/test_backup_ceph.py b/cinder/tests/unit/test_backup_ceph.py index 4e51cce3253..2ff1378ba50 100644 --- a/cinder/tests/unit/test_backup_ceph.py +++ b/cinder/tests/unit/test_backup_ceph.py @@ -773,7 +773,7 @@ class BackupCephTestCase(test.TestCase): @common_mocks def test_diff_restore_allowed_with_image_not_exists(self): - '''Test diff restore not allowed when backup not diff-format.''' + """Test diff restore not allowed when backup not diff-format.""" not_allowed = (False, None) backup_base = 'backup.base' rbd_io = self._get_wrapped_rbd_io(self.service.rbd.Image()) @@ -794,12 +794,12 @@ class BackupCephTestCase(test.TestCase): @common_mocks def test_diff_restore_allowed_with_no_restore_point(self): - '''Test diff restore not allowed when no restore point found. + """Test diff restore not allowed when no restore point found. Detail conditions: 1. backup base is diff-format 2. restore point does not exist - ''' + """ not_allowed = (False, None) backup_base = 'backup.base' rbd_io = self._get_wrapped_rbd_io(self.service.rbd.Image()) @@ -824,13 +824,13 @@ class BackupCephTestCase(test.TestCase): @common_mocks def test_diff_restore_allowed_with_not_rbd(self): - '''Test diff restore not allowed when destination volume is not rbd. + """Test diff restore not allowed when destination volume is not rbd. Detail conditions: 1. backup base is diff-format 2. restore point exists 3. destination volume is not an rbd. - ''' + """ backup_base = 'backup.base' restore_point = 'backup.snap.1' rbd_io = self._get_wrapped_rbd_io(self.service.rbd.Image()) @@ -858,14 +858,14 @@ class BackupCephTestCase(test.TestCase): @common_mocks def test_diff_restore_allowed_with_same_volume(self): - '''Test diff restore not allowed when volumes are same. + """Test diff restore not allowed when volumes are same. Detail conditions: 1. backup base is diff-format 2. restore point exists 3. destination volume is an rbd 4. source and destination volumes are the same - ''' + """ backup_base = 'backup.base' restore_point = 'backup.snap.1' rbd_io = self._get_wrapped_rbd_io(self.service.rbd.Image()) @@ -891,7 +891,7 @@ class BackupCephTestCase(test.TestCase): @common_mocks def test_diff_restore_allowed_with_has_extents(self): - '''Test diff restore not allowed when destination volume has data. + """Test diff restore not allowed when destination volume has data. Detail conditions: 1. backup base is diff-format @@ -899,7 +899,7 @@ class BackupCephTestCase(test.TestCase): 3. destination volume is an rbd 4. source and destination volumes are different 5. destination volume has data on it - full copy is mandated - ''' + """ backup_base = 'backup.base' restore_point = 'backup.snap.1' rbd_io = self._get_wrapped_rbd_io(self.service.rbd.Image()) @@ -931,7 +931,7 @@ class BackupCephTestCase(test.TestCase): @common_mocks def test_diff_restore_allowed_with_no_extents(self): - '''Test diff restore allowed when no data in destination volume. + """Test diff restore allowed when no data in destination volume. Detail conditions: 1. backup base is diff-format @@ -939,7 +939,7 @@ class BackupCephTestCase(test.TestCase): 3. destination volume is an rbd 4. source and destination volumes are different 5. destination volume no data on it - ''' + """ backup_base = 'backup.base' restore_point = 'backup.snap.1' rbd_io = self._get_wrapped_rbd_io(self.service.rbd.Image()) diff --git a/cinder/tests/unit/test_db_api.py b/cinder/tests/unit/test_db_api.py index 4e91b03b1a9..cb5eb746f3c 100644 --- a/cinder/tests/unit/test_db_api.py +++ b/cinder/tests/unit/test_db_api.py @@ -540,7 +540,7 @@ class DBAPIVolumeTestCase(BaseTest): match_keys=['id', 'display_name', 'volume_metadata', 'created_at']): - """"Verifies that volumes are returned in the correct order.""" + """Verifies that volumes are returned in the correct order.""" if project_id: result = db.volume_get_all_by_project(self.ctxt, project_id, marker, limit, @@ -821,7 +821,7 @@ class DBAPIVolumeTestCase(BaseTest): self._assertEqualsVolumeOrderResult(correct_order) def test_volume_get_all_by_filters_sort_keys_paginate(self): - '''Verifies sort order with pagination.''' + """Verifies sort order with pagination.""" # Volumes that will reply to the query test1_avail = db.volume_create(self.ctxt, {'display_name': 'test', 'size': 1, @@ -1814,7 +1814,7 @@ class DBAPIBackupTestCase(BaseTest): class DBAPIProcessSortParamTestCase(test.TestCase): def test_process_sort_params_defaults(self): - '''Verifies default sort parameters.''' + """Verifies default sort parameters.""" sort_keys, sort_dirs = sqlalchemy_api.process_sort_params([], []) self.assertEqual(['created_at', 'id'], sort_keys) self.assertEqual(['asc', 'asc'], sort_dirs) @@ -1824,21 +1824,21 @@ class DBAPIProcessSortParamTestCase(test.TestCase): self.assertEqual(['asc', 'asc'], sort_dirs) def test_process_sort_params_override_default_keys(self): - '''Verifies that the default keys can be overridden.''' + """Verifies that the default keys can be overridden.""" sort_keys, sort_dirs = sqlalchemy_api.process_sort_params( [], [], default_keys=['key1', 'key2', 'key3']) self.assertEqual(['key1', 'key2', 'key3'], sort_keys) self.assertEqual(['asc', 'asc', 'asc'], sort_dirs) def test_process_sort_params_override_default_dir(self): - '''Verifies that the default direction can be overridden.''' + """Verifies that the default direction can be overridden.""" sort_keys, sort_dirs = sqlalchemy_api.process_sort_params( [], [], default_dir='dir1') self.assertEqual(['created_at', 'id'], sort_keys) self.assertEqual(['dir1', 'dir1'], sort_dirs) def test_process_sort_params_override_default_key_and_dir(self): - '''Verifies that the default key and dir can be overridden.''' + """Verifies that the default key and dir can be overridden.""" sort_keys, sort_dirs = sqlalchemy_api.process_sort_params( [], [], default_keys=['key1', 'key2', 'key3'], default_dir='dir1') @@ -1851,7 +1851,7 @@ class DBAPIProcessSortParamTestCase(test.TestCase): self.assertEqual([], sort_dirs) def test_process_sort_params_non_default(self): - '''Verifies that non-default keys are added correctly.''' + """Verifies that non-default keys are added correctly.""" sort_keys, sort_dirs = sqlalchemy_api.process_sort_params( ['key1', 'key2'], ['asc', 'desc']) self.assertEqual(['key1', 'key2', 'created_at', 'id'], sort_keys) @@ -1859,7 +1859,7 @@ class DBAPIProcessSortParamTestCase(test.TestCase): self.assertEqual(['asc', 'desc', 'asc', 'asc'], sort_dirs) def test_process_sort_params_default(self): - '''Verifies that default keys are added correctly.''' + """Verifies that default keys are added correctly.""" sort_keys, sort_dirs = sqlalchemy_api.process_sort_params( ['id', 'key2'], ['asc', 'desc']) self.assertEqual(['id', 'key2', 'created_at'], sort_keys) @@ -1872,7 +1872,7 @@ class DBAPIProcessSortParamTestCase(test.TestCase): self.assertEqual(['asc', 'asc', 'asc'], sort_dirs) def test_process_sort_params_default_dir(self): - '''Verifies that the default dir is applied to all keys.''' + """Verifies that the default dir is applied to all keys.""" # Direction is set, ignore default dir sort_keys, sort_dirs = sqlalchemy_api.process_sort_params( ['id', 'key2'], ['desc'], default_dir='dir') @@ -1886,7 +1886,7 @@ class DBAPIProcessSortParamTestCase(test.TestCase): self.assertEqual(['dir', 'dir', 'dir'], sort_dirs) def test_process_sort_params_unequal_length(self): - '''Verifies that a sort direction list is applied correctly.''' + """Verifies that a sort direction list is applied correctly.""" sort_keys, sort_dirs = sqlalchemy_api.process_sort_params( ['id', 'key2', 'key3'], ['desc']) self.assertEqual(['id', 'key2', 'key3', 'created_at'], sort_keys) @@ -1904,14 +1904,14 @@ class DBAPIProcessSortParamTestCase(test.TestCase): self.assertEqual(['desc', 'asc', 'asc', 'desc'], sort_dirs) def test_process_sort_params_extra_dirs_lengths(self): - '''InvalidInput raised if more directions are given.''' + """InvalidInput raised if more directions are given.""" self.assertRaises(exception.InvalidInput, sqlalchemy_api.process_sort_params, ['key1', 'key2'], ['asc', 'desc', 'desc']) def test_process_sort_params_invalid_sort_dir(self): - '''InvalidInput raised if invalid directions are given.''' + """InvalidInput raised if invalid directions are given.""" for dirs in [['foo'], ['asc', 'foo'], ['asc', 'desc', 'foo']]: self.assertRaises(exception.InvalidInput, sqlalchemy_api.process_sort_params, diff --git a/cinder/tests/unit/test_dellscapi.py b/cinder/tests/unit/test_dellscapi.py index 17f715751da..dca9a00cfda 100644 --- a/cinder/tests/unit/test_dellscapi.py +++ b/cinder/tests/unit/test_dellscapi.py @@ -35,10 +35,10 @@ from cinder.volume.drivers.dell import dell_storagecenter_api 'close_connection') class DellSCSanAPITestCase(test.TestCase): - '''DellSCSanAPITestCase + """DellSCSanAPITestCase Class to test the Storage Center API using Mock. - ''' + """ SC = {u'IPv6ManagementIPPrefix': 128, u'connectionError': u'', @@ -5635,10 +5635,10 @@ class DellSCSanAPITestCase(test.TestCase): class DellSCSanAPIConnectionTestCase(test.TestCase): - '''DellSCSanAPIConnectionTestCase + """DellSCSanAPIConnectionTestCase Class to test the Storage Center API connection using Mock. - ''' + """ # Create a Response object that indicates OK response_ok = models.Response() diff --git a/cinder/tests/unit/test_v7000_common.py b/cinder/tests/unit/test_v7000_common.py index 5894b6450a9..1801bd060a9 100644 --- a/cinder/tests/unit/test_v7000_common.py +++ b/cinder/tests/unit/test_v7000_common.py @@ -743,7 +743,7 @@ class V7000CommonTestCase(test.TestCase): def test_get_volume_type_extra_spec(self, m_get_volume_type, m_get_admin_context): - '''Volume_type extra specs are found successfully.''' + """Volume_type extra specs are found successfully.""" vol = VOLUME.copy() vol['volume_type_id'] = 1 volume_type = {'extra_specs': {'override:test_key': 'test_value'}} @@ -762,7 +762,7 @@ class V7000CommonTestCase(test.TestCase): def test_get_violin_extra_spec(self, m_get_volume_type, m_get_admin_context): - '''Volume_type extra specs are found successfully.''' + """Volume_type extra specs are found successfully.""" vol = VOLUME.copy() vol['volume_type_id'] = 1 volume_type = {'extra_specs': {'violin:test_key': 'test_value'}} diff --git a/cinder/tests/unit/test_volume.py b/cinder/tests/unit/test_volume.py index 2fde332ff08..58b542422be 100644 --- a/cinder/tests/unit/test_volume.py +++ b/cinder/tests/unit/test_volume.py @@ -1023,7 +1023,7 @@ class VolumeTestCase(BaseVolumeTestCase): @mock.patch.object(db, 'volume_get', side_effect=exception.VolumeNotFound( volume_id='12345678-1234-5678-1234-567812345678')) def test_delete_volume_not_found(self, mock_get_volume): - """"Test delete volume moves on if the volume does not exist.""" + """Test delete volume moves on if the volume does not exist.""" volume_id = '12345678-1234-5678-1234-567812345678' self.assertTrue(self.volume.delete_volume(self.context, volume_id)) self.assertTrue(mock_get_volume.called) diff --git a/cinder/tests/unit/volume/drivers/netapp/eseries/fakes.py b/cinder/tests/unit/volume/drivers/netapp/eseries/fakes.py index 548670d5666..024fec8dc11 100644 --- a/cinder/tests/unit/volume/drivers/netapp/eseries/fakes.py +++ b/cinder/tests/unit/volume/drivers/netapp/eseries/fakes.py @@ -433,7 +433,7 @@ def create_configuration_eseries(): def deepcopy_return_value_method_decorator(fn): - '''Returns a deepcopy of the returned value of the wrapped function.''' + """Returns a deepcopy of the returned value of the wrapped function.""" def decorator(*args, **kwargs): return copy.deepcopy(fn(*args, **kwargs)) @@ -441,9 +441,9 @@ def deepcopy_return_value_method_decorator(fn): def deepcopy_return_value_class_decorator(cls): - '''Wraps all 'non-protected' methods of a class with the + """Wraps all 'non-protected' methods of a class with the deepcopy_return_value_method_decorator decorator. - ''' + """ class NewClass(cls): def __getattribute__(self, attr_name): obj = super(NewClass, self).__getattribute__(attr_name) diff --git a/cinder/volume/drivers/dell/dell_storagecenter_api.py b/cinder/volume/drivers/dell/dell_storagecenter_api.py index b538d569c9c..dab55ec2386 100644 --- a/cinder/volume/drivers/dell/dell_storagecenter_api.py +++ b/cinder/volume/drivers/dell/dell_storagecenter_api.py @@ -11,7 +11,7 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -'''Interface for interacting with the Dell Storage Center array.''' +"""Interface for interacting with the Dell Storage Center array.""" import json import os.path @@ -30,11 +30,11 @@ LOG = logging.getLogger(__name__) class PayloadFilter(object): - '''PayloadFilter + """PayloadFilter Simple class for creating filters for interacting with the Dell Storage API DropTop2 and later. - ''' + """ def __init__(self, filtertype='AND'): self.payload = {} @@ -52,11 +52,11 @@ class PayloadFilter(object): class LegacyPayloadFilter(object): - '''LegacyPayloadFilter + """LegacyPayloadFilter Simple class for creating filters for interacting with the Dell Storage API pre DropTop2. - ''' + """ def __init__(self, filter_type='AND'): self.payload = {'filterType': filter_type, @@ -73,13 +73,13 @@ class LegacyPayloadFilter(object): class HttpClient(object): - '''HttpClient + """HttpClient Helper for making the REST calls. - ''' + """ def __init__(self, host, port, user, password, verify): - '''HttpClient handles the REST requests. + """HttpClient handles the REST requests. :param host: IP address of the Dell Data Collector. :param port: Port the Data Collector is listening on. @@ -87,7 +87,7 @@ class HttpClient(object): :param password: Password. :param verify: Boolean indicating whether certificate verification should be turned on or not. - ''' + """ self.baseUrl = 'https://%s:%s/api/rest/' % (host, port) self.session = requests.Session() self.session.auth = (user, password) @@ -140,28 +140,28 @@ class HttpClient(object): class StorageCenterApiHelper(object): - '''StorageCenterApiHelper + """StorageCenterApiHelper Helper class for API access. Handles opening and closing the connection to the Dell Enterprise Manager. - ''' + """ def __init__(self, config): self.config = config def open_connection(self): - '''Creates the StorageCenterApi object. + """Creates the StorageCenterApi object. :return: StorageCenterApi object. :raises: VolumeBackendAPIException - ''' + """ connection = None ssn = self.config.dell_sc_ssn LOG.info(_LI('open_connection to %(ssn)s at %(ip)s'), {'ssn': ssn, 'ip': self.config.san_ip}) if ssn: - '''Open connection to Enterprise Manager.''' + """Open connection to Enterprise Manager.""" connection = StorageCenterApi(self.config.san_ip, self.config.dell_sc_api_port, self.config.san_login, @@ -182,7 +182,7 @@ class StorageCenterApiHelper(object): class StorageCenterApi(object): - '''StorageCenterApi + """StorageCenterApi Handles calls to Dell Enterprise Manager (EM) via the REST API interface. @@ -195,11 +195,11 @@ class StorageCenterApi(object): 2.1.0 - Added support for ManageableVD. 2.2.0 - Added API 2.2 support. 2.3.0 - Added Legacy Port Mode Support - ''' + """ APIVERSION = '2.3.0' def __init__(self, host, port, user, password, verify): - '''This creates a connection to Dell Enterprise Manager. + """This creates a connection to Dell Enterprise Manager. :param host: IP address of the Dell Data Collector. :param port: Port the Data Collector is listening on. @@ -207,7 +207,7 @@ class StorageCenterApi(object): :param password: Password. :param verify: Boolean indicating whether certificate verification should be turned on or not. - ''' + """ self.notes = 'Created by Dell Cinder Driver' self.ssn = None self.vfname = 'openstack' @@ -227,11 +227,11 @@ class StorageCenterApi(object): self.close_connection() def _path_to_array(self, path): - '''Breaks a path into a reversed string array. + """Breaks a path into a reversed string array. :param path: Path to a folder on the Storage Center. :return: A reversed array of each path element. - ''' + """ array = [] while True: (path, tail) = os.path.split(path) @@ -241,16 +241,16 @@ class StorageCenterApi(object): array.append(tail) def _first_result(self, blob): - '''Get the first result from the JSON return value. + """Get the first result from the JSON return value. :param blob: Full return from a REST call. :return: The JSON encoded dict or the first item in a JSON encoded list. - ''' + """ return self._get_result(blob, None, None) def _get_result(self, blob, attribute, value): - '''Find the result specified by attribute and value. + """Find the result specified by attribute and value. If the JSON blob is a list then it will be searched for the attribute and value combination. If attribute and value are not specified then @@ -265,7 +265,7 @@ class StorageCenterApi(object): is None this value is ignored. :returns: The JSON content in blob, the dict specified by matching the attribute and value or None. - ''' + """ rsp = None content = self._get_json(blob) if content is not None: @@ -289,11 +289,11 @@ class StorageCenterApi(object): return rsp def _get_json(self, blob): - '''Returns a dict from the JSON of a REST response. + """Returns a dict from the JSON of a REST response. :param blob: The response from a REST call. :returns: JSON or None on error. - ''' + """ try: return blob.json() except AttributeError: @@ -302,11 +302,11 @@ class StorageCenterApi(object): return None def _get_id(self, blob): - '''Returns the instanceId from a Dell REST object. + """Returns the instanceId from a Dell REST object. :param blob: A Dell SC REST call's response. :returns: The instanceId from the Dell SC object or None on error. - ''' + """ try: if isinstance(blob, dict): return blob.get('instanceId') @@ -322,10 +322,10 @@ class StorageCenterApi(object): return PayloadFilter(filterType) def open_connection(self): - '''Authenticate against Dell Enterprise Manager. + """Authenticate against Dell Enterprise Manager. :raises: VolumeBackendAPIException. - ''' + """ payload = {} payload['Application'] = 'Cinder REST Driver' @@ -369,7 +369,7 @@ class StorageCenterApi(object): _('Failed to connect to Enterprise Manager')) def close_connection(self): - '''Logout of Dell Enterprise Manager.''' + """Logout of Dell Enterprise Manager.""" r = self.client.post('ApiConnection/Logout', {}) if r.status_code != 204: @@ -379,11 +379,11 @@ class StorageCenterApi(object): self.client = None def find_sc(self): - '''Check that the SC is there and being managed by EM. + """Check that the SC is there and being managed by EM. :returns: The SC SSN. :raises: VolumeBackendAPIException - ''' + """ r = self.client.get('StorageCenter/StorageCenter') result = self._get_result(r, 'scSerialNumber', @@ -400,7 +400,7 @@ class StorageCenterApi(object): # Folder functions def _create_folder(self, url, parent, folder): - '''Creates folder under parent. + """Creates folder under parent. This can create both to server and volume folders. The REST url sent in defines the folder type being created on the Dell Storage @@ -411,7 +411,7 @@ class StorageCenterApi(object): :param parent: The instance ID of this folder's parent folder. :param folder: The folder name to be created. This is one level deep. :returns: The REST folder object. - ''' + """ scfolder = None payload = {} payload['Name'] = folder @@ -432,7 +432,7 @@ class StorageCenterApi(object): return scfolder def _create_folder_path(self, url, foldername): - '''Creates a folder path from a fully qualified name. + """Creates a folder path from a fully qualified name. The REST url sent in defines the folder type being created on the Dell Storage Center backend. Thus this is generic to server and volume @@ -442,7 +442,7 @@ class StorageCenterApi(object): (server or volume) folder type. :param foldername: The full folder name with path. :returns: The REST folder object. - ''' + """ path = self._path_to_array(foldername) folderpath = '' instanceId = '' @@ -474,7 +474,7 @@ class StorageCenterApi(object): return scfolder def _find_folder(self, url, foldername): - '''Find a folder on the SC using the specified url. + """Find a folder on the SC using the specified url. Most of the time the folder will already have been created so we look for the end folder and check that the rest of the path is @@ -489,7 +489,7 @@ class StorageCenterApi(object): folders.) :param foldername: Full path to the folder we are looking for. :returns: Dell folder object. - ''' + """ pf = self._get_payload_filter() pf.append('scSerialNumber', self.ssn) basename = os.path.basename(foldername) @@ -515,13 +515,13 @@ class StorageCenterApi(object): return folder def _find_volume_folder(self, create=False): - '''Looks for the volume folder where backend volumes will be created. + """Looks for the volume folder where backend volumes will be created. Volume folder is specified in the cindef.conf. See __init. :param create: If True will create the folder if not found. :returns: Folder object. - ''' + """ folder = self._find_folder('StorageCenter/ScVolumeFolder/GetList', self.vfname) # Doesn't exist? make it @@ -531,14 +531,14 @@ class StorageCenterApi(object): return folder def _init_volume(self, scvolume): - '''Initializes the volume. + """Initializes the volume. Maps the volume to a random server and immediately unmaps it. This initializes the volume. Don't wig out if this fails. :param scvolume: Dell Volume object. - ''' + """ pf = self._get_payload_filter() pf.append('scSerialNumber', scvolume.get('scSerialNumber'), 'Equals') r = self.client.post('StorageCenter/ScServer/GetList', pf.payload) @@ -567,7 +567,7 @@ class StorageCenterApi(object): self._get_id(scvolume)) def _find_storage_profile(self, storage_profile): - '''Looks for a Storage Profile on the array. + """Looks for a Storage Profile on the array. Storage Profiles determine tiering settings. If not specified a volume will use the Default storage profile. @@ -575,7 +575,7 @@ class StorageCenterApi(object): :param storage_profile: The Storage Profile name to find with any spaces stripped. :returns: The Storage Profile object or None. - ''' + """ if not storage_profile: return None @@ -598,7 +598,7 @@ class StorageCenterApi(object): return None def create_volume(self, name, size, storage_profile=None): - '''Creates a new volume on the Storage Center. + """Creates a new volume on the Storage Center. It will create it in a folder called self.vfname. If self.vfname does not exist it will create it. If it cannot create it @@ -609,7 +609,7 @@ class StorageCenterApi(object): :param size: The size of the volume to be created in GB. :param storage_profile: Optional storage profile to set for the volume. :returns: Dell Volume object or None. - ''' + """ LOG.debug('Create Volume %(name)s %(ssn)s %(folder)s %(profile)s', {'name': name, 'ssn': self.ssn, @@ -669,14 +669,14 @@ class StorageCenterApi(object): return scvolume def _get_volume_list(self, name, deviceid, filterbyvfname=True): - '''Return the specified list of volumes. + """Return the specified list of volumes. :param name: Volume name. :param deviceid: Volume device ID on the SC backend. :param filterbyvfname: If set to true then this filters by the preset folder name. :return: Returns the scvolume list or None. - ''' + """ result = None # We need a name or a device ID to find a volume. if name or deviceid: @@ -706,7 +706,7 @@ class StorageCenterApi(object): return result def find_volume(self, name): - '''Search self.ssn for volume of name. + """Search self.ssn for volume of name. This searches the folder self.vfname (specified in the cinder.conf) for the volume first. If not found it searches the entire array for @@ -716,7 +716,7 @@ class StorageCenterApi(object): volume ID. :returns: Dell Volume object or None if not found. :raises VolumeBackendAPIException: If multiple copies are found. - ''' + """ LOG.debug('Searching %(sn)s for %(name)s', {'sn': self.ssn, 'name': name}) @@ -749,14 +749,14 @@ class StorageCenterApi(object): return None if not vollist else vollist[0] def delete_volume(self, name): - '''Deletes the volume from the SC backend array. + """Deletes the volume from the SC backend array. If the volume cannot be found we claim success. :param name: Name of the volume to search for. This is the cinder volume ID. :returns: Boolean indicating success or failure. - ''' + """ vol = self.find_volume(name) if vol is not None: r = self.client.delete('StorageCenter/ScVolume/%s' @@ -777,14 +777,14 @@ class StorageCenterApi(object): return True def _find_server_folder(self, create=False): - '''Looks for the server folder on the Dell Storage Center. + """Looks for the server folder on the Dell Storage Center. This is the folder where a server objects for mapping volumes will be created. Server folder is specified in cinder.conf. See __init. :param create: If True will create the folder if not found. :return: Folder object. - ''' + """ folder = self._find_folder('StorageCenter/ScServerFolder/GetList', self.sfname) if folder is None and create is True: @@ -793,7 +793,7 @@ class StorageCenterApi(object): return folder def _add_hba(self, scserver, wwnoriscsiname, isfc=False): - '''This adds a server HBA to the Dell server object. + """This adds a server HBA to the Dell server object. The HBA is taken from the connector provided in initialize_connection. The Dell server object is largely a container object for the list of @@ -804,7 +804,7 @@ class StorageCenterApi(object): :param wwnoriscsiname: The WWN or IQN to add to this server. :param isfc: Boolean indicating whether this is an FC HBA or not. :returns: Boolean indicating success or failure. - ''' + """ payload = {} if isfc is True: payload['HbaPortType'] = 'FibreChannel' @@ -826,7 +826,7 @@ class StorageCenterApi(object): return True def _find_serveros(self, osname='Red Hat Linux 6.x'): - '''Returns the serveros instance id of the specified osname. + """Returns the serveros instance id of the specified osname. Required to create a Dell server object. @@ -835,7 +835,7 @@ class StorageCenterApi(object): :param osname: The name of the OS to look for. :returns: InstanceId of the ScServerOperatingSystem object. - ''' + """ pf = self._get_payload_filter() pf.append('scSerialNumber', self.ssn) r = self.client.post('StorageCenter/ScServerOperatingSystem/GetList', @@ -855,14 +855,14 @@ class StorageCenterApi(object): return None def create_server_multiple_hbas(self, wwns): - '''Creates a server with multiple WWNS associated with it. + """Creates a server with multiple WWNS associated with it. Same as create_server except it can take a list of HBAs. :param wwns: A list of FC WWNs or iSCSI IQNs associated with this server. :returns: Dell server object. - ''' + """ scserver = None # Our instance names for wwn in wwns: @@ -878,7 +878,7 @@ class StorageCenterApi(object): return scserver def create_server(self, wwnoriscsiname, isfc=False): - '''Creates a Dell server object on the the Storage Center. + """Creates a Dell server object on the the Storage Center. Adds the first HBA identified by wwnoriscsiname to it. @@ -886,7 +886,7 @@ class StorageCenterApi(object): this Dell server object. :param isfc: Boolean indicating whether this is an FC HBA or not. :returns: Dell server object. - ''' + """ scserver = None payload = {} payload['Name'] = 'Server_' + wwnoriscsiname @@ -933,7 +933,7 @@ class StorageCenterApi(object): return scserver def find_server(self, instance_name): - '''Hunts for a server on the Dell backend by instance_name. + """Hunts for a server on the Dell backend by instance_name. The instance_name is the same as the server's HBA. This is the IQN or WWN listed in the connector. If found, the server the HBA is attached @@ -943,7 +943,7 @@ class StorageCenterApi(object): the connector. In cinder a server is identified by its HBA. :returns: Dell server object or None. - ''' + """ scserver = None # We search for our server by first finding our HBA hba = self._find_serverhba(instance_name) @@ -968,7 +968,7 @@ class StorageCenterApi(object): return scserver def _find_serverhba(self, instance_name): - '''Hunts for a server HBA on the Dell backend by instance_name. + """Hunts for a server HBA on the Dell backend by instance_name. Instance_name is the same as the IQN or WWN specified in the connector. @@ -976,7 +976,7 @@ class StorageCenterApi(object): :param instance_name: Instance_name is a FC WWN or iSCSI IQN from the connector. :returns: Dell server HBA object. - ''' + """ scserverhba = None # We search for our server by first finding our HBA pf = self._get_payload_filter() @@ -993,11 +993,11 @@ class StorageCenterApi(object): return scserverhba def _find_domains(self, cportid): - '''Find the list of Dell domain objects associated with the cportid. + """Find the list of Dell domain objects associated with the cportid. :param cportid: The Instance ID of the Dell controller port. :returns: List of fault domains associated with this controller port. - ''' + """ r = self.client.get('StorageCenter/ScControllerPort/%s/FaultDomainList' % cportid) if r.status_code == 200: @@ -1011,11 +1011,11 @@ class StorageCenterApi(object): return None def _find_fc_initiators(self, scserver): - '''Returns a list of FC WWNs associated with the specified Dell server. + """Returns a list of FC WWNs associated with the specified Dell server. :param scserver: The Dell backend server object. :returns: A list of FC WWNs associated with this server. - ''' + """ initiators = [] r = self.client.get('StorageCenter/ScServer/%s/HbaList' % self._get_id(scserver)) @@ -1034,11 +1034,11 @@ class StorageCenterApi(object): return initiators def get_volume_count(self, scserver): - '''Returns the number of volumes attached to specified Dell server. + """Returns the number of volumes attached to specified Dell server. :param scserver: The Dell backend server object. :returns: Mapping count. -1 if there was an error. - ''' + """ r = self.client.get('StorageCenter/ScServer/%s/MappingList' % self._get_id(scserver)) if r.status_code == 200: @@ -1048,11 +1048,11 @@ class StorageCenterApi(object): return -1 def _find_mappings(self, scvolume): - '''Find the Dell volume object mappings. + """Find the Dell volume object mappings. :param scvolume: Dell volume object. :returns: A list of Dell mappings objects. - ''' + """ mappings = [] if scvolume.get('active', False): r = self.client.get('StorageCenter/ScVolume/%s/MappingList' @@ -1070,11 +1070,11 @@ class StorageCenterApi(object): return mappings def _find_mapping_profiles(self, scvolume): - '''Find the Dell volume object mapping profiles. + """Find the Dell volume object mapping profiles. :param scvolume: Dell volume object. :returns: A list of Dell mapping profile objects. - ''' + """ mapping_profiles = [] if scvolume.get('active', False): r = self.client.get('StorageCenter/ScVolume/%s/MappingProfileList' @@ -1092,11 +1092,11 @@ class StorageCenterApi(object): return mapping_profiles def _find_controller_port(self, cportid): - '''Finds the SC controller port object for the specified cportid. + """Finds the SC controller port object for the specified cportid. :param cportid: The instanceID of the Dell backend controller port. :returns: The controller port object. - ''' + """ controllerport = None r = self.client.get('StorageCenter/ScControllerPort/%s' % cportid) @@ -1111,12 +1111,12 @@ class StorageCenterApi(object): return controllerport def find_wwns(self, scvolume, scserver): - '''Finds the lun and wwns of the mapped volume. + """Finds the lun and wwns of the mapped volume. :param scvolume: Storage Center volume object. :param scserver: Storage Center server opbject. :returns: Lun, wwns, initiator target map - ''' + """ lun = None # our lun. We return the first lun. wwns = [] # list of targets itmap = {} # dict of initiators and the associated targets @@ -1166,14 +1166,14 @@ class StorageCenterApi(object): return lun, wwns, itmap def _find_active_controller(self, scvolume): - '''Finds the controller on which the Dell volume is active. + """Finds the controller on which the Dell volume is active. There can be more than one Dell backend controller per Storage center but a given volume can only be active on one of them at a time. :param scvolume: Dell backend volume object. :returns: Active controller ID. - ''' + """ actvctrl = None # TODO(Swanson): We have a function that gets this. Call that. r = self.client.get('StorageCenter/ScVolume/%s/VolumeConfiguration' @@ -1220,11 +1220,11 @@ class StorageCenterApi(object): return isvpmode def _find_controller_port_iscsi_config(self, cportid): - '''Finds the SC controller port object for the specified cportid. + """Finds the SC controller port object for the specified cportid. :param cportid: The instanceID of the Dell backend controller port. :returns: The controller port object. - ''' + """ controllerport = None r = self.client.get('StorageCenter/' 'ScControllerPortIscsiConfiguration/%s' @@ -1242,7 +1242,7 @@ class StorageCenterApi(object): return controllerport def find_iscsi_properties(self, scvolume, ip=None, port=None): - '''Finds target information for a given Dell scvolume object mapping. + """Finds target information for a given Dell scvolume object mapping. The data coming back is both the preferred path and all the paths. @@ -1251,7 +1251,7 @@ class StorageCenterApi(object): :param port: The preferred target portal port. :returns: iSCSI property dictionary. :raises: VolumeBackendAPIException - ''' + """ LOG.debug('enter find_iscsi_properties') LOG.debug('scvolume: %s', scvolume) # Our mutable process object. @@ -1267,7 +1267,7 @@ class StorageCenterApi(object): # Process just looks for the best port to return. def process(lun, iqn, address, port, readonly, status, active): - '''Process this mapping information. + """Process this mapping information. :param lun: SCSI Lun. :param iqn: iSCSI IQN address. @@ -1279,7 +1279,7 @@ class StorageCenterApi(object): :param active: Boolean indicating whether this is on the active controller or not. :return: Nothing - ''' + """ portals.append(address + ':' + six.text_type(port)) iqns.append(iqn) @@ -1391,7 +1391,7 @@ class StorageCenterApi(object): return data def map_volume(self, scvolume, scserver): - '''Maps the Dell backend volume object to the Dell server object. + """Maps the Dell backend volume object to the Dell server object. The check for the Dell server object existence is elsewhere; does not create the Dell server object. @@ -1399,7 +1399,7 @@ class StorageCenterApi(object): :param scvolume: Storage Center volume object. :param scserver: Storage Center server opbject. :returns: SC mapping profile or None - ''' + """ # Make sure we have what we think we have serverid = self._get_id(scserver) volumeid = self._get_id(scvolume) @@ -1432,7 +1432,7 @@ class StorageCenterApi(object): return None def unmap_volume(self, scvolume, scserver): - '''Unmaps the Dell volume object from the Dell server object. + """Unmaps the Dell volume object from the Dell server object. Deletes all mappings to a Dell server object, not just the ones on the path defined in cinder.conf. @@ -1440,7 +1440,7 @@ class StorageCenterApi(object): :param scvolume: Storage Center volume object. :param scserver: Storage Center server opbject. :returns: True or False. - ''' + """ rtn = True serverid = self._get_id(scserver) volumeid = self._get_id(scvolume) @@ -1468,12 +1468,12 @@ class StorageCenterApi(object): return rtn def get_storage_usage(self): - '''Gets the storage usage object from the Dell backend. + """Gets the storage usage object from the Dell backend. This contains capacity and usage information for the SC. :returns: The SC storageusage object. - ''' + """ storageusage = None if self.ssn is not None: r = self.client.get('StorageCenter/StorageCenter/%s/StorageUsage' @@ -1488,7 +1488,7 @@ class StorageCenterApi(object): return storageusage def create_replay(self, scvolume, replayid, expire): - '''Takes a snapshot of a volume. + """Takes a snapshot of a volume. One could snap a volume before it has been activated, so activate by mapping and unmapping to a random server and let them. This @@ -1503,7 +1503,7 @@ class StorageCenterApi(object): cloning a volume we will snap it right before creating the clone. :returns: The Dell replay object or None. - ''' + """ replay = None if scvolume is not None: if (scvolume.get('active') is not True or @@ -1530,7 +1530,7 @@ class StorageCenterApi(object): return replay def find_replay(self, scvolume, replayid): - '''Searches for the replay by replayid. + """Searches for the replay by replayid. replayid is stored in the replay's description attribute. @@ -1539,7 +1539,7 @@ class StorageCenterApi(object): snapshot ID as we do not have space for the entire GUID in the replay description. :returns: Dell replay object or None. - ''' + """ r = self.client.get('StorageCenter/ScVolume/%s/ReplayList' % self._get_id(scvolume)) try: @@ -1568,7 +1568,7 @@ class StorageCenterApi(object): return None def delete_replay(self, scvolume, replayid): - '''Finds a Dell replay by replayid string and expires it. + """Finds a Dell replay by replayid string and expires it. Once marked for expiration we do not return the replay as a snapshot even though it might still exist. (Backend requirements.) @@ -1578,7 +1578,7 @@ class StorageCenterApi(object): ID as we do not have space for the entire GUID in the replay description. :returns: Boolean for success or failure. - ''' + """ LOG.debug('Expiring replay %s', replayid) replay = self.find_replay(scvolume, replayid) @@ -1595,12 +1595,12 @@ class StorageCenterApi(object): return True def create_view_volume(self, volname, screplay): - '''Creates a new volume named volname from the screplay. + """Creates a new volume named volname from the screplay. :param volname: Name of new volume. This is the cinder volume ID. :param screplay: Dell replay object from which to make a new volume. :returns: Dell volume object or None. - ''' + """ folder = self._find_volume_folder(True) # payload is just the volume name and folder if we have one. @@ -1627,7 +1627,7 @@ class StorageCenterApi(object): return volume def create_cloned_volume(self, volumename, scvolume): - '''Creates a volume named volumename from a copy of scvolume. + """Creates a volume named volumename from a copy of scvolume. This is done by creating a replay and then a view volume from that replay. The replay is set to expire after an hour. It is only @@ -1638,7 +1638,7 @@ class StorageCenterApi(object): :param volumename: Name of new volume. This is the cinder volume ID. :param scvolume: Dell volume object. :returns: The new volume's Dell volume object. - ''' + """ clone = None replay = self.create_replay(scvolume, 'Cinder Clone Replay', @@ -1651,12 +1651,12 @@ class StorageCenterApi(object): return clone def expand_volume(self, scvolume, newsize): - '''Expands scvolume to newsize GBs. + """Expands scvolume to newsize GBs. :param scvolume: Dell volume object to be expanded. :param newsize: The new size of the volume object. :returns: The updated Dell volume object on success or None on failure. - ''' + """ payload = {} payload['NewSize'] = '%d GB' % newsize r = self.client.post('StorageCenter/ScVolume/%s/ExpandToSize' @@ -1678,14 +1678,14 @@ class StorageCenterApi(object): return vol def rename_volume(self, scvolume, name): - '''Rename scvolume to name. + """Rename scvolume to name. This is mostly used by update_migrated_volume. :param scvolume: The Dell volume object to be renamed. :param name: The new volume name. :returns: Boolean indicating success or failure. - ''' + """ payload = {} payload['Name'] = name r = self.client.post('StorageCenter/ScVolume/%s/Modify' @@ -1774,7 +1774,7 @@ class StorageCenterApi(object): return self._get_json(r) def _delete_server(self, scserver): - '''Deletes scserver from the backend. + """Deletes scserver from the backend. Just give it a shot. If it fails it doesn't matter to cinder. This is generally used when a create_server call fails in the middle of @@ -1785,7 +1785,7 @@ class StorageCenterApi(object): :param scserver: Dell server object to delete. :returns: Nothing. Only logs messages. - ''' + """ if scserver.get('deleteAllowed') is True: r = self.client.delete('StorageCenter/ScServer/%s' % self._get_id(scserver)) @@ -1797,13 +1797,13 @@ class StorageCenterApi(object): LOG.debug('_delete_server: deleteAllowed is False.') def find_replay_profile(self, name): - '''Finds the Dell SC replay profile object name. + """Finds the Dell SC replay profile object name. :param name: Name of the replay profile object. This is the consistency group id. :return: Dell SC replay profile or None. :raises: VolumeBackendAPIException - ''' + """ self.cg_except_on_no_support() pf = self._get_payload_filter() pf.append('ScSerialNumber', self.ssn) @@ -1824,12 +1824,12 @@ class StorageCenterApi(object): return None def create_replay_profile(self, name): - '''Creates a replay profile on the Dell SC. + """Creates a replay profile on the Dell SC. :param name: The ID of the consistency group. This will be matched to the name on the Dell SC. :return: SC profile or None. - ''' + """ self.cg_except_on_no_support() profile = self.find_replay_profile(name) if not profile: @@ -1847,12 +1847,12 @@ class StorageCenterApi(object): return profile def delete_replay_profile(self, profile): - '''Delete the replay profile from the Dell SC. + """Delete the replay profile from the Dell SC. :param profile: SC replay profile. :return: Nothing. :raises: VolumeBackendAPIException - ''' + """ self.cg_except_on_no_support() r = self.client.delete('StorageCenter/ScReplayProfile/%s' % self._get_id(profile)) @@ -1870,11 +1870,11 @@ class StorageCenterApi(object): _('Error deleting replay profile.')) def _get_volume_configuration(self, scvolume): - '''Get the ScVolumeConfiguration object. + """Get the ScVolumeConfiguration object. :param scvolume: The Dell SC volume object. :return: The SCVolumeConfiguration object or None. - ''' + """ r = self.client.get('StorageCenter/ScVolume/%s/VolumeConfiguration' % self._get_id(scvolume)) if r.status_code == 200: @@ -1883,13 +1883,13 @@ class StorageCenterApi(object): return None def _update_volume_profiles(self, scvolume, addid=None, removeid=None): - '''Either Adds or removes the listed profile from the SC volume. + """Either Adds or removes the listed profile from the SC volume. :param scvolume: Dell SC volume object. :param addid: Profile ID to be added to the SC volume configuration. :param removeid: ID to be removed to the SC volume configuration. :return: True/False on success/failure. - ''' + """ if scvolume: scvolumecfg = self._get_volume_configuration(scvolume) if scvolumecfg: @@ -1922,13 +1922,13 @@ class StorageCenterApi(object): return False def _add_cg_volumes(self, profileid, add_volumes): - '''Trundles through add_volumes and adds the replay profile to them. + """Trundles through add_volumes and adds the replay profile to them. :param profileid: The ID of the replay profile. :param add_volumes: List of Dell SC volume objects that are getting added to the consistency group. :return: True/False on success/failure. - ''' + """ for vol in add_volumes: if (self._update_volume_profiles(self.find_volume(vol['id']), addid=profileid, @@ -1940,13 +1940,13 @@ class StorageCenterApi(object): return True def _remove_cg_volumes(self, profileid, remove_volumes): - '''Removes the replay profile from the remove_volumes list of vols. + """Removes the replay profile from the remove_volumes list of vols. :param profileid: The ID of the replay profile. :param remove_volumes: List of Dell SC volume objects that are getting removed from the consistency group. :return: True/False on success/failure. - ''' + """ for vol in remove_volumes: if (self._update_volume_profiles(self.find_volume(vol['id']), addid=None, @@ -1959,7 +1959,7 @@ class StorageCenterApi(object): def update_cg_volumes(self, profile, add_volumes=None, remove_volumes=None): - '''Adds or removes the profile from the specified volumes + """Adds or removes the profile from the specified volumes :param profile: Dell SC replay profile object. :param add_volumes: List of volumes we are adding to the consistency @@ -1969,7 +1969,7 @@ class StorageCenterApi(object): consistency group. (Which is to say we are removing the profile from this list of volumes.) :return: True/False on success/failure. - ''' + """ self.cg_except_on_no_support() ret = True profileid = self._get_id(profile) @@ -1982,11 +1982,11 @@ class StorageCenterApi(object): return ret def _init_cg_volumes(self, profileid): - '''Gets the cg volume list and maps/unmaps the non active volumes. + """Gets the cg volume list and maps/unmaps the non active volumes. :param profileid: Replay profile identifier. :return: Nothing - ''' + """ r = self.client.get('StorageCenter/ScReplayProfile/%s/VolumeList' % profileid) if r.status_code == 200: @@ -1997,14 +1997,14 @@ class StorageCenterApi(object): self._init_volume(vol) def snap_cg_replay(self, profile, replayid, expire): - '''Snaps a replay of a consistency group. + """Snaps a replay of a consistency group. :param profile: The name of the consistency group profile. :param replayid: The name of the replay. :param expire: Time in mintues before a replay expires. 0 means no expiration. :returns: Dell SC replay object. - ''' + """ self.cg_except_on_no_support() if profile: # We have to make sure these are snappable. @@ -2029,7 +2029,7 @@ class StorageCenterApi(object): return False def find_cg_replay(self, profile, replayid): - '''Searches for the replay by replayid. + """Searches for the replay by replayid. replayid is stored in the replay's description attribute. @@ -2038,7 +2038,7 @@ class StorageCenterApi(object): snapshot ID as we do not have space for the entire GUID in the replay description. :returns: Dell replay object or None. - ''' + """ self.cg_except_on_no_support() r = self.client.get('StorageCenter/ScReplayProfile/%s/ReplayList' % self._get_id(profile)) @@ -2064,7 +2064,7 @@ class StorageCenterApi(object): return None def delete_cg_replay(self, profile, replayid): - '''Finds a Dell replay by replayid string and expires it. + """Finds a Dell replay by replayid string and expires it. Once marked for expiration we do not return the replay as a snapshot even though it might still exist. (Backend requirements.) @@ -2074,7 +2074,7 @@ class StorageCenterApi(object): ID as we do not have space for the entire GUID in the replay description. :returns: Boolean for success or failure. - ''' + """ self.cg_except_on_no_support() LOG.debug('Expiring consistency group replay %s', replayid) replay = self.find_replay(profile, @@ -2098,7 +2098,7 @@ class StorageCenterApi(object): raise NotImplementedError(msg) def _size_to_gb(self, spacestring): - '''Splits a SC size string into GB and a remainder. + """Splits a SC size string into GB and a remainder. Space is returned in a string like ... 7.38197504E8 Bytes @@ -2106,7 +2106,7 @@ class StorageCenterApi(object): :param spacestring: SC size string. :return: Size in GB and remainder in byte. - ''' + """ try: n = spacestring.split(' ', 1) fgb = int(float(n[0]) // 1073741824) @@ -2119,7 +2119,7 @@ class StorageCenterApi(object): _('Error retrieving volume size')) def manage_existing(self, newname, existing): - '''Finds the volume named existing and renames it. + """Finds the volume named existing and renames it. This checks a few things. The volume has to exist. There can only be one volume by that name. Since cinder manages volumes @@ -2133,7 +2133,7 @@ class StorageCenterApi(object): :param existing: The existing volume dict.. :return: Nothing. :raises: VolumeBackendAPIException, ManageExistingInvalidReference - ''' + """ vollist = self._get_volume_list(existing.get('source-name'), existing.get('source-id'), False) @@ -2184,12 +2184,12 @@ class StorageCenterApi(object): _('Volume not found. (%s)') % existing) def get_unmanaged_volume_size(self, existing): - '''Looks up the volume named existing and returns its size string. + """Looks up the volume named existing and returns its size string. :param existing: Existing volume dict. :return: The SC configuredSize string. :raises: ManageExistingInvalidReference - ''' + """ vollist = self._get_volume_list(existing.get('source-name'), existing.get('source-id'), False) @@ -2209,14 +2209,14 @@ class StorageCenterApi(object): _('Volume not found. (%s)') % existing) def unmanage(self, scvolume): - '''Unmanage our volume. + """Unmanage our volume. We simply rename with with a prefix of 'Unmanaged_'. That's it. :param scvolume: The Dell SC volume object. :return: Nothing. :raises: VolumeBackendAPIException - ''' + """ newname = 'Unmanaged_' + scvolume['name'] payload = {} payload['Name'] = newname diff --git a/cinder/volume/drivers/dell/dell_storagecenter_common.py b/cinder/volume/drivers/dell/dell_storagecenter_common.py index 5627dd57aa6..0dc2e9018c0 100644 --- a/cinder/volume/drivers/dell/dell_storagecenter_common.py +++ b/cinder/volume/drivers/dell/dell_storagecenter_common.py @@ -61,12 +61,12 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD, self.configuration.safe_get('volume_backend_name') or 'Dell' def _bytes_to_gb(self, spacestring): - '''Space is returned in a string like ... + """Space is returned in a string like ... 7.38197504E8 Bytes Need to split that apart and convert to GB. returns gbs in int form - ''' + """ try: n = spacestring.split(' ', 1) fgbs = float(n[0]) / 1073741824.0 @@ -78,22 +78,22 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD, return None def do_setup(self, context): - '''One time driver setup. + """One time driver setup. Called once by the manager after the driver is loaded. Sets up clients, check licenses, sets up protocol specific helpers. - ''' + """ self._client = dell_storagecenter_api.StorageCenterApiHelper( self.configuration) def check_for_setup_error(self): - '''Validates the configuration information.''' + """Validates the configuration information.""" with self._client.open_connection() as api: api.find_sc() def _get_volume_extra_specs(self, volume): - '''Gets extra specs for the given volume.''' + """Gets extra specs for the given volume.""" type_id = volume.get('volume_type_id') if type_id: return volume_types.get_volume_type_extra_specs(type_id) @@ -101,13 +101,13 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD, return {} def _add_volume_to_consistency_group(self, api, scvolume, volume): - '''Just a helper to add a volume to a consistency group. + """Just a helper to add a volume to a consistency group. :param api: Dell SC API opbject. :param scvolume: Dell SC Volume object. :param volume: Cinder Volume object. :return: Nothing. - ''' + """ if scvolume and volume.get('consistencygroup_id'): profile = api.find_replay_profile( volume.get('consistencygroup_id')) @@ -115,7 +115,7 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD, api.update_cg_volumes(profile, [volume]) def create_volume(self, volume): - '''Create a volume.''' + """Create a volume.""" # We use id as our name as it is unique. volume_name = volume.get('id') @@ -166,7 +166,7 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD, raise exception.VolumeIsBusy(volume_name=volume_name) def create_snapshot(self, snapshot): - '''Create snapshot''' + """Create snapshot""" # our volume name is the volume id volume_name = snapshot.get('volume_id') snapshot_id = snapshot.get('id') @@ -192,7 +192,7 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD, snapshot_id) def create_volume_from_snapshot(self, volume, snapshot): - '''Create new volume from other volume's snapshot on appliance.''' + """Create new volume from other volume's snapshot on appliance.""" scvolume = None src_volume_name = snapshot.get('volume_id') # This snapshot could have been created on its own or as part of a @@ -239,7 +239,7 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD, _('Failed to create volume %s') % volume_name) def create_cloned_volume(self, volume, src_vref): - '''Creates a clone of the specified volume.''' + """Creates a clone of the specified volume.""" scvolume = None src_volume_name = src_vref.get('id') volume_name = volume.get('id') @@ -270,7 +270,7 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD, _('Failed to create volume %s') % volume_name) def delete_snapshot(self, snapshot): - '''delete_snapshot''' + """delete_snapshot""" volume_name = snapshot.get('volume_id') snapshot_id = snapshot.get('id') LOG.debug('Deleting snapshot %(snap)s from volume %(vol)s', @@ -289,19 +289,19 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD, _('Failed to delete snapshot %s') % snapshot_id) def create_export(self, context, volume): - '''Create an export of a volume. + """Create an export of a volume. The volume exists on creation and will be visible on initialize connection. So nothing to do here. - ''' + """ pass def ensure_export(self, context, volume): - '''Ensure an export of a volume. + """Ensure an export of a volume. Per the eqlx driver we just make sure that the volume actually exists where we think it does. - ''' + """ scvolume = None volume_name = volume.get('id') LOG.debug('Checking existence of volume %s', volume_name) @@ -318,15 +318,15 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD, _('Unable to find volume %s') % volume_name) def remove_export(self, context, volume): - '''Remove an export of a volume. + """Remove an export of a volume. We do nothing here to match the nothing we do in create export. Again we do everything in initialize and terminate connection. - ''' + """ pass def extend_volume(self, volume, new_size): - '''Extend the size of the volume.''' + """Extend the size of the volume.""" volume_name = volume.get('id') LOG.debug('Extending volume %(vol)s to %(size)s', {'vol': volume_name, @@ -342,17 +342,17 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD, _('Unable to extend volume %s') % volume_name) def get_volume_stats(self, refresh=False): - '''Get volume status. + """Get volume status. If 'refresh' is True, run update the stats first. - ''' + """ if refresh: self._update_volume_stats() return self._stats def _update_volume_stats(self): - '''Retrieve stats info from volume group.''' + """Retrieve stats info from volume group.""" with self._client.open_connection() as api: storageusage = api.get_storage_usage() if api.find_sc() else None @@ -383,14 +383,14 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD, def update_migrated_volume(self, ctxt, volume, new_volume, original_volume_status): - '''Return model update for migrated volume. + """Return model update for migrated volume. :param volume: The original volume that was migrated to this backend :param new_volume: The migration volume object that was created on this backend as part of the migration process :param original_volume_status: The status of the original volume :return model_update to update DB with any needed changes - ''' + """ # We use id as our volume name so we need to rename the backend # volume to the original volume name. original_volume_name = volume.get('id') @@ -413,13 +413,13 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD, return {'_name_id': new_volume['_name_id'] or new_volume['id']} def create_consistencygroup(self, context, group): - '''This creates a replay profile on the storage backend. + """This creates a replay profile on the storage backend. :param context: the context of the caller. :param group: the dictionary of the consistency group to be created. :return: Nothing on success. :raises: VolumeBackendAPIException - ''' + """ gid = group['id'] with self._client.open_connection() as api: cgroup = api.create_replay_profile(gid) @@ -430,12 +430,12 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD, _('Unable to create consistency group %s') % gid) def delete_consistencygroup(self, context, group): - '''Delete the Dell SC profile associated with this consistency group. + """Delete the Dell SC profile associated with this consistency group. :param context: the context of the caller. :param group: the dictionary of the consistency group to be created. :return: Updated model_update, volumes. - ''' + """ gid = group['id'] with self._client.open_connection() as api: profile = api.find_replay_profile(gid) @@ -457,7 +457,7 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD, def update_consistencygroup(self, context, group, add_volumes=None, remove_volumes=None): - '''Updates a consistency group. + """Updates a consistency group. :param context: the context of the caller. :param group: the dictionary of the consistency group to be updated. @@ -480,7 +480,7 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD, If the driver throws an exception, the status of the group as well as those of the volumes to be added/removed will be set to 'error'. - ''' + """ gid = group['id'] with self._client.open_connection() as api: profile = api.find_replay_profile(gid) @@ -497,13 +497,13 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD, _('Unable to update consistency group %s') % gid) def create_cgsnapshot(self, context, cgsnapshot): - '''Takes a snapshot of the consistency group. + """Takes a snapshot of the consistency group. :param context: the context of the caller. :param cgsnapshot: Information about the snapshot to take. :return: Updated model_update, snapshots. :raises: VolumeBackendAPIException. - ''' + """ cgid = cgsnapshot['consistencygroup_id'] snapshotid = cgsnapshot['id'] @@ -530,7 +530,7 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD, _('Unable to snap Consistency Group %s') % cgid) def delete_cgsnapshot(self, context, cgsnapshot): - '''Deletes a cgsnapshot. + """Deletes a cgsnapshot. If profile isn't found return success. If failed to delete the replay (the snapshot) then raise an exception. @@ -539,7 +539,7 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD, :param cgsnapshot: Information about the snapshot to delete. :return: Updated model_update, snapshots. :raises: VolumeBackendAPIException. - ''' + """ cgid = cgsnapshot['consistencygroup_id'] snapshotid = cgsnapshot['id'] diff --git a/cinder/volume/drivers/dell/dell_storagecenter_fc.py b/cinder/volume/drivers/dell/dell_storagecenter_fc.py index 4a4f65104c0..12642dec56b 100644 --- a/cinder/volume/drivers/dell/dell_storagecenter_fc.py +++ b/cinder/volume/drivers/dell/dell_storagecenter_fc.py @@ -12,7 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. -'''Volume driver for Dell Storage Center.''' +"""Volume driver for Dell Storage Center.""" from oslo_log import log as logging from oslo_utils import excutils @@ -29,7 +29,7 @@ LOG = logging.getLogger(__name__) class DellStorageCenterFCDriver(dell_storagecenter_common.DellCommonDriver, driver.FibreChannelDriver): - '''Implements commands for Dell EqualLogic SAN ISCSI management. + """Implements commands for Dell EqualLogic SAN ISCSI management. To enable the driver add the following line to the cinder configuration: volume_driver=cinder.volume.drivers.dell.DellStorageCenterFCDriver @@ -42,7 +42,7 @@ class DellStorageCenterFCDriver(dell_storagecenter_common.DellCommonDriver, driver. 2.1.0 - Added support for ManageableVD. 2.2.0 - Driver retype support for switching volume's Storage Profile - ''' + """ VERSION = '2.2.0' @@ -53,7 +53,7 @@ class DellStorageCenterFCDriver(dell_storagecenter_common.DellCommonDriver, @fczm_utils.AddFCZone def initialize_connection(self, volume, connector): - '''Initializes the connection and returns connection info. + """Initializes the connection and returns connection info. Assign any created volume to a compute node/host so that it can be used from that host. @@ -61,7 +61,7 @@ class DellStorageCenterFCDriver(dell_storagecenter_common.DellCommonDriver, The driver returns a driver_volume_type of 'fibre_channel'. The target_wwn can be a single entry or a list of wwns that correspond to the list of remote wwn(s) that will export the volume. - ''' + """ # We use id to name the volume name as it is a # known unique name. @@ -154,10 +154,10 @@ class DellStorageCenterFCDriver(dell_storagecenter_common.DellCommonDriver, _('Terminate connection unable to connect to backend.')) def get_volume_stats(self, refresh=False): - '''Get volume status. + """Get volume status. If 'refresh' is True, run update the stats first. - ''' + """ if refresh: self._update_volume_stats() # Update our protocol to the correct one. diff --git a/cinder/volume/drivers/dell/dell_storagecenter_iscsi.py b/cinder/volume/drivers/dell/dell_storagecenter_iscsi.py index 6334342ea90..5bc9ae4a803 100644 --- a/cinder/volume/drivers/dell/dell_storagecenter_iscsi.py +++ b/cinder/volume/drivers/dell/dell_storagecenter_iscsi.py @@ -12,7 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. -'''Volume driver for Dell Storage Center.''' +"""Volume driver for Dell Storage Center.""" from oslo_log import log as logging from oslo_utils import excutils @@ -27,7 +27,7 @@ LOG = logging.getLogger(__name__) class DellStorageCenterISCSIDriver(dell_storagecenter_common.DellCommonDriver, driver.ISCSIDriver): - '''Implements commands for Dell StorageCenter ISCSI management. + """Implements commands for Dell StorageCenter ISCSI management. To enable the driver add the following line to the cinder configuration: volume_driver=cinder.volume.drivers.dell.DellStorageCenterISCSIDriver @@ -40,7 +40,7 @@ class DellStorageCenterISCSIDriver(dell_storagecenter_common.DellCommonDriver, driver. 2.1.0 - Added support for ManageableVD. 2.2.0 - Driver retype support for switching volume's Storage Profile - ''' + """ VERSION = '2.2.0' diff --git a/cinder/volume/drivers/eqlx.py b/cinder/volume/drivers/eqlx.py index 622982bda2a..74adebebeb0 100644 --- a/cinder/volume/drivers/eqlx.py +++ b/cinder/volume/drivers/eqlx.py @@ -421,7 +421,7 @@ class DellEQLSanISCSIDriver(san.SanISCSIDriver): 'volume "%s".'), volume['name']) def create_snapshot(self, snapshot): - """"Create snapshot of existing volume on appliance.""" + """Create snapshot of existing volume on appliance.""" try: out = self._eql_execute('volume', 'select', snapshot['volume_name'], diff --git a/cinder/volume/drivers/ibm/storwize_svc/ssh.py b/cinder/volume/drivers/ibm/storwize_svc/ssh.py index d707fbb0b46..4cc30f27463 100644 --- a/cinder/volume/drivers/ibm/storwize_svc/ssh.py +++ b/cinder/volume/drivers/ibm/storwize_svc/ssh.py @@ -363,7 +363,7 @@ class StorwizeSSH(object): class CLIResponse(object): - '''Parse SVC CLI output and generate iterable.''' + """Parse SVC CLI output and generate iterable.""" def __init__(self, raw, ssh_cmd=None, delim='!', with_header=True): super(CLIResponse, self).__init__() diff --git a/cinder/volume/drivers/netapp/common.py b/cinder/volume/drivers/netapp/common.py index afb074c4226..8414096ad8e 100644 --- a/cinder/volume/drivers/netapp/common.py +++ b/cinder/volume/drivers/netapp/common.py @@ -56,7 +56,7 @@ NETAPP_UNIFIED_DRIVER_REGISTRY = { class NetAppDriver(driver.ProxyVD): - """"NetApp unified block storage driver. + """NetApp unified block storage driver. Acts as a factory to create NetApp storage drivers based on the storage family and protocol configured. @@ -85,7 +85,7 @@ class NetAppDriver(driver.ProxyVD): @staticmethod def create_driver(storage_family, storage_protocol, *args, **kwargs): - """"Creates an appropriate driver based on family and protocol.""" + """Creates an appropriate driver based on family and protocol.""" storage_family = storage_family.lower() storage_protocol = storage_protocol.lower() diff --git a/cinder/volume/drivers/san/hp/hp_3par_iscsi.py b/cinder/volume/drivers/san/hp/hp_3par_iscsi.py index 0f8a28b18d8..a51f837c4f0 100644 --- a/cinder/volume/drivers/san/hp/hp_3par_iscsi.py +++ b/cinder/volume/drivers/san/hp/hp_3par_iscsi.py @@ -641,7 +641,7 @@ class HP3PARISCSIDriver(cinder.volume.driver.ISCSIDriver): return key def _get_least_used_nsp(self, common, vluns, nspss): - """"Return the nsp that has the fewest active vluns.""" + """Return the nsp that has the fewest active vluns.""" # return only the nsp (node:server:port) # count the number of nsps nsp_counts = {} diff --git a/cinder/volume/drivers/srb.py b/cinder/volume/drivers/srb.py index 30305a677ea..2083e25a693 100644 --- a/cinder/volume/drivers/srb.py +++ b/cinder/volume/drivers/srb.py @@ -218,14 +218,14 @@ class LVM(lvm.LVM): @contextlib.contextmanager def patched(obj, attr, fun): - '''Context manager to locally patch a method. + """Context manager to locally patch a method. Within the managed context, the `attr` method of `obj` will be replaced by a method which calls `fun` passing in the original `attr` attribute of `obj` as well as any positional and keyword arguments. At the end of the context, the original method is restored. - ''' + """ orig = getattr(obj, attr) @@ -242,7 +242,7 @@ def patched(obj, attr, fun): @contextlib.contextmanager def handle_process_execution_error(message, info_message, reraise=True): - '''Consistently handle `putils.ProcessExecutionError` exceptions + """Consistently handle `putils.ProcessExecutionError` exceptions This context-manager will catch any `putils.ProcessExecutionError` exceptions raised in the managed block, and generate logging output @@ -259,7 +259,7 @@ def handle_process_execution_error(message, info_message, reraise=True): object will be raised instead (so you most likely want it to be some `Exception`). Any `False` value will result in the exception to be swallowed. - ''' + """ try: yield @@ -460,8 +460,8 @@ class SRBDriver(driver.VolumeDriver): @staticmethod def _activate_lv(orig, *args, **kwargs): - '''Use with `patched` to patch `lvm.LVM.activate_lv` to ignore `EEXIST` - ''' + """Use with `patched` to patch `lvm.LVM.activate_lv` to ignore `EEXIST` + """ try: orig(*args, **kwargs) except putils.ProcessExecutionError as exc: diff --git a/cinder/volume/rpcapi.py b/cinder/volume/rpcapi.py index 04812f5681d..8a027b81b80 100644 --- a/cinder/volume/rpcapi.py +++ b/cinder/volume/rpcapi.py @@ -29,7 +29,7 @@ CONF = cfg.CONF class VolumeAPI(object): - '''Client side of the volume rpc API. + """Client side of the volume rpc API. API version history: @@ -68,7 +68,7 @@ class VolumeAPI(object): source_volid, source_replicaid, consistencygroup_id and cgsnapshot_id from create_volume. All off them are already passed either in request_spec or available in the DB. - ''' + """ BASE_RPC_API_VERSION = '1.0'