26
26
from taskflow import task
27
27
28
28
from glance .async_ import utils
29
+ from glance .common import format_inspector
29
30
from glance .i18n import _ , _LI
30
31
31
32
LOG = logging .getLogger (__name__ )
@@ -88,8 +89,43 @@ def _execute(self, action, file_path, **kwargs):
88
89
'target' : target_format }
89
90
self .dest_path = dest_path
90
91
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
+
91
126
try :
92
127
stdout , stderr = putils .trycmd ("qemu-img" , "info" ,
128
+ "-f" , source_format ,
93
129
"--output=json" ,
94
130
src_path ,
95
131
prlimit = utils .QEMU_IMG_PROC_LIMITS ,
@@ -106,13 +142,10 @@ def _execute(self, action, file_path, **kwargs):
106
142
raise RuntimeError (stderr )
107
143
108
144
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' )
116
149
117
150
virtual_size = metadata .get ('virtual-size' , 0 )
118
151
action .set_image_attribute (virtual_size = virtual_size )
@@ -122,6 +155,14 @@ def _execute(self, action, file_path, **kwargs):
122
155
raise RuntimeError (
123
156
'QCOW images with backing files are not allowed' )
124
157
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
+
125
166
if metadata .get ('format' ) == 'vmdk' :
126
167
create_type = metadata .get (
127
168
'format-specific' , {}).get (
0 commit comments