1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
From 6740c4141ea1152529b82cbf6e5b808eaba912e7 Mon Sep 17 00:00:00 2001
From: Chet Burgess <cfb@metacloud.com>
Date: Thu, 9 May 2013 09:57:28 +0000
Subject: [PATCH] Check QCOW2 image size during root disk creation
glance can only tell us the size of the file, not the virtual
size of the QCOW2. As such we need to check the virtual size of
the image once its cached and ensure it's <= to the flavor's
root disk size.
Change-Id: I833467284126557eb598b8350a84e10c06292fa9
Fixes: bug 1177830
(cherry picked from commit 44a8aba1d5da87d54db48079103fdef946666d80)
---
nova/tests/test_imagebackend.py | 18 ++++++++++++++++++
nova/virt/libvirt/imagebackend.py | 12 ++++++++++++
2 files changed, 30 insertions(+)
diff --git a/nova/tests/test_imagebackend.py b/nova/tests/test_imagebackend.py
index f0bb718..da14f20 100644
--- a/nova/tests/test_imagebackend.py
+++ b/nova/tests/test_imagebackend.py
@@ -17,6 +17,7 @@
import os
+from nova import exception
from nova import flags
from nova import test
from nova.tests import fake_libvirt_utils
@@ -190,7 +191,10 @@ class Qcow2TestCase(_ImageTestCase):
fn = self.prepare_mocks()
fn(target=self.TEMPLATE_PATH)
self.mox.StubOutWithMock(os.path, 'exists')
+ self.mox.StubOutWithMock(imagebackend.disk, 'get_disk_size')
os.path.exists(self.QCOW2_BASE).AndReturn(False)
+ imagebackend.disk.get_disk_size(self.TEMPLATE_PATH
+ ).AndReturn(self.SIZE)
imagebackend.libvirt_utils.copy_image(self.TEMPLATE_PATH,
self.QCOW2_BASE)
imagebackend.disk.extend(self.QCOW2_BASE, self.SIZE)
@@ -203,11 +207,25 @@ class Qcow2TestCase(_ImageTestCase):
self.mox.VerifyAll()
+ def test_create_image_too_small(self):
+ self.mox.StubOutWithMock(imagebackend.disk, 'get_disk_size')
+ imagebackend.disk.get_disk_size(self.TEMPLATE_PATH
+ ).AndReturn(self.SIZE)
+ self.mox.ReplayAll()
+
+ image = self.image_class(self.INSTANCE, self.NAME)
+ self.assertRaises(exception.ImageTooLarge, image.create_image, None,
+ self.TEMPLATE_PATH, 1)
+ self.mox.VerifyAll()
+
def test_create_image_with_size_template_exists(self):
fn = self.prepare_mocks()
fn(target=self.TEMPLATE_PATH)
self.mox.StubOutWithMock(os.path, 'exists')
+ self.mox.StubOutWithMock(imagebackend.disk, 'get_disk_size')
os.path.exists(self.QCOW2_BASE).AndReturn(True)
+ imagebackend.disk.get_disk_size(self.TEMPLATE_PATH
+ ).AndReturn(self.SIZE)
imagebackend.libvirt_utils.create_cow_image(self.QCOW2_BASE,
self.PATH)
self.mox.ReplayAll()
diff --git a/nova/virt/libvirt/imagebackend.py b/nova/virt/libvirt/imagebackend.py
index 0f2f044..5e7023e 100644
--- a/nova/virt/libvirt/imagebackend.py
+++ b/nova/virt/libvirt/imagebackend.py
@@ -19,14 +19,17 @@ import abc
import contextlib
import os
+from nova import exception
from nova import flags
from nova.openstack.common import cfg
from nova.openstack.common import excutils
+from nova.openstack.common import log as logging
from nova import utils
from nova.virt.disk import api as disk
from nova.virt.libvirt import config
from nova.virt.libvirt import utils as libvirt_utils
+
__imagebackend_opts = [
cfg.StrOpt('libvirt_images_type',
default='default',
@@ -46,6 +49,8 @@ __imagebackend_opts = [
FLAGS = flags.FLAGS
FLAGS.register_opts(__imagebackend_opts)
+LOG = logging.getLogger(__name__)
+
class Image(object):
__metaclass__ = abc.ABCMeta
@@ -170,6 +175,13 @@ class Qcow2(Image):
disk.extend(qcow2_base, size)
libvirt_utils.create_cow_image(qcow2_base, target)
+ # NOTE(cfb): Having a flavor that sets the root size to 0 and having
+ # nova effectively ignore that size and use the size of the
+ # image is considered a feature at this time, not a bug.
+ if size and size < disk.get_disk_size(base):
+ LOG.error('%s virtual size larger than flavor root disk size %s' %
+ (base, size))
+ raise exception.ImageTooLarge()
prepare_template(target=base, *args, **kwargs)
with utils.remove_path_on_error(self.path):
copy_qcow2_image(base, self.path, size)
--
1.8.1.5
|