~ubuntu-branches/ubuntu/wily/python-oslo.vmware/wily

« back to all changes in this revision

Viewing changes to tests/test_api.py

  • Committer: Package Import Robot
  • Author(s): Thomas Goirand
  • Date: 2014-03-05 15:29:17 UTC
  • Revision ID: package-import@ubuntu.com-20140305152917-9n6zp4cktcwyr3ul
Tags: upstream-0.2
ImportĀ upstreamĀ versionĀ 0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (c) 2014 VMware, Inc.
 
2
# 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
 
 
16
"""
 
17
Unit tests for session management and API invocation classes.
 
18
"""
 
19
 
 
20
import mock
 
21
 
 
22
from oslo.vmware import api
 
23
from oslo.vmware import exceptions
 
24
from oslo.vmware import vim_util
 
25
from tests import base
 
26
 
 
27
 
 
28
class RetryDecoratorTest(base.TestCase):
 
29
    """Tests for retry decorator class."""
 
30
 
 
31
    def test_retry(self):
 
32
        result = "RESULT"
 
33
 
 
34
        @api.RetryDecorator()
 
35
        def func(*args, **kwargs):
 
36
            return result
 
37
 
 
38
        self.assertEqual(result, func())
 
39
 
 
40
        def func2(*args, **kwargs):
 
41
            return result
 
42
 
 
43
        retry = api.RetryDecorator()
 
44
        self.assertEqual(result, retry(func2)())
 
45
        self.assertTrue(retry._retry_count == 0)
 
46
 
 
47
    def test_retry_with_expected_exceptions(self):
 
48
        result = "RESULT"
 
49
        responses = [exceptions.VimSessionOverLoadException(None),
 
50
                     exceptions.VimSessionOverLoadException(None),
 
51
                     result]
 
52
 
 
53
        def func(*args, **kwargs):
 
54
            response = responses.pop(0)
 
55
            if isinstance(response, Exception):
 
56
                raise response
 
57
            return response
 
58
 
 
59
        sleep_time_incr = 1
 
60
        retry_count = 2
 
61
        retry = api.RetryDecorator(10, sleep_time_incr, 10,
 
62
                                   (exceptions.VimSessionOverLoadException,))
 
63
        self.assertEqual(result, retry(func)())
 
64
        self.assertTrue(retry._retry_count == retry_count)
 
65
        self.assertEqual(retry_count * sleep_time_incr, retry._sleep_time)
 
66
 
 
67
    def test_retry_with_max_retries(self):
 
68
        responses = [exceptions.VimSessionOverLoadException(None),
 
69
                     exceptions.VimSessionOverLoadException(None),
 
70
                     exceptions.VimSessionOverLoadException(None)]
 
71
 
 
72
        def func(*args, **kwargs):
 
73
            response = responses.pop(0)
 
74
            if isinstance(response, Exception):
 
75
                raise response
 
76
            return response
 
77
 
 
78
        retry = api.RetryDecorator(2, 0, 0,
 
79
                                   (exceptions.VimSessionOverLoadException,))
 
80
        self.assertRaises(exceptions.VimSessionOverLoadException, retry(func))
 
81
        self.assertTrue(retry._retry_count == 2)
 
82
 
 
83
    def test_retry_with_unexpected_exception(self):
 
84
 
 
85
        def func(*args, **kwargs):
 
86
            raise exceptions.VimException(None)
 
87
 
 
88
        retry = api.RetryDecorator()
 
89
        self.assertRaises(exceptions.VimException, retry(func))
 
90
        self.assertTrue(retry._retry_count == 0)
 
91
 
 
92
 
 
93
class VMwareAPISessionTest(base.TestCase):
 
94
    """Tests for VMwareAPISession."""
 
95
 
 
96
    SERVER_IP = '10.1.2.3'
 
97
    USERNAME = 'admin'
 
98
    PASSWORD = 'password'
 
99
 
 
100
    def setUp(self):
 
101
        super(VMwareAPISessionTest, self).setUp()
 
102
        patcher = mock.patch('oslo.vmware.vim.Vim')
 
103
        self.addCleanup(patcher.stop)
 
104
        self.VimMock = patcher.start()
 
