Skip to content

Commit

Permalink
Check QCOW2 image size during root disk creation
Browse files Browse the repository at this point in the history
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 44a8aba)
  • Loading branch information
Chet Burgess authored and mikalstill committed May 15, 2013
1 parent 74aa04e commit 6740c41
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 0 deletions.
18 changes: 18 additions & 0 deletions nova/tests/test_imagebackend.py
Expand Up @@ -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
Expand Down Expand Up @@ -190,7 +191,10 @@ def test_create_image_with_size(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(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)
Expand All @@ -203,11 +207,25 @@ def test_create_image_with_size(self):

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()
Expand Down
12 changes: 12 additions & 0 deletions nova/virt/libvirt/imagebackend.py
Expand Up @@ -19,14 +19,17 @@
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',
Expand All @@ -46,6 +49,8 @@
FLAGS = flags.FLAGS
FLAGS.register_opts(__imagebackend_opts)

LOG = logging.getLogger(__name__)


class Image(object):
__metaclass__ = abc.ABCMeta
Expand Down Expand Up @@ -170,6 +175,13 @@ def copy_qcow2_image(base, target, size):
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)
Expand Down

0 comments on commit 6740c41

Please sign in to comment.