Coverage for manila/tests/share/drivers/netapp/dataontap/client/test_client_base.py: 100%
103 statements
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
1# Copyright (c) 2014 Alex Meade. All rights reserved.
2# Copyright (c) 2014 Clinton Knight. All rights reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
16from unittest import mock
18import ddt
19from oslo_log import log
21from manila.share.drivers.netapp.dataontap.client import api as netapp_api
22from manila.share.drivers.netapp.dataontap.client import client_base
23from manila import test
24from manila.tests.share.drivers.netapp.dataontap.client import fakes as fake
27@ddt.ddt
28class NetAppBaseClientTestCase(test.TestCase):
30 def setUp(self):
31 super(NetAppBaseClientTestCase, self).setUp()
33 # Mock loggers as themselves to allow logger arg validation
34 mock_logger = log.getLogger('mock_logger')
35 self.mock_object(client_base.LOG,
36 'error',
37 mock.Mock(side_effect=mock_logger.error))
38 self.mock_object(client_base.LOG,
39 'exception',
40 mock.Mock(side_effect=mock_logger.error))
42 self.client = client_base.NetAppBaseClient(**fake.CONNECTION_INFO)
43 self.client.connection = mock.MagicMock()
44 self.connection = self.client.connection
45 self.connection.zapi_client = mock.Mock()
46 self.connection.rest_client = mock.Mock()
48 def test_get_ontapi_version(self):
49 version_response = netapp_api.NaElement(fake.ONTAPI_VERSION_RESPONSE)
50 self.connection.invoke_successfully.return_value = version_response
52 major, minor = self.client.get_ontapi_version(cached=False)
54 self.assertEqual('1', major)
55 self.assertEqual('19', minor)
57 def test_get_ontapi_version_cached(self):
59 self.connection.get_api_version.return_value = (1, 20)
61 major, minor = self.client.get_ontapi_version()
63 self.assertEqual(1, self.connection.get_api_version.call_count)
64 self.assertEqual(1, major)
65 self.assertEqual(20, minor)
67 def test_get_system_version(self):
68 version_response = netapp_api.NaElement(
69 fake.SYSTEM_GET_VERSION_RESPONSE)
70 self.connection.invoke_successfully.return_value = version_response
72 result = self.client.get_system_version(cached=False)
74 self.assertEqual(fake.VERSION, result['version'])
75 self.assertEqual((8, 2, 1), result['version-tuple'])
77 def test_get_system_version_cached(self):
79 self.connection.get_system_version.return_value = {
80 'version': fake.VERSION,
81 'version-tuple': (8, 2, 1)
82 }
84 result = self.client.get_system_version()
86 self.assertEqual(fake.VERSION, result['version'])
87 self.assertEqual((8, 2, 1), result['version-tuple'])
89 def test_init_features(self):
91 self.client._init_features()
93 self.assertSetEqual(set(), self.client.features.defined_features)
95 @ddt.data('tag_name', '{http://www.netapp.com/filer/admin}tag_name')
96 def test_strip_xml_namespace(self, element):
98 result = self.client._strip_xml_namespace(element)
100 self.assertEqual('tag_name', result)
102 @ddt.data(True, False)
103 def test_send_request(self, use_zapi):
105 element = netapp_api.NaElement('fake-api')
107 self.client.send_request('fake-api', use_zapi=use_zapi)
109 self.assertEqual(
110 element.to_string(),
111 self.connection.invoke_successfully.call_args[0][0].to_string())
112 self.assertTrue(
113 self.connection.invoke_successfully.call_args[1][
114 'enable_tunneling'])
115 self.assertEqual(
116 use_zapi,
117 self.connection.invoke_successfully.call_args[1][
118 'use_zapi'])
120 def test_send_request_no_tunneling(self):
122 element = netapp_api.NaElement('fake-api')
124 self.client.send_request('fake-api', enable_tunneling=False)
126 self.assertEqual(
127 element.to_string(),
128 self.connection.invoke_successfully.call_args[0][0].to_string())
129 self.assertFalse(
130 self.connection.invoke_successfully.call_args[1][
131 'enable_tunneling'])
133 @ddt.data(True, False)
134 def test_send_request_with_args(self, use_zapi):
136 element = netapp_api.NaElement('fake-api')
137 api_args = {'arg1': 'data1', 'arg2': 'data2'}
139 self.client.send_request('fake-api', api_args=api_args,
140 use_zapi=use_zapi)
142 self.assertEqual(
143 element.to_string(),
144 self.connection.invoke_successfully.call_args[0][0].to_string())
145 self.assertEqual(
146 api_args, self.connection.invoke_successfully.call_args[1][
147 'api_args'])
148 self.assertTrue(
149 self.connection.invoke_successfully.call_args[1][
150 'enable_tunneling'])
151 self.assertEqual(
152 use_zapi,
153 self.connection.invoke_successfully.call_args[1][
154 'use_zapi'])
156 def test_get_licenses(self):
158 api_response = netapp_api.NaElement(fake.LICENSE_V2_LIST_INFO_RESPONSE)
159 self.mock_object(
160 self.client, 'send_request', mock.Mock(return_value=api_response))
162 response = self.client.get_licenses()
164 self.assertSequenceEqual(fake.LICENSES, response)
166 def test_get_licenses_api_error(self):
168 self.mock_object(self.client,
169 'send_request',
170 mock.Mock(side_effect=netapp_api.NaApiError))
172 self.assertRaises(netapp_api.NaApiError, self.client.get_licenses)
173 self.assertEqual(1, client_base.LOG.exception.call_count)
175 def test_send_ems_log_message(self):
177 self.assertRaises(NotImplementedError,
178 self.client.send_ems_log_message,
179 {})
182@ddt.ddt
183class FeaturesTestCase(test.TestCase):
185 def setUp(self):
186 super(FeaturesTestCase, self).setUp()
187 self.features = client_base.Features()
189 def test_init(self):
190 self.assertSetEqual(set(), self.features.defined_features)
192 def test_add_feature_default(self):
193 self.features.add_feature('FEATURE_1')
195 self.assertTrue(self.features.FEATURE_1)
196 self.assertIn('FEATURE_1', self.features.defined_features)
198 @ddt.data(True, False)
199 def test_add_feature(self, value):
200 self.features.add_feature('FEATURE_2', value)
202 self.assertEqual(value, self.features.FEATURE_2)
203 self.assertIn('FEATURE_2', self.features.defined_features)
205 @ddt.data('True', 'False', 0, 1, 1.0, None, [], {}, (True,))
206 def test_add_feature_type_error(self, value):
207 self.assertRaises(TypeError,
208 self.features.add_feature,
209 'FEATURE_3',
210 value)
211 self.assertNotIn('FEATURE_3', self.features.defined_features)
213 def test_get_attr_missing(self):
214 self.assertRaises(AttributeError, getattr, self.features, 'FEATURE_4')