105
        self.VimMock.side_effect = lambda *args, **kw: mock.Mock()
 
106
 
 
107
    def _create_api_session(self, _create_session, retry_count=10,
 
108
                            task_poll_interval=1):
 
109
        return api.VMwareAPISession(VMwareAPISessionTest.SERVER_IP,
 
110
                                    VMwareAPISessionTest.USERNAME,
 
111
                                    VMwareAPISessionTest.PASSWORD,
 
112
                                    retry_count,
 
113
                                    task_poll_interval,
 
114
                                    'https',
 
115
                                    _create_session)
 
116
 
 
117
    def test_vim(self):
 
118
        api_session = self._create_api_session(False)
 
119
        api_session.vim
 
120
        self.VimMock.assert_called_with(protocol=api_session._scheme,
 
121
                                        host=VMwareAPISessionTest.SERVER_IP,
 
122
                                        wsdl_loc=api_session._wsdl_loc)
 
123
 
 
124
    def test_create_session(self):
 
125
        session = mock.Mock()
 
126
        session.key = "12345"
 
127
        api_session = self._create_api_session(False)
 
128
        vim_obj = api_session.vim
 
129
        vim_obj.Login.return_value = session
 
130
 
 
131
        api_session._create_session()
 
132
        session_manager = vim_obj.service_content.sessionManager
 
133
        vim_obj.Login.assert_called_once_with(
 
134
            session_manager, userName=VMwareAPISessionTest.USERNAME,
 
135
            password=VMwareAPISessionTest.PASSWORD)
 
136
        self.assertFalse(vim_obj.TerminateSession.called)
 
137
        self.assertEqual(session.key, api_session._session_id)
 
138
 
 
139
    def test_create_session_with_existing_session(self):
 
140
        old_session_key = '12345'
 
141
        new_session_key = '67890'
 
142
        session = mock.Mock()
 
143
        session.key = new_session_key
 
144
        api_session = self._create_api_session(False)
 
145
        api_session._session_id = old_session_key
 
146
        vim_obj = api_session.vim
 
147
        vim_obj.Login.return_value = session
 
148
 
 
149
        api_session._create_session()
 
150
        session_manager = vim_obj.service_content.sessionManager
 
151
        vim_obj.Login.assert_called_once_with(
 
152
            session_manager, userName=VMwareAPISessionTest.USERNAME,
 
153
            password=VMwareAPISessionTest.PASSWORD)
 
154
        vim_obj.TerminateSession.assert_called_once_with(
 
155
            session_manager, sessionId=[old_session_key])
 
156
        self.assertEqual(new_session_key, api_session._session_id)
 
157
 
 
158
    def test_invoke_api(self):
 
159
        api_session = self._create_api_session(True)
 
160
        response = mock.Mock()
 
161
 
 
162
        def api(*args, **kwargs):
 
163
            return response
 
164
 
 
165
        module = mock.Mock()
 
166
        module.api = api
 
167
        ret = api_session.invoke_api(module, 'api')
 
168
        self.assertEqual(response, ret)
 
169
 
 
170
    def test_invoke_api_with_expected_exception(self):
 
171
        api_session = self._create_api_session(True)
 
172
        ret = mock.Mock()
 
173
        responses = [exceptions.VimConnectionException(None), ret]
 
174
 
 
175
        def api(*args, **kwargs):
 
176
            response = responses.pop(0)
 
177
            if isinstance(response, Exception):
 
178
                raise response
 
179
            return response
 
180
 
 
181
        module = mock.Mock()
 
182
        module.api = api
 
183
        self.assertEqual(ret, api_session.invoke_api(module, 'api'))
 
184
 
 
185
    def test_invoke_api_with_vim_fault_exception(self):
 
186
        api_session = self._create_api_session(True)
 
187
 
 
188
        def api(*args, **kwargs):
 
189
            raise exceptions.VimFaultException([], None)
 
190
 
 
191
        module = mock.Mock()
 
192
        module.api = api
 
193
        self.assertRaises(exceptions.VimFaultException,
 
194
                          lambda: api_session.invoke_api(module, 'api'))
 
195
 
 
196
    def test_invoke_api_with_empty_response(self):
 
