From bb0aac560dbc5a2859f02824d36bf76d17039358 Mon Sep 17 00:00:00 2001 From: Rodrigo Barbieri Date: Fri, 29 Jun 2018 10:06:37 -0300 Subject: [PATCH] [NetApp ONTAP] Add filtering to API trace logging API Tracing is valuable when diagnosing problems or unexpected behaviors with the ONTAP Cinder drivers. However, turning it on may spam logs and make it rather harder to trace through specific API calls. Added an API trace pattern filter in order to filter out undesired API calls from the DEBUG log. Change-Id: Ic0563848205a941cf8e779eee42e24ecdaf847dd --- cinder/opts.py | 1 + .../netapp/dataontap/client/test_api.py | 1 - .../dataontap/client/test_client_base.py | 26 +- .../dataontap/client/test_client_cmode.py | 246 ++++++++++-------- .../netapp/dataontap/test_block_cmode.py | 1 + .../netapp/dataontap/test_nfs_cmode.py | 1 + .../drivers/netapp/dataontap/utils/fakes.py | 1 + .../netapp/dataontap/utils/test_utils.py | 7 +- .../unit/volume/drivers/netapp/test_utils.py | 19 ++ .../drivers/netapp/dataontap/client/api.py | 15 +- .../netapp/dataontap/client/client_base.py | 25 +- .../netapp/dataontap/client/client_cmode.py | 115 ++++---- .../drivers/netapp/dataontap/nfs_base.py | 2 - .../drivers/netapp/dataontap/nfs_cmode.py | 10 - .../drivers/netapp/dataontap/utils/utils.py | 4 +- cinder/volume/drivers/netapp/options.py | 10 + cinder/volume/drivers/netapp/utils.py | 20 ++ .../netapp-log-filter-f3256f55c3ac3faa.yaml | 6 + 18 files changed, 297 insertions(+), 213 deletions(-) create mode 100644 releasenotes/notes/netapp-log-filter-f3256f55c3ac3faa.yaml 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.