diff --git a/cinder/opts.py b/cinder/opts.py index 48505d3f47d..eda55de604d 100644 --- a/cinder/opts.py +++ b/cinder/opts.py @@ -333,6 +333,7 @@ def list_opts(): cinder_volume_drivers_netapp_options.netapp_nfs_extra_opts, cinder_volume_drivers_netapp_options.netapp_san_opts, cinder_volume_drivers_netapp_options.netapp_replication_opts, + cinder_volume_drivers_netapp_options.netapp_support_opts, cinder_volume_drivers_nexenta_options.NEXENTA_CONNECTION_OPTS, cinder_volume_drivers_nexenta_options.NEXENTA_ISCSI_OPTS, cinder_volume_drivers_nexenta_options.NEXENTA_DATASET_OPTS, diff --git a/cinder/tests/unit/volume/drivers/netapp/dataontap/client/test_api.py b/cinder/tests/unit/volume/drivers/netapp/dataontap/client/test_api.py index c1f104716f0..48d4372e30e 100644 --- a/cinder/tests/unit/volume/drivers/netapp/dataontap/client/test_api.py +++ b/cinder/tests/unit/volume/drivers/netapp/dataontap/client/test_api.py @@ -225,7 +225,6 @@ class NetAppApiServerTests(test.TestCase): def test_send_http_request_valid(self): """Tests the method send_http_request with valid parameters""" na_element = zapi_fakes.FAKE_NA_ELEMENT - self.root._trace = True self.mock_object(self.root, '_create_request', return_value=('abc', zapi_fakes.FAKE_NA_ELEMENT)) self.mock_object(netapp_api, 'LOG') diff --git a/cinder/tests/unit/volume/drivers/netapp/dataontap/client/test_client_base.py b/cinder/tests/unit/volume/drivers/netapp/dataontap/client/test_client_base.py index 60c72c2e51c..8d18e07cb4c 100644 --- a/cinder/tests/unit/volume/drivers/netapp/dataontap/client/test_client_base.py +++ b/cinder/tests/unit/volume/drivers/netapp/dataontap/client/test_client_base.py @@ -34,7 +34,8 @@ CONNECTION_INFO = {'hostname': 'hostname', 'transport_type': 'https', 'port': 443, 'username': 'admin', - 'password': 'passw0rd'} + 'password': 'passw0rd', + 'api_trace_pattern': 'fake_regex'} class NetAppBaseClientTestCase(test.TestCase): @@ -53,7 +54,8 @@ class NetAppBaseClientTestCase(test.TestCase): self.fake_lun = six.text_type(uuid.uuid4()) self.fake_size = '1024' self.fake_metadata = {'OsType': 'linux', 'SpaceReserved': 'true'} - self.mock_send_request = self.mock_object(self.client, 'send_request') + self.mock_send_request = self.mock_object( + self.client.connection, 'send_request') def test_get_ontapi_version(self): version_response = netapp_api.NaElement( @@ -534,7 +536,7 @@ class NetAppBaseClientTestCase(test.TestCase): 'volume': fake.SNAPSHOT['volume_id'], 'snapshot': fake.SNAPSHOT['name'], } - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.delete_snapshot(api_args['volume'], api_args['snapshot']) @@ -543,8 +545,8 @@ class NetAppBaseClientTestCase(test.TestCase): 'volume': api_args['volume'], 'snapshot': api_args['snapshot'], } - self.client.send_request.assert_called_once_with('snapshot-delete', - asserted_api_args) + self.client.connection.send_request.assert_called_once_with( + 'snapshot-delete', asserted_api_args) def test_create_cg_snapshot(self): self.mock_object(self.client, '_start_cg_snapshot', @@ -571,21 +573,21 @@ class NetAppBaseClientTestCase(test.TestCase): 'timeout': 'relaxed', 'volumes': [{'volume-name': fake.CG_VOLUME_NAME}], } - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client._start_cg_snapshot([fake.CG_VOLUME_NAME], snapshot_init['snapshot']) - self.client.send_request.assert_called_once_with('cg-start', - snapshot_init) + self.client.connection.send_request.assert_called_once_with( + 'cg-start', snapshot_init) def test_commit_cg_snapshot(self): snapshot_commit = {'cg-id': fake.CG_VOLUME_ID} - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client._commit_cg_snapshot(snapshot_commit['cg-id']) - self.client.send_request.assert_called_once_with( + self.client.connection.send_request.assert_called_once_with( 'cg-commit', {'cg-id': snapshot_commit['cg-id']}) def test_wait_for_busy_snapshot_raise_exception(self): @@ -609,7 +611,7 @@ class NetAppBaseClientTestCase(test.TestCase): mock_get_snapshot.assert_has_calls(calls) def test_rename_snapshot(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.rename_snapshot( fake.SNAPSHOT['volume_id'], fake.SNAPSHOT_NAME, @@ -622,5 +624,5 @@ class NetAppBaseClientTestCase(test.TestCase): client_base.DELETED_PREFIX + fake.SNAPSHOT_NAME, } - self.client.send_request.assert_called_once_with( + self.client.connection.send_request.assert_called_once_with( 'snapshot-rename', api_args) 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 2b75a7653bf..ff0969225c4 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 @@ -42,7 +42,8 @@ CONNECTION_INFO = {'hostname': 'hostname', 'port': 443, 'username': 'admin', 'password': 'passw0rd', - 'vserver': 'fake_vserver'} + 'vserver': 'fake_vserver', + 'api_trace_pattern': 'fake_regex'} @ddt.ddt @@ -64,7 +65,8 @@ class NetAppCmodeClientTestCase(test.TestCase): self.vserver = CONNECTION_INFO['vserver'] self.fake_volume = six.text_type(uuid.uuid4()) self.fake_lun = six.text_type(uuid.uuid4()) - self.mock_send_request = self.mock_object(self.client, 'send_request') + self.mock_send_request = self.mock_object( + self.client.connection, 'send_request') def _mock_api_error(self, code='fake'): return mock.Mock(side_effect=netapp_api.NaApiError(code=code)) @@ -115,7 +117,7 @@ class NetAppCmodeClientTestCase(test.TestCase): fake_client.STORAGE_DISK_GET_ITER_RESPONSE_PAGE_3), ] mock_send_request = self.mock_object( - self.client, 'send_request', + self.client.connection, 'send_request', side_effect=copy.deepcopy(api_responses)) storage_disk_get_iter_args = { @@ -156,7 +158,8 @@ class NetAppCmodeClientTestCase(test.TestCase): api_response = netapp_api.NaElement( fake_client.STORAGE_DISK_GET_ITER_RESPONSE) - mock_send_request = self.mock_object(self.client, 'send_request', + mock_send_request = self.mock_object(self.client.connection, + 'send_request', return_value=api_response) storage_disk_get_iter_args = { @@ -183,7 +186,8 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_send_iter_request_not_found(self): api_response = netapp_api.NaElement(fake_client.NO_RECORDS_RESPONSE) - mock_send_request = self.mock_object(self.client, 'send_request', + mock_send_request = self.mock_object(self.client.connection, + 'send_request', return_value=api_response) result = self.client.send_iter_request('storage-disk-get-iter') @@ -202,7 +206,7 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_send_iter_request_invalid(self, fake_response): api_response = netapp_api.NaElement(fake_response) - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', return_value=api_response) @@ -268,7 +272,7 @@ class NetAppCmodeClientTestCase(test.TestCase): api_response = netapp_api.NaElement( fake_client.NO_RECORDS_RESPONSE) - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', return_value=api_response) @@ -1558,7 +1562,7 @@ class NetAppCmodeClientTestCase(test.TestCase): flexvol_name=fake_client.VOLUME_NAMES[0]) def test_create_flexvol(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.create_flexvol( fake_client.VOLUME_NAME, fake_client.VOLUME_AGGREGATE_NAME, 100) @@ -1571,15 +1575,15 @@ class NetAppCmodeClientTestCase(test.TestCase): 'junction-path': '/%s' % fake_client.VOLUME_NAME, } - self.client.send_request.assert_called_once_with('volume-create', - volume_create_args) + self.client.connection.send_request.assert_called_once_with( + 'volume-create', volume_create_args) @ddt.data('dp', 'rw', None) def test_create_volume_with_extra_specs(self, volume_type): self.mock_object(self.client, 'enable_flexvol_dedupe') self.mock_object(self.client, 'enable_flexvol_compression') - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.create_flexvol( fake_client.VOLUME_NAME, fake_client.VOLUME_AGGREGATE_NAME, 100, @@ -1603,8 +1607,8 @@ class NetAppCmodeClientTestCase(test.TestCase): volume_create_args['junction-path'] = ('/%s' % fake_client.VOLUME_NAME) - self.client.send_request.assert_called_with('volume-create', - volume_create_args) + self.client.connection.send_request.assert_called_with( + 'volume-create', volume_create_args) self.client.enable_flexvol_dedupe.assert_called_once_with( fake_client.VOLUME_NAME) self.client.enable_flexvol_compression.assert_called_once_with( @@ -1644,7 +1648,7 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_flexvol_exists_not_found(self): api_response = netapp_api.NaElement(fake_client.NO_RECORDS_RESPONSE) - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', return_value=api_response) @@ -1652,7 +1656,7 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_rename_flexvol(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.rename_flexvol(fake_client.VOLUME_NAME, 'new_name') @@ -1661,12 +1665,12 @@ class NetAppCmodeClientTestCase(test.TestCase): 'new-volume-name': 'new_name', } - self.client.send_request.assert_called_once_with( + self.client.connection.send_request.assert_called_once_with( 'volume-rename', volume_rename_api_args) def test_mount_flexvol_default_junction_path(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.mount_flexvol(fake_client.VOLUME_NAME) @@ -1675,12 +1679,12 @@ class NetAppCmodeClientTestCase(test.TestCase): 'junction-path': '/%s' % fake_client.VOLUME_NAME, } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('volume-mount', volume_mount_args)]) def test_mount_flexvol(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') fake_path = '/fake_path' self.client.mount_flexvol(fake_client.VOLUME_NAME, @@ -1691,34 +1695,34 @@ class NetAppCmodeClientTestCase(test.TestCase): 'junction-path': fake_path, } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('volume-mount', volume_mount_args)]) def test_enable_flexvol_dedupe(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.enable_flexvol_dedupe(fake_client.VOLUME_NAME) sis_enable_args = {'path': '/vol/%s' % fake_client.VOLUME_NAME} - self.client.send_request.assert_called_once_with('sis-enable', - sis_enable_args) + self.client.connection.send_request.assert_called_once_with( + 'sis-enable', sis_enable_args) def test_disable_flexvol_dedupe(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.disable_flexvol_dedupe(fake_client.VOLUME_NAME) sis_disable_args = {'path': '/vol/%s' % fake_client.VOLUME_NAME} - self.client.send_request.assert_called_once_with('sis-disable', - sis_disable_args) + self.client.connection.send_request.assert_called_once_with( + 'sis-disable', sis_disable_args) def test_enable_flexvol_compression(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.enable_flexvol_compression(fake_client.VOLUME_NAME) @@ -1727,12 +1731,12 @@ class NetAppCmodeClientTestCase(test.TestCase): 'enable-compression': 'true' } - self.client.send_request.assert_called_once_with('sis-set-config', - sis_set_config_args) + self.client.connection.send_request.assert_called_once_with( + 'sis-set-config', sis_set_config_args) def test_disable_flexvol_compression(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.disable_flexvol_compression(fake_client.VOLUME_NAME) @@ -1741,8 +1745,8 @@ class NetAppCmodeClientTestCase(test.TestCase): 'enable-compression': 'false' } - self.client.send_request.assert_called_once_with('sis-set-config', - sis_set_config_args) + self.client.connection.send_request.assert_called_once_with( + 'sis-set-config', sis_set_config_args) def test_get_flexvol_dedupe_info(self): @@ -1867,19 +1871,19 @@ class NetAppCmodeClientTestCase(test.TestCase): api_response = netapp_api.NaElement( fake_client.CLONE_SPLIT_STATUS_RESPONSE) - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', return_value=api_response) result = self.client.get_clone_split_info(fake_client.VOLUME_NAMES[0]) self.assertEqual(fake_client.VOLUME_CLONE_SPLIT_STATUS, result) - self.client.send_request.assert_called_once_with( + self.client.connection.send_request.assert_called_once_with( 'clone-split-status', {'volume-name': fake_client.VOLUME_NAMES[0]}) def test_get_clone_split_info_api_error(self): - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', side_effect=self._mock_api_error()) @@ -1892,7 +1896,7 @@ class NetAppCmodeClientTestCase(test.TestCase): api_response = netapp_api.NaElement( fake_client.CLONE_SPLIT_STATUS_NO_DATA_RESPONSE) - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', return_value=api_response) @@ -1933,7 +1937,7 @@ class NetAppCmodeClientTestCase(test.TestCase): api_response = netapp_api.NaElement( fake_client.NO_RECORDS_RESPONSE) - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', return_value=api_response) @@ -1944,7 +1948,7 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_is_flexvol_mirrored_api_error(self): - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', side_effect=self._mock_api_error()) @@ -1999,7 +2003,7 @@ class NetAppCmodeClientTestCase(test.TestCase): api_response = netapp_api.NaElement( fake_client.NO_RECORDS_RESPONSE) - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', return_value=api_response) @@ -2010,7 +2014,7 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_is_flexvol_encrypted_api_error(self): - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', side_effect=self._mock_api_error()) @@ -2023,13 +2027,13 @@ class NetAppCmodeClientTestCase(test.TestCase): api_response = netapp_api.NaElement( fake_client.AGGR_GET_ITER_RESPONSE) - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', return_value=api_response) result = self.client._get_aggregates() - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('aggr-get-iter', {}, enable_tunneling=False)]) self.assertListEqual( [aggr.to_string() for aggr in api_response.get_child_by_name( @@ -2040,7 +2044,7 @@ class NetAppCmodeClientTestCase(test.TestCase): api_response = netapp_api.NaElement( fake_client.AGGR_GET_SPACE_RESPONSE) - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', return_value=api_response) @@ -2068,7 +2072,7 @@ class NetAppCmodeClientTestCase(test.TestCase): 'desired-attributes': desired_attributes } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('aggr-get-iter', aggr_get_iter_args, enable_tunneling=False)]) self.assertListEqual( @@ -2079,13 +2083,13 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_get_aggregates_not_found(self): api_response = netapp_api.NaElement(fake_client.NO_RECORDS_RESPONSE) - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', return_value=api_response) result = self.client._get_aggregates() - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('aggr-get-iter', {}, enable_tunneling=False)]) self.assertListEqual([], result) @@ -2126,7 +2130,9 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_get_node_for_aggregate_api_not_found(self): api_error = self._mock_api_error(netapp_api.EAPINOTFOUND) - self.mock_object(self.client, 'send_request', side_effect=api_error) + self.mock_object(self.client.connection, + 'send_request', + side_effect=api_error) result = self.client.get_node_for_aggregate( fake_client.VOLUME_AGGREGATE_NAME) @@ -2135,7 +2141,9 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_get_node_for_aggregate_api_error(self): - self.mock_object(self.client, 'send_request', self._mock_api_error()) + self.mock_object(self.client.connection, + 'send_request', + self._mock_api_error()) self.assertRaises(netapp_api.NaApiError, self.client.get_node_for_aggregate, @@ -2144,7 +2152,7 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_get_node_for_aggregate_not_found(self): api_response = netapp_api.NaElement(fake_client.NO_RECORDS_RESPONSE) - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', return_value=api_response) @@ -2194,7 +2202,7 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_get_aggregate_not_found(self): api_response = netapp_api.NaElement(fake_client.NO_RECORDS_RESPONSE) - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', return_value=api_response) @@ -2204,7 +2212,7 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_get_aggregate_api_error(self): - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', side_effect=self._mock_api_error()) @@ -2215,7 +2223,7 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_get_aggregate_api_not_found(self): api_error = netapp_api.NaApiError(code=netapp_api.EAPINOTFOUND) - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_iter_request', side_effect=api_error) @@ -2227,7 +2235,7 @@ class NetAppCmodeClientTestCase(test.TestCase): api_response = netapp_api.NaElement( fake_client.SYSTEM_NODE_GET_ITER_RESPONSE) - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', mock.Mock(return_value=api_response)) @@ -2238,7 +2246,7 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_list_cluster_nodes_not_found(self): api_response = netapp_api.NaElement(fake_client.NO_RECORDS_RESPONSE) - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', mock.Mock(return_value=api_response)) @@ -2490,7 +2498,7 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_get_aggregate_capacity_not_found(self): api_response = netapp_api.NaElement(fake_client.NO_RECORDS_RESPONSE) - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', return_value=api_response) @@ -2501,7 +2509,7 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_get_aggregate_capacity_api_error(self): - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', side_effect=self._mock_api_error()) @@ -2513,7 +2521,8 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_get_aggregate_capacity_api_not_found(self): api_error = netapp_api.NaApiError(code=netapp_api.EAPINOTFOUND) - self.mock_object(self.client, 'send_request', side_effect=api_error) + self.mock_object( + self.client.connection, 'send_request', side_effect=api_error) result = self.client.get_aggregate_capacity( fake_client.VOLUME_AGGREGATE_NAME) @@ -2711,7 +2720,7 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_create_cluster_peer(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.create_cluster_peer(['fake_address_1', 'fake_address_2'], 'fake_user', 'fake_password', @@ -2726,7 +2735,7 @@ class NetAppCmodeClientTestCase(test.TestCase): 'password': 'fake_password', 'passphrase': 'fake_passphrase', } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('cluster-peer-create', cluster_peer_create_args)]) def test_get_cluster_peers(self): @@ -2795,12 +2804,12 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_delete_cluster_peer(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.delete_cluster_peer(fake_client.CLUSTER_NAME) cluster_peer_delete_args = {'cluster-name': fake_client.CLUSTER_NAME} - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('cluster-peer-delete', cluster_peer_delete_args)]) def test_get_cluster_peer_policy(self): @@ -2809,7 +2818,7 @@ class NetAppCmodeClientTestCase(test.TestCase): api_response = netapp_api.NaElement( fake_client.CLUSTER_PEER_POLICY_GET_RESPONSE) - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', return_value=api_response) @@ -2820,7 +2829,7 @@ class NetAppCmodeClientTestCase(test.TestCase): 'passphrase-minimum-length': 8, } self.assertEqual(expected, result) - self.assertTrue(self.client.send_request.called) + self.assertTrue(self.client.connection.send_request.called) def test_get_cluster_peer_policy_not_supported(self): @@ -2830,25 +2839,25 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_set_cluster_peer_policy_not_supported(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.set_cluster_peer_policy() - self.assertFalse(self.client.send_request.called) + self.assertFalse(self.client.connection.send_request.called) def test_set_cluster_peer_policy_no_arguments(self): self.client.features.add_feature('CLUSTER_PEER_POLICY') - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.set_cluster_peer_policy() - self.assertFalse(self.client.send_request.called) + self.assertFalse(self.client.connection.send_request.called) def test_set_cluster_peer_policy(self): self.client.features.add_feature('CLUSTER_PEER_POLICY') - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.set_cluster_peer_policy( is_unauthenticated_access_permitted=True, @@ -2858,13 +2867,13 @@ class NetAppCmodeClientTestCase(test.TestCase): 'is-unauthenticated-access-permitted': 'true', 'passphrase-minlength': '12', } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('cluster-peer-policy-modify', cluster_peer_policy_modify_args)]) def test_create_vserver_peer(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.create_vserver_peer('fake_vserver', 'fake_vserver_peer') @@ -2875,12 +2884,12 @@ class NetAppCmodeClientTestCase(test.TestCase): {'vserver-peer-application': 'snapmirror'}, ], } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('vserver-peer-create', vserver_peer_create_args)]) def test_delete_vserver_peer(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.delete_vserver_peer('fake_vserver', 'fake_vserver_peer') @@ -2888,12 +2897,12 @@ class NetAppCmodeClientTestCase(test.TestCase): 'vserver': 'fake_vserver', 'peer-vserver': 'fake_vserver_peer', } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('vserver-peer-delete', vserver_peer_delete_args)]) def test_accept_vserver_peer(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.accept_vserver_peer('fake_vserver', 'fake_vserver_peer') @@ -2901,7 +2910,7 @@ class NetAppCmodeClientTestCase(test.TestCase): 'vserver': 'fake_vserver', 'peer-vserver': 'fake_vserver_peer', } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('vserver-peer-accept', vserver_peer_accept_args)]) def test_get_vserver_peers(self): @@ -2964,7 +2973,7 @@ class NetAppCmodeClientTestCase(test.TestCase): {'schedule': None, 'policy': None}) @ddt.unpack def test_create_snapmirror(self, schedule, policy): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.create_snapmirror( fake_client.SM_SOURCE_VSERVER, fake_client.SM_SOURCE_VOLUME, @@ -2982,12 +2991,13 @@ class NetAppCmodeClientTestCase(test.TestCase): snapmirror_create_args['schedule'] = schedule if policy: snapmirror_create_args['policy'] = policy - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('snapmirror-create', snapmirror_create_args)]) def test_create_snapmirror_already_exists(self): api_error = netapp_api.NaApiError(code=netapp_api.ERELATION_EXISTS) - self.mock_object(self.client, 'send_request', side_effect=api_error) + self.mock_object( + self.client.connection, 'send_request', side_effect=api_error) self.client.create_snapmirror( fake_client.SM_SOURCE_VSERVER, fake_client.SM_SOURCE_VOLUME, @@ -3000,12 +3010,13 @@ class NetAppCmodeClientTestCase(test.TestCase): 'destination-volume': fake_client.SM_DEST_VOLUME, 'relationship-type': 'data_protection', } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('snapmirror-create', snapmirror_create_args)]) def test_create_snapmirror_error(self): api_error = netapp_api.NaApiError(code=0) - self.mock_object(self.client, 'send_request', side_effect=api_error) + self.mock_object( + self.client.connection, 'send_request', side_effect=api_error) self.assertRaises(netapp_api.NaApiError, self.client.create_snapmirror, @@ -3013,7 +3024,7 @@ class NetAppCmodeClientTestCase(test.TestCase): fake_client.SM_SOURCE_VOLUME, fake_client.SM_DEST_VSERVER, fake_client.SM_DEST_VOLUME) - self.assertTrue(self.client.send_request.called) + self.assertTrue(self.client.connection.send_request.called) @ddt.data( { @@ -3030,7 +3041,7 @@ class NetAppCmodeClientTestCase(test.TestCase): api_response = netapp_api.NaElement( fake_client.SNAPMIRROR_INITIALIZE_RESULT) - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', return_value=api_response) @@ -3050,7 +3061,7 @@ class NetAppCmodeClientTestCase(test.TestCase): snapmirror_initialize_args['source-snapshot'] = source_snapshot if transfer_priority: snapmirror_initialize_args['transfer-priority'] = transfer_priority - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('snapmirror-initialize', snapmirror_initialize_args)]) expected = { @@ -3065,7 +3076,7 @@ class NetAppCmodeClientTestCase(test.TestCase): @ddt.data(True, False) def test_release_snapmirror(self, relationship_info_only): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.release_snapmirror( fake_client.SM_SOURCE_VSERVER, fake_client.SM_SOURCE_VOLUME, @@ -3084,12 +3095,12 @@ class NetAppCmodeClientTestCase(test.TestCase): } } } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('snapmirror-release-iter', snapmirror_release_args)]) def test_quiesce_snapmirror(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.quiesce_snapmirror( fake_client.SM_SOURCE_VSERVER, fake_client.SM_SOURCE_VOLUME, @@ -3101,13 +3112,13 @@ class NetAppCmodeClientTestCase(test.TestCase): 'destination-vserver': fake_client.SM_DEST_VSERVER, 'destination-volume': fake_client.SM_DEST_VOLUME, } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('snapmirror-quiesce', snapmirror_quiesce_args)]) @ddt.data(True, False) def test_abort_snapmirror(self, clear_checkpoint): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.abort_snapmirror( fake_client.SM_SOURCE_VSERVER, fake_client.SM_SOURCE_VOLUME, @@ -3121,13 +3132,14 @@ class NetAppCmodeClientTestCase(test.TestCase): 'destination-volume': fake_client.SM_DEST_VOLUME, 'clear-checkpoint': 'true' if clear_checkpoint else 'false', } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('snapmirror-abort', snapmirror_abort_args)]) def test_abort_snapmirror_no_transfer_in_progress(self): api_error = netapp_api.NaApiError( code=netapp_api.ENOTRANSFER_IN_PROGRESS) - self.mock_object(self.client, 'send_request', side_effect=api_error) + self.mock_object( + self.client.connection, 'send_request', side_effect=api_error) self.client.abort_snapmirror( fake_client.SM_SOURCE_VSERVER, fake_client.SM_SOURCE_VOLUME, @@ -3140,12 +3152,13 @@ class NetAppCmodeClientTestCase(test.TestCase): 'destination-volume': fake_client.SM_DEST_VOLUME, 'clear-checkpoint': 'false', } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('snapmirror-abort', snapmirror_abort_args)]) def test_abort_snapmirror_error(self): api_error = netapp_api.NaApiError(code=0) - self.mock_object(self.client, 'send_request', side_effect=api_error) + self.mock_object( + self.client.connection, 'send_request', side_effect=api_error) self.assertRaises(netapp_api.NaApiError, self.client.abort_snapmirror, @@ -3156,7 +3169,7 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_break_snapmirror(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.break_snapmirror( fake_client.SM_SOURCE_VSERVER, fake_client.SM_SOURCE_VOLUME, @@ -3168,7 +3181,7 @@ class NetAppCmodeClientTestCase(test.TestCase): 'destination-vserver': fake_client.SM_DEST_VSERVER, 'destination-volume': fake_client.SM_DEST_VOLUME, } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('snapmirror-break', snapmirror_break_args)]) @ddt.data( @@ -3189,7 +3202,7 @@ class NetAppCmodeClientTestCase(test.TestCase): def test_modify_snapmirror(self, schedule, policy, tries, max_transfer_rate): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.modify_snapmirror( fake_client.SM_SOURCE_VSERVER, fake_client.SM_SOURCE_VOLUME, @@ -3211,12 +3224,12 @@ class NetAppCmodeClientTestCase(test.TestCase): snapmirror_modify_args['tries'] = tries if max_transfer_rate: snapmirror_modify_args['max-transfer-rate'] = max_transfer_rate - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('snapmirror-modify', snapmirror_modify_args)]) def test_delete_snapmirror(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.delete_snapmirror( fake_client.SM_SOURCE_VSERVER, fake_client.SM_SOURCE_VOLUME, @@ -3232,12 +3245,12 @@ class NetAppCmodeClientTestCase(test.TestCase): } } } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('snapmirror-destroy-iter', snapmirror_delete_args)]) def test_update_snapmirror(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.update_snapmirror( fake_client.SM_SOURCE_VSERVER, fake_client.SM_SOURCE_VOLUME, @@ -3249,13 +3262,14 @@ class NetAppCmodeClientTestCase(test.TestCase): 'destination-vserver': fake_client.SM_DEST_VSERVER, 'destination-volume': fake_client.SM_DEST_VOLUME, } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('snapmirror-update', snapmirror_update_args)]) def test_update_snapmirror_already_transferring(self): api_error = netapp_api.NaApiError( code=netapp_api.ETRANSFER_IN_PROGRESS) - self.mock_object(self.client, 'send_request', side_effect=api_error) + self.mock_object( + self.client.connection, 'send_request', side_effect=api_error) self.client.update_snapmirror( fake_client.SM_SOURCE_VSERVER, fake_client.SM_SOURCE_VOLUME, @@ -3267,12 +3281,13 @@ class NetAppCmodeClientTestCase(test.TestCase): 'destination-vserver': fake_client.SM_DEST_VSERVER, 'destination-volume': fake_client.SM_DEST_VOLUME, } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('snapmirror-update', snapmirror_update_args)]) def test_update_snapmirror_already_transferring_two(self): api_error = netapp_api.NaApiError(code=netapp_api.EANOTHER_OP_ACTIVE) - self.mock_object(self.client, 'send_request', side_effect=api_error) + self.mock_object( + self.client.connection, 'send_request', side_effect=api_error) self.client.update_snapmirror( fake_client.SM_SOURCE_VSERVER, fake_client.SM_SOURCE_VOLUME, @@ -3284,12 +3299,13 @@ class NetAppCmodeClientTestCase(test.TestCase): 'destination-vserver': fake_client.SM_DEST_VSERVER, 'destination-volume': fake_client.SM_DEST_VOLUME, } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('snapmirror-update', snapmirror_update_args)]) def test_update_snapmirror_error(self): api_error = netapp_api.NaApiError(code=0) - self.mock_object(self.client, 'send_request', side_effect=api_error) + self.mock_object( + self.client.connection, 'send_request', side_effect=api_error) self.assertRaises(netapp_api.NaApiError, self.client.update_snapmirror, @@ -3299,7 +3315,7 @@ class NetAppCmodeClientTestCase(test.TestCase): fake_client.SM_DEST_VOLUME) def test_resume_snapmirror(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.resume_snapmirror( fake_client.SM_SOURCE_VSERVER, fake_client.SM_SOURCE_VOLUME, @@ -3311,13 +3327,14 @@ class NetAppCmodeClientTestCase(test.TestCase): 'destination-vserver': fake_client.SM_DEST_VSERVER, 'destination-volume': fake_client.SM_DEST_VOLUME, } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('snapmirror-resume', snapmirror_resume_args)]) def test_resume_snapmirror_not_quiesed(self): api_error = netapp_api.NaApiError( code=netapp_api.ERELATION_NOT_QUIESCED) - self.mock_object(self.client, 'send_request', side_effect=api_error) + self.mock_object( + self.client.connection, 'send_request', side_effect=api_error) self.client.resume_snapmirror( fake_client.SM_SOURCE_VSERVER, fake_client.SM_SOURCE_VOLUME, @@ -3329,12 +3346,13 @@ class NetAppCmodeClientTestCase(test.TestCase): 'destination-vserver': fake_client.SM_DEST_VSERVER, 'destination-volume': fake_client.SM_DEST_VOLUME, } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('snapmirror-resume', snapmirror_resume_args)]) def test_resume_snapmirror_error(self): api_error = netapp_api.NaApiError(code=0) - self.mock_object(self.client, 'send_request', side_effect=api_error) + self.mock_object( + self.client.connection, 'send_request', side_effect=api_error) self.assertRaises(netapp_api.NaApiError, self.client.resume_snapmirror, @@ -3344,7 +3362,7 @@ class NetAppCmodeClientTestCase(test.TestCase): fake_client.SM_DEST_VOLUME) def test_resync_snapmirror(self): - self.mock_object(self.client, 'send_request') + self.mock_object(self.client.connection, 'send_request') self.client.resync_snapmirror( fake_client.SM_SOURCE_VSERVER, fake_client.SM_SOURCE_VOLUME, @@ -3356,7 +3374,7 @@ class NetAppCmodeClientTestCase(test.TestCase): 'destination-vserver': fake_client.SM_DEST_VSERVER, 'destination-volume': fake_client.SM_DEST_VOLUME, } - self.client.send_request.assert_has_calls([ + self.client.connection.send_request.assert_has_calls([ mock.call('snapmirror-resync', snapmirror_resync_args)]) def test__get_snapmirrors(self): @@ -3545,7 +3563,7 @@ class NetAppCmodeClientTestCase(test.TestCase): @ddt.unpack def test_get_snapshots_marked_for_deletion(self, mock_return, expected): api_response = netapp_api.NaElement(mock_return) - self.mock_object(self.client, + self.mock_object(self.client.connection, 'send_request', return_value=api_response) @@ -3568,6 +3586,6 @@ class NetAppCmodeClientTestCase(test.TestCase): }, } - self.client.send_request.assert_called_once_with( + self.client.connection.send_request.assert_called_once_with( 'snapshot-get-iter', api_args) self.assertListEqual(expected, result) diff --git a/cinder/tests/unit/volume/drivers/netapp/dataontap/test_block_cmode.py b/cinder/tests/unit/volume/drivers/netapp/dataontap/test_block_cmode.py index b1f487c9992..c6e8b3cb374 100644 --- a/cinder/tests/unit/volume/drivers/netapp/dataontap/test_block_cmode.py +++ b/cinder/tests/unit/volume/drivers/netapp/dataontap/test_block_cmode.py @@ -80,6 +80,7 @@ class NetAppBlockStorageCmodeLibraryTestCase(test.TestCase): config.netapp_transport_type = 'https' config.netapp_server_port = '443' config.netapp_vserver = 'openstack' + config.netapp_api_trace_pattern = 'fake_regex' return config @mock.patch.object(perf_cmode, 'PerformanceCmodeLibrary', mock.Mock()) diff --git a/cinder/tests/unit/volume/drivers/netapp/dataontap/test_nfs_cmode.py b/cinder/tests/unit/volume/drivers/netapp/dataontap/test_nfs_cmode.py index 9cadf9bce75..305e6c9d47b 100644 --- a/cinder/tests/unit/volume/drivers/netapp/dataontap/test_nfs_cmode.py +++ b/cinder/tests/unit/volume/drivers/netapp/dataontap/test_nfs_cmode.py @@ -81,6 +81,7 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase): config.netapp_server_port = '80' config.netapp_vserver = fake.VSERVER_NAME config.netapp_copyoffload_tool_path = 'copyoffload_tool_path' + config.netapp_api_trace_pattern = 'fake_regex' return config @ddt.data({'active_backend_id': None, 'targets': ['dev1', 'dev2']}, 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 47ffccaa2c4..9055261242d 100644 --- a/cinder/tests/unit/volume/drivers/netapp/dataontap/utils/fakes.py +++ b/cinder/tests/unit/volume/drivers/netapp/dataontap/utils/fakes.py @@ -155,5 +155,6 @@ def get_fake_cmode_config(backend_name): config.append_config_values(na_opts.netapp_cluster_opts) config.append_config_values(na_opts.netapp_san_opts) config.append_config_values(na_opts.netapp_replication_opts) + config.append_config_values(na_opts.netapp_support_opts) return config diff --git a/cinder/tests/unit/volume/drivers/netapp/dataontap/utils/test_utils.py b/cinder/tests/unit/volume/drivers/netapp/dataontap/utils/test_utils.py index 7262dd80544..755f2ef6466 100644 --- a/cinder/tests/unit/volume/drivers/netapp/dataontap/utils/test_utils.py +++ b/cinder/tests/unit/volume/drivers/netapp/dataontap/utils/test_utils.py @@ -46,6 +46,8 @@ class NetAppCDOTDataMotionTestCase(test.TestCase): group=self.backend) CONF.set_override('netapp_server_port', 8866, group=self.backend) + CONF.set_override('netapp_api_trace_pattern', "fake_regex", + group=self.backend) def test_get_backend_configuration(self): self.mock_object(utils, 'CONF') @@ -88,7 +90,7 @@ class NetAppCDOTDataMotionTestCase(test.TestCase): self.mock_cmode_client.assert_called_once_with( hostname='fake_hostname', password='fake_password', username='fake_user', transport_type='https', port=8866, - trace=mock.ANY, vserver=None) + trace=mock.ANY, vserver=None, api_trace_pattern="fake_regex") def test_get_client_for_backend_with_vserver(self): self.mock_object(utils, 'get_backend_configuration', @@ -102,7 +104,8 @@ class NetAppCDOTDataMotionTestCase(test.TestCase): self.mock_cmode_client.assert_called_once_with( hostname='fake_hostname', password='fake_password', username='fake_user', transport_type='https', port=8866, - trace=mock.ANY, vserver='fake_vserver') + trace=mock.ANY, vserver='fake_vserver', + api_trace_pattern="fake_regex") @ddt.ddt diff --git a/cinder/tests/unit/volume/drivers/netapp/test_utils.py b/cinder/tests/unit/volume/drivers/netapp/test_utils.py index 40c6534a5b1..8f98aa2f3f7 100644 --- a/cinder/tests/unit/volume/drivers/netapp/test_utils.py +++ b/cinder/tests/unit/volume/drivers/netapp/test_utils.py @@ -28,8 +28,11 @@ from oslo_concurrency import processutils as putils from cinder import context from cinder import exception from cinder import test +from cinder.tests.unit.volume.drivers.netapp.dataontap.client import ( + fakes as zapi_fakes) import cinder.tests.unit.volume.drivers.netapp.fakes as fake from cinder import version +from cinder.volume.drivers.netapp.dataontap.client import api as netapp_api from cinder.volume.drivers.netapp import utils as na_utils from cinder.volume import qos_specs from cinder.volume import volume_types @@ -158,6 +161,22 @@ class NetAppDriverUtilsTestCase(test.TestCase): self.assertEqual(fake_extra_specs, result) + def test_trace_filter_func_api(self): + na_utils.setup_api_trace_pattern("^(?!(perf)).*$") + na_element = zapi_fakes.FAKE_NA_ELEMENT + all_args = {'na_element': na_element} + self.assertTrue(na_utils.trace_filter_func_api(all_args)) + + def test_trace_filter_func_api_invalid(self): + all_args = {'fake': 'not_na_element'} + self.assertTrue(na_utils.trace_filter_func_api(all_args)) + + def test_trace_filter_func_api_filtered(self): + na_utils.setup_api_trace_pattern("^(?!(perf)).*$") + na_element = netapp_api.NaElement("perf-object-counter-list-info") + all_args = {'na_element': na_element} + self.assertFalse(na_utils.trace_filter_func_api(all_args)) + def test_get_volume_extra_specs_no_type_id(self): fake_volume = {} self.mock_object(context, 'get_admin_context') diff --git a/cinder/volume/drivers/netapp/dataontap/client/api.py b/cinder/volume/drivers/netapp/dataontap/client/api.py index aae2c3e007e..3f0c5ac83af 100644 --- a/cinder/volume/drivers/netapp/dataontap/client/api.py +++ b/cinder/volume/drivers/netapp/dataontap/client/api.py @@ -34,6 +34,7 @@ from cinder import exception from cinder.i18n import _ from cinder import ssh_utils from cinder import utils +from cinder.volume.drivers.netapp import utils as na_utils LOG = logging.getLogger(__name__) @@ -67,7 +68,7 @@ class NaServer(object): def __init__(self, host, server_type=SERVER_TYPE_FILER, transport_type=TRANSPORT_TYPE_HTTP, style=STYLE_LOGIN_PASSWORD, username=None, - password=None, port=None): + password=None, port=None, api_trace_pattern=None): self._host = host self.set_server_type(server_type) self.set_transport_type(transport_type) @@ -78,6 +79,9 @@ class NaServer(object): self._password = password self._refresh_conn = True + if api_trace_pattern is not None: + na_utils.setup_api_trace_pattern(api_trace_pattern) + LOG.debug('Using NetApp controller: %s', self._host) def set_transport_type(self, transport_type): @@ -171,7 +175,7 @@ class NaServer(object): """Set the vserver to use if tunneling gets enabled.""" self._vserver = vserver - @utils.trace_api + @utils.trace_api(filter_function=na_utils.trace_filter_func_api) def send_http_request(self, na_element, enable_tunneling=False): """Invoke the API on the server.""" if not na_element or not isinstance(na_element, NaElement): @@ -221,6 +225,13 @@ class NaServer(object): or 'Execution status is failed due to unknown reason' raise NaApiError(code, msg) + def send_request(self, api_name, api_args=None, enable_tunneling=True): + """Sends request to Ontapi.""" + request = NaElement(api_name) + if api_args: + request.translate_struct(api_args) + return self.invoke_successfully(request, enable_tunneling) + def _create_request(self, na_element, enable_tunneling=False): """Creates request in the desired format.""" netapp_elem = NaElement('netapp') diff --git a/cinder/volume/drivers/netapp/dataontap/client/client_base.py b/cinder/volume/drivers/netapp/dataontap/client/client_base.py index 24c4bc9ba1f..7fe19604e0d 100644 --- a/cinder/volume/drivers/netapp/dataontap/client/client_base.py +++ b/cinder/volume/drivers/netapp/dataontap/client/client_base.py @@ -41,12 +41,14 @@ class Client(object): host = kwargs['hostname'] username = kwargs['username'] password = kwargs['password'] + api_trace_pattern = kwargs['api_trace_pattern'] self.connection = netapp_api.NaServer( host=host, transport_type=kwargs['transport_type'], port=kwargs['port'], username=username, - password=password) + password=password, + api_trace_pattern=api_trace_pattern) self.ssh_client = self._init_ssh_client(host, username, password) @@ -82,13 +84,6 @@ class Client(object): if not isinstance(elem, netapp_api.NaElement): raise ValueError('Expects NaElement') - def send_request(self, api_name, api_args=None, enable_tunneling=True): - """Sends request to Ontapi.""" - request = netapp_api.NaElement(api_name) - if api_args: - request.translate_struct(api_args) - return self.connection.invoke_successfully(request, enable_tunneling) - def create_lun(self, volume_name, lun_name, size, metadata, qos_policy_group_name=None): """Issues API request for creating LUN on volume.""" @@ -288,9 +283,9 @@ class Client(object): """Gets info about one or more Data ONTAP performance counters.""" api_args = {'objectname': object_name} - result = self.send_request('perf-object-counter-list-info', - api_args, - enable_tunneling=False) + result = self.connection.send_request('perf-object-counter-list-info', + api_args, + enable_tunneling=False) counters = result.get_child_by_name( 'counters') or netapp_api.NaElement('None') @@ -317,7 +312,7 @@ class Client(object): def delete_snapshot(self, volume_name, snapshot_name): """Deletes a volume snapshot.""" api_args = {'volume': volume_name, 'snapshot': snapshot_name} - self.send_request('snapshot-delete', api_args) + self.connection.send_request('snapshot-delete', api_args) def create_cg_snapshot(self, volume_names, snapshot_name): """Creates a consistency group snapshot out of one or more flexvols. @@ -341,12 +336,12 @@ class Client(object): {'volume-name': volume_name} for volume_name in volume_names ], } - result = self.send_request('cg-start', snapshot_init) + result = self.connection.send_request('cg-start', snapshot_init) return result.get_child_content('cg-id') def _commit_cg_snapshot(self, cg_id): snapshot_commit = {'cg-id': cg_id} - self.send_request('cg-commit', snapshot_commit) + self.connection.send_request('cg-commit', snapshot_commit) def get_snapshot(self, volume_name, snapshot_name): """Gets a single snapshot.""" @@ -384,4 +379,4 @@ class Client(object): 'current-name': current_name, 'new-name': new_name, } - return self.send_request('snapshot-rename', api_args) + return self.connection.send_request('snapshot-rename', api_args) diff --git a/cinder/volume/drivers/netapp/dataontap/client/client_cmode.py b/cinder/volume/drivers/netapp/dataontap/client/client_cmode.py index 5829159b4bc..54abeaf94cd 100644 --- a/cinder/volume/drivers/netapp/dataontap/client/client_cmode.py +++ b/cinder/volume/drivers/netapp/dataontap/client/client_cmode.py @@ -111,7 +111,7 @@ class Client(client_base.Client): api_args['max-records'] = max_page_length # Get first page - result = self.send_request( + result = self.connection.send_request( api_name, api_args, enable_tunneling=enable_tunneling) # Most commonly, we can just return here if there is no more data @@ -130,7 +130,7 @@ class Client(client_base.Client): while next_tag is not None: next_api_args = copy.deepcopy(api_args) next_api_args['tag'] = next_tag - next_result = self.send_request( + next_result = self.connection.send_request( api_name, next_api_args, enable_tunneling=enable_tunneling) next_attributes_list = next_result.get_child_by_name( @@ -204,7 +204,8 @@ class Client(client_base.Client): try: node_client.set_vserver(self._get_ems_log_destination_vserver()) - node_client.send_request('ems-autosupport-log', message_dict) + node_client.connection.send_request('ems-autosupport-log', + message_dict) LOG.debug('EMS executed successfully.') except netapp_api.NaApiError as e: LOG.warning('Failed to invoke EMS. %s', e) @@ -526,7 +527,7 @@ class Client(client_base.Client): 'file': file_path, 'vserver': self.vserver, } - return self.send_request('file-assign-qos', api_args, False) + return self.connection.send_request('file-assign-qos', api_args, False) def provision_qos_policy_group(self, qos_policy_group_info): """Create QOS policy group on the backend if appropriate.""" @@ -562,9 +563,9 @@ class Client(client_base.Client): }, }, } - result = self.send_request('qos-policy-group-get-iter', - api_args, - False) + result = self.connection.send_request('qos-policy-group-get-iter', + api_args, + False) return self._has_records(result) def qos_policy_group_create(self, qos_policy_group_name, max_throughput): @@ -574,7 +575,8 @@ class Client(client_base.Client): 'max-throughput': max_throughput, 'vserver': self.vserver, } - return self.send_request('qos-policy-group-create', api_args, False) + return self.connection.send_request( + 'qos-policy-group-create', api_args, False) def qos_policy_group_modify(self, qos_policy_group_name, max_throughput): """Modifies a QOS policy group.""" @@ -582,12 +584,14 @@ class Client(client_base.Client): 'policy-group': qos_policy_group_name, 'max-throughput': max_throughput, } - return self.send_request('qos-policy-group-modify', api_args, False) + return self.connection.send_request( + 'qos-policy-group-modify', api_args, False) def qos_policy_group_delete(self, qos_policy_group_name): """Attempts to delete a QOS policy group.""" api_args = {'policy-group': qos_policy_group_name} - return self.send_request('qos-policy-group-delete', api_args, False) + return self.connection.send_request( + 'qos-policy-group-delete', api_args, False) def qos_policy_group_rename(self, qos_policy_group_name, new_name): """Renames a QOS policy group.""" @@ -595,7 +599,8 @@ class Client(client_base.Client): 'policy-group-name': qos_policy_group_name, 'new-name': new_name, } - return self.send_request('qos-policy-group-rename', api_args, False) + return self.connection.send_request( + 'qos-policy-group-rename', api_args, False) def mark_qos_policy_group_for_deletion(self, qos_policy_group_info): """Do (soft) delete of backing QOS policy group for a cinder volume.""" @@ -639,7 +644,8 @@ class Client(client_base.Client): } try: - self.send_request('qos-policy-group-delete-iter', api_args, False) + self.connection.send_request( + 'qos-policy-group-delete-iter', api_args, False) except netapp_api.NaApiError as ex: msg = 'Could not delete QOS policy groups. Details: %(ex)s' msg_args = {'ex': ex} @@ -651,7 +657,8 @@ class Client(client_base.Client): 'path': path, 'qos-policy-group': qos_policy_group, } - return self.send_request('lun-set-qos-policy-group', api_args) + return self.connection.send_request( + 'lun-set-qos-policy-group', api_args) def get_if_info_by_ip(self, ip): """Gets the network interface info by ip.""" @@ -777,7 +784,7 @@ class Client(client_base.Client): }, }, } - result = self.send_request( + result = self.connection.send_request( 'system-user-capability-get-iter', api_args, False) if not self._has_records(result): @@ -812,7 +819,7 @@ class Client(client_base.Client): raise ValueError(_('Non-getter API passed to API test method.')) try: - self.send_request(api, enable_tunneling=False) + self.connection.send_request(api, enable_tunneling=False) except netapp_api.NaApiError as ex: if ex.code in (netapp_api.EAPIPRIVILEGE, netapp_api.EAPINOTFOUND): return False @@ -1134,8 +1141,8 @@ class Client(client_base.Client): """Get the status of unsplit file/LUN clones in a flexvol.""" try: - result = self.send_request('clone-split-status', - {'volume-name': flexvol_name}) + result = self.connection.send_request( + 'clone-split-status', {'volume-name': flexvol_name}) except netapp_api.NaApiError: LOG.exception('Failed to get clone split info for volume %s.', flexvol_name) @@ -1243,7 +1250,7 @@ class Client(client_base.Client): if snapshot_reserve is not None: api_args['percentage-snapshot-reserve'] = six.text_type( snapshot_reserve) - self.send_request('volume-create', api_args) + self.connection.send_request('volume-create', api_args) # cDOT compression requires that deduplication be enabled. if dedupe_enabled or compression_enabled: @@ -1280,7 +1287,7 @@ class Client(client_base.Client): 'volume': orig_flexvol_name, 'new-volume-name': new_flexvol_name, } - self.send_request('volume-rename', api_args) + self.connection.send_request('volume-rename', api_args) def mount_flexvol(self, flexvol_name, junction_path=None): """Mounts a volume on a junction path.""" @@ -1289,17 +1296,17 @@ class Client(client_base.Client): 'junction-path': (junction_path if junction_path else '/%s' % flexvol_name) } - self.send_request('volume-mount', api_args) + self.connection.send_request('volume-mount', api_args) def enable_flexvol_dedupe(self, flexvol_name): """Enable deduplication on volume.""" api_args = {'path': '/vol/%s' % flexvol_name} - self.send_request('sis-enable', api_args) + self.connection.send_request('sis-enable', api_args) def disable_flexvol_dedupe(self, flexvol_name): """Disable deduplication on volume.""" api_args = {'path': '/vol/%s' % flexvol_name} - self.send_request('sis-disable', api_args) + self.connection.send_request('sis-disable', api_args) def enable_flexvol_compression(self, flexvol_name): """Enable compression on volume.""" @@ -1307,7 +1314,7 @@ class Client(client_base.Client): 'path': '/vol/%s' % flexvol_name, 'enable-compression': 'true' } - self.send_request('sis-set-config', api_args) + self.connection.send_request('sis-set-config', api_args) def disable_flexvol_compression(self, flexvol_name): """Disable compression on volume.""" @@ -1315,7 +1322,7 @@ class Client(client_base.Client): 'path': '/vol/%s' % flexvol_name, 'enable-compression': 'false' } - self.send_request('sis-set-config', api_args) + self.connection.send_request('sis-set-config', api_args) @utils.trace_method def delete_file(self, path_to_file): @@ -1327,7 +1334,7 @@ class Client(client_base.Client): # Use fast clone deletion engine if it is supported. if self.features.FAST_CLONE_DELETE: api_args['is-clone-file'] = 'true' - self.send_request('file-delete-file', api_args, True) + self.connection.send_request('file-delete-file', api_args, True) def _get_aggregates(self, aggregate_names=None, desired_attributes=None): @@ -1343,9 +1350,9 @@ class Client(client_base.Client): if desired_attributes: api_args['desired-attributes'] = desired_attributes - result = self.send_request('aggr-get-iter', - api_args, - enable_tunneling=False) + result = self.connection.send_request('aggr-get-iter', + api_args, + enable_tunneling=False) if not self._has_records(result): return [] else: @@ -1566,9 +1573,9 @@ class Client(client_base.Client): } } - result = self.send_request('perf-object-instance-list-info-iter', - api_args, - enable_tunneling=False) + result = self.connection.send_request( + 'perf-object-instance-list-info-iter', api_args, + enable_tunneling=False) uuids = [] @@ -1595,9 +1602,8 @@ class Client(client_base.Client): ], } - result = self.send_request('perf-object-get-instances', - api_args, - enable_tunneling=False) + result = self.connection.send_request( + 'perf-object-get-instances', api_args, enable_tunneling=False) counter_data = [] @@ -1648,7 +1654,7 @@ class Client(client_base.Client): }, } - result = self.send_request('snapshot-get-iter', api_args) + result = self.connection.send_request('snapshot-get-iter', api_args) snapshots = [] @@ -1689,7 +1695,7 @@ class Client(client_base.Client): }, }, } - result = self.send_request('snapshot-get-iter', api_args) + result = self.connection.send_request('snapshot-get-iter', api_args) self._handle_get_snapshot_return_failure(result, snapshot_name) @@ -1764,7 +1770,7 @@ class Client(client_base.Client): if passphrase: api_args['passphrase'] = passphrase - self.send_request('cluster-peer-create', api_args) + self.connection.send_request('cluster-peer-create', api_args) def get_cluster_peers(self, remote_cluster_name=None): """Gets one or more cluster peer relationships.""" @@ -1822,7 +1828,7 @@ class Client(client_base.Client): """Deletes a cluster peer relationship.""" api_args = {'cluster-name': cluster_name} - self.send_request('cluster-peer-delete', api_args) + self.connection.send_request('cluster-peer-delete', api_args) def get_cluster_peer_policy(self): """Gets the cluster peering policy configuration.""" @@ -1830,7 +1836,7 @@ class Client(client_base.Client): if not self.features.CLUSTER_PEER_POLICY: return {} - result = self.send_request('cluster-peer-policy-get') + result = self.connection.send_request('cluster-peer-policy-get') attributes = result.get_child_by_name( 'attributes') or netapp_api.NaElement('none') @@ -1876,7 +1882,7 @@ class Client(client_base.Client): api_args['passphrase-minlength'] = six.text_type( passphrase_minimum_length) - self.send_request('cluster-peer-policy-modify', api_args) + self.connection.send_request('cluster-peer-policy-modify', api_args) def create_vserver_peer(self, vserver_name, peer_vserver_name): """Creates a Vserver peer relationship for SnapMirrors.""" @@ -1887,19 +1893,19 @@ class Client(client_base.Client): {'vserver-peer-application': 'snapmirror'}, ], } - self.send_request('vserver-peer-create', api_args) + self.connection.send_request('vserver-peer-create', api_args) def delete_vserver_peer(self, vserver_name, peer_vserver_name): """Deletes a Vserver peer relationship.""" api_args = {'vserver': vserver_name, 'peer-vserver': peer_vserver_name} - self.send_request('vserver-peer-delete', api_args) + self.connection.send_request('vserver-peer-delete', api_args) def accept_vserver_peer(self, vserver_name, peer_vserver_name): """Accepts a pending Vserver peer relationship.""" api_args = {'vserver': vserver_name, 'peer-vserver': peer_vserver_name} - self.send_request('vserver-peer-accept', api_args) + self.connection.send_request('vserver-peer-accept', api_args) def get_vserver_peers(self, vserver_name=None, peer_vserver_name=None): """Gets one or more Vserver peer relationships.""" @@ -1962,7 +1968,7 @@ class Client(client_base.Client): api_args['policy'] = policy try: - self.send_request('snapmirror-create', api_args) + self.connection.send_request('snapmirror-create', api_args) except netapp_api.NaApiError as e: if e.code != netapp_api.ERELATION_EXISTS: raise @@ -1984,7 +1990,8 @@ class Client(client_base.Client): if transfer_priority: api_args['transfer-priority'] = transfer_priority - result = self.send_request('snapmirror-initialize', api_args) + result = self.connection.send_request('snapmirror-initialize', + api_args) result_info = {} result_info['operation-id'] = result.get_child_content( @@ -2016,7 +2023,7 @@ class Client(client_base.Client): } } } - self.send_request('snapmirror-release-iter', api_args) + self.connection.send_request('snapmirror-release-iter', api_args) def quiesce_snapmirror(self, source_vserver, source_volume, destination_vserver, destination_volume): @@ -2029,7 +2036,7 @@ class Client(client_base.Client): 'destination-volume': destination_volume, 'destination-vserver': destination_vserver, } - self.send_request('snapmirror-quiesce', api_args) + self.connection.send_request('snapmirror-quiesce', api_args) def abort_snapmirror(self, source_vserver, source_volume, destination_vserver, destination_volume, @@ -2045,7 +2052,7 @@ class Client(client_base.Client): 'clear-checkpoint': 'true' if clear_checkpoint else 'false', } try: - self.send_request('snapmirror-abort', api_args) + self.connection.send_request('snapmirror-abort', api_args) except netapp_api.NaApiError as e: if e.code != netapp_api.ENOTRANSFER_IN_PROGRESS: raise @@ -2061,7 +2068,7 @@ class Client(client_base.Client): 'destination-volume': destination_volume, 'destination-vserver': destination_vserver, } - self.send_request('snapmirror-break', api_args) + self.connection.send_request('snapmirror-break', api_args) def modify_snapmirror(self, source_vserver, source_volume, destination_vserver, destination_volume, @@ -2085,7 +2092,7 @@ class Client(client_base.Client): if max_transfer_rate is not None: api_args['max-transfer-rate'] = max_transfer_rate - self.send_request('snapmirror-modify', api_args) + self.connection.send_request('snapmirror-modify', api_args) def delete_snapmirror(self, source_vserver, source_volume, destination_vserver, destination_volume): @@ -2102,7 +2109,7 @@ class Client(client_base.Client): } } } - self.send_request('snapmirror-destroy-iter', api_args) + self.connection.send_request('snapmirror-destroy-iter', api_args) def update_snapmirror(self, source_vserver, source_volume, destination_vserver, destination_volume): @@ -2116,7 +2123,7 @@ class Client(client_base.Client): 'destination-vserver': destination_vserver, } try: - self.send_request('snapmirror-update', api_args) + self.connection.send_request('snapmirror-update', api_args) except netapp_api.NaApiError as e: if (e.code != netapp_api.ETRANSFER_IN_PROGRESS and e.code != netapp_api.EANOTHER_OP_ACTIVE): @@ -2134,7 +2141,7 @@ class Client(client_base.Client): 'destination-vserver': destination_vserver, } try: - self.send_request('snapmirror-resume', api_args) + self.connection.send_request('snapmirror-resume', api_args) except netapp_api.NaApiError as e: if e.code != netapp_api.ERELATION_NOT_QUIESCED: raise @@ -2150,7 +2157,7 @@ class Client(client_base.Client): 'destination-volume': destination_volume, 'destination-vserver': destination_vserver, } - self.send_request('snapmirror-resync', api_args) + self.connection.send_request('snapmirror-resync', api_args) def _get_snapmirrors(self, source_vserver=None, source_volume=None, destination_vserver=None, destination_volume=None, diff --git a/cinder/volume/drivers/netapp/dataontap/nfs_base.py b/cinder/volume/drivers/netapp/dataontap/nfs_base.py index 7025a68c0f8..fe297924b68 100644 --- a/cinder/volume/drivers/netapp/dataontap/nfs_base.py +++ b/cinder/volume/drivers/netapp/dataontap/nfs_base.py @@ -672,7 +672,6 @@ class NetAppNfsDriver(driver.ManageableVD, else: return False - @utils.trace_method def _touch_path_to_refresh(self, path): try: # Touching parent directory forces NFS client to flush its cache. @@ -680,7 +679,6 @@ class NetAppNfsDriver(driver.ManageableVD, except processutils.ProcessExecutionError: LOG.exception("Failed to touch path %s.", path) - @utils.trace_method def _discover_file_till_timeout(self, path, timeout=75): """Checks if file size at path is equal to size.""" # Sometimes nfs takes time to discover file diff --git a/cinder/volume/drivers/netapp/dataontap/nfs_cmode.py b/cinder/volume/drivers/netapp/dataontap/nfs_cmode.py index 5b06ec54389..d38fb3a42af 100644 --- a/cinder/volume/drivers/netapp/dataontap/nfs_cmode.py +++ b/cinder/volume/drivers/netapp/dataontap/nfs_cmode.py @@ -99,7 +99,6 @@ class NetAppCmodeNfsDriver(nfs_base.NetAppNfsDriver, ssc = self.ssc_library.get_ssc() self.perf_library._update_for_failover(self.zapi_client, ssc) - @utils.trace_method def check_for_setup_error(self): """Check that the driver is working and can communicate.""" self._add_looping_tasks() @@ -404,7 +403,6 @@ class NetAppCmodeNfsDriver(nfs_base.NetAppNfsDriver, return ssc_vol_name return None - @utils.trace_method def delete_volume(self, volume): """Deletes a logical volume.""" self._delete_backing_file_for_volume(volume) @@ -443,7 +441,6 @@ class NetAppCmodeNfsDriver(nfs_base.NetAppNfsDriver, 'backend.', {'path': path_on_backend, 'file_id': file_id}) self.zapi_client.delete_file(path_on_backend) - @utils.trace_method def delete_snapshot(self, snapshot): """Deletes a snapshot.""" self._delete_backing_file_for_snapshot(snapshot) @@ -660,7 +657,6 @@ class NetAppCmodeNfsDriver(nfs_base.NetAppNfsDriver, return cloned - @utils.trace_method def unmanage(self, volume): """Removes the specified volume from Cinder management. @@ -705,7 +701,6 @@ class NetAppCmodeNfsDriver(nfs_base.NetAppNfsDriver, return flexvols - @utils.trace_method def delete_group_snapshot(self, context, group_snapshot, snapshots): """Delete files backing each snapshot in the group snapshot. @@ -718,7 +713,6 @@ class NetAppCmodeNfsDriver(nfs_base.NetAppNfsDriver, return None, None - @utils.trace_method def create_group(self, context, group): """Driver entry point for creating a generic volume group. @@ -731,7 +725,6 @@ class NetAppCmodeNfsDriver(nfs_base.NetAppNfsDriver, model_update = {'status': fields.GroupStatus.AVAILABLE} return model_update - @utils.trace_method def delete_group(self, context, group, volumes): """Driver entry point for deleting a generic volume group. @@ -753,7 +746,6 @@ class NetAppCmodeNfsDriver(nfs_base.NetAppNfsDriver, "deleted.", {'vol': volume}) return model_update, volumes_model_update - @utils.trace_method def update_group(self, context, group, add_volumes=None, remove_volumes=None): """Driver entry point for updating a generic volume group. @@ -765,7 +757,6 @@ class NetAppCmodeNfsDriver(nfs_base.NetAppNfsDriver, return None, None, None - @utils.trace_method def create_group_snapshot(self, context, group_snapshot, snapshots): """Creates a Cinder group snapshot object. @@ -825,7 +816,6 @@ class NetAppCmodeNfsDriver(nfs_base.NetAppNfsDriver, self.zapi_client.mark_snapshot_for_deletion( flexvol_name, group_snapshot['id']) - @utils.trace_method def create_group_from_src(self, context, group, volumes, group_snapshot=None, sorted_snapshots=None, source_group=None, sorted_source_vols=None): diff --git a/cinder/volume/drivers/netapp/dataontap/utils/utils.py b/cinder/volume/drivers/netapp/dataontap/utils/utils.py index dc9a6d30d97..eabae47053f 100644 --- a/cinder/volume/drivers/netapp/dataontap/utils/utils.py +++ b/cinder/volume/drivers/netapp/dataontap/utils/utils.py @@ -57,6 +57,7 @@ def get_backend_configuration(backend_name): config.append_config_values(na_opts.netapp_cluster_opts) config.append_config_values(na_opts.netapp_san_opts) config.append_config_values(na_opts.netapp_replication_opts) + config.append_config_values(na_opts.netapp_support_opts) return config @@ -72,7 +73,8 @@ def get_client_for_backend(backend_name, vserver_name=None): hostname=config.netapp_server_hostname, port=config.netapp_server_port, vserver=vserver_name or config.netapp_vserver, - trace=utils.TRACE_API) + trace=utils.TRACE_API, + api_trace_pattern=config.netapp_api_trace_pattern) return client diff --git a/cinder/volume/drivers/netapp/options.py b/cinder/volume/drivers/netapp/options.py index 0fa3360bfcb..17ef9e5c409 100644 --- a/cinder/volume/drivers/netapp/options.py +++ b/cinder/volume/drivers/netapp/options.py @@ -197,6 +197,15 @@ netapp_replication_opts = [ 'SnapMirror transfers to complete before aborting ' 'during a failover.'), ] +netapp_support_opts = [ + cfg.StrOpt('netapp_api_trace_pattern', + default='(.*)', + help=('A regular expression to limit the API tracing. This ' + 'option is honored only if enabling ``api`` tracing ' + 'with the ``trace_flags`` option. By default, ' + 'all APIs will be traced.')), +] + CONF = cfg.CONF CONF.register_opts(netapp_proxy_opts, group=conf.SHARED_CONF_GROUP) CONF.register_opts(netapp_connection_opts, group=conf.SHARED_CONF_GROUP) @@ -209,3 +218,4 @@ CONF.register_opts(netapp_eseries_opts, group=conf.SHARED_CONF_GROUP) CONF.register_opts(netapp_nfs_extra_opts, group=conf.SHARED_CONF_GROUP) CONF.register_opts(netapp_san_opts, group=conf.SHARED_CONF_GROUP) CONF.register_opts(netapp_replication_opts, group=conf.SHARED_CONF_GROUP) +CONF.register_opts(netapp_support_opts, group=conf.SHARED_CONF_GROUP) diff --git a/cinder/volume/drivers/netapp/utils.py b/cinder/volume/drivers/netapp/utils.py index 61bb5ed78d3..e99458d4c58 100644 --- a/cinder/volume/drivers/netapp/utils.py +++ b/cinder/volume/drivers/netapp/utils.py @@ -57,6 +57,7 @@ BACKEND_QOS_CONSUMERS = frozenset(['back-end', 'both']) # Secret length cannot be less than 96 bits. http://tools.ietf.org/html/rfc3723 CHAP_SECRET_LENGTH = 16 DEFAULT_CHAP_USER_NAME = 'NetApp_iSCSI_CHAP_Username' +API_TRACE_PATTERN = '(.*)' def validate_instantiation(**kwargs): @@ -127,6 +128,25 @@ def get_volume_extra_specs(volume): return extra_specs +def setup_api_trace_pattern(api_trace_pattern): + global API_TRACE_PATTERN + try: + re.compile(api_trace_pattern) + except (re.error, TypeError): + msg = _('Cannot parse the API trace pattern. %s is not a ' + 'valid python regular expression.') % api_trace_pattern + raise exception.InvalidConfigurationValue(reason=msg) + API_TRACE_PATTERN = api_trace_pattern + + +def trace_filter_func_api(all_args): + na_element = all_args.get('na_element') + if na_element is None: + return True + api_name = na_element.get_name() + return re.match(API_TRACE_PATTERN, api_name) is not None + + def resolve_hostname(hostname): """Resolves host name to IP address.""" res = socket.getaddrinfo(hostname, None)[0] diff --git a/releasenotes/notes/netapp-log-filter-f3256f55c3ac3faa.yaml b/releasenotes/notes/netapp-log-filter-f3256f55c3ac3faa.yaml new file mode 100644 index 00000000000..139ebd39aff --- /dev/null +++ b/releasenotes/notes/netapp-log-filter-f3256f55c3ac3faa.yaml @@ -0,0 +1,6 @@ +--- +features: + - The NetApp ONTAP driver supports a new configuration option + ``netapp_api_trace_pattern`` to enable filtering backend API + interactions to log. This option must be specified in the backend + section when desired and it accepts a valid python regular expression.