197
        api_session = self._create_api_session(True)
 
198
        vim_obj = api_session.vim
 
199
        vim_obj.SessionIsActive.return_value = True
 
200
 
 
201
        def api(*args, **kwargs):
 
202
            raise exceptions.VimFaultException(
 
203
                [exceptions.NOT_AUTHENTICATED], None)
 
204
 
 
205
        module = mock.Mock()
 
206
        module.api = api
 
207
        ret = api_session.invoke_api(module, 'api')
 
208
        self.assertEqual([], ret)
 
209
        vim_obj.SessionIsActive.assert_called_once_with(
 
210
            vim_obj.service_content.sessionManager,
 
211
            sessionID=api_session._session_id,
 
212
            userName=api_session._session_username)
 
213
 
 
214
    def test_wait_for_task(self):
 
215
        api_session = self._create_api_session(True)
 
216
        task_info_list = [('queued', 0), ('running', 40), ('success', 100)]
 
217
        task_info_list_size = len(task_info_list)
 
218
 
 
219
        def invoke_api_side_effect(module, method, *args, **kwargs):
 
220
            (state, progress) = task_info_list.pop(0)
 
221
            task_info = mock.Mock()
 
222
            task_info.progress = progress
 
223
            task_info.state = state
 
224
            return task_info
 
225
 
 
226
        api_session.invoke_api = mock.Mock(side_effect=invoke_api_side_effect)
 
227
        task = mock.Mock()
 
228
        ret = api_session.wait_for_task(task)
 
229
        self.assertEqual('success', ret.state)
 
230
        self.assertEqual(100, ret.progress)
 
231
        api_session.invoke_api.assert_called_with(vim_util,
 
232
                                                  'get_object_property',
 
233
                                                  api_session.vim, task,
 
234
                                                  'info')
 
235
        self.assertEqual(task_info_list_size,
 
236
                         api_session.invoke_api.call_count)
 
237
 
 
238
    def test_wait_for_task_with_error_state(self):
 
239
        api_session = self._create_api_session(True)
 
240
        task_info_list = [('queued', 0), ('running', 40), ('error', -1)]
 
241
        task_info_list_size = len(task_info_list)
 
242
 
 
243
        def invoke_api_side_effect(module, method, *args, **kwargs):
 
244
            (state, progress) = task_info_list.pop(0)
 
245
            task_info = mock.Mock()
 
246
            task_info.progress = progress
 
247
            task_info.state = state
 
248
            return task_info
 
249
 
 
250
        api_session.invoke_api = mock.Mock(side_effect=invoke_api_side_effect)
 
251
        task = mock.Mock()
 
252
        self.assertRaises(exceptions.VMwareDriverException,
 
253
                          lambda: api_session.wait_for_task(task))
 
254
        api_session.invoke_api.assert_called_with(vim_util,
 
255
                                                  'get_object_property',
 
256
                                                  api_session.vim, task,
 
257
                                                  'info')
 
258
        self.assertEqual(task_info_list_size,
 
259
                         api_session.invoke_api.call_count)
 
260
 
 
261
    def test_wait_for_task_with_invoke_api_exception(self):
 
262
        api_session = self._create_api_session(True)
 
263
        api_session.invoke_api = mock.Mock(
 
264
            side_effect=exceptions.VimException(None))
 
265
        task = mock.Mock()
 
266
        self.assertRaises(exceptions.VimException,
 
267
                          lambda: api_session.wait_for_task(task))
 
268
        api_session.invoke_api.assert_called_once_with(vim_util,
 
269
                                                       'get_object_property',
 
270
                                                       api_session.vim, task,
 
271
                                                       'info')
 
272
 
 
273
    def test_wait_for_lease_ready(self):
 
274
        api_session = self._create_api_session(True)
 
275
        lease_states = ['initializing', 'ready']
 
276
        num_states = len(lease_states)
 
277
 
 
278
        def invoke_api_side_effect(module, method, *args, **kwargs):
 
279
            return lease_states.pop(0)
 
280
 
 
281
        api_session.invoke_api = mock.Mock(side_effect=invoke_api_side_effect)
 
282
        lease = mock.Mock()
 
283
        api_session.wait_for_lease_ready(lease)
 
