2121
2222from nova .compute import utils as compute_utils
2323from nova import exception
24- from nova .image import format_inspector
2524from nova import test
2625from nova .virt import images
2726
@@ -101,15 +100,16 @@ def test_qemu_img_info_with_disk_not_found(self, exists, mocked_execute):
101100 mocked_execute .assert_called_once ()
102101
103102 @mock .patch .object (images , 'IMAGE_API' )
104- @mock .patch ('nova.image.format_inspector.get_inspector ' )
103+ @mock .patch ('nova.image.format_inspector.detect_file_format ' )
105104 @mock .patch .object (images , 'convert_image' ,
106105 side_effect = exception .ImageUnacceptable )
107106 @mock .patch .object (images , 'qemu_img_info' )
108107 @mock .patch .object (images , 'fetch' )
109108 def test_fetch_to_raw_errors (self , convert_image , qemu_img_info , fetch ,
110- get_inspector , glance ):
111- inspector = get_inspector . return_value . from_file .return_value
109+ mock_detect , glance ):
110+ inspector = mock_detect .return_value
112111 inspector .safety_check .return_value = True
112+ inspector .__str__ .return_value = 'qcow2'
113113 glance .get .return_value = {'disk_format' : 'qcow2' }
114114 qemu_img_info .backing_file = None
115115 qemu_img_info .file_format = 'qcow2'
@@ -120,16 +120,17 @@ def test_fetch_to_raw_errors(self, convert_image, qemu_img_info, fetch,
120120 None , 'href123' , '/no/path' )
121121
122122 @mock .patch .object (images , 'IMAGE_API' )
123- @mock .patch ('nova.image.format_inspector.get_inspector ' )
123+ @mock .patch ('nova.image.format_inspector.detect_file_format ' )
124124 @mock .patch .object (images , 'convert_image' ,
125125 side_effect = exception .ImageUnacceptable )
126126 @mock .patch .object (images , 'qemu_img_info' )
127127 @mock .patch .object (images , 'fetch' )
128128 def test_fetch_to_raw_data_file (self , convert_image , qemu_img_info_fn ,
129- fetch , mock_gi , mock_glance ):
129+ fetch , mock_detect , mock_glance ):
130130 mock_glance .get .return_value = {'disk_format' : 'qcow2' }
131- inspector = mock_gi . return_value . from_file .return_value
131+ inspector = mock_detect .return_value
132132 inspector .safety_check .return_value = True
133+ inspector .__str__ .return_value = 'qcow2'
133134 # NOTE(danms): the above test needs the following line as well, as it
134135 # is broken without it.
135136 qemu_img_info = qemu_img_info_fn .return_value
@@ -142,16 +143,17 @@ def test_fetch_to_raw_data_file(self, convert_image, qemu_img_info_fn,
142143 images .fetch_to_raw ,
143144 None , 'href123' , '/no/path' )
144145
145- @mock .patch ('nova.image.format_inspector.get_inspector ' )
146+ @mock .patch ('nova.image.format_inspector.detect_file_format ' )
146147 @mock .patch .object (images , 'IMAGE_API' )
147148 @mock .patch ('os.rename' )
148149 @mock .patch .object (images , 'qemu_img_info' )
149150 @mock .patch .object (images , 'fetch' )
150151 def test_fetch_to_raw_from_raw (self , fetch , qemu_img_info_fn , mock_rename ,
151- mock_glance , mock_gi ):
152+ mock_glance , mock_detect ):
152153 # Make sure we support a case where we fetch an already-raw image and
153154 # qemu-img returns None for "format_specific".
154155 mock_glance .get .return_value = {'disk_format' : 'raw' }
156+ mock_detect .return_value .__str__ .return_value = 'raw'
155157 qemu_img_info = qemu_img_info_fn .return_value
156158 qemu_img_info .file_format = 'raw'
157159 qemu_img_info .backing_file = None
@@ -215,14 +217,15 @@ def test_convert_image_vmdk_allowed_list_checking(self):
215217 format = 'json' ))
216218
217219 @mock .patch .object (images , 'IMAGE_API' )
218- @mock .patch ('nova.image.format_inspector.get_inspector ' )
220+ @mock .patch ('nova.image.format_inspector.detect_file_format ' )
219221 @mock .patch .object (images , 'fetch' )
220222 @mock .patch ('nova.privsep.qemu.unprivileged_qemu_img_info' )
221- def test_fetch_checks_vmdk_rules (self , mock_info , mock_fetch , mock_gi ,
223+ def test_fetch_checks_vmdk_rules (self , mock_info , mock_fetch , mock_detect ,
222224 mock_glance ):
223225 mock_glance .get .return_value = {'disk_format' : 'vmdk' }
224- inspector = mock_gi . return_value . from_file .return_value
226+ inspector = mock_detect .return_value
225227 inspector .safety_check .return_value = True
228+ inspector .__str__ .return_value = 'vmdk'
226229 info = {'format' : 'vmdk' ,
227230 'format-specific' : {
228231 'type' : 'vmdk' ,
@@ -235,22 +238,54 @@ def test_fetch_checks_vmdk_rules(self, mock_info, mock_fetch, mock_gi,
235238 images .fetch_to_raw , None , 'foo' , 'anypath' )
236239 self .assertIn ('Invalid VMDK create-type specified' , str (e ))
237240
241+ @mock .patch ('os.rename' )
238242 @mock .patch .object (images , 'IMAGE_API' )
239243 @mock .patch ('nova.image.format_inspector.get_inspector' )
244+ @mock .patch ('nova.image.format_inspector.detect_file_format' )
245+ @mock .patch .object (images , 'fetch' )
246+ @mock .patch ('nova.privsep.qemu.unprivileged_qemu_img_info' )
247+ def test_fetch_iso_is_raw (
248+ self , mock_info , mock_fetch , mock_detect_file_format , mock_gi ,
249+ mock_glance , mock_rename ):
250+ mock_glance .get .return_value = {'disk_format' : 'iso' }
251+ inspector = mock_gi .return_value .from_file .return_value
252+ inspector .safety_check .return_value = True
253+ inspector .__str__ .return_value = 'iso'
254+ mock_detect_file_format .return_value = inspector
255+ # qemu-img does not have a parser for iso so it is treated as raw
256+ info = {
257+ "virtual-size" : 356352 ,
258+ "filename" : "foo.iso" ,
259+ "format" : "raw" ,
260+ "actual-size" : 356352 ,
261+ "dirty-flag" : False
262+ }
263+ mock_info .return_value = jsonutils .dumps (info )
264+ with mock .patch ('os.path.exists' , return_value = True ):
265+ images .fetch_to_raw (None , 'foo' , 'anypath' )
266+ # Make sure we called info with -f raw for an iso, since qemu-img does
267+ # not support iso
268+ mock_info .assert_called_once_with ('anypath.part' , format = None )
269+ # Make sure that since we considered this to be a raw file, we did the
270+ # just-rename-don't-convert path
271+ mock_rename .assert_called_once_with ('anypath.part' , 'anypath' )
272+
273+ @mock .patch .object (images , 'IMAGE_API' )
274+ @mock .patch ('nova.image.format_inspector.detect_file_format' )
240275 @mock .patch .object (images , 'qemu_img_info' )
241276 @mock .patch .object (images , 'fetch' )
242- def test_fetch_to_raw_inspector (self , fetch , qemu_img_info , mock_gi ,
277+ def test_fetch_to_raw_inspector (self , fetch , qemu_img_info , mock_detect ,
243278 mock_glance ):
244279 # Image claims to be qcow2, is qcow2, but fails safety check, so we
245280 # abort before qemu-img-info
246281 mock_glance .get .return_value = {'disk_format' : 'qcow2' }
247- inspector = mock_gi . return_value . from_file .return_value
282+ inspector = mock_detect .return_value
248283 inspector .safety_check .return_value = False
284+ inspector .__str__ .return_value = 'qcow2'
249285 self .assertRaises (exception .ImageUnacceptable ,
250286 images .fetch_to_raw , None , 'href123' , '/no.path' )
251287 qemu_img_info .assert_not_called ()
252- mock_gi .assert_called_once_with ('qcow2' )
253- mock_gi .return_value .from_file .assert_called_once_with ('/no.path.part' )
288+ mock_detect .assert_called_once_with ('/no.path.part' )
254289 inspector .safety_check .assert_called_once_with ()
255290 mock_glance .get .assert_called_once_with (None , 'href123' )
256291
@@ -264,18 +299,17 @@ def test_fetch_to_raw_inspector(self, fetch, qemu_img_info, mock_gi,
264299 # Image claims to be qcow2 in glance, but the image is something else,
265300 # so we abort before qemu-img-info
266301 qemu_img_info .reset_mock ()
267- mock_gi .reset_mock ()
302+ mock_detect .reset_mock ()
268303 inspector .safety_check .reset_mock ()
269- mock_gi .return_value .from_file .side_effect = (
270- format_inspector .ImageFormatError )
304+ mock_detect .return_value .__str__ .return_value = 'vmdk'
271305 self .assertRaises (exception .ImageUnacceptable ,
272306 images .fetch_to_raw , None , 'href123' , '/no.path' )
273- mock_gi .assert_called_once_with ('qcow2 ' )
274- inspector .safety_check .assert_not_called ()
307+ mock_detect .assert_called_once_with ('/no.path.part ' )
308+ inspector .safety_check .assert_called_once_with ()
275309 qemu_img_info .assert_not_called ()
276310
277311 @mock .patch .object (images , 'IMAGE_API' )
278- @mock .patch ('nova.image.format_inspector.get_inspector ' )
312+ @mock .patch ('nova.image.format_inspector.detect_file_format ' )
279313 @mock .patch .object (images , 'qemu_img_info' )
280314 @mock .patch .object (images , 'fetch' )
281315 def test_fetch_to_raw_inspector_disabled (self , fetch , qemu_img_info ,
@@ -288,36 +322,41 @@ def test_fetch_to_raw_inspector_disabled(self, fetch, qemu_img_info,
288322 # If deep inspection is disabled, we should never call the inspector
289323 mock_gi .assert_not_called ()
290324 # ... and we let qemu-img detect the format itself.
291- qemu_img_info .assert_called_once_with ('/no.path.part' ,
292- format = None )
325+ qemu_img_info .assert_called_once_with ('/no.path.part' )
293326 mock_glance .get .assert_not_called ()
294327
295328 @mock .patch .object (images , 'IMAGE_API' )
296329 @mock .patch .object (images , 'qemu_img_info' )
297- def test_fetch_inspect_ami (self , imginfo , glance ):
330+ @mock .patch ('nova.image.format_inspector.detect_file_format' )
331+ def test_fetch_inspect_ami (self , detect , imginfo , glance ):
298332 glance .get .return_value = {'disk_format' : 'ami' }
333+ detect .return_value .__str__ .return_value = 'raw'
299334 self .assertRaises (exception .ImageUnacceptable ,
300335 images .fetch_to_raw , None , 'href123' , '/no.path' )
301336 # Make sure 'ami was translated into 'raw' before we call qemu-img
302- imginfo .assert_called_once_with ('/no.path.part' , format = 'raw' )
337+ imginfo .assert_called_once_with ('/no.path.part' )
303338
304339 @mock .patch .object (images , 'IMAGE_API' )
305340 @mock .patch .object (images , 'qemu_img_info' )
306- def test_fetch_inspect_aki (self , imginfo , glance ):
341+ @mock .patch ('nova.image.format_inspector.detect_file_format' )
342+ def test_fetch_inspect_aki (self , detect , imginfo , glance ):
307343 glance .get .return_value = {'disk_format' : 'aki' }
344+ detect .return_value .__str__ .return_value = 'raw'
308345 self .assertRaises (exception .ImageUnacceptable ,
309346 images .fetch_to_raw , None , 'href123' , '/no.path' )
310347 # Make sure 'aki was translated into 'raw' before we call qemu-img
311- imginfo .assert_called_once_with ('/no.path.part' , format = 'raw' )
348+ imginfo .assert_called_once_with ('/no.path.part' )
312349
313350 @mock .patch .object (images , 'IMAGE_API' )
314351 @mock .patch .object (images , 'qemu_img_info' )
315- def test_fetch_inspect_ari (self , imginfo , glance ):
352+ @mock .patch ('nova.image.format_inspector.detect_file_format' )
353+ def test_fetch_inspect_ari (self , detect , imginfo , glance ):
316354 glance .get .return_value = {'disk_format' : 'ari' }
355+ detect .return_value .__str__ .return_value = 'raw'
317356 self .assertRaises (exception .ImageUnacceptable ,
318357 images .fetch_to_raw , None , 'href123' , '/no.path' )
319358 # Make sure 'aki was translated into 'raw' before we call qemu-img
320- imginfo .assert_called_once_with ('/no.path.part' , format = 'raw' )
359+ imginfo .assert_called_once_with ('/no.path.part' )
321360
322361 @mock .patch .object (images , 'IMAGE_API' )
323362 @mock .patch .object (images , 'qemu_img_info' )
@@ -330,13 +369,16 @@ def test_fetch_inspect_unknown_format(self, imginfo, glance):
330369
331370 @mock .patch .object (images , 'IMAGE_API' )
332371 @mock .patch .object (images , 'qemu_img_info' )
333- @mock .patch ('nova.image.format_inspector.get_inspector ' )
334- def test_fetch_inspect_disagrees_qemu (self , mock_gi , imginfo , glance ):
372+ @mock .patch ('nova.image.format_inspector.detect_file_format ' )
373+ def test_fetch_inspect_disagrees_qemu (self , mock_detect , imginfo , glance ):
335374 glance .get .return_value = {'disk_format' : 'qcow2' }
375+ mock_detect .return_value .__str__ .return_value = 'qcow2'
336376 # Glance and inspector think it is a qcow2 file, but qemu-img does not
337- # agree. It was forced to interpret as a qcow2, but returned no
338- # format information as a result.
377+ # agree.
339378 imginfo .return_value .data_file = None
340- self .assertRaises (exception .ImageUnacceptable ,
341- images .fetch_to_raw , None , 'href123' , '/no.path' )
342- imginfo .assert_called_once_with ('/no.path.part' , format = 'qcow2' )
379+ imginfo .return_value .file_format = 'vmdk'
380+ ex = self .assertRaises (exception .ImageUnacceptable ,
381+ images .fetch_to_raw ,
382+ None , 'href123' , '/no.path' )
383+ self .assertIn ('content does not match disk_format' , str (ex ))
384+ imginfo .assert_called_once_with ('/no.path.part' )
0 commit comments