1
# Copyright (c) 2014 VMware, Inc.
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
8
# http://www.apache.org/licenses/LICENSE-2.0
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
17
Unit tests for functions and classes for image transfer.
22
from eventlet import greenthread
23
from eventlet import timeout
26
from oslo.vmware import exceptions
27
from oslo.vmware import image_transfer
28
from oslo.vmware import rw_handles
29
from oslo_vmware import image_transfer as new_image_transfer
30
from tests import base
33
class BlockingQueueTest(base.TestCase):
34
"""Tests for BlockingQueue."""
39
max_transfer_size = 30
40
queue = image_transfer.BlockingQueue(max_size, max_transfer_size)
42
def get_side_effect():
43
return [1] * chunk_size
45
queue.get = mock.Mock(side_effect=get_side_effect)
47
data_item = queue.read(chunk_size)
51
self.assertEqual(max_transfer_size, queue._transferred)
52
exp_calls = [mock.call()] * int(math.ceil(float(max_transfer_size) /
54
self.assertEqual(exp_calls, queue.get.call_args_list)
57
queue = image_transfer.BlockingQueue(10, 30)
58
queue.put = mock.Mock()
60
for _ in range(0, write_count):
62
exp_calls = [mock.call([1])] * write_count
63
self.assertEqual(exp_calls, queue.put.call_args_list)
66
queue = image_transfer.BlockingQueue(10, 30)
67
self.assertRaises(IOError, queue.seek, 5)
70
queue = image_transfer.BlockingQueue(10, 30)
71
self.assertEqual(0, queue.tell())
72
queue.get = mock.Mock(return_value=[1] * 10)
74
self.assertEqual(10, queue.tell())
77
class ImageWriterTest(base.TestCase):
78
"""Tests for ImageWriter class."""
80
def _create_image_writer(self):
81
self.image_service = mock.Mock()
82
self.context = mock.Mock()
83
self.input_file = mock.Mock()
84
self.image_id = mock.Mock()
85
return image_transfer.ImageWriter(self.context, self.input_file,
86
self.image_service, self.image_id)
88
@mock.patch.object(greenthread, 'sleep')
89
def test_start(self, mock_sleep):
90
writer = self._create_image_writer()
91
status_list = ['queued', 'saving', 'active']
93
def image_service_show_side_effect(context, image_id):
94
status = status_list.pop(0)
95
return {'status': status}
97
self.image_service.show.side_effect = image_service_show_side_effect
98
exp_calls = [mock.call(self.context, self.image_id)] * len(status_list)
100
self.assertTrue(writer.wait())
101
self.image_service.update.assert_called_once_with(self.context,
103
data=self.input_file)
104
self.assertEqual(exp_calls, self.image_service.show.call_args_list)
106
def test_start_with_killed_status(self):
107
writer = self._create_image_writer()
109
def image_service_show_side_effect(_context, _image_id):
110
return {'status': 'killed'}
112
self.image_service.show.side_effect = image_service_show_side_effect
114
self.assertRaises(exceptions.ImageTransferException,
116
self.image_service.update.assert_called_once_with(self.context,
118
data=self.input_file)
119
self.image_service.show.assert_called_once_with(self.context,
122
def test_start_with_unknown_status(self):
123
writer = self._create_image_writer()
125
def image_service_show_side_effect(_context, _image_id):
126
return {'status': 'unknown'}
128
self.image_service.show.side_effect = image_service_show_side_effect
130
self.assertRaises(exceptions.ImageTransferException,
132
self.image_service.update.assert_called_once_with(self.context,
134
data=self.input_file)
135
self.image_service.show.assert_called_once_with(self.context,
138
def test_start_with_image_service_show_exception(self):
139
writer = self._create_image_writer()
140
self.image_service.show.side_effect = RuntimeError()
142
self.assertRaises(exceptions.ImageTransferException, writer.wait)
143
self.image_service.update.assert_called_once_with(self.context,
145
data=self.input_file)
146
self.image_service.show.assert_called_once_with(self.context,
150
class FileReadWriteTaskTest(base.TestCase):
151
"""Tests for FileReadWriteTask class."""
153
def test_start(self):
154
data_items = [[1] * 10, [1] * 20, [1] * 5, []]
156
def input_file_read_side_effect(arg):
157
self.assertEqual(arg, rw_handles.READ_CHUNKSIZE)
158
data = data_items[input_file_read_side_effect.i]
159
input_file_read_side_effect.i += 1
162
input_file_read_side_effect.i = 0
163
input_file = mock.Mock()
164
input_file.read.side_effect = input_file_read_side_effect
165
output_file = mock.Mock()
166
rw_task = image_transfer.FileReadWriteTask(input_file, output_file)
168
self.assertTrue(rw_task.wait())
169
self.assertEqual(len(data_items), input_file.read.call_count)
172
for i in range(0, len(data_items)):
173
exp_calls.append(mock.call(data_items[i]))
174
self.assertEqual(exp_calls, output_file.write.call_args_list)
176
self.assertEqual(len(data_items),
177
input_file.update_progress.call_count)
178
self.assertEqual(len(data_items),
179
output_file.update_progress.call_count)
181
def test_start_with_read_exception(self):
182
input_file = mock.Mock()
183
input_file.read.side_effect = RuntimeError()
184
output_file = mock.Mock()
185
rw_task = image_transfer.FileReadWriteTask(input_file, output_file)
187
self.assertRaises(exceptions.ImageTransferException, rw_task.wait)
188
input_file.read.assert_called_once_with(rw_handles.READ_CHUNKSIZE)
191
class ImageTransferUtilityTest(base.TestCase):
192
"""Tests for image_transfer utility methods."""
194
@mock.patch.object(timeout, 'Timeout')
195
@mock.patch('oslo_vmware.image_transfer.ImageWriter')
196
@mock.patch('oslo_vmware.image_transfer.FileReadWriteTask')
197
@mock.patch('oslo_vmware.image_transfer.BlockingQueue')
198
def test_start_transfer(self, fake_BlockingQueue, fake_FileReadWriteTask,
199
fake_ImageWriter, fake_Timeout):
201
context = mock.Mock()
202
read_file_handle = mock.Mock()
203
read_file_handle.close = mock.Mock()
204
image_service = mock.Mock()
205
image_id = mock.Mock()
206
blocking_queue = mock.Mock()
208
write_file_handle1 = mock.Mock()
209
write_file_handle1.close = mock.Mock()
210
write_file_handle2 = None
211
write_file_handles = [write_file_handle1, write_file_handle2]
214
blocking_queue_size = 10
218
fake_BlockingQueue.return_value = blocking_queue
219
fake_timer = mock.Mock()
220
fake_timer.cancel = mock.Mock()
221
fake_Timeout.return_value = fake_timer
223
for write_file_handle in write_file_handles:
224
new_image_transfer._start_transfer(
229
write_file_handle=write_file_handle,
230
image_service=image_service,
232
image_meta=image_meta)
234
exp_calls = [mock.call(blocking_queue_size,
235
max_data_size)] * len(write_file_handles)
236
self.assertEqual(exp_calls,
237
fake_BlockingQueue.call_args_list)
239
exp_calls2 = [mock.call(read_file_handle, blocking_queue),
240
mock.call(blocking_queue, write_file_handle1),
241
mock.call(read_file_handle, blocking_queue)]
242
self.assertEqual(exp_calls2,
243
fake_FileReadWriteTask.call_args_list)
245
exp_calls3 = mock.call(context, blocking_queue, image_service,
246
image_id, image_meta)
247
self.assertEqual(exp_calls3,
248
fake_ImageWriter.call_args)
250
exp_calls4 = [mock.call(timeout_secs)] * len(write_file_handles)
251
self.assertEqual(exp_calls4,
252
fake_Timeout.call_args_list)
254
self.assertEqual(len(write_file_handles),
255
fake_timer.cancel.call_count)
257
self.assertEqual(len(write_file_handles),
258
read_file_handle.close.call_count)
260
write_file_handle1.close.assert_called_once()
262
@mock.patch('oslo_vmware.rw_handles.FileWriteHandle')
263
@mock.patch('oslo_vmware.rw_handles.ImageReadHandle')
264
@mock.patch('oslo_vmware.image_transfer._start_transfer')
265
def test_download_flat_image(
268
fake_rw_handles_ImageReadHandle,
269
fake_rw_handles_FileWriteHandle):
271
context = mock.Mock()
272
image_id = mock.Mock()
273
image_service = mock.Mock()
274
image_service.download = mock.Mock()
275
image_service.download.return_value = 'fake_iter'
277
fake_ImageReadHandle = 'fake_ImageReadHandle'
278
fake_FileWriteHandle = 'fake_FileWriteHandle'
286
file_path = '/fake_path'
288
fake_rw_handles_ImageReadHandle.return_value = fake_ImageReadHandle
289
fake_rw_handles_FileWriteHandle.return_value = fake_FileWriteHandle
291
image_transfer.download_flat_image(
296
image_size=image_size,
299
data_center_name=dc_path,
300
datastore_name=ds_name,
304
image_service.download.assert_called_once_with(context, image_id)
306
fake_rw_handles_ImageReadHandle.assert_called_once_with('fake_iter')
308
fake_rw_handles_FileWriteHandle.assert_called_once_with(
318
fake_transfer.assert_called_once_with(
321
fake_ImageReadHandle,
323
write_file_handle=fake_FileWriteHandle)
325
@mock.patch('oslo_vmware.rw_handles.VmdkWriteHandle')
326
@mock.patch('oslo_vmware.image_transfer._start_transfer')
327
def test_download_stream_optimized_data(self, fake_transfer,
328
fake_rw_handles_VmdkWriteHandle):
330
context = mock.Mock()
331
session = mock.Mock()
332
read_handle = mock.Mock()
337
resource_pool = 'rp-1'
338
vm_folder = 'folder-1'
339
vm_import_spec = None
341
fake_VmdkWriteHandle = mock.Mock()
342
fake_VmdkWriteHandle.get_imported_vm = mock.Mock()
343
fake_rw_handles_VmdkWriteHandle.return_value = fake_VmdkWriteHandle
345
image_transfer.download_stream_optimized_data(
352
resource_pool=resource_pool,
354
vm_import_spec=vm_import_spec,
355
image_size=image_size)
357
fake_rw_handles_VmdkWriteHandle.assert_called_once_with(
366
fake_transfer.assert_called_once_with(
371
write_file_handle=fake_VmdkWriteHandle)
373
fake_VmdkWriteHandle.get_imported_vm.assert_called_once()
375
@mock.patch('oslo_vmware.rw_handles.ImageReadHandle')
376
@mock.patch('oslo_vmware.image_transfer.download_stream_optimized_data')
377
def test_download_stream_optimized_image(
378
self, fake_download_stream_optimized_data,
379
fake_rw_handles_ImageReadHandle):
381
context = mock.Mock()
382
session = mock.Mock()
383
image_id = mock.Mock()
388
resource_pool = 'rp-1'
389
vm_folder = 'folder-1'
390
vm_import_spec = None
392
fake_iter = 'fake_iter'
393
image_service = mock.Mock()
394
image_service.download = mock.Mock()
395
image_service.download.return_value = fake_iter
397
fake_ImageReadHandle = 'fake_ImageReadHandle'
398
fake_rw_handles_ImageReadHandle.return_value = fake_ImageReadHandle
400
image_transfer.download_stream_optimized_image(
408
resource_pool=resource_pool,
410
vm_import_spec=vm_import_spec,
411
image_size=image_size)
413
image_service.download.assert_called_once_with(context, image_id)
415
fake_rw_handles_ImageReadHandle.assert_called_once_with(fake_iter)
417
fake_download_stream_optimized_data.assert_called_once_with(
420
fake_ImageReadHandle,
424
resource_pool=resource_pool,
426
vm_import_spec=vm_import_spec,
427
image_size=image_size)
429
@mock.patch('oslo_vmware.image_transfer._start_transfer')
430
@mock.patch('oslo_vmware.rw_handles.VmdkReadHandle')
431
def test_copy_stream_optimized_disk(
432
self, vmdk_read_handle, start_transfer):
434
read_handle = mock.sentinel.read_handle
435
vmdk_read_handle.return_value = read_handle
437
context = mock.sentinel.context
438
timeout = mock.sentinel.timeout
439
write_handle = mock.Mock(name='/cinder/images/tmpAbcd.vmdk')
440
session = mock.sentinel.session
441
host = mock.sentinel.host
442
port = mock.sentinel.port
443
vm = mock.sentinel.vm
444
vmdk_file_path = mock.sentinel.vmdk_file_path
445
vmdk_size = mock.sentinel.vmdk_size
447
image_transfer.copy_stream_optimized_disk(
448
context, timeout, write_handle, session=session, host=host,
449
port=port, vm=vm, vmdk_file_path=vmdk_file_path,
452
vmdk_read_handle.assert_called_once_with(
453
session, host, port, vm, vmdk_file_path, vmdk_size)
454
start_transfer.assert_called_once_with(
455
context, timeout, read_handle, vmdk_size,
456
write_file_handle=write_handle)
458
@mock.patch('oslo_vmware.rw_handles.VmdkReadHandle')
459
@mock.patch('oslo_vmware.image_transfer._start_transfer')
460
def test_upload_image(self, fake_transfer, fake_rw_handles_VmdkReadHandle):
462
context = mock.Mock()
463
image_id = mock.Mock()
464
owner_id = mock.Mock()
465
session = mock.Mock()
467
image_service = mock.Mock()
473
file_path = '/fake_path'
475
image_name = 'fake_image'
478
fake_VmdkReadHandle = 'fake_VmdkReadHandle'
479
fake_rw_handles_VmdkReadHandle.return_value = fake_VmdkReadHandle
481
image_transfer.upload_image(context,
490
vmdk_file_path=file_path,
491
vmdk_size=image_size,
493
image_name=image_name,
494
image_version=image_version)
496
fake_rw_handles_VmdkReadHandle.assert_called_once_with(session,
503
image_metadata = {'disk_format': 'vmdk',
504
'is_public': is_public,
507
'container_format': 'bare',
509
'properties': {'vmware_image_version': image_version,
510
'vmware_disktype': 'streamOptimized',
511
'owner_id': owner_id}}
513
fake_transfer.assert_called_once_with(context,
517
image_service=image_service,
519
image_meta=image_metadata)