Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
convert images that are not 'raw' to 'raw' during caching to node
This uses 'qemu-img' to convert images that are not 'raw' to be 'raw'.
By doing so, it
 a.) refuses to run uploaded images that have a backing image reference
     (LP: #853330, CVE-2011-3147)
 b.) ensures that when FLAGS.use_cow_images is False, and the libvirt
     xml written specifies 'driver_type="raw"' that the disk referenced
     is also raw format. (LP: #837102)
 c.) removes compression that might be present to avoid cpu bottlenecks
     (LP: #837100)

It does have the negative side affect of using more space in the case where
the user uploaded a qcow2 (or other advanced image format) that could have
been used directly by the hypervisor.  That could, later, be remedied by
another 'qemu-img convert' being done to the "preferred" format of the
hypervisor.
  • Loading branch information
smoser committed Sep 19, 2011
1 parent 3da916d commit ff9d353
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 1 deletion.
55 changes: 55 additions & 0 deletions nova/virt/images.py
Expand Up @@ -21,6 +21,9 @@
Handling of VM disk images.
"""

import os

from nova import exception
from nova import flags
from nova.image import glance as glance_image_service
import nova.image
Expand All @@ -42,3 +45,55 @@ def fetch(context, image_href, path, _user_id, _project_id):
with open(path, "wb") as image_file:
metadata = image_service.get(context, image_id, image_file)
return metadata


def fetch_to_raw(context, image_href, path, _user_id, _project_id):
path_tmp = "%s.part" % path
metadata = fetch(context, image_href, path_tmp, _user_id, _project_id)

def _qemu_img_info(path):

out, err = utils.execute('qemu-img', 'info', path)

# output of qemu-img is 'field: value'
# the fields of interest are 'file format' and 'backing file'
data = {}
for line in out.splitlines():
(field, val) = line.split(':', 1)
if val[0] == " ":
val = val[1:]
data[field] = val

return(data)

data = _qemu_img_info(path_tmp)

fmt = data.get("file format", None)
if fmt == None:
raise exception.ImageUnacceptable(
reason="'qemu-img info' parsing failed.", image_id=image_href)

if fmt != "raw":
staged = "%s.converted" % path
if "backing file" in data:
raise exception.ImageUnacceptable(image_id=image_href,
reason="Dangerous! fmt=%s with backing file: %s" %
(fmt, data['backing file']))

LOG.debug("%s was %s, converting to raw" % (image_href, fmt))
out, err = utils.execute('qemu-img', 'convert', '-O', 'raw',
path_tmp, staged)
os.unlink(path_tmp)

data = _qemu_img_info(staged)
if data.get('file format', None) != "raw":
raise exception.ImageUnacceptable(image_id=image_href,
reason="Dangerous! Converted to raw, but format is now %s" %
data.get('file format', None))

os.rename(staged, path)

else:
os.rename(path_tmp, path)

return metadata
2 changes: 1 addition & 1 deletion nova/virt/libvirt/connection.py
Expand Up @@ -769,7 +769,7 @@ def call_if_not_exists(base, fn, *args, **kwargs):
def _fetch_image(self, context, target, image_id, user_id, project_id,
size=None):
"""Grab image and optionally attempt to resize it"""
images.fetch(context, image_id, target, user_id, project_id)
images.fetch_to_raw(context, image_id, target, user_id, project_id)
if size:
disk.extend(target, size)

Expand Down

0 comments on commit ff9d353

Please sign in to comment.