diff options
| author | Scott Moser <smoser@ubuntu.com> | 2011-09-19 16:57:44 -0400 |
|---|---|---|
| committer | Scott Moser <smoser@ubuntu.com> | 2011-09-19 16:57:44 -0400 |
| commit | ff9d353b2f4fee469e530fbc8dc231a41f6fed84 (patch) | |
| tree | 403391d86026633729899e9acb7cbcf53007987f | |
| parent | 3da916de6165e1e7012f61a05a6a0d9d06906b48 (diff) | |
| download | nova-ff9d353b2f4fee469e530fbc8dc231a41f6fed84.tar.gz nova-ff9d353b2f4fee469e530fbc8dc231a41f6fed84.tar.xz nova-ff9d353b2f4fee469e530fbc8dc231a41f6fed84.zip | |
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.
| -rw-r--r-- | nova/virt/images.py | 55 | ||||
| -rw-r--r-- | nova/virt/libvirt/connection.py | 2 |
2 files changed, 56 insertions, 1 deletions
diff --git a/nova/virt/images.py b/nova/virt/images.py index 810b359d9..c8a95bb00 100644 --- a/nova/virt/images.py +++ b/nova/virt/images.py @@ -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 @@ -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 diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py index 4a0849127..44a733340 100644 --- a/nova/virt/libvirt/connection.py +++ b/nova/virt/libvirt/connection.py @@ -769,7 +769,7 @@ class LibvirtConnection(driver.ComputeDriver): 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) |
