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

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. 

15 

16from unittest import mock 

17 

18import ddt 

19from oslo_log import log 

20 

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 

25 

26 

27@ddt.ddt 

28class NetAppBaseClientTestCase(test.TestCase): 

29 

30 def setUp(self): 

31 super(NetAppBaseClientTestCase, self).setUp() 

32 

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)) 

41 

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() 

47 

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 

51 

52 major, minor = self.client.get_ontapi_version(cached=False) 

53 

54 self.assertEqual('1', major) 

55 self.assertEqual('19', minor) 

56 

57 def test_get_ontapi_version_cached(self): 

58 

59 self.connection.get_api_version.return_value = (1, 20) 

60 

61 major, minor = self.client.get_ontapi_version() 

62 

63 self.assertEqual(1, self.connection.get_api_version.call_count) 

64 self.assertEqual(1, major) 

65 self.assertEqual(20, minor) 

66 

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 

71 

72 result = self.client.get_system_version(cached=False) 

73 

74 self.assertEqual(fake.VERSION, result['version']) 

75 self.assertEqual((8, 2, 1), result['version-tuple']) 

76 

77 def test_get_system_version_cached(self): 

78 

79 self.connection.get_system_version.return_value = { 

80 'version': fake.VERSION, 

81 'version-tuple': (8, 2, 1) 

82 } 

83 

84 result = self.client.get_system_version() 

85 

86 self.assertEqual(fake.VERSION, result['version']) 

87 self.assertEqual((8, 2, 1), result['version-tuple']) 

88 

89 def test_init_features(self): 

90 

91 self.client._init_features() 

92 

93 self.assertSetEqual(set(), self.client.features.defined_features) 

94 

95 @ddt.data('tag_name', '{http://www.netapp.com/filer/admin}tag_name') 

96 def test_strip_xml_namespace(self, element): 

97 

98 result = self.client._strip_xml_namespace(element) 

99 

100 self.assertEqual('tag_name', result) 

101 

102 @ddt.data(True, False) 

103 def test_send_request(self, use_zapi): 

104 

105 element = netapp_api.NaElement('fake-api') 

106 

107 self.client.send_request('fake-api', use_zapi=use_zapi) 

108 

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']) 

119 

120 def test_send_request_no_tunneling(self): 

121 

122 element = netapp_api.NaElement('fake-api') 

123 

124 self.client.send_request('fake-api', enable_tunneling=False) 

125 

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']) 

132 

133 @ddt.data(True, False) 

134 def test_send_request_with_args(self, use_zapi): 

135 

136 element = netapp_api.NaElement('fake-api') 

137 api_args = {'arg1': 'data1', 'arg2': 'data2'} 

138 

139 self.client.send_request('fake-api', api_args=api_args, 

140 use_zapi=use_zapi) 

141 

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']) 

155 

156 def test_get_licenses(self): 

157 

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)) 

161 

162 response = self.client.get_licenses() 

163 

164 self.assertSequenceEqual(fake.LICENSES, response) 

165 

166 def test_get_licenses_api_error(self): 

167 

168 self.mock_object(self.client, 

169 'send_request', 

170 mock.Mock(side_effect=netapp_api.NaApiError)) 

171 

172 self.assertRaises(netapp_api.NaApiError, self.client.get_licenses) 

173 self.assertEqual(1, client_base.LOG.exception.call_count) 

174 

175 def test_send_ems_log_message(self): 

176 

177 self.assertRaises(NotImplementedError, 

178 self.client.send_ems_log_message, 

179 {}) 

180 

181 

182@ddt.ddt 

183class FeaturesTestCase(test.TestCase): 

184 

185 def setUp(self): 

186 super(FeaturesTestCase, self).setUp() 

187 self.features = client_base.Features() 

188 

189 def test_init(self): 

190 self.assertSetEqual(set(), self.features.defined_features) 

191 

192 def test_add_feature_default(self): 

193 self.features.add_feature('FEATURE_1') 

194 

195 self.assertTrue(self.features.FEATURE_1) 

196 self.assertIn('FEATURE_1', self.features.defined_features) 

197 

198 @ddt.data(True, False) 

199 def test_add_feature(self, value): 

200 self.features.add_feature('FEATURE_2', value) 

201 

202 self.assertEqual(value, self.features.FEATURE_2) 

203 self.assertIn('FEATURE_2', self.features.defined_features) 

204 

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) 

212 

213 def test_get_attr_missing(self): 

214 self.assertRaises(AttributeError, getattr, self.features, 'FEATURE_4')