diff options
-rw-r--r-- | .pylintrc | 2 | ||||
-rw-r--r-- | cinder/backup/drivers/ceph.py | 1 | ||||
-rw-r--r-- | cinder/tests/unit/api/v2/test_snapshots.py | 2 | ||||
-rw-r--r-- | cinder/tests/unit/backup/drivers/test_backup_ceph.py | 29 | ||||
-rw-r--r-- | cinder/tests/unit/volume/drivers/hpe/test_hpe3par.py | 5 | ||||
-rw-r--r-- | cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py | 4 | ||||
-rw-r--r-- | cinder/tests/unit/volume/drivers/test_rbd.py | 45 | ||||
-rw-r--r-- | cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py | 4 | ||||
-rw-r--r-- | cinder/volume/drivers/rbd.py | 7 | ||||
-rw-r--r-- | cinder/volume/targets/driver.py | 8 | ||||
-rw-r--r-- | releasenotes/notes/hitachi-vsp-add-hostgroup-name-format-option-4c8e4a5ddd69b9bd.yaml | 26 | ||||
-rw-r--r-- | releasenotes/notes/rbd-total_capacity-60f10b45e3a8c8ea.yaml | 8 |
12 files changed, 96 insertions, 45 deletions
@@ -224,7 +224,7 @@ additional-builtins=_ [TYPECHECK] # List of module names for which member attributes should not be checked ignored-modules=six.moves,_MovedItems,alembic.context,alembic.op, - alembic.config,pyxcli,storpool,oslo_privsep.capabilities + alembic.config,pyxcli,storpool,oslo_privsep.capabilities,nvmet signature-mutators=unittest.mock.patch,unittest.mock.patch.object,sqlalchemy.util._preloaded.dependencies # This is for cinder.objects.*, and requests.packages.*, but due to diff --git a/cinder/backup/drivers/ceph.py b/cinder/backup/drivers/ceph.py index d21e458bf..0e329bd88 100644 --- a/cinder/backup/drivers/ceph.py +++ b/cinder/backup/drivers/ceph.py @@ -350,7 +350,6 @@ class CephBackupDriver(driver.BackupDriver): Incremental backups use a new base name so we support old and new style format. """ - # Ensure no unicode if not backup: return "volume-%s.backup.base" % volume_id diff --git a/cinder/tests/unit/api/v2/test_snapshots.py b/cinder/tests/unit/api/v2/test_snapshots.py index ce58abb40..d85ae2d33 100644 --- a/cinder/tests/unit/api/v2/test_snapshots.py +++ b/cinder/tests/unit/api/v2/test_snapshots.py @@ -528,7 +528,7 @@ class SnapshotApiTest(test.TestCase): @mock.patch.object(db, 'snapshot_get_all_by_project') @mock.patch('cinder.db.snapshot_metadata_get', return_value=dict()) - def test_list_snpashots_with_wrong_limit_and_offset(self, + def test_list_snapshots_with_wrong_limit_and_offset(self, mock_metadata_get, mock_snapshot_get_all): """Test list with negative and non numeric limit and offset.""" diff --git a/cinder/tests/unit/backup/drivers/test_backup_ceph.py b/cinder/tests/unit/backup/drivers/test_backup_ceph.py index 9bd350703..813c6fea2 100644 --- a/cinder/tests/unit/backup/drivers/test_backup_ceph.py +++ b/cinder/tests/unit/backup/drivers/test_backup_ceph.py @@ -17,6 +17,7 @@ import hashlib import json import os +import subprocess import tempfile import threading from unittest import mock @@ -136,8 +137,7 @@ class BackupCephTestCase(test.TestCase): 'user_foo', 'conf_foo') return linuxrbd.RBDVolumeIOWrapper(rbd_meta) - def _setup_mock_popen(self, mock_popen, retval=None, p1hook=None, - p2hook=None): + def _setup_mock_popen(self, retval=None, p1hook=None, p2hook=None): class MockPopen(object): hooks = [p2hook, p1hook] @@ -157,7 +157,7 @@ class BackupCephTestCase(test.TestCase): self.callstack.append('communicate') return retval - mock_popen.side_effect = MockPopen + subprocess.Popen.side_effect = MockPopen def setUp(self): global RAISED_EXCEPTIONS @@ -468,8 +468,7 @@ class BackupCephTestCase(test.TestCase): @common_mocks @mock.patch('fcntl.fcntl', spec=True) - @mock.patch('subprocess.Popen', spec=True) - def test_backup_volume_from_rbd(self, mock_popen, mock_fnctl): + def test_backup_volume_from_rbd(self, mock_fnctl): """Test full RBD backup generated successfully.""" backup_name = self.service._get_backup_base_name(self.volume_id, self.alt_backup) @@ -485,8 +484,7 @@ class BackupCephTestCase(test.TestCase): self.callstack.append('read') return self.volume_file.read(self.data_length) - self._setup_mock_popen(mock_popen, - ['out', 'err'], + self._setup_mock_popen(['out', 'err'], p1hook=mock_read_data, p2hook=mock_write_data) @@ -647,8 +645,7 @@ class BackupCephTestCase(test.TestCase): @common_mocks @mock.patch('fcntl.fcntl', spec=True) - @mock.patch('subprocess.Popen', spec=True) - def test_backup_volume_from_rbd_fail(self, mock_popen, mock_fnctl): + def test_backup_volume_from_rbd_fail(self, mock_fnctl): """Test of when an exception occurs in an exception handler. In _backup_rbd(), after an exception.BackupRBDOperationFailed @@ -670,8 +667,7 @@ class BackupCephTestCase(test.TestCase): self.callstack.append('read') return self.volume_file.read(self.data_length) - self._setup_mock_popen(mock_popen, - ['out', 'err'], + self._setup_mock_popen(['out', 'err'], p1hook=mock_read_data, p2hook=mock_write_data) @@ -726,8 +722,7 @@ class BackupCephTestCase(test.TestCase): @common_mocks @mock.patch('fcntl.fcntl', spec=True) - @mock.patch('subprocess.Popen', spec=True) - def test_backup_volume_from_rbd_fail2(self, mock_popen, mock_fnctl): + def test_backup_volume_from_rbd_fail2(self, mock_fnctl): """Test of when an exception occurs in an exception handler. In backup(), after an exception.BackupOperationError occurs in @@ -748,8 +743,7 @@ class BackupCephTestCase(test.TestCase): self.callstack.append('read') return self.volume_file.read(self.data_length) - self._setup_mock_popen(mock_popen, - ['out', 'err'], + self._setup_mock_popen(['out', 'err'], p1hook=mock_read_data, p2hook=mock_write_data) @@ -1324,10 +1318,9 @@ class BackupCephTestCase(test.TestCase): @common_mocks @mock.patch('fcntl.fcntl', spec=True) - @mock.patch('subprocess.Popen', spec=True) - def test_piped_execute(self, mock_popen, mock_fcntl): + def test_piped_execute(self, mock_fcntl): mock_fcntl.return_value = 0 - self._setup_mock_popen(mock_popen, ['out', 'err']) + self._setup_mock_popen(['out', 'err']) self.service._piped_execute(['foo'], ['bar']) self.assertEqual(['popen_init', 'popen_init', 'stdout_close', 'communicate'], self.callstack) diff --git a/cinder/tests/unit/volume/drivers/hpe/test_hpe3par.py b/cinder/tests/unit/volume/drivers/hpe/test_hpe3par.py index d19824208..1d1e440cb 100644 --- a/cinder/tests/unit/volume/drivers/hpe/test_hpe3par.py +++ b/cinder/tests/unit/volume/drivers/hpe/test_hpe3par.py @@ -749,10 +749,7 @@ class HPE3PARBaseDriver(test.TestCase): configuration.unique_fqdn_network = True return configuration - @mock.patch( - 'hpe3parclient.client.HPE3ParClient', - spec=True, - ) + @mock.patch('hpe3parclient.client.HPE3ParClient') def setup_mock_client(self, _m_client, driver, conf=None, m_conf=None, is_primera=False, wsapi_version=wsapi_version_latest): diff --git a/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py b/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py index 8581253b6..1266fa9f4 100644 --- a/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py +++ b/cinder/tests/unit/volume/drivers/ibm/test_storwize_svc.py @@ -6527,8 +6527,6 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): self.assertTrue(each_pool['multiattach']) self.assertLessEqual(each_pool['free_capacity_gb'], each_pool['total_capacity_gb']) - self.assertLessEqual(each_pool['allocated_capacity_gb'], - each_pool['total_capacity_gb']) self.assertEqual(25, each_pool['reserved_percentage']) self.assertEqual(is_thin_provisioning_enabled, each_pool['thin_provisioning_support']) @@ -6543,8 +6541,6 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase): self._def_flags['storwize_svc_volpool_name']) self.assertAlmostEqual(3328.0, each_pool['total_capacity_gb']) self.assertAlmostEqual(3287.5, each_pool['free_capacity_gb']) - self.assertAlmostEqual(25.0, - each_pool['allocated_capacity_gb']) if is_thin_provisioning_enabled: self.assertAlmostEqual( 1576.96, each_pool['provisioned_capacity_gb']) diff --git a/cinder/tests/unit/volume/drivers/test_rbd.py b/cinder/tests/unit/volume/drivers/test_rbd.py index 21645886f..57dae3af1 100644 --- a/cinder/tests/unit/volume/drivers/test_rbd.py +++ b/cinder/tests/unit/volume/drivers/test_rbd.py @@ -1969,6 +1969,51 @@ class RBDTestCase(test.TestCase): ]) self.assertEqual((free_capacity, total_capacity), result) + @ddt.data( + # Normal case, no quota and dynamic total + {'free_capacity': 27.0, 'total_capacity': 28.44}, + # No quota and static total + {'dynamic_total': False, + 'free_capacity': 27.0, 'total_capacity': 59.96}, + # Quota and dynamic total + {'quota_max_bytes': 3221225472, 'max_avail': 1073741824, + 'free_capacity': 1, 'total_capacity': 2.44}, + # Quota and static total + {'quota_max_bytes': 3221225472, 'max_avail': 1073741824, + 'dynamic_total': False, + 'free_capacity': 1, 'total_capacity': 3.00}, + # Quota and dynamic total when free would be negative + {'quota_max_bytes': 1073741824, + 'free_capacity': 0, 'total_capacity': 1.44}, + ) + @ddt.unpack + @common_mocks + def test_get_pool_nautilus(self, free_capacity, total_capacity, + max_avail=28987613184, quota_max_bytes=0, + dynamic_total=True): + client = self.mock_client.return_value + client.__enter__.return_value = client + client.cluster.mon_command.side_effect = [ + (0, '{"stats":{"total_bytes":64385286144,' + '"total_used_bytes":3289628672,"total_avail_bytes":61095657472},' + '"pools":[{"name":"rbd","id":2,"stats":{"kb_used":1510197,' + '"stored":1546440971,"bytes_used":4639322913,"max_avail":%s,' + '"objects":412}},{"name":"volumes","id":3,"stats":{"kb_used":0,' + '"bytes_used":0,"max_avail":28987613184,"objects":0}}]}\n' % + max_avail, ''), + (0, '{"pool_name":"volumes","pool_id":4,"quota_max_objects":0,' + '"quota_max_bytes":%s}\n' % quota_max_bytes, ''), + ] + with mock.patch.object(self.driver.configuration, 'safe_get', + return_value=dynamic_total): + result = self.driver._get_pool_stats() + client.cluster.mon_command.assert_has_calls([ + mock.call('{"prefix":"df", "format":"json"}', b''), + mock.call('{"prefix":"osd pool get-quota", "pool": "rbd",' + ' "format":"json"}', b''), + ]) + self.assertEqual((free_capacity, total_capacity), result) + @common_mocks def test_get_pool_bytes(self): """Test for mon_commands returning bytes instead of strings.""" diff --git a/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py b/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py index 938741156..ede96c72e 100644 --- a/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py +++ b/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py @@ -6850,8 +6850,6 @@ class StorwizeSVCCommonDriver(san.SanDriver, easy_tier = pool_data['easy_tier'] in ['on', 'auto'] total_capacity_gb = float(pool_data['capacity']) / units.Gi free_capacity_gb = float(pool_data['free_capacity']) / units.Gi - allocated_capacity_gb = (float(pool_data['used_capacity']) / - units.Gi) provisioned_capacity_gb = float( pool_data['virtual_capacity']) / units.Gi @@ -6878,7 +6876,6 @@ class StorwizeSVCCommonDriver(san.SanDriver, 'pool_name': pool_data['name'], 'total_capacity_gb': total_capacity_gb, 'free_capacity_gb': free_capacity_gb, - 'allocated_capacity_gb': allocated_capacity_gb, 'provisioned_capacity_gb': provisioned_capacity_gb, 'compression_support': compression_enabled, 'reserved_percentage': @@ -6911,7 +6908,6 @@ class StorwizeSVCCommonDriver(san.SanDriver, pool_stats = {'pool_name': pool, 'total_capacity_gb': 0, 'free_capacity_gb': 0, - 'allocated_capacity_gb': 0, 'provisioned_capacity_gb': 0, 'thin_provisioning_support': True, 'thick_provisioning_support': False, diff --git a/cinder/volume/drivers/rbd.py b/cinder/volume/drivers/rbd.py index 07cc72174..6cc86c2c5 100644 --- a/cinder/volume/drivers/rbd.py +++ b/cinder/volume/drivers/rbd.py @@ -722,12 +722,15 @@ class RBDDriver(driver.CloneableImageVD, driver.MigrateVD, total_capacity: float free_capacity: float + + # In Nautilus bytes_used was renamed to stored + bytes_used = pool_stats.get('stored', pool_stats['bytes_used']) quota_outbuf = encodeutils.safe_decode(quota_outbuf) bytes_quota = json.loads(quota_outbuf)['quota_max_bytes'] # With quota the total is the quota limit and free is quota - used if bytes_quota: total_capacity = bytes_quota - free_capacity = max(min(total_capacity - pool_stats['bytes_used'], + free_capacity = max(min(total_capacity - bytes_used, pool_stats['max_avail']), 0) # Without quota free is pools max available and total is global size @@ -737,7 +740,7 @@ class RBDDriver(driver.CloneableImageVD, driver.MigrateVD, # If we want dynamic total capacity (default behavior) if self.configuration.safe_get('report_dynamic_total_capacity'): - total_capacity = free_capacity + pool_stats['bytes_used'] + total_capacity = free_capacity + bytes_used free_capacity = round((float(free_capacity) / units.Gi), 2) total_capacity = round((float(total_capacity) / units.Gi), 2) diff --git a/cinder/volume/targets/driver.py b/cinder/volume/targets/driver.py index 9e186629b..644664b45 100644 --- a/cinder/volume/targets/driver.py +++ b/cinder/volume/targets/driver.py @@ -85,3 +85,11 @@ class Target(object, metaclass=abc.ABCMeta): """ a_host = A.get('host') return a_host and (a_host == B.get('host')) + + def extend_target(self, volume): + """Reinitializes a target after the volume has been extended. + + Most drivers don't need to do anything, but in other cases this may + cause IO disruption. + """ + pass diff --git a/releasenotes/notes/hitachi-vsp-add-hostgroup-name-format-option-4c8e4a5ddd69b9bd.yaml b/releasenotes/notes/hitachi-vsp-add-hostgroup-name-format-option-4c8e4a5ddd69b9bd.yaml index 20ed2cb80..e96aa8b28 100644 --- a/releasenotes/notes/hitachi-vsp-add-hostgroup-name-format-option-4c8e4a5ddd69b9bd.yaml +++ b/releasenotes/notes/hitachi-vsp-add-hostgroup-name-format-option-4c8e4a5ddd69b9bd.yaml @@ -3,6 +3,7 @@ features: - | Hitachi driver: Add a config option ``hitachi_group_name_format`` for hostgroup name format. + When using this option, users can specify the name format of host groups or iSCSI targets. Rules of the format: @@ -12,22 +13,25 @@ features: * The specified value must start with ``HBSD-``. * You can use the following variables: - * ``{wwn}``: FC driver only. This is replaced with the smallest - WWPN of the WWPNs of the connecting node. - * ``{ip}``: iSCSI driver only. This is replaced with the IP address of - the connecting node. - * ``{host}``: This is replaced with the host name of the connecting node. + ``{wwn}`` + `FC driver only.` This is replaced with the smallest + WWPN of the WWPNs of the connecting node. + ``{ip}`` + `iSCSI driver only.` This is replaced with the IP address of + the connecting node. + ``{host}`` + This is replaced with the host name of the connecting node. * You can use each variable in the specified value no more than once. * The specified value must include the following variables: - * FC driver: ``{wwn}`` - * iSCSI driver: ``{ip}`` + * FC driver: ``{wwn}`` + * iSCSI driver: ``{ip}`` * The maximum length of a specified value is as follows: - * FC driver: 64 - * iSCSI driver: 32 + * FC driver: 64 + * iSCSI driver: 32 * In the length calculation, use the following values as the length of each variable: @@ -46,8 +50,10 @@ features: iSCSI targets do not exceed the maximum length. If you specify this parameter, it is recommended that you specify ``True`` - for the hitachi_group_create parameter to collect necessary + for the ``hitachi_group_create`` parameter to collect necessary information automatically. + Examples: + * FC driver: ``HBSD-{host}-{wwn}`` * iSCSI driver: ``HBSD-{host}-{ip}`` diff --git a/releasenotes/notes/rbd-total_capacity-60f10b45e3a8c8ea.yaml b/releasenotes/notes/rbd-total_capacity-60f10b45e3a8c8ea.yaml new file mode 100644 index 000000000..1efa65097 --- /dev/null +++ b/releasenotes/notes/rbd-total_capacity-60f10b45e3a8c8ea.yaml @@ -0,0 +1,8 @@ +--- +fixes: + - | + RBD driver `bug #1960206 + <https://bugs.launchpad.net/cinder/+bug/1960206>`_: Fixed + ``total_capacity`` reported by the driver to the scheduler on Ceph clusters + that have renamed the ``bytes_used`` field to ``stored``. (e.g., `Nautilus + <https://docs.ceph.com/en/nautilus/releases/nautilus/#upgrade-compatibility-notes>`_). |