diff --git a/cinder/tests/unit/volume/drivers/netapp/dataontap/client/fakes.py b/cinder/tests/unit/volume/drivers/netapp/dataontap/client/fakes.py index 67c00fcf373..0e3e9c73314 100644 --- a/cinder/tests/unit/volume/drivers/netapp/dataontap/client/fakes.py +++ b/cinder/tests/unit/volume/drivers/netapp/dataontap/client/fakes.py @@ -904,7 +904,7 @@ VOLUME_INFO_SSC = { 'name': VOLUME_NAMES[0], 'vserver': VOLUME_VSERVER_NAME, 'junction-path': '/%s' % VOLUME_NAMES[0], - 'aggregate': VOLUME_AGGREGATE_NAMES[0], + 'aggregate': [VOLUME_AGGREGATE_NAMES[0]], 'space-guarantee-enabled': True, 'language': 'c.utf_8', 'percentage-snapshot-reserve': '5', diff --git a/cinder/tests/unit/volume/drivers/netapp/dataontap/client/test_client_cmode.py b/cinder/tests/unit/volume/drivers/netapp/dataontap/client/test_client_cmode.py index e5ed24de6fb..5dafed495cb 100644 --- a/cinder/tests/unit/volume/drivers/netapp/dataontap/client/test_client_cmode.py +++ b/cinder/tests/unit/volume/drivers/netapp/dataontap/client/test_client_cmode.py @@ -4095,7 +4095,7 @@ class NetAppCmodeClientTestCase(test.TestCase): return_value=fake_client.VOLUME_DEDUPE_INFO_SSC) expected_prov_opts = { - 'aggregate': 'fake_aggr1', + 'aggregate': ['fake_aggr1'], 'compression_enabled': False, 'dedupe_enabled': True, 'language': 'c.utf_8', diff --git a/cinder/tests/unit/volume/drivers/netapp/dataontap/client/test_client_cmode_rest.py b/cinder/tests/unit/volume/drivers/netapp/dataontap/client/test_client_cmode_rest.py index d798be911ea..d0a3c3fbef0 100644 --- a/cinder/tests/unit/volume/drivers/netapp/dataontap/client/test_client_cmode_rest.py +++ b/cinder/tests/unit/volume/drivers/netapp/dataontap/client/test_client_cmode_rest.py @@ -2515,7 +2515,7 @@ class NetAppRestCmodeClientTestCase(test.TestCase): return_value=fake_client.VOLUME_DEDUPE_INFO_SSC) expected_prov_opts = { - 'aggregate': 'fake_aggr1', + 'aggregate': ['fake_aggr1'], 'compression_enabled': False, 'dedupe_enabled': True, 'language': 'c.utf_8', diff --git a/cinder/tests/unit/volume/drivers/netapp/dataontap/utils/fakes.py b/cinder/tests/unit/volume/drivers/netapp/dataontap/utils/fakes.py index b5c1a990c3e..12739e13850 100644 --- a/cinder/tests/unit/volume/drivers/netapp/dataontap/utils/fakes.py +++ b/cinder/tests/unit/volume/drivers/netapp/dataontap/utils/fakes.py @@ -134,6 +134,19 @@ SSC_AGGREGATE_INFO = { }, } +PROVISIONING_OPTS_FLEXGROUP = { + 'aggregate': ['fake_aggregate'], + 'thin_provisioned': True, + 'snapshot_policy': None, + 'language': 'en_US', + 'dedupe_enabled': True, + 'compression_enabled': True, + 'snapshot_reserve': '12', + 'volume_type': 'rw', + 'size': 20, + 'is_flexgroup': True, +} + PROVISIONING_OPTS = { 'aggregate': ['fake_aggregate'], 'thin_provisioned': True, diff --git a/cinder/tests/unit/volume/drivers/netapp/dataontap/utils/test_data_motion.py b/cinder/tests/unit/volume/drivers/netapp/dataontap/utils/test_data_motion.py index 0ba8a2fe927..c71ad392722 100644 --- a/cinder/tests/unit/volume/drivers/netapp/dataontap/utils/test_data_motion.py +++ b/cinder/tests/unit/volume/drivers/netapp/dataontap/utils/test_data_motion.py @@ -671,7 +671,7 @@ class NetAppCDOTDataMotionMixinTestCase(test.TestCase): is_flexgroup): self.mock_object( self.mock_src_client, 'get_provisioning_options_from_flexvol', - return_value={'size': size, 'aggregate': 'aggr01', + return_value={'size': size, 'aggregate': ['aggr1'], 'is_flexgroup': is_flexgroup}) self.mock_object(self.dm_mixin, '_get_replication_aggregate_map', return_value=aggr_map) @@ -702,11 +702,11 @@ class NetAppCDOTDataMotionMixinTestCase(test.TestCase): new=test_utils.ZeroIntervalWithTimeoutLoopingCall) def test_create_destination_flexgroup_online_timeout(self, volume_state): aggr_map = { - fakes.PROVISIONING_OPTS['aggregate'][0]: 'aggr01', + fakes.PROVISIONING_OPTS_FLEXGROUP['aggregate'][0]: 'aggr01', 'aggr20': 'aggr02', } - provisioning_opts = copy.deepcopy(fakes.PROVISIONING_OPTS) - expected_prov_opts = copy.deepcopy(fakes.PROVISIONING_OPTS) + provisioning_opts = copy.deepcopy(fakes.PROVISIONING_OPTS_FLEXGROUP) + expected_prov_opts = copy.deepcopy(fakes.PROVISIONING_OPTS_FLEXGROUP) expected_prov_opts.pop('volume_type', None) expected_prov_opts.pop('size', None) expected_prov_opts.pop('aggregate', None) @@ -745,7 +745,7 @@ class NetAppCDOTDataMotionMixinTestCase(test.TestCase): mock_create_volume_async.assert_called_once_with( self.dest_flexvol_name, ['aggr01'], - fakes.PROVISIONING_OPTS['size'], + fakes.PROVISIONING_OPTS_FLEXGROUP['size'], volume_type='dp', **expected_prov_opts) mock_volume_state.assert_called_with( name=self.dest_flexvol_name) @@ -754,19 +754,16 @@ class NetAppCDOTDataMotionMixinTestCase(test.TestCase): @ddt.data('flexvol', 'flexgroup') def test_create_destination_flexvol(self, volume_style): + provisioning_opts = copy.deepcopy(fakes.PROVISIONING_OPTS) aggr_map = { - fakes.PROVISIONING_OPTS['aggregate'][0]: 'aggr01', + provisioning_opts['aggregate'][0]: 'aggr01', 'aggr20': 'aggr02', } - provisioning_opts = copy.deepcopy(fakes.PROVISIONING_OPTS) - expected_prov_opts = copy.deepcopy(fakes.PROVISIONING_OPTS) + expected_prov_opts = copy.deepcopy(provisioning_opts) expected_prov_opts.pop('volume_type', None) expected_prov_opts.pop('size', None) expected_prov_opts.pop('aggregate', None) expected_prov_opts.pop('is_flexgroup', None) - mock_get_provisioning_opts_call = self.mock_object( - self.mock_src_client, 'get_provisioning_options_from_flexvol', - return_value=provisioning_opts) mock_is_flexvol_encrypted = self.mock_object( self.mock_src_client, 'is_flexvol_encrypted', return_value=False) @@ -782,6 +779,11 @@ class NetAppCDOTDataMotionMixinTestCase(test.TestCase): pool_is_flexgroup = False if volume_style == 'flexgroup': pool_is_flexgroup = True + provisioning_opts = copy.deepcopy( + fakes.PROVISIONING_OPTS_FLEXGROUP) + self.mock_object(self.dm_mixin, + '_get_replication_volume_online_timeout', + return_value=2) mock_create_volume_async = self.mock_object(self.mock_dest_client, 'create_volume_async') mock_dedupe_enabled = self.mock_object( @@ -792,6 +794,10 @@ class NetAppCDOTDataMotionMixinTestCase(test.TestCase): mock_create_flexvol = self.mock_object(self.mock_dest_client, 'create_flexvol') + mock_get_provisioning_opts_call = self.mock_object( + self.mock_src_client, 'get_provisioning_options_from_flexvol', + return_value=provisioning_opts) + retval = self.dm_mixin.create_destination_flexvol( self.src_backend, self.dest_backend, self.src_flexvol_name, self.dest_flexvol_name, @@ -809,7 +815,7 @@ class NetAppCDOTDataMotionMixinTestCase(test.TestCase): mock_create_volume_async.assert_called_once_with( self.dest_flexvol_name, ['aggr01'], - fakes.PROVISIONING_OPTS['size'], + fakes.PROVISIONING_OPTS_FLEXGROUP['size'], volume_type='dp', **expected_prov_opts) mock_volume_state.assert_called_once_with( name=self.dest_flexvol_name) diff --git a/cinder/volume/drivers/netapp/dataontap/client/client_cmode.py b/cinder/volume/drivers/netapp/dataontap/client/client_cmode.py index 32b01b17810..a35af9d53de 100644 --- a/cinder/volume/drivers/netapp/dataontap/client/client_cmode.py +++ b/cinder/volume/drivers/netapp/dataontap/client/client_cmode.py @@ -1518,8 +1518,9 @@ class Client(client_base.Client): volume_id_attributes = volume_attributes.get_child_by_name( 'volume-id-attributes') or netapp_api.NaElement('none') - aggr = volume_id_attributes.get_child_content( + aggr_name = volume_id_attributes.get_child_content( 'containing-aggregate-name') + aggr = [aggr_name] if aggr_name else None if not aggr: aggr_list_attr = volume_id_attributes.get_child_by_name( 'aggr-list') or netapp_api.NaElement('none') diff --git a/cinder/volume/drivers/netapp/dataontap/client/client_cmode_rest.py b/cinder/volume/drivers/netapp/dataontap/client/client_cmode_rest.py index c6c55a30695..5d92e45fc7c 100644 --- a/cinder/volume/drivers/netapp/dataontap/client/client_cmode_rest.py +++ b/cinder/volume/drivers/netapp/dataontap/client/client_cmode_rest.py @@ -450,7 +450,7 @@ class RestClient(object): aggregate = None if unique_volume['style'] == 'flexvol': # flexvol has only 1 aggregate - aggregate = unique_volume['aggregates'][0]['name'] + aggregate = [unique_volume['aggregates'][0]['name']] else: aggregate = [aggr["name"] for aggr in unique_volume.get('aggregates', [])] diff --git a/cinder/volume/drivers/netapp/dataontap/utils/capabilities.py b/cinder/volume/drivers/netapp/dataontap/utils/capabilities.py index aedd9e1ffa2..1e3cf8ae5d6 100644 --- a/cinder/volume/drivers/netapp/dataontap/utils/capabilities.py +++ b/cinder/volume/drivers/netapp/dataontap/utils/capabilities.py @@ -140,7 +140,7 @@ class CapabilitiesLibrary(object): 'netapp_thin_provisioned': six.text_type(not netapp_thick).lower(), 'thick_provisioning_support': thick, 'thin_provisioning_support': not thick, - 'netapp_aggregate': volume_info.get('aggregate'), + 'netapp_aggregate': volume_info.get('aggregate')[0], 'netapp_is_flexgroup': six.text_type(is_flexgroup).lower(), } diff --git a/releasenotes/notes/netapp-ontap-fix-flexvol-replica-create-c7772837df20021f.yaml b/releasenotes/notes/netapp-ontap-fix-flexvol-replica-create-c7772837df20021f.yaml new file mode 100644 index 00000000000..c19831b6225 --- /dev/null +++ b/releasenotes/notes/netapp-ontap-fix-flexvol-replica-create-c7772837df20021f.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + NetApp ONTAP driver `Bug #1927784 + `_: + Fixed the replication setup with FlexVol pools.