284
        api_session.invoke_api.assert_called_with(vim_util,
 
285
                                                  'get_object_property',
 
286
                                                  api_session.vim, lease,
 
287
                                                  'state')
 
288
        self.assertEqual(num_states, api_session.invoke_api.call_count)
 
289
 
 
290
    def test_wait_for_lease_ready_with_error_state(self):
 
291
        api_session = self._create_api_session(True)
 
292
        responses = ['initializing', 'error', 'error_msg']
 
293
 
 
294
        def invoke_api_side_effect(module, method, *args, **kwargs):
 
295
            return responses.pop(0)
 
296
 
 
297
        api_session.invoke_api = mock.Mock(side_effect=invoke_api_side_effect)
 
298
        lease = mock.Mock()
 
299
        self.assertRaises(exceptions.VimException,
 
300
                          lambda: api_session.wait_for_lease_ready(lease))
 
301
        exp_calls = [mock.call(vim_util, 'get_object_property',
 
302
                               api_session.vim, lease, 'state')] * 2
 
303
        exp_calls.append(mock.call(vim_util, 'get_object_property',
 
304
                                   api_session.vim, lease, 'error'))
 
305
        self.assertEqual(exp_calls, api_session.invoke_api.call_args_list)
 
306
 
 
307
    def test_wait_for_lease_ready_with_unknown_state(self):
 
308
        api_session = self._create_api_session(True)
 
309
 
 
310
        def invoke_api_side_effect(module, method, *args, **kwargs):
 
311
            return 'unknown'
 
312
 
 
313
        api_session.invoke_api = mock.Mock(side_effect=invoke_api_side_effect)
 
314
        lease = mock.Mock()
 
315
        self.assertRaises(exceptions.VimException,
 
316
                          lambda: api_session.wait_for_lease_ready(lease))
 
317
        api_session.invoke_api.assert_called_once_with(vim_util,
 
318
                                                       'get_object_property',
 
319
                                                       api_session.vim,
 
320
                                                       lease, 'state')
 
321
 
 
322
    def test_wait_for_lease_ready_with_invoke_api_exception(self):
 
323
        api_session = self._create_api_session(True)
 
324
        api_session.invoke_api = mock.Mock(
 
325
            side_effect=exceptions.VimException(None))
 
326
        lease = mock.Mock()
 
327
        self.assertRaises(exceptions.VimException,
 
328
                          lambda: api_session.wait_for_lease_ready(lease))
 
329
        api_session.invoke_api.assert_called_once_with(
 
330
            vim_util, 'get_object_property', api_session.vim, lease,
 
331
            'state')
 
332
 
 
333
    def _poll_task_well_known_exceptions(self, fault,
 
334
                                         expected_exception):
 
335
        api_session = self._create_api_session(False)
 
336
 
 
337
        def fake_invoke_api(self, module, method, *args, **kwargs):
 
338
            task_info = mock.Mock()
 
339
            task_info.progress = -1
 
340
            task_info.state = 'error'
 
341
            error = mock.Mock()
 
342
            error.localizedMessage = "Error message"
 
343
            error_fault = mock.Mock()
 
344
            error_fault.__class__.__name__ = fault
 
345
            error.fault = error_fault
 
346
            task_info.error = error
 
347
            return task_info
 
348
 
 
349
        with (
 
350
            mock.patch.object(api_session, 'invoke_api', fake_invoke_api)
 
351
        ):
 
352
            self.assertRaises(expected_exception,
 
353
                              api_session._poll_task, 'fake-task')
 
354
 
 
355
    def test_poll_task_well_known_exceptions(self):
 
356
        for k, v in exceptions._fault_classes_registry.iteritems():
 
357
            self._poll_task_well_known_exceptions(k, v)
 
358
 
 
359
    def test_poll_task_unknown_exception(self):
 
360
        _unknown_exceptions = {
 
361
            'NoDiskSpace': exceptions.VMwareDriverException,
 
362
            'RuntimeFault': exceptions.VMwareDriverException
 
363
        }
 
364
 
 
365
        for k, v in _unknown_exceptions.iteritems():
 
366
            self._poll_task_well_known_exceptions(k, v)