summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorScott Moser <smoser@ubuntu.com>2011-09-19 16:57:44 -0400
committerScott Moser <smoser@ubuntu.com>2011-09-19 16:57:44 -0400
commitff9d353b2f4fee469e530fbc8dc231a41f6fed84 (patch)
tree403391d86026633729899e9acb7cbcf53007987f
parent3da916de6165e1e7012f61a05a6a0d9d06906b48 (diff)
downloadnova-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.py55
-rw-r--r--nova/virt/libvirt/connection.py2
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)