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

« back to all changes in this revision

Viewing changes to oslo_vmware/tests/test_image_transfer.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2015-02-09 11:35:16 UTC
  • mfrom: (1.1.7)
  • Revision ID: package-import@ubuntu.com-20150209113516-ybu8v73zi8amrx4b
Tags: 0.9.0-0ubuntu1
* New upstream release.
* Transition new namespace.
* debian/patches/use-toggle-lazyfixture.patch: Dropped
* debian/control: Add python-oslo.concurrency.

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 functions and classes for image transfer.
 
18
"""
 
19
 
 
20
import math
 
21
 
 
22
from eventlet import greenthread
 
23
from eventlet import timeout
 
24
import mock
 
25
 
 
26
from oslo_vmware import exceptions
 
27
from oslo_vmware import image_transfer
 
28
from oslo_vmware import rw_handles
 
29
from oslo_vmware.tests import base
 
30
 
 
31
 
 
32
class BlockingQueueTest(base.TestCase):
 
33
    """Tests for BlockingQueue."""
 
34
 
 
35
    def test_read(self):
 
36
        max_size = 10
 
37
        chunk_size = 10
 
38
        max_transfer_size = 30
 
39
        queue = image_transfer.BlockingQueue(max_size, max_transfer_size)
 
40
 
 
41
        def get_side_effect():
 
42
            return [1] * chunk_size
 
43
 
 
44
        queue.get = mock.Mock(side_effect=get_side_effect)
 
45
        while True:
 
46
            data_item = queue.read(chunk_size)
 
47
            if not data_item:
 
48
                break
 
49
 
 
50
        self.assertEqual(max_transfer_size, queue._transferred)
 
51
        exp_calls = [mock.call()] * int(math.ceil(float(max_transfer_size) /
 
52
                                                  chunk_size))
 
53
        self.assertEqual(exp_calls, queue.get.call_args_list)
 
54
 
 
55
    def test_write(self):
 
56
        queue = image_transfer.BlockingQueue(10, 30)
 
57
        queue.put = mock.Mock()
 
58
        write_count = 10
 
59
        for _ in range(0, write_count):
 
60
            queue.write([1])
 
61
        exp_calls = [mock.call([1])] * write_count
 
62
        self.assertEqual(exp_calls, queue.put.call_args_list)
 
63
 
 
64
    def test_seek(self):
 
65
        queue = image_transfer.BlockingQueue(10, 30)
 
66
        self.assertRaises(IOError, queue.seek, 5)
 
67
 
 
68
    def test_tell(self):
 
69
        queue = image_transfer.BlockingQueue(10, 30)
 
70
        self.assertEqual(0, queue.tell())
 
71
        queue.get = mock.Mock(return_value=[1] * 10)
 
72
        queue.read(10)
 
73
        self.assertEqual(10, queue.tell())
 
74
 
 
75
 
 
76
class ImageWriterTest(base.TestCase):
 
77
    """Tests for ImageWriter class."""
 
78
 
 
79
    def _create_image_writer(self):
 
80
        self.image_service = mock.Mock()
 
81
        self.context = mock.Mock()
 
82
        self.input_file = mock.Mock()
 
83
        self.image_id = mock.Mock()
 
84
        return image_transfer.ImageWriter(self.context, self.input_file,
 
85
                                          self.image_service, self.image_id)
 
86
 
 
87
    @mock.patch.object(greenthread, 'sleep')
 
88
    def test_start(self, mock_sleep):
 
89
        writer = self._create_image_writer()
 
90
        status_list = ['queued', 'saving', 'active']
 
91
 
 
92
        def image_service_show_side_effect(context, image_id):
 
93
            status = status_list.pop(0)
 
94
            return {'status': status}
 
95
 
 
96
        self.image_service.show.side_effect = image_service_show_side_effect
 
97
        exp_calls = [mock.call(self.context, self.image_id)] * len(status_list)
 
98
        writer.start()
 
99
        self.assertTrue(writer.wait())
 
100
        self.image_service.update.assert_called_once_with(self.context,
 
101
                                                          self.image_id, {},
 
102
                                                          data=self.input_file)
 
103
        self.assertEqual(exp_calls, self.image_service.show.call_args_list)
 
104
 
 
105
    def test_start_with_killed_status(self):
 
106
        writer = self._create_image_writer()
 
107
 
 
108
        def image_service_show_side_effect(_context, _image_id):
 
109
            return {'status': 'killed'}
 
110
 
 
111
        self.image_service.show.side_effect = image_service_show_side_effect
 
112
        writer.start()
 
113
        self.assertRaises(exceptions.ImageTransferException,
 
114
                          writer.wait)
 
115
        self.image_service.update.assert_called_once_with(self.context,
 
116
                                                          self.image_id, {},
 
117
                                                          data=self.input_file)
 
118
        self.image_service.show.assert_called_once_with(self.context,
 
119
                                                        self.image_id)
 
120
 
 
121
    def test_start_with_unknown_status(self):
 
122
        writer = self._create_image_writer()
 
123
 
 
124
        def image_service_show_side_effect(_context, _image_id):
 
125
            return {'status': 'unknown'}
 
126
 
 
127
        self.image_service.show.side_effect = image_service_show_side_effect
 
128
        writer.start()
 
129
        self.assertRaises(exceptions.ImageTransferException,
 
130
                          writer.wait)
 
131
        self.image_service.update.assert_called_once_with(self.context,
 
132
                                                          self.image_id, {},
 
133
                                                          data=self.input_file)
 
134
        self.image_service.show.assert_called_once_with(self.context,
 
135
                                                        self.image_id)
 
136
 
 
137
    def test_start_with_image_service_show_exception(self):
 
138
        writer = self._create_image_writer()
 
139
        self.image_service.show.side_effect = RuntimeError()
 
140
        writer.start()
 
141
        self.assertRaises(exceptions.ImageTransferException, writer.wait)
 
142
        self.image_service.update.assert_called_once_with(self.context,
 
143
                                                          self.image_id, {},
 
144
                                                          data=self.input_file)
 
145
        self.image_service.show.assert_called_once_with(self.context,
 
146
                                                        self.image_id)
 
147
 
 
148
 
 
149
class FileReadWriteTaskTest(base.TestCase):
 
150
    """Tests for FileReadWriteTask class."""
 
151
 
 
152
    def test_start(self):
 
153
        data_items = [[1] * 10, [1] * 20, [1] * 5, []]
 
154
 
 
155
        def input_file_read_side_effect(arg):
 
156
            self.assertEqual(arg, rw_handles.READ_CHUNKSIZE)
 
157
            data = data_items[input_file_read_side_effect.i]
 
158
            input_file_read_side_effect.i += 1
 
159
            return data
 
160
 
 
161
        input_file_read_side_effect.i = 0
 
162
        input_file = mock.Mock()
 
163
        input_file.read.side_effect = input_file_read_side_effect
 
164
        output_file = mock.Mock()
 
165
        rw_task = image_transfer.FileReadWriteTask(input_file, output_file)
 
166
        rw_task.start()
 
167
        self.assertTrue(rw_task.wait())
 
168
        self.assertEqual(len(data_items), input_file.read.call_count)
 
169
 
 
170
        exp_calls = []
 
171
        for i in range(0, len(data_items)):
 
172
            exp_calls.append(mock.call(data_items[i]))
 
173
        self.assertEqual(exp_calls, output_file.write.call_args_list)
 
174
 
 
175
        self.assertEqual(len(data_items),
 
176
                         input_file.update_progress.call_count)
 
177
        self.assertEqual(len(data_items),
 
178
                         output_file.update_progress.call_count)
 
179
 
 
180
    def test_start_with_read_exception(self):
 
181
        input_file = mock.Mock()
 
182
        input_file.read.side_effect = RuntimeError()
 
183
        output_file = mock.Mock()
 
184
        rw_task = image_transfer.FileReadWriteTask(input_file, output_file)
 
185
        rw_task.start()
 
186
        self.assertRaises(exceptions.ImageTransferException, rw_task.wait)
 
187
        input_file.read.assert_called_once_with(rw_handles.READ_CHUNKSIZE)
 
188
 
 
189
 
 
190
class ImageTransferUtilityTest(base.TestCase):
 
191
    """Tests for image_transfer utility methods."""
 
192
 
 
193
    @mock.patch.object(timeout, 'Timeout')
 
194
    @mock.patch.object(image_transfer, 'ImageWriter')
 
195
    @mock.patch.object(image_transfer, 'FileReadWriteTask')
 
196
    @mock.patch.object(image_transfer, 'BlockingQueue')
 
197
    def test_start_transfer(self, fake_BlockingQueue, fake_FileReadWriteTask,
 
198
                            fake_ImageWriter, fake_Timeout):
 
199
 
 
200
        context = mock.Mock()
 
201
        read_file_handle = mock.Mock()
 
202
        read_file_handle.close = mock.Mock()
 
203
        image_service = mock.Mock()
 
204
        image_id = mock.Mock()
 
205
        blocking_queue = mock.Mock()
 
206
 
 
207
        write_file_handle1 = mock.Mock()
 
208
        write_file_handle1.close = mock.Mock()
 
209
        write_file_handle2 = None
 
210
        write_file_handles = [write_file_handle1, write_file_handle2]
 
211
 
 
212
        timeout_secs = 10
 
213
        blocking_queue_size = 10
 
214
        image_meta = {}
 
215
        max_data_size = 30
 
216
 
 
217
        fake_BlockingQueue.return_value = blocking_queue
 
218
        fake_timer = mock.Mock()
 
219
        fake_timer.cancel = mock.Mock()
 
220
        fake_Timeout.return_value = fake_timer
 
221
 
 
222
        for write_file_handle in write_file_handles:
 
223
            image_transfer._start_transfer(context,
 
224
                                           timeout_secs,
 
225
                                           read_file_handle,
 
226
                                           max_data_size,
 
227
                                           write_file_handle=write_file_handle,
 
228
                                           image_service=image_service,
 
229
                                           image_id=image_id,
 
230
                                           image_meta=image_meta)
 
231
 
 
232
        exp_calls = [mock.call(blocking_queue_size,
 
233
                               max_data_size)] * len(write_file_handles)
 
234
        self.assertEqual(exp_calls,
 
235
                         fake_BlockingQueue.call_args_list)
 
236
 
 
237
        exp_calls2 = [mock.call(read_file_handle, blocking_queue),
 
238
                      mock.call(blocking_queue, write_file_handle1),
 
239
                      mock.call(read_file_handle, blocking_queue)]
 
240
        self.assertEqual(exp_calls2,
 
241
                         fake_FileReadWriteTask.call_args_list)
 
242
 
 
243
        exp_calls3 = mock.call(context, blocking_queue, image_service,
 
244
                               image_id, image_meta)
 
245
        self.assertEqual(exp_calls3,
 
246
                         fake_ImageWriter.call_args)
 
247
 
 
248
        exp_calls4 = [mock.call(timeout_secs)] * len(write_file_handles)
 
249
        self.assertEqual(exp_calls4,
 
250
                         fake_Timeout.call_args_list)
 
251
 
 
252
        self.assertEqual(len(write_file_handles),
 
253
                         fake_timer.cancel.call_count)
 
254
 
 
255
        self.assertEqual(len(write_file_handles),
 
256
                         read_file_handle.close.call_count)
 
257
 
 
258
        write_file_handle1.close.assert_called_once()
 
259
 
 
260
    @mock.patch.object(image_transfer, 'FileReadWriteTask')
 
261
    @mock.patch.object(image_transfer, 'BlockingQueue')
 
262
    def test_start_transfer_with_no_image_destination(self, fake_BlockingQueue,
 
263
                                                      fake_FileReadWriteTask):
 
264
 
 
265
        context = mock.Mock()
 
266
        read_file_handle = mock.Mock()
 
267
        write_file_handle = None
 
268
        image_service = None
 
269
        image_id = None
 
270
        timeout_secs = 10
 
271
        image_meta = {}
 
272
        blocking_queue_size = 10
 
273
        max_data_size = 30
 
274
        blocking_queue = mock.Mock()
 
275
 
 
276
        fake_BlockingQueue.return_value = blocking_queue
 
277
 
 
278
        self.assertRaises(ValueError,
 
279
                          image_transfer._start_transfer,
 
280
                          context,
 
281
                          timeout_secs,
 
282
                          read_file_handle,
 
283
                          max_data_size,
 
284
                          write_file_handle=write_file_handle,
 
285
                          image_service=image_service,
 
286
                          image_id=image_id,
 
287
                          image_meta=image_meta)
 
288
 
 
289
        fake_BlockingQueue.assert_called_once_with(blocking_queue_size,
 
290
                                                   max_data_size)
 
291
 
 
292
        fake_FileReadWriteTask.assert_called_once_with(read_file_handle,
 
293
                                                       blocking_queue)
 
294
 
 
295
    @mock.patch('oslo_vmware.rw_handles.FileWriteHandle')
 
296
    @mock.patch('oslo_vmware.rw_handles.ImageReadHandle')
 
297
    @mock.patch.object(image_transfer, '_start_transfer')
 
298
    def test_download_flat_image(
 
299
            self,
 
300
            fake_transfer,
 
301
            fake_rw_handles_ImageReadHandle,
 
302
            fake_rw_handles_FileWriteHandle):
 
303
 
 
304
        context = mock.Mock()
 
305
        image_id = mock.Mock()
 
306
        image_service = mock.Mock()
 
307
        image_service.download = mock.Mock()
 
308
        image_service.download.return_value = 'fake_iter'
 
309
 
 
310
        fake_ImageReadHandle = 'fake_ImageReadHandle'
 
311
        fake_FileWriteHandle = 'fake_FileWriteHandle'
 
312
        cookies = []
 
313
        timeout_secs = 10
 
314
        image_size = 1000
 
315
        host = '127.0.0.1'
 
316
        port = 443
 
317
        dc_path = 'dc1'
 
318
        ds_name = 'ds1'
 
319
        file_path = '/fake_path'
 
320
 
 
321
        fake_rw_handles_ImageReadHandle.return_value = fake_ImageReadHandle
 
322
        fake_rw_handles_FileWriteHandle.return_value = fake_FileWriteHandle
 
323
 
 
324
        image_transfer.download_flat_image(
 
325
            context,
 
326
            timeout_secs,
 
327
            image_service,
 
328
            image_id,
 
329
            image_size=image_size,
 
330
            host=host,
 
331
            port=port,
 
332
            data_center_name=dc_path,
 
333
            datastore_name=ds_name,
 
334
            cookies=cookies,
 
335
            file_path=file_path)
 
336
 
 
337
        image_service.download.assert_called_once_with(context, image_id)
 
338
 
 
339
        fake_rw_handles_ImageReadHandle.assert_called_once_with('fake_iter')
 
340
 
 
341
        fake_rw_handles_FileWriteHandle.assert_called_once_with(
 
342
            host,
 
343
            port,
 
344
            dc_path,
 
345
            ds_name,
 
346
            cookies,
 
347
            file_path,
 
348
            image_size,
 
349
            cacerts=None)
 
350
 
 
351
        fake_transfer.assert_called_once_with(
 
352
            context,
 
353
            timeout_secs,
 
354
            fake_ImageReadHandle,
 
355
            image_size,
 
356
            write_file_handle=fake_FileWriteHandle)
 
357
 
 
358
    @mock.patch('oslo_vmware.rw_handles.VmdkWriteHandle')
 
359
    @mock.patch.object(image_transfer, '_start_transfer')
 
360
    def test_download_stream_optimized_data(self, fake_transfer,
 
361
                                            fake_rw_handles_VmdkWriteHandle):
 
362
 
 
363
        context = mock.Mock()
 
364
        session = mock.Mock()
 
365
        read_handle = mock.Mock()
 
366
        timeout_secs = 10
 
367
        image_size = 1000
 
368
        host = '127.0.0.1'
 
369
        port = 443
 
370
        resource_pool = 'rp-1'
 
371
        vm_folder = 'folder-1'
 
372
        vm_import_spec = None
 
373
 
 
374
        fake_VmdkWriteHandle = mock.Mock()
 
375
        fake_VmdkWriteHandle.get_imported_vm = mock.Mock()
 
376
        fake_rw_handles_VmdkWriteHandle.return_value = fake_VmdkWriteHandle
 
377
 
 
378
        image_transfer.download_stream_optimized_data(
 
379
            context,
 
380
            timeout_secs,
 
381
            read_handle,
 
382
            session=session,
 
383
            host=host,
 
384
            port=port,
 
385
            resource_pool=resource_pool,
 
386
            vm_folder=vm_folder,
 
387
            vm_import_spec=vm_import_spec,
 
388
            image_size=image_size)
 
389
 
 
390
        fake_rw_handles_VmdkWriteHandle.assert_called_once_with(
 
391
            session,
 
392
            host,
 
393
            port,
 
394
            resource_pool,
 
395
            vm_folder,
 
396
            vm_import_spec,
 
397
            image_size)
 
398
 
 
399
        fake_transfer.assert_called_once_with(
 
400
            context,
 
401
            timeout_secs,
 
402
            read_handle,
 
403
            image_size,
 
404
            write_file_handle=fake_VmdkWriteHandle)
 
405
 
 
406
        fake_VmdkWriteHandle.get_imported_vm.assert_called_once()
 
407
 
 
408
    @mock.patch('oslo_vmware.rw_handles.ImageReadHandle')
 
409
    @mock.patch.object(image_transfer, 'download_stream_optimized_data')
 
410
    def test_download_stream_optimized_image(
 
411
            self, fake_download_stream_optimized_data,
 
412
            fake_rw_handles_ImageReadHandle):
 
413
 
 
414
        context = mock.Mock()
 
415
        session = mock.Mock()
 
416
        image_id = mock.Mock()
 
417
        timeout_secs = 10
 
418
        image_size = 1000
 
419
        host = '127.0.0.1'
 
420
        port = 443
 
421
        resource_pool = 'rp-1'
 
422
        vm_folder = 'folder-1'
 
423
        vm_import_spec = None
 
424
 
 
425
        fake_iter = 'fake_iter'
 
426
        image_service = mock.Mock()
 
427
        image_service.download = mock.Mock()
 
428
        image_service.download.return_value = fake_iter
 
429
 
 
430
        fake_ImageReadHandle = 'fake_ImageReadHandle'
 
431
        fake_rw_handles_ImageReadHandle.return_value = fake_ImageReadHandle
 
432
 
 
433
        image_transfer.download_stream_optimized_image(
 
434
            context,
 
435
            timeout_secs,
 
436
            image_service,
 
437
            image_id,
 
438
            session=session,
 
439
            host=host,
 
440
            port=port,
 
441
            resource_pool=resource_pool,
 
442
            vm_folder=vm_folder,
 
443
            vm_import_spec=vm_import_spec,
 
444
            image_size=image_size)
 
445
 
 
446
        image_service.download.assert_called_once_with(context, image_id)
 
447
 
 
448
        fake_rw_handles_ImageReadHandle.assert_called_once_with(fake_iter)
 
449
 
 
450
        fake_download_stream_optimized_data.assert_called_once_with(
 
451
            context,
 
452
            timeout_secs,
 
453
            fake_ImageReadHandle,
 
454
            session=session,
 
455
            host=host,
 
456
            port=port,
 
457
            resource_pool=resource_pool,
 
458
            vm_folder=vm_folder,
 
459
            vm_import_spec=vm_import_spec,
 
460
            image_size=image_size)
 
461
 
 
462
    @mock.patch.object(image_transfer, '_start_transfer')
 
463
    @mock.patch('oslo_vmware.rw_handles.VmdkReadHandle')
 
464
    def test_copy_stream_optimized_disk(
 
465
            self, vmdk_read_handle, start_transfer):
 
466
 
 
467
        read_handle = mock.sentinel.read_handle
 
468
        vmdk_read_handle.return_value = read_handle
 
469
 
 
470
        context = mock.sentinel.context
 
471
        timeout = mock.sentinel.timeout
 
472
        write_handle = mock.Mock(name='/cinder/images/tmpAbcd.vmdk')
 
473
        session = mock.sentinel.session
 
474
        host = mock.sentinel.host
 
475
        port = mock.sentinel.port
 
476
        vm = mock.sentinel.vm
 
477
        vmdk_file_path = mock.sentinel.vmdk_file_path
 
478
        vmdk_size = mock.sentinel.vmdk_size
 
479
 
 
480
        image_transfer.copy_stream_optimized_disk(
 
481
            context, timeout, write_handle, session=session, host=host,
 
482
            port=port, vm=vm, vmdk_file_path=vmdk_file_path,
 
483
            vmdk_size=vmdk_size)
 
484
 
 
485
        vmdk_read_handle.assert_called_once_with(
 
486
            session, host, port, vm, vmdk_file_path, vmdk_size)
 
487
        start_transfer.assert_called_once_with(
 
488
            context, timeout, read_handle, vmdk_size,
 
489
            write_file_handle=write_handle)
 
490
 
 
491
    @mock.patch('oslo_vmware.rw_handles.VmdkReadHandle')
 
492
    @mock.patch.object(image_transfer, '_start_transfer')
 
493
    def test_upload_image(self, fake_transfer, fake_rw_handles_VmdkReadHandle):
 
494
 
 
495
        context = mock.Mock()
 
496
        image_id = mock.Mock()
 
497
        owner_id = mock.Mock()
 
498
        session = mock.Mock()
 
499
        vm = mock.Mock()
 
500
        image_service = mock.Mock()
 
501
 
 
502
        timeout_secs = 10
 
503
        image_size = 1000
 
504
        host = '127.0.0.1'
 
505
        port = 443
 
506
        file_path = '/fake_path'
 
507
        is_public = False
 
508
        image_name = 'fake_image'
 
509
        image_version = 1
 
510
 
 
511
        fake_VmdkReadHandle = 'fake_VmdkReadHandle'
 
512
        fake_rw_handles_VmdkReadHandle.return_value = fake_VmdkReadHandle
 
513
 
 
514
        image_transfer.upload_image(context,
 
515
                                    timeout_secs,
 
516
                                    image_service,
 
517
                                    image_id,
 
518
                                    owner_id,
 
519
                                    session=session,
 
520
                                    host=host,
 
521
                                    port=port,
 
522
                                    vm=vm,
 
523
                                    vmdk_file_path=file_path,
 
524
                                    vmdk_size=image_size,
 
525
                                    is_public=is_public,
 
526
                                    image_name=image_name,
 
527
                                    image_version=image_version)
 
528
 
 
529
        fake_rw_handles_VmdkReadHandle.assert_called_once_with(session,
 
530
                                                               host,
 
531
                                                               port,
 
532
                                                               vm,
 
533
                                                               file_path,
 
534
                                                               image_size)
 
535
 
 
536
        image_metadata = {'disk_format': 'vmdk',
 
537
                          'is_public': is_public,
 
538
                          'name': image_name,
 
539
                          'status': 'active',
 
540
                          'container_format': 'bare',
 
541
                          'size': 0,
 
542
                          'properties': {'vmware_image_version': image_version,
 
543
                                         'vmware_disktype': 'streamOptimized',
 
544
                                         'owner_id': owner_id}}
 
545
 
 
546
        fake_transfer.assert_called_once_with(context,
 
547
                                              timeout_secs,
 
548
                                              fake_VmdkReadHandle,
 
549
                                              0,
 
550
                                              image_service=image_service,
 
551
                                              image_id=image_id,
 
552
                                              image_meta=image_metadata)