Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ff9d353

Browse files
committed
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.
1 parent 3da916d commit ff9d353

2 files changed

Lines changed: 56 additions & 1 deletion

File tree

nova/virt/images.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
Handling of VM disk images.
2222
"""
2323

24+
import os
25+
26+
from nova import exception
2427
from nova import flags
2528
from nova.image import glance as glance_image_service
2629
import nova.image
@@ -42,3 +45,55 @@ def fetch(context, image_href, path, _user_id, _project_id):
4245
with open(path, "wb") as image_file:
4346
metadata = image_service.get(context, image_id, image_file)
4447
return metadata
48+
49+
50+
def fetch_to_raw(context, image_href, path, _user_id, _project_id):
51+
path_tmp = "%s.part" % path
52+
metadata = fetch(context, image_href, path_tmp, _user_id, _project_id)
53+
54+
def _qemu_img_info(path):
55+
56+
out, err = utils.execute('qemu-img', 'info', path)
57+
58+
# output of qemu-img is 'field: value'
59+
# the fields of interest are 'file format' and 'backing file'
60+
data = {}
61+
for line in out.splitlines():
62+
(field, val) = line.split(':', 1)
63+
if val[0] == " ":
64+
val = val[1:]
65+
data[field] = val
66+
67+
return(data)
68+
69+
data = _qemu_img_info(path_tmp)
70+
71+
fmt = data.get("file format", None)
72+
if fmt == None:
73+
raise exception.ImageUnacceptable(
74+
reason="'qemu-img info' parsing failed.", image_id=image_href)
75+
76+
if fmt != "raw":
77+
staged = "%s.converted" % path
78+
if "backing file" in data:
79+
raise exception.ImageUnacceptable(image_id=image_href,
80+
reason="Dangerous! fmt=%s with backing file: %s" %
81+
(fmt, data['backing file']))
82+
83+
LOG.debug("%s was %s, converting to raw" % (image_href, fmt))
84+
out, err = utils.execute('qemu-img', 'convert', '-O', 'raw',
85+
path_tmp, staged)
86+
os.unlink(path_tmp)
87+
88+
data = _qemu_img_info(staged)
89+
if data.get('file format', None) != "raw":
90+
raise exception.ImageUnacceptable(image_id=image_href,
91+
reason="Dangerous! Converted to raw, but format is now %s" %
92+
data.get('file format', None))
93+
94+
os.rename(staged, path)
95+
96+
else:
97+
os.rename(path_tmp, path)
98+
99+
return metadata

nova/virt/libvirt/connection.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ def call_if_not_exists(base, fn, *args, **kwargs):
769769
def _fetch_image(self, context, target, image_id, user_id, project_id,
770770
size=None):
771771
"""Grab image and optionally attempt to resize it"""
772-
images.fetch(context, image_id, target, user_id, project_id)
772+
images.fetch_to_raw(context, image_id, target, user_id, project_id)
773773
if size:
774774
disk.extend(target, size)
775775

0 commit comments

Comments
 (0)