2626from taskflow import task
2727
2828from glance .async_ import utils
29+ from glance .common import format_inspector
2930from glance .i18n import _ , _LI
3031
3132LOG = logging .getLogger (__name__ )
@@ -88,8 +89,43 @@ def _execute(self, action, file_path, **kwargs):
8889 'target' : target_format }
8990 self .dest_path = dest_path
9091
92+ # Backport fixup due to lack of
93+ # Ic51c5fd87caf04d38aeaf758ad2d0e2f28098e4d in Yoga:
94+ #source_format = action.image_disk_format
95+ source_format = action ._image .disk_format
96+ inspector_cls = format_inspector .get_inspector (source_format )
97+ if not inspector_cls :
98+ # We cannot convert from disk_format types that qemu-img doesn't
99+ # support (like iso, ploop, etc). The ones it supports overlaps
100+ # with the ones we have inspectors for, so reject conversion for
101+ # any format we don't have an inspector for.
102+ raise RuntimeError (
103+ 'Unable to convert from format %s' % source_format )
104+
105+ # Use our own cautious inspector module (if we have one for this
106+ # format) to make sure a file is the format the submitter claimed
107+ # it is and that it passes some basic safety checks _before_ we run
108+ # qemu-img on it.
109+ # See https://bugs.launchpad.net/nova/+bug/2059809 for details.
110+ try :
111+ inspector = inspector_cls .from_file (src_path )
112+ if not inspector .safety_check ():
113+ LOG .error ('Image failed %s safety check; aborting conversion' ,
114+ source_format )
115+ raise RuntimeError ('Image has disallowed configuration' )
116+ except RuntimeError :
117+ raise
118+ except format_inspector .ImageFormatError as e :
119+ LOG .error ('Image claimed to be %s format failed format '
120+ 'inspection: %s' , source_format , e )
121+ raise RuntimeError ('Image format detection failed' )
122+ except Exception as e :
123+ LOG .exception ('Unknown error inspecting image format: %s' , e )
124+ raise RuntimeError ('Unable to inspect image' )
125+
91126 try :
92127 stdout , stderr = putils .trycmd ("qemu-img" , "info" ,
128+ "-f" , source_format ,
93129 "--output=json" ,
94130 src_path ,
95131 prlimit = utils .QEMU_IMG_PROC_LIMITS ,
@@ -106,13 +142,10 @@ def _execute(self, action, file_path, **kwargs):
106142 raise RuntimeError (stderr )
107143
108144 metadata = json .loads (stdout )
109- try :
110- source_format = metadata ['format' ]
111- except KeyError :
112- msg = ("Failed to do introspection as part of image "
113- "conversion for %(iid)s: Source format not reported" )
114- LOG .error (msg , {'iid' : self .image_id })
115- raise RuntimeError (msg )
145+ if metadata .get ('format' ) != source_format :
146+ LOG .error ('Image claiming to be %s reported as %s by qemu-img' ,
147+ source_format , metadata .get ('format' , 'unknown' ))
148+ raise RuntimeError ('Image metadata disagrees about format' )
116149
117150 virtual_size = metadata .get ('virtual-size' , 0 )
118151 action .set_image_attribute (virtual_size = virtual_size )
@@ -122,6 +155,14 @@ def _execute(self, action, file_path, **kwargs):
122155 raise RuntimeError (
123156 'QCOW images with backing files are not allowed' )
124157
158+ try :
159+ data_file = metadata ['format-specific' ]['data' ]['data-file' ]
160+ except KeyError :
161+ data_file = None
162+ if data_file is not None :
163+ raise RuntimeError (
164+ 'QCOW images with data-file set are not allowed' )
165+
125166 if metadata .get ('format' ) == 'vmdk' :
126167 create_type = metadata .get (
127168 'format-specific' , {}).get (
0 commit comments