diff -Nru cinder-16.2.0/AUTHORS cinder-16.2.1/AUTHORS --- cinder-16.2.0/AUTHORS 2020-10-01 16:54:10.000000000 +0000 +++ cinder-16.2.1/AUTHORS 2020-12-08 15:45:32.000000000 +0000 @@ -314,6 +314,7 @@ Ghanshyam Mann Ghanshyan Mann Ghe Rivero +GirishChilukuri Giulio Fidente Glenn M. Gobeli Gloria Gu @@ -456,6 +457,7 @@ Kartik Bommepally Kazumasa Nomura Kedar Vidvans +Keigo Noha Keisuke Kuroki Ken'ichi Ohmichi Ken'ichi Ohmichi @@ -809,6 +811,7 @@ Szymon Wróblewski Tadas Ustinavičius Takahiro Shida +Takashi Kajinami Takashi Menjo Takashi NATSUME Takashi Natsume diff -Nru cinder-16.2.0/ChangeLog cinder-16.2.1/ChangeLog --- cinder-16.2.0/ChangeLog 2020-10-01 16:54:09.000000000 +0000 +++ cinder-16.2.1/ChangeLog 2020-12-08 15:45:32.000000000 +0000 @@ -1,10 +1,24 @@ CHANGES ======= +16.2.1 +------ + +* Fix volume rekey during clone +* [IBM DS8K]: Fixed rest API issue to get bundle +* PowerMax Driver - Fix non-temporary snapshot delete +* Do not fail when depth is greater than rbd\_max\_clone\_depth +* Fix service\_get\_log tests +* Fix: listing volumes with filters +* RBD: Run flatten in a different thread when cloning a volume +* Change default glance\_num\_retries to 3 +* PowerMax Driver - Replica rdfg suspend fix + 16.2.0 ------ * Add general release note for 16.2.0 +* NEC driver: fix a snapshot detach error * PowerMax Driver - Failover group vol update fix * PowerMax Driver - Force add rep group volume * Modify default/delete volume type logic diff -Nru cinder-16.2.0/cinder/common/config.py cinder-16.2.1/cinder/common/config.py --- cinder-16.2.0/cinder/common/config.py 2020-10-01 16:50:09.000000000 +0000 +++ cinder-16.2.1/cinder/common/config.py 2020-12-08 15:44:57.000000000 +0000 @@ -174,7 +174,7 @@ 'is not specified it defaults to http.'), cfg.IntOpt('glance_num_retries', min=0, - default=0, + default=3, help='Number retries when downloading an image from glance'), cfg.BoolOpt('glance_api_insecure', default=False, diff -Nru cinder-16.2.0/cinder/tests/unit/api/contrib/test_services.py cinder-16.2.1/cinder/tests/unit/api/contrib/test_services.py --- cinder-16.2.0/cinder/tests/unit/api/contrib/test_services.py 2020-10-01 16:50:09.000000000 +0000 +++ cinder-16.2.1/cinder/tests/unit/api/contrib/test_services.py 2020-12-08 15:44:58.000000000 +0000 @@ -824,32 +824,34 @@ self.controller._get_log, req, self.context, body=body) - @mock.patch('cinder.api.contrib.services.ServiceController._get_log') - def test_get_log_w_server_filter(self, get_log_mock): + def test_get_log_w_server_filter_same_host(self): server_filter = 'controller-0' - - body = {'host': CONF.host, 'server': server_filter} + CONF.set_override('host', server_filter) + body = {'binary': constants.API_BINARY, 'server': server_filter} req = FakeRequest(version=mv.LOG_LEVEL) - log_levels = self.controller._get_log(req, mock.sentinel.context, body) - - self.assertEqual(get_log_mock.return_value, log_levels) - get_log_mock.assert_called_once_with(req, mock.sentinel.context, body) - self.assertNotEqual(log_levels['binary'], constants.API_BINARY) - self.assertIsNot(log_levels, constants.API_BINARY) - - @mock.patch('cinder.api.contrib.services.ServiceController._get_log') - def test_get_log_w_server_equals_to_host(self, get_log_mock): - server_filter = 'server-0' + log_levels = self.controller._get_log( + req=req, context=mock.sentinel.context, body=body) + log_levels = log_levels['log_levels'] + + self.assertEqual(1, len(log_levels)) + self.assertEqual('controller-0', log_levels[0]['host']) + self.assertEqual('cinder-api', log_levels[0]['binary']) + # since there are a lot of log levels, we just check if the key-value + # exists for levels + self.assertIsNotNone(log_levels[0]['levels']) - body = {'host': CONF.host, 'server': server_filter} + def test_get_log_w_server_filter_different_host(self): + server_filter = 'controller-0' + CONF.set_override('host', 'controller-different-host') + body = {'binary': constants.API_BINARY, 'server': server_filter} req = FakeRequest(version=mv.LOG_LEVEL) - log_levels = self.controller._get_log(req, mock.sentinel.context, body) + log_levels = self.controller._get_log( + req=req, context=mock.sentinel.context, body=body) + log_levels = log_levels['log_levels'] - self.assertEqual(get_log_mock.return_value, log_levels) - self.assertNotEqual(log_levels['binary'], constants.API_BINARY) - self.assertIsNot(log_levels, constants.API_BINARY) + self.assertEqual(0, len(log_levels)) @ddt.data(None, '', '*') @mock.patch('cinder.objects.ServiceList.get_all') diff -Nru cinder-16.2.0/cinder/tests/unit/api/v3/test_volumes.py cinder-16.2.1/cinder/tests/unit/api/v3/test_volumes.py --- cinder-16.2.0/cinder/tests/unit/api/v3/test_volumes.py 2020-10-01 16:50:09.000000000 +0000 +++ cinder-16.2.1/cinder/tests/unit/api/v3/test_volumes.py 2020-12-08 15:44:58.000000000 +0000 @@ -291,6 +291,23 @@ else: self.assertNotIn('count', res_dict) + def test_list_volume_with_multiple_filters(self): + metadata = {'key_X': 'value_X'} + self._create_multiple_volumes_with_different_project() + test_utils.create_volume(self.ctxt, metadata=metadata) + + self.mock_object(ViewBuilder, '_get_volume_type', + v2_fakes.fake_volume_type_name_get) + # Request with 'all_tenants' and 'metadata' + req = fakes.HTTPRequest.blank( + "/v3/volumes/detail?all_tenants=1" + "&metadata=%7B%27key_X%27%3A+%27value_X%27%7D") + ctxt = context.RequestContext(fake.USER_ID, fake.PROJECT_ID, False) + req.environ['cinder.context'] = ctxt + res_dict = self.controller._get_volumes(req, is_detail=True) + self.assertEqual(1, len(res_dict['volumes'])) + self.assertEqual(metadata, res_dict['volumes'][0]['metadata']) + def test_volume_index_filter_by_group_id_in_unsupport_version(self): self._create_volume_with_group() req = fakes.HTTPRequest.blank(("/v3/volumes?group_id=%s") % diff -Nru cinder-16.2.0/cinder/tests/unit/volume/drivers/dell_emc/powermax/test_powermax_common.py cinder-16.2.1/cinder/tests/unit/volume/drivers/dell_emc/powermax/test_powermax_common.py --- cinder-16.2.0/cinder/tests/unit/volume/drivers/dell_emc/powermax/test_powermax_common.py 2020-10-01 16:50:09.000000000 +0000 +++ cinder-16.2.1/cinder/tests/unit/volume/drivers/dell_emc/powermax/test_powermax_common.py 2020-12-08 15:44:58.000000000 +0000 @@ -1624,6 +1624,34 @@ self.data.extra_specs, snap_name) self.assertEqual(ref_response, (clone_dict, rep_update, rep_info_dict)) + @mock.patch.object( + rest.PowerMaxRest, 'get_slo_list', return_value=['Diamond']) + @mock.patch.object( + common.PowerMaxCommon, '_create_volume', + return_value=(tpd.PowerMaxData.rep_info_dict, + tpd.PowerMaxData.replication_update, + tpd.PowerMaxData.rep_info_dict)) + @mock.patch.object(rest.PowerMaxRest, 'rdf_resume_with_retries') + @mock.patch.object(rest.PowerMaxRest, 'srdf_suspend_replication') + @mock.patch.object(rest.PowerMaxRest, 'wait_for_rdf_pair_sync') + def test_create_replica_rep_enabled( + self, mck_wait, mck_susp, mck_res, mck_create, mck_slo): + array = self.data.array + clone_volume = self.data.test_clone_volume + source_device_id = self.data.device_id + snap_name = self.data.snap_location['snap_name'] + extra_specs = deepcopy(self.data.rep_extra_specs_rep_config) + __, rep_extra_specs, __, __ = self.common.prepare_replication_details( + extra_specs) + rdfg = extra_specs['rdf_group_no'] + self.common._create_replica( + array, clone_volume, source_device_id, rep_extra_specs, snap_name) + mck_wait.assert_called_once_with( + array, rdfg, source_device_id, rep_extra_specs) + mck_susp.assert_called_once_with( + array, rep_extra_specs['sg_name'], rdfg, rep_extra_specs) + mck_res.assert_called_once_with(array, rep_extra_specs) + def test_create_replica_no_snap_name(self): array = self.data.array clone_volume = self.data.test_clone_volume @@ -3094,19 +3122,6 @@ port = self.common._get_unisphere_port() self.assertEqual(ref_port, port) - @mock.patch.object(common.PowerMaxCommon, - '_do_sync_check') - def test_sync_check_no_source_device_on_array(self, mock_check): - with mock.patch.object(self.rest, 'get_volume', - side_effect=exception.VolumeBackendAPIException( - "404 00123 does not exist")): - array = self.data.array - device_id = self.data.device_id - extra_specs = self.data.extra_specs - self.common._sync_check(array, device_id, extra_specs, - source_device_id='00123') - mock_check.assert_not_called() - def test_sync_check(self): array = self.data.array device_id = self.data.device_id @@ -3115,13 +3130,13 @@ with mock.patch.object(self.common, '_do_sync_check') as mck_sync: self.common._sync_check(array, device_id, extra_specs, False, self.data.device_id2) - mck_sync.assert_called_with(array, self.data.device_id2, + mck_sync.assert_called_with(array, self.data.device_id, extra_specs, False) mck_sync.reset_mock() with mock.patch.object(self.common, '_get_target_source_device', return_value=self.data.device_id3): self.common._sync_check(array, device_id, extra_specs, True) - mck_sync.assert_called_with(array, self.data.device_id3, + mck_sync.assert_called_with(array, self.data.device_id, extra_specs, True) mck_sync.reset_mock() self.common._sync_check(array, device_id, extra_specs) @@ -3144,30 +3159,64 @@ @mock.patch.object(provision.PowerMaxProvision, 'delete_temp_volume_snap') @mock.patch.object(provision.PowerMaxProvision, 'unlink_snapvx_tgt_volume') - def test_unlink_targets_and_delete_temp_snapvx(self, mck_break, mck_del): + def test_unlink_targets_and_delete_temp_snapvx_legacy( + self, mck_break, mck_del): array = self.data.array extra_specs = self.data.extra_specs - session = self.data.snap_tgt_session_cm_enabled - snap_name = session['snap_name'] + session = deepcopy(self.data.snap_tgt_session_cm_enabled) + legacy_snap_name = 'EMC_SMI' + session['snap_name'] = legacy_snap_name source = session['source_vol_id'] generation = session['generation'] target = session['target_vol_id'] + self.common._unlink_targets_and_delete_temp_snapvx( + session, array, extra_specs) + mck_break.assert_called_with(array, target, source, legacy_snap_name, + extra_specs, generation, True) + mck_del.assert_called_once_with( + array, legacy_snap_name, source, generation) + @mock.patch.object(provision.PowerMaxProvision, 'delete_temp_volume_snap') + @mock.patch.object(provision.PowerMaxProvision, 'unlink_snapvx_tgt_volume') + def test_unlink_targets_and_delete_temp_snapvx_is_temp( + self, mck_break, mck_del): + array = self.data.array + extra_specs = self.data.extra_specs + session = deepcopy(self.data.snap_tgt_session_cm_enabled) + snap_name = session['snap_name'] + source = session['source_vol_id'] + generation = session['generation'] + target = session['target_vol_id'] self.common._unlink_targets_and_delete_temp_snapvx( session, array, extra_specs) mck_break.assert_called_with(array, target, source, snap_name, extra_specs, generation, True) mck_del.assert_called_once_with(array, snap_name, source, generation) - mck_break.reset_mock() - mck_del.reset_mock() + def test_unlink_targets_and_delete_temp_snapvx_no_snap_name_found(self): + array = self.data.array + extra_specs = self.data.extra_specs + session = dict() + self.assertRaises(exception.VolumeBackendAPIException, + self.common._unlink_targets_and_delete_temp_snapvx, + session, array, extra_specs) - session['copy_mode'] = False - session['expired'] = True + @mock.patch.object(provision.PowerMaxProvision, 'delete_temp_volume_snap') + @mock.patch.object(provision.PowerMaxProvision, 'unlink_snapvx_tgt_volume') + def test_unlink_targets_and_delete_temp_snapvx_not_legacy_not_temp( + self, mck_break, mck_del): + array = self.data.array + extra_specs = self.data.extra_specs + session = deepcopy(self.data.snap_tgt_session_cm_enabled) + session['snap_name'] = 'not_leg_or_tmp' + snap_name = session['snap_name'] + source = session['source_vol_id'] + generation = session['generation'] + target = session['target_vol_id'] self.common._unlink_targets_and_delete_temp_snapvx( session, array, extra_specs) mck_break.assert_called_with(array, target, source, snap_name, - extra_specs, generation, False) + extra_specs, generation, True) mck_del.assert_not_called() @mock.patch.object(rest.PowerMaxRest, 'find_snap_vx_sessions', diff -Nru cinder-16.2.0/cinder/tests/unit/volume/drivers/ibm/test_ds8k_proxy.py cinder-16.2.1/cinder/tests/unit/volume/drivers/ibm/test_ds8k_proxy.py --- cinder-16.2.0/cinder/tests/unit/volume/drivers/ibm/test_ds8k_proxy.py 2020-10-01 16:50:09.000000000 +0000 +++ cinder-16.2.1/cinder/tests/unit/volume/drivers/ibm/test_ds8k_proxy.py 2020-12-08 15:44:58.000000000 +0000 @@ -535,7 +535,7 @@ "name": "", "state": "online", "release": "7.5.1", - "bundle": "87.51.9.0", + "bundle": "87.51.63.0", "MTM": "2421-961", "sn": "1300741", "wwnn": TEST_SOURCE_WWNN, @@ -563,7 +563,7 @@ "name": "", "state": "online", "release": "7.5.1", - "bundle": "87.51.9.0", + "bundle": "87.51.63.0", "MTM": "2421-962", "sn": "1300742", "wwnn": TEST_TARGET_WWNN, @@ -989,7 +989,7 @@ self._get_value('san_login'), self._get_value('san_password'), None, True) - self.backend['rest_version'] = self._get_version()['bundle_version'] + self.backend['rest_version'] = self._get_version()['bundle'] class FakeDS8KECKDHelper(FakeDS8KCommonHelper, helper.DS8KECKDHelper): @@ -1167,7 +1167,7 @@ def test_verify_rest_version_for_5_7_fb(self, mock_get_version): """test the min version of REST for fb volume in 7.x.""" mock_get_version.return_value = { - "bundle_version": "5.7.50.0" + "bundle": "87.50.38.0" } self.assertRaises(exception.VolumeDriverException, FakeDS8KCommonHelper, self.configuration, None) @@ -1176,7 +1176,7 @@ def test_verify_rest_version_for_5_8_fb(self, mock_get_version): """test the min version of REST for fb volume in 8.1.""" mock_get_version.return_value = { - "bundle_version": "5.8.10.0" + "bundle": "88.10.112.0" } FakeDS8KCommonHelper(self.configuration, None) @@ -1189,7 +1189,7 @@ self.configuration.ds8k_ssid_prefix = 'FF' self.configuration.san_clustername = TEST_ECKD_POOL_ID mock_get_version.return_value = { - "bundle_version": "5.7.50.0" + "bundle": "87.50.22.0" } self.assertRaises(exception.VolumeDriverException, FakeDS8KECKDHelper, self.configuration, None) @@ -1203,7 +1203,7 @@ self.configuration.ds8k_ssid_prefix = 'FF' self.configuration.san_clustername = TEST_ECKD_POOL_ID mock_get_version.return_value = { - "bundle_version": "5.8.10.0" + "bundle": "88.10.112.0" } self.assertRaises(exception.VolumeDriverException, FakeDS8KECKDHelper, self.configuration, None) @@ -1217,7 +1217,7 @@ self.configuration.ds8k_ssid_prefix = 'FF' self.configuration.san_clustername = TEST_ECKD_POOL_ID mock_get_version.return_value = { - "bundle_version": "5.8.20.0" + "bundle": "88.20.40.0" } self.assertRaises(exception.VolumeDriverException, FakeDS8KECKDHelper, self.configuration, None) @@ -3214,8 +3214,8 @@ self.driver.create_group, self.ctxt, group) - @ddt.data({'bundle_version': "5.7.51.1067"}, - {'bundle_version': "5.8.20.1058"}) + @ddt.data({'bundle': "87.51.60.0"}, + {'bundle': "88.20.47.0"}) @mock.patch.object(helper.DS8KCommonHelper, '_get_version') def test_create_replication_consisgroup_should_verify_rest_version( self, rest_version, mock_get_version): diff -Nru cinder-16.2.0/cinder/tests/unit/volume/drivers/nec/test_volume.py cinder-16.2.1/cinder/tests/unit/volume/drivers/nec/test_volume.py --- cinder-16.2.0/cinder/tests/unit/volume/drivers/nec/test_volume.py 2020-10-01 16:50:09.000000000 +0000 +++ cinder-16.2.1/cinder/tests/unit/volume/drivers/nec/test_volume.py 2020-12-08 15:44:58.000000000 +0000 @@ -1351,8 +1351,12 @@ attachment = volume_attachment.VolumeAttachmentList( objects=[attach_object]) snap.volume_attachment = attachment - ret = self.fc_terminate_connection_snapshot(snap, connector) + mocker = self.mock_object(self, '_is_multi_attachment', + mock.Mock(wraps=self._is_multi_attachment)) + ret = self.fc_terminate_connection_snapshot(snap, connector, + is_snapshot=True) self.assertEqual('fibre_channel', ret['driver_volume_type']) + mocker.assert_not_called() def test_remove_export_snapshot(self): snap = DummySnapshot('46045673-41e7-44a7-9333-02f07feab04b') diff -Nru cinder-16.2.0/cinder/tests/unit/volume/drivers/test_rbd.py cinder-16.2.1/cinder/tests/unit/volume/drivers/test_rbd.py --- cinder-16.2.0/cinder/tests/unit/volume/drivers/test_rbd.py 2020-10-01 16:50:09.000000000 +0000 +++ cinder-16.2.1/cinder/tests/unit/volume/drivers/test_rbd.py 2020-12-08 15:44:58.000000000 +0000 @@ -1171,6 +1171,9 @@ def test_create_cloned_volume_w_flatten(self, mock_enable_repl): self.cfg.rbd_max_clone_depth = 1 + client = self.mock_client.return_value + client.__enter__.return_value = client + with mock.patch.object(self.driver, '_get_clone_info') as \ mock_get_clone_info: mock_get_clone_info.return_value = ( @@ -1200,9 +1203,13 @@ .assert_called_once_with('.'.join( (self.volume_b.name, 'clone_snap')))) - # We expect the driver to close both volumes, so 2 is expected + self.mock_proxy.assert_called_once_with( + self.driver, self.volume_b.name, + client=client, ioctx=client.ioctx) + + # Source volume is closed by direct call of close() self.assertEqual( - 2, self.mock_rbd.Image.return_value.close.call_count) + 1, self.mock_rbd.Image.return_value.close.call_count) self.assertTrue(mock_get_clone_depth.called) mock_enable_repl.assert_not_called() diff -Nru cinder-16.2.0/cinder/tests/unit/volume/test_volume.py cinder-16.2.1/cinder/tests/unit/volume/test_volume.py --- cinder-16.2.0/cinder/tests/unit/volume/test_volume.py 2020-10-01 16:50:09.000000000 +0000 +++ cinder-16.2.1/cinder/tests/unit/volume/test_volume.py 2020-12-08 15:44:58.000000000 +0000 @@ -21,6 +21,7 @@ from unittest import mock import uuid +import castellan from castellan.common import exception as castellan_exception from castellan import key_manager import ddt @@ -89,6 +90,16 @@ return snap +class KeyObject(object): + def get_encoded(arg): + return "asdf".encode('utf-8') + + +class KeyObject2(object): + def get_encoded(arg): + return "qwert".encode('utf-8') + + @ddt.ddt class VolumeTestCase(base.BaseVolumeTestCase): @@ -1763,6 +1774,40 @@ mock_at.assert_called() mock_det.assert_called() + @mock.patch('cinder.db.sqlalchemy.api.volume_encryption_metadata_get') + def test_setup_encryption_keys(self, mock_enc_metadata_get): + key_mgr = fake_keymgr.fake_api() + self.mock_object(castellan.key_manager, 'API', return_value=key_mgr) + key_id = key_mgr.store(self.context, KeyObject()) + key2_id = key_mgr.store(self.context, KeyObject2()) + + params = {'status': 'creating', + 'size': 1, + 'host': CONF.host, + 'encryption_key_id': key_id} + vol = tests_utils.create_volume(self.context, **params) + + self.volume.create_volume(self.context, vol) + db.volume_update(self.context, + vol['id'], + {'encryption_key_id': key_id}) + + mock_enc_metadata_get.return_value = {'cipher': 'aes-xts-plain64', + 'key_size': 256, + 'provider': 'luks'} + ctxt = context.get_admin_context() + + enc_info = {'encryption_key_id': key_id} + with mock.patch('cinder.volume.volume_utils.create_encryption_key', + return_value=key2_id): + r = cinder.volume.flows.manager.create_volume.\ + CreateVolumeFromSpecTask._setup_encryption_keys(ctxt, + vol, + enc_info) + (source_pass, new_pass, new_key_id) = r + self.assertNotEqual(source_pass, new_pass) + self.assertEqual(new_key_id, key2_id) + @mock.patch.object(key_manager, 'API', fake_keymgr.fake_api) def test_create_volume_from_snapshot_with_encryption(self): """Test volume can be created from a snapshot of an encrypted volume""" diff -Nru cinder-16.2.0/cinder/volume/api.py cinder-16.2.1/cinder/volume/api.py --- cinder-16.2.0/cinder/volume/api.py 2020-10-01 16:50:09.000000000 +0000 +++ cinder-16.2.1/cinder/volume/api.py 2020-12-08 15:44:58.000000000 +0000 @@ -2034,8 +2034,8 @@ # To translate any true/false equivalent to True/False # which is only acceptable format in database queries. - - for key, val in filters.items(): + temp_dict = filters.copy() + for key, val in temp_dict.items(): try: if key in booleans: filters[key] = self._check_boolean_filter_value( @@ -2048,6 +2048,11 @@ # the filter becomes different from the user input. continue else: + # this is required as ast.literal_eval(/) + # raises exception. Eg: ast.literal_eval(5) generates + # ValueError: malformed node or string: 5 + if not isinstance(val, str): + val = str(val) filters[key] = ast.literal_eval(val) except (ValueError, SyntaxError): LOG.debug('Could not evaluate value %s, assuming string', val) diff -Nru cinder-16.2.0/cinder/volume/drivers/dell_emc/powermax/common.py cinder-16.2.1/cinder/volume/drivers/dell_emc/powermax/common.py --- cinder-16.2.0/cinder/volume/drivers/dell_emc/powermax/common.py 2020-10-01 16:50:09.000000000 +0000 +++ cinder-16.2.1/cinder/volume/drivers/dell_emc/powermax/common.py 2020-12-08 15:44:58.000000000 +0000 @@ -2721,6 +2721,9 @@ rep_extra_specs['sg_name'] = ( self.utils.get_rdf_management_group_name( rep_extra_specs[utils.REP_CONFIG])) + self.rest.wait_for_rdf_pair_sync( + array, rep_extra_specs['rdf_group_no'], target_device_id, + rep_extra_specs) self.rest.srdf_suspend_replication( array, rep_extra_specs['sg_name'], rep_extra_specs['rdf_group_no'], rep_extra_specs) @@ -2790,16 +2793,10 @@ if source_device_id: @coordination.synchronized("emc-source-{src_device_id}") def do_unlink_and_delete_snap(src_device_id): - # Check if source device exists on the array - try: - self.rest.get_volume(array, src_device_id) - except exception.VolumeBackendAPIException: - LOG.debug("Device %(device_id)s not found on array, no " - "sync check required.", - {'device_id': src_device_id}) - return + LOG.debug("Locking on source device %(device_id)s.", + {'device_id': src_device_id}) self._do_sync_check( - array, src_device_id, extra_specs, tgt_only) + array, device_id, extra_specs, tgt_only) do_unlink_and_delete_snap(source_device_id) else: @@ -2840,10 +2837,16 @@ :param array: the array serial number :param extra_specs: extra specifications """ - snap_name = session['snap_name'] - source = session['source_vol_id'] + snap_name = session.get('snap_name') + if not snap_name: + msg = _("Snap_name not present in volume's snapvx session. " + "Unable to perform unlink and cleanup.") + LOG.error(msg) + raise exception.VolumeBackendAPIException(msg) + source = session.get('source_vol_id') generation = session['generation'] - expired = session['expired'] + is_legacy = 'EMC_SMI' in snap_name + is_temp = utils.CLONE_SNAPSHOT_NAME in snap_name target, cm_enabled = None, False if session.get('target_vol_id'): @@ -2862,10 +2865,13 @@ # Candidates for deletion: # 1. If legacy snapshot with 'EMC_SMI' in snapshot name - # 2. If snapVX snapshot with copy mode enabled - # 3. If snapVX snapshot with copy mode disabled and not expired - if ('EMC_SMI' in snap_name or cm_enabled or ( - not cm_enabled and not expired)): + # 2. If snapVX snapshot is temporary + # If a target is present in the snap session it will be unlinked by + # the provision.unlink_snapvx_tgt_volume call above. This accounts + # for both CM enabled and disabled, as such by this point there will + # either be no target or it would have been unlinked, therefore + # delete if it is legacy or temp. + if is_legacy or is_temp: LOG.debug( "Deleting temporary snapshot. Source: %(vol)s, snap name: " "%(name)s, generation: %(gen)s.", { diff -Nru cinder-16.2.0/cinder/volume/drivers/dell_emc/powermax/fc.py cinder-16.2.1/cinder/volume/drivers/dell_emc/powermax/fc.py --- cinder-16.2.0/cinder/volume/drivers/dell_emc/powermax/fc.py 2020-10-01 16:50:09.000000000 +0000 +++ cinder-16.2.1/cinder/volume/drivers/dell_emc/powermax/fc.py 2020-12-08 15:44:58.000000000 +0000 @@ -131,9 +131,11 @@ 4.2.7 - Fix to enable legacy volumes to live migrate (#1867163) 4.2.8 - Force flag to add to rep enable storage groups (#1892057) 4.2.9 - Failover group volume update (#1888831) + 4.2.10 - Replica RDFG suspend fix (#1892718) + 4.2.11 - Fix non-temporary snapshot delete (#1887962) """ - VERSION = "4.2.9" + VERSION = "4.2.11" # ThirdPartySystems wiki CI_WIKI_NAME = "EMC_VMAX_CI" diff -Nru cinder-16.2.0/cinder/volume/drivers/dell_emc/powermax/iscsi.py cinder-16.2.1/cinder/volume/drivers/dell_emc/powermax/iscsi.py --- cinder-16.2.0/cinder/volume/drivers/dell_emc/powermax/iscsi.py 2020-10-01 16:50:09.000000000 +0000 +++ cinder-16.2.1/cinder/volume/drivers/dell_emc/powermax/iscsi.py 2020-12-08 15:44:58.000000000 +0000 @@ -136,9 +136,11 @@ 4.2.7 - Fix to enable legacy volumes to live migrate (#1867163) 4.2.8 - Force flag to add to rep enable storage groups (#1892057) 4.2.9 - Failover group volume update (#1888831) + 4.2.10 - Replica RDFG suspend fix (#1892718) + 4.2.11 - Fix non-temporary snapshot delete (#1887962) """ - VERSION = "4.2.9" + VERSION = "4.2.11" # ThirdPartySystems wiki CI_WIKI_NAME = "EMC_VMAX_CI" diff -Nru cinder-16.2.0/cinder/volume/drivers/ibm/ibm_storage/ds8k_helper.py cinder-16.2.1/cinder/volume/drivers/ibm/ibm_storage/ds8k_helper.py --- cinder-16.2.0/cinder/volume/drivers/ibm/ibm_storage/ds8k_helper.py 2020-10-01 16:50:09.000000000 +0000 +++ cinder-16.2.1/cinder/volume/drivers/ibm/ibm_storage/ds8k_helper.py 2020-12-08 15:44:57.000000000 +0000 @@ -61,10 +61,10 @@ OPTIONAL_PARAMS = ['ds8k_host_type', 'lss_range_for_cg'] # if use new REST API, please update the version below - VALID_REST_VERSION_5_7_MIN = '5.7.51.1047' + VALID_REST_VERSION_87_51_MIN = '87.51.52.0' INVALID_STORAGE_VERSION = '8.0.1' - REST_VERSION_5_7_MIN_PPRC_CG = '5.7.51.1068' - REST_VERSION_5_8_MIN_PPRC_CG = '5.8.20.1059' + REST_VERSION_87_51_MIN_PPRC_CG = '87.51.63.0' + REST_VERSION_88_20_MIN_PPRC_CG = '88.20.112.0' def __init__(self, conf, HTTPConnectorObject=None): self.conf = conf @@ -148,7 +148,7 @@ except restclient.TimeoutException: raise restclient.APIException( data=(_("Can't connect to %(host)s") % {'host': san_ip})) - self.backend['rest_version'] = self._get_version()['bundle_version'] + self.backend['rest_version'] = self._get_version()['bundle'] LOG.info("Connection to DS8K storage system %(host)s has been " "established successfully, the version of REST is %(rest)s.", {'host': self._get_value('san_ip'), @@ -224,14 +224,15 @@ "if you want to use this version of driver, " "please upgrade the CCL.") % self.INVALID_STORAGE_VERSION)) - if ('5.7' in self.backend['rest_version'] and + rest_ver = self.backend['rest_version'][0:2] + if ('87' == rest_ver and dist_version.LooseVersion(self.backend['rest_version']) < - dist_version.LooseVersion(self.VALID_REST_VERSION_5_7_MIN)): + dist_version.LooseVersion(self.VALID_REST_VERSION_87_51_MIN)): raise exception.VolumeDriverException( message=(_("REST version %(invalid)s is lower than " "%(valid)s, please upgrade it in DS8K.") % {'invalid': self.backend['rest_version'], - 'valid': self.VALID_REST_VERSION_5_7_MIN})) + 'valid': self.VALID_REST_VERSION_87_51_MIN})) def verify_rest_version_for_pprc_cg(self): if '8.1' in self.backend['rest_version']: @@ -239,14 +240,15 @@ message=_("REST for DS8K 8.1 does not support PPRC " "consistency group, please upgrade the CCL.")) valid_rest_version = None - if ('5.7' in self.backend['rest_version'] and + rest_ver = self.backend['rest_version'][0:2] + if ('87' == rest_ver and dist_version.LooseVersion(self.backend['rest_version']) < - dist_version.LooseVersion(self.REST_VERSION_5_7_MIN_PPRC_CG)): - valid_rest_version = self.REST_VERSION_5_7_MIN_PPRC_CG - elif ('5.8' in self.backend['rest_version'] and + dist_version.LooseVersion(self.REST_VERSION_87_51_MIN_PPRC_CG)): + valid_rest_version = self.REST_VERSION_87_51_MIN_PPRC_CG + elif ('88' == rest_ver and dist_version.LooseVersion(self.backend['rest_version']) < - dist_version.LooseVersion(self.REST_VERSION_5_8_MIN_PPRC_CG)): - valid_rest_version = self.REST_VERSION_5_8_MIN_PPRC_CG + dist_version.LooseVersion(self.REST_VERSION_88_20_MIN_PPRC_CG)): + valid_rest_version = self.REST_VERSION_88_20_MIN_PPRC_CG if valid_rest_version: raise exception.VolumeDriverException( @@ -760,7 +762,7 @@ self._client.send('DELETE', '/volumes/%s' % lun_id) def _get_version(self): - return self._client.fetchone('GET', '') + return self._client.fetchone('GET', '/systems') @proxy.logger def _create_lun(self, volData): @@ -1042,8 +1044,8 @@ OPTIONAL_PARAMS = ['ds8k_host_type', 'port_pairs', 'ds8k_ssid_prefix', 'lss_range_for_cg'] # if use new REST API, please update the version below - VALID_REST_VERSION_5_7_MIN = '5.7.51.1068' - VALID_REST_VERSION_5_8_MIN = '5.8.20.1059' + VALID_REST_VERSION_87_51_MIN = '87.51.63.0' + VALID_REST_VERSION_88_20_MIN = '88.20.112.0' MIN_VALID_STORAGE_VERSION = '8.1' INVALID_STORAGE_VERSION = '8.0.1' @@ -1094,19 +1096,20 @@ dist_version.LooseVersion(self.MIN_VALID_STORAGE_VERSION)): self._disable_thin_provision = True - if (('5.7' in self.backend['rest_version'] and + rest_ver = self.backend['rest_version'][0:2] + if (('87' == rest_ver and dist_version.LooseVersion(self.backend['rest_version']) < - dist_version.LooseVersion(self.VALID_REST_VERSION_5_7_MIN)) or - ('5.8' in self.backend['rest_version'] and + dist_version.LooseVersion(self.VALID_REST_VERSION_87_51_MIN)) or + ('88' == rest_ver and dist_version.LooseVersion(self.backend['rest_version']) < - dist_version.LooseVersion(self.VALID_REST_VERSION_5_8_MIN))): + dist_version.LooseVersion(self.VALID_REST_VERSION_88_20_MIN))): raise exception.VolumeDriverException( message=(_("REST version %(invalid)s is lower than " "%(valid)s, please upgrade it in DS8K.") % {'invalid': self.backend['rest_version'], - 'valid': (self.VALID_REST_VERSION_5_7_MIN if '5.7' - in self.backend['rest_version'] else - self.VALID_REST_VERSION_5_8_MIN)})) + 'valid': (self.VALID_REST_VERSION_87_51_MIN + if '87' == rest_ver else + self.VALID_REST_VERSION_88_20_MIN)})) @proxy.logger def _get_device_mapping(self): diff -Nru cinder-16.2.0/cinder/volume/drivers/nec/volume_helper.py cinder-16.2.1/cinder/volume/drivers/nec/volume_helper.py --- cinder-16.2.0/cinder/volume/drivers/nec/volume_helper.py 2020-10-01 16:50:09.000000000 +0000 +++ cinder-16.2.1/cinder/volume/drivers/nec/volume_helper.py 2020-12-08 15:44:57.000000000 +0000 @@ -24,6 +24,7 @@ from cinder import coordination from cinder import exception from cinder.i18n import _ +from cinder import utils from cinder.volume.drivers.nec import cli from cinder.volume.drivers.nec import volume_common from cinder.volume import volume_utils @@ -1321,14 +1322,12 @@ '(%(msgparm)s) (%(exception)s)', {'msgparm': msgparm, 'exception': e}) - def _fc_terminate_connection(self, volume, connector): + @utils.trace + def _fc_terminate_connection(self, vol_or_snap, connector, + is_snapshot=False): """Disallow connection from connector.""" - LOG.debug('_fc_terminate_connection' - '(Volume ID = %(id)s, connector = %(connector)s) Start.', - {'id': volume.id, 'connector': connector}) - - if connector is not None and ( - self._is_multi_attachment(volume, connector)): + if not is_snapshot and connector is not None and ( + self._is_multi_attachment(vol_or_snap, connector)): return xml = self._cli.view_all(self._properties['ismview_path']) @@ -1350,10 +1349,15 @@ info['data'] = {'target_wwn': target_wwns, 'initiator_target_map': init_targ_map} + if is_snapshot: + # Detaching the snapshot is performed in the + # remove_export_snapshot. + return info + if connector is not None and self._properties['ldset_name'] == '': # delete LD from LD set. ldname = self.get_ldname( - volume.id, self._properties['ld_name_format']) + vol_or_snap.id, self._properties['ld_name_format']) if ldname not in lds: LOG.debug('Logical Disk `%s` has unbound already.', ldname) return info @@ -1370,19 +1374,14 @@ 'Logical Disk Set (%s)') % errnum) raise exception.VolumeBackendAPIException(data=msg) - LOG.debug('_fc_terminate_connection' - '(Volume ID = %(id)s, connector = %(connector)s, ' - 'info = %(info)s) End.', - {'id': volume.id, - 'connector': connector, - 'info': info}) return info def fc_terminate_connection_snapshot(self, snapshot, connector, **kwargs): msgparm = ('Volume ID = %(id)s, Connector = %(connector)s' % {'id': snapshot.id, 'connector': connector}) try: - ret = self._fc_terminate_connection(snapshot, connector) + ret = self._fc_terminate_connection(snapshot, connector, + is_snapshot=True) LOG.info('Terminated FC Connection snapshot(%s)', msgparm) self.remove_export_snapshot(None, snapshot) return ret diff -Nru cinder-16.2.0/cinder/volume/drivers/rbd.py cinder-16.2.1/cinder/volume/drivers/rbd.py --- cinder-16.2.0/cinder/volume/drivers/rbd.py 2020-10-01 16:50:09.000000000 +0000 +++ cinder-16.2.1/cinder/volume/drivers/rbd.py 2020-12-08 15:44:58.000000000 +0000 @@ -83,7 +83,9 @@ default=5, help='Maximum number of nested volume clones that are ' 'taken before a flatten occurs. Set to 0 to disable ' - 'cloning.'), + 'cloning. Note: lowering this value will not affect ' + 'existing volumes whose clone depth exceeds the new ' + 'value.'), cfg.IntOpt('rbd_store_chunk_size', default=4, help='Volumes will be chunked into objects of this size ' '(in megabytes).'), @@ -640,12 +642,6 @@ if not parent: return depth - # If clone depth was reached, flatten should have occurred so if it has - # been exceeded then something has gone wrong. - if depth > self.configuration.rbd_max_clone_depth: - raise Exception(_("clone depth exceeds limit of %s") % - (self.configuration.rbd_max_clone_depth)) - return self._get_clone_depth(client, parent, depth + 1) def _extend_if_required(self, volume, src_vref): @@ -715,16 +711,18 @@ depth = self._get_clone_depth(client, src_name) # If dest volume is a clone and rbd_max_clone_depth reached, # flatten the dest after cloning. Zero rbd_max_clone_depth means - # infinite is allowed. + # volumes are always flattened. if depth >= self.configuration.rbd_max_clone_depth: LOG.info("maximum clone depth (%d) has been reached - " "flattening dest volume", self.configuration.rbd_max_clone_depth) - dest_volume = self.rbd.Image(client.ioctx, dest_name) + + # Flatten destination volume try: - # Flatten destination volume - LOG.debug("flattening dest volume %s", dest_name) - dest_volume.flatten() + with RBDVolumeProxy(self, dest_name, client=client, + ioctx=client.ioctx) as dest_volume: + LOG.debug("flattening dest volume %s", dest_name) + dest_volume.flatten() except Exception as e: msg = (_("Failed to flatten volume %(volume)s with " "error: %(error)s.") % @@ -733,8 +731,6 @@ LOG.exception(msg) src_volume.close() raise exception.VolumeBackendAPIException(data=msg) - finally: - dest_volume.close() try: # remove temporary snap diff -Nru cinder-16.2.0/cinder/volume/flows/manager/create_volume.py cinder-16.2.1/cinder/volume/flows/manager/create_volume.py --- cinder-16.2.0/cinder/volume/flows/manager/create_volume.py 2020-10-01 16:50:09.000000000 +0000 +++ cinder-16.2.1/cinder/volume/flows/manager/create_volume.py 2020-12-08 15:44:58.000000000 +0000 @@ -498,7 +498,7 @@ new_key_id = volume_utils.create_encryption_key(context, keymgr, volume.volume_type_id) - new_key = keymgr.get(context, encryption['encryption_key_id']) + new_key = keymgr.get(context, new_key_id) new_pass = binascii.hexlify(new_key.get_encoded()).decode('utf-8') return (source_pass, new_pass, new_key_id) diff -Nru cinder-16.2.0/cinder.egg-info/pbr.json cinder-16.2.1/cinder.egg-info/pbr.json --- cinder-16.2.0/cinder.egg-info/pbr.json 2020-10-01 16:54:10.000000000 +0000 +++ cinder-16.2.1/cinder.egg-info/pbr.json 2020-12-08 15:45:32.000000000 +0000 @@ -1 +1 @@ -{"git_version": "53d482275", "is_release": true} \ No newline at end of file +{"git_version": "2f0d23644", "is_release": true} \ No newline at end of file diff -Nru cinder-16.2.0/cinder.egg-info/PKG-INFO cinder-16.2.1/cinder.egg-info/PKG-INFO --- cinder-16.2.0/cinder.egg-info/PKG-INFO 2020-10-01 16:54:10.000000000 +0000 +++ cinder-16.2.1/cinder.egg-info/PKG-INFO 2020-12-08 15:45:32.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: cinder -Version: 16.2.0 +Version: 16.2.1 Summary: OpenStack Block Storage Home-page: https://docs.openstack.org/cinder/latest/ Author: OpenStack diff -Nru cinder-16.2.0/cinder.egg-info/SOURCES.txt cinder-16.2.1/cinder.egg-info/SOURCES.txt --- cinder-16.2.0/cinder.egg-info/SOURCES.txt 2020-10-01 16:54:10.000000000 +0000 +++ cinder-16.2.1/cinder.egg-info/SOURCES.txt 2020-12-08 15:45:32.000000000 +0000 @@ -2061,8 +2061,14 @@ releasenotes/notes/bug-1874134-netapp-ONTAP-fix-max-resize-size-ad2d88da8721560e.yaml releasenotes/notes/bug-1875570-nfs-image-volume-cache-c45e840a6ec2a702.yaml releasenotes/notes/bug-1879578-volume_type-regression-de82f4152c7b2f77.yaml +releasenotes/notes/bug-1887885-nec-fix-snapshot-detach-error-fff3012e0e9a2d2b.yaml releasenotes/notes/bug-1887908-nec-live-migration-failure-withfc-3128fff7c48e739f.yaml +releasenotes/notes/bug-1887962-643379faf20f01cf.yaml releasenotes/notes/bug-1893107-ussuri-03765453337a7909.yaml +releasenotes/notes/bug-1895510-REST-API-issue-to-get-bundle-198a3b89255759bb.yaml +releasenotes/notes/bug-1898918-b24a93d7d5aff238.yaml +releasenotes/notes/bug-1901241-361b1b361bfa5152.yaml +releasenotes/notes/bug-1904440-clone-rekey-fd57a2b5f6224e0f.yaml releasenotes/notes/bug-fix-1866871-f9d61defc00f4007.yaml releasenotes/notes/bug-fix-1867163-27afa39ac77b9e15.yaml releasenotes/notes/bug-invalid-content-type-1715094-8yu8i9w425ua08f3.yaml @@ -2178,6 +2184,7 @@ releasenotes/notes/fix-hnas-stats-reporting-1335e582e46ff440.yaml releasenotes/notes/fix-import-backup-quota-issue-8yh69hd19u7tuu23.yaml releasenotes/notes/fix-kaminario-unique_fqdn_network-ecde36f614c30733.yaml +releasenotes/notes/fix-list-volume-filtering-3f2bf93ab9b98974.yaml releasenotes/notes/fix-multiattach-deletion-b3990acf1f5fd378.yaml releasenotes/notes/fix-netapp-cg-da4fd6c396e5bedb.yaml releasenotes/notes/fix-netapp-force_detach-36bdf75dd2c9a030.yaml @@ -2258,6 +2265,7 @@ releasenotes/notes/improve-volume-transfer-records-5599e82ade4d302c.yaml releasenotes/notes/improvement-to-get-group-detail-0e8b68114e79a8a2.yaml releasenotes/notes/improvement-to-query-consistency-group-detail-84a906d45383e067.yaml +releasenotes/notes/increase_glance_num_retries-66b455a0729c4535.yaml releasenotes/notes/infinidat-add-infinibox-driver-67cc33fc3fbff1bb.yaml releasenotes/notes/infinidat-compression-a828904aaba90da2.yaml releasenotes/notes/infinidat-group-support-44cd0715de1ea502.yaml diff -Nru cinder-16.2.0/debian/changelog cinder-16.2.1/debian/changelog --- cinder-16.2.0/debian/changelog 2020-10-19 18:37:28.000000000 +0000 +++ cinder-16.2.1/debian/changelog 2021-01-19 10:33:38.000000000 +0000 @@ -1,3 +1,9 @@ +cinder (2:16.2.1-0ubuntu1) focal; urgency=medium + + * New stable point release for OpenStack Ussuri (LP: #1912322). + + -- Chris MacNaughton Tue, 19 Jan 2021 10:33:38 +0000 + cinder (2:16.2.0-0ubuntu1) focal; urgency=medium [ Chris MacNaughton ] diff -Nru cinder-16.2.0/doc/source/reference/support-matrix.ini cinder-16.2.1/doc/source/reference/support-matrix.ini --- cinder-16.2.0/doc/source/reference/support-matrix.ini 2020-10-01 16:50:09.000000000 +0000 +++ cinder-16.2.1/doc/source/reference/support-matrix.ini 2020-12-08 15:44:58.000000000 +0000 @@ -357,7 +357,7 @@ driver.linbit_linstor=missing driver.lvm=missing driver.macrosan=missing -driver.nec=missing +driver.nec=complete driver.netapp_ontap=missing driver.netapp_solidfire=missing driver.nexenta=missing diff -Nru cinder-16.2.0/PKG-INFO cinder-16.2.1/PKG-INFO --- cinder-16.2.0/PKG-INFO 2020-10-01 16:54:10.000000000 +0000 +++ cinder-16.2.1/PKG-INFO 2020-12-08 15:45:33.323938800 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: cinder -Version: 16.2.0 +Version: 16.2.1 Summary: OpenStack Block Storage Home-page: https://docs.openstack.org/cinder/latest/ Author: OpenStack diff -Nru cinder-16.2.0/releasenotes/notes/bug-1887885-nec-fix-snapshot-detach-error-fff3012e0e9a2d2b.yaml cinder-16.2.1/releasenotes/notes/bug-1887885-nec-fix-snapshot-detach-error-fff3012e0e9a2d2b.yaml --- cinder-16.2.0/releasenotes/notes/bug-1887885-nec-fix-snapshot-detach-error-fff3012e0e9a2d2b.yaml 1970-01-01 00:00:00.000000000 +0000 +++ cinder-16.2.1/releasenotes/notes/bug-1887885-nec-fix-snapshot-detach-error-fff3012e0e9a2d2b.yaml 2020-12-08 15:44:57.000000000 +0000 @@ -0,0 +1,6 @@ +--- +fixes: + - | + `Bug #1887885 `_: + In NEC driver, fix a snapshot detach error. + diff -Nru cinder-16.2.0/releasenotes/notes/bug-1887962-643379faf20f01cf.yaml cinder-16.2.1/releasenotes/notes/bug-1887962-643379faf20f01cf.yaml --- cinder-16.2.0/releasenotes/notes/bug-1887962-643379faf20f01cf.yaml 1970-01-01 00:00:00.000000000 +0000 +++ cinder-16.2.1/releasenotes/notes/bug-1887962-643379faf20f01cf.yaml 2020-12-08 15:44:57.000000000 +0000 @@ -0,0 +1,7 @@ +--- +fixes: + - | + `Bug #1887962 `_: + PowerMax driver fix to rectify incorrectly deleted non-temporary + snapshots when calling do_sync_check used in multiple operations due + to missing check for temporary snapshot name. diff -Nru cinder-16.2.0/releasenotes/notes/bug-1895510-REST-API-issue-to-get-bundle-198a3b89255759bb.yaml cinder-16.2.1/releasenotes/notes/bug-1895510-REST-API-issue-to-get-bundle-198a3b89255759bb.yaml --- cinder-16.2.0/releasenotes/notes/bug-1895510-REST-API-issue-to-get-bundle-198a3b89255759bb.yaml 1970-01-01 00:00:00.000000000 +0000 +++ cinder-16.2.1/releasenotes/notes/bug-1895510-REST-API-issue-to-get-bundle-198a3b89255759bb.yaml 2020-12-08 15:44:57.000000000 +0000 @@ -0,0 +1,6 @@ +--- +fixes: + - | + `Bug #1895510 `_: + IBM DS8K: Fixed compatability issue when using the IBM DS8K driver + with storage version R9 and later. diff -Nru cinder-16.2.0/releasenotes/notes/bug-1898918-b24a93d7d5aff238.yaml cinder-16.2.1/releasenotes/notes/bug-1898918-b24a93d7d5aff238.yaml --- cinder-16.2.0/releasenotes/notes/bug-1898918-b24a93d7d5aff238.yaml 1970-01-01 00:00:00.000000000 +0000 +++ cinder-16.2.1/releasenotes/notes/bug-1898918-b24a93d7d5aff238.yaml 2020-12-08 15:44:57.000000000 +0000 @@ -0,0 +1,7 @@ +--- +fixes: + - | + RBD driver `Bug #1898918 + `_: Fix thread block caused + by the flatten operation during cloning a volume. Now the flatten operation + is executed in a different thread. diff -Nru cinder-16.2.0/releasenotes/notes/bug-1901241-361b1b361bfa5152.yaml cinder-16.2.1/releasenotes/notes/bug-1901241-361b1b361bfa5152.yaml --- cinder-16.2.0/releasenotes/notes/bug-1901241-361b1b361bfa5152.yaml 1970-01-01 00:00:00.000000000 +0000 +++ cinder-16.2.1/releasenotes/notes/bug-1901241-361b1b361bfa5152.yaml 2020-12-08 15:44:57.000000000 +0000 @@ -0,0 +1,8 @@ +--- +fixes: + - | + RBD driver `bug #1901241 + `_: + Fixed an issue where decreasing the ``rbd_max_clone_depth`` configuration + option would prevent volumes that had already exceeded that depth from + being cloned. diff -Nru cinder-16.2.0/releasenotes/notes/bug-1904440-clone-rekey-fd57a2b5f6224e0f.yaml cinder-16.2.1/releasenotes/notes/bug-1904440-clone-rekey-fd57a2b5f6224e0f.yaml --- cinder-16.2.0/releasenotes/notes/bug-1904440-clone-rekey-fd57a2b5f6224e0f.yaml 1970-01-01 00:00:00.000000000 +0000 +++ cinder-16.2.1/releasenotes/notes/bug-1904440-clone-rekey-fd57a2b5f6224e0f.yaml 2020-12-08 15:44:57.000000000 +0000 @@ -0,0 +1,8 @@ +--- +fixes: + - | + `Bug #1904440 `_: + When an iSCSI/FC encrypted volume was cloned, the rekey operation would + stamp the wrong encryption key on the newly cloned volume. This resulted + in a volume that could not be attached. It does not present a security + problem. diff -Nru cinder-16.2.0/releasenotes/notes/fix-list-volume-filtering-3f2bf93ab9b98974.yaml cinder-16.2.1/releasenotes/notes/fix-list-volume-filtering-3f2bf93ab9b98974.yaml --- cinder-16.2.0/releasenotes/notes/fix-list-volume-filtering-3f2bf93ab9b98974.yaml 1970-01-01 00:00:00.000000000 +0000 +++ cinder-16.2.1/releasenotes/notes/fix-list-volume-filtering-3f2bf93ab9b98974.yaml 2020-12-08 15:44:57.000000000 +0000 @@ -0,0 +1,5 @@ +--- +fixes: + - | + `Bug #1883490 `_: + Fixed incorrect response of listing volumes with filters. \ No newline at end of file diff -Nru cinder-16.2.0/releasenotes/notes/increase_glance_num_retries-66b455a0729c4535.yaml cinder-16.2.1/releasenotes/notes/increase_glance_num_retries-66b455a0729c4535.yaml --- cinder-16.2.0/releasenotes/notes/increase_glance_num_retries-66b455a0729c4535.yaml 1970-01-01 00:00:00.000000000 +0000 +++ cinder-16.2.1/releasenotes/notes/increase_glance_num_retries-66b455a0729c4535.yaml 2020-12-08 15:44:57.000000000 +0000 @@ -0,0 +1,9 @@ +--- +upgrade: + - | + The default value of the configuration option, ``glance_num_retries``, + has been changed to 3 in this release. Its former value was 0. + The option controls how many times to retry a Glance API call + in response to a HTTP connection failure, timeout or ServiceUnavailable status. + By this change, Cinder can be more resilient to temporary failure and continue + the request if a retry succeeds.