Skip to content

Commit

Permalink
NFS drivers don't honor vm size with volume from an image
Browse files Browse the repository at this point in the history
The bug has been encountered with the NFS generic driver
(cinder.volume.nfs.NfsDriver) and the NetApp NFS driver
(cinder.volume.drivers.netapp.nfs.NetAppDirectCmodeNfsDriver). I believe
that drivers based on distributed filesystem such as GlusterFS, nexenta
and scality are also impacted however I didn't test it those backends.
However since most of them already inherit from the RemoteFsDriver
class, this should be fine.

Change-Id: I14575da69a2c99c7cbcece27b40a171153371ee3
Fixes: bug #1183459
  • Loading branch information
leseb committed Jun 7, 2013
1 parent b782597 commit 824a3b4
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 0 deletions.
6 changes: 6 additions & 0 deletions cinder/image/image_utils.py
Expand Up @@ -191,6 +191,12 @@ def convert_image(source, dest, out_format):
utils.execute(*cmd, run_as_root=True)


def resize_image(source, size):
"""Changes the virtual size of the image."""
cmd = ('qemu-img', 'resize', source, '%sG' % size)
utils.execute(*cmd, run_as_root=False)


def fetch(context, image_service, image_id, path, _user_id, _project_id):
# TODO(vish): Improve context handling and add owner and auth data
# when it is added to glance. Right now there is no
Expand Down
45 changes: 45 additions & 0 deletions cinder/tests/test_image_utils.py
@@ -0,0 +1,45 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright (c) 2013 eNovance , Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Unit tests for image utils."""

from cinder.image import image_utils
from cinder import test
from cinder import utils
import mox


class TestUtils(test.TestCase):
def setUp(self):
super(TestUtils, self).setUp()
self._mox = mox.Mox()
self.addCleanup(self._mox.UnsetStubs)

def test_resize_image(self):
mox = self._mox
mox.StubOutWithMock(utils, 'execute')

TEST_IMG_SOURCE = 'boobar.img'
TEST_IMG_SIZE_IN_GB = 1

utils.execute('qemu-img', 'resize', TEST_IMG_SOURCE,
'%sG' % TEST_IMG_SIZE_IN_GB, run_as_root=False)

mox.ReplayAll()

image_utils.resize_image(TEST_IMG_SOURCE, TEST_IMG_SIZE_IN_GB)

mox.VerifyAll()
33 changes: 33 additions & 0 deletions cinder/tests/test_nfs.py
Expand Up @@ -33,6 +33,8 @@
from cinder import test
from cinder import units

from cinder.image import image_utils

from cinder.volume import configuration as conf
from cinder.volume.drivers import nfs

Expand Down Expand Up @@ -167,6 +169,37 @@ def test_mount_nfs_should_mount_correctly(self):

mox.VerifyAll()

def test_copy_image_to_volume(self):
"""resize_image common case usage."""
mox = self._mox
drv = self._driver

TEST_IMG_SOURCE = 'foo.img'

volume = {'size': self.TEST_SIZE_IN_GB, 'name': TEST_IMG_SOURCE}

def fake_local_path(volume):
return volume['name']

self.stubs.Set(drv, 'local_path', fake_local_path)

mox.StubOutWithMock(image_utils, 'fetch_to_raw')
image_utils.fetch_to_raw(None, None, None, TEST_IMG_SOURCE)

mox.StubOutWithMock(image_utils, 'resize_image')
image_utils.resize_image(TEST_IMG_SOURCE, self.TEST_SIZE_IN_GB)

mox.StubOutWithMock(image_utils, 'qemu_img_info')
data = mox_lib.MockAnything()
data.virtual_size = 1024 ** 3
image_utils.qemu_img_info(TEST_IMG_SOURCE).AndReturn(data)

mox.ReplayAll()

drv.copy_image_to_volume(None, volume, None, None)

mox.VerifyAll()

def test_mount_nfs_should_suppress_already_mounted_error(self):
"""_mount_nfs should suppress already mounted error if ensure=True
"""
Expand Down
17 changes: 17 additions & 0 deletions cinder/volume/drivers/nfs.py
Expand Up @@ -122,6 +122,23 @@ def copy_image_to_volume(self, context, volume, image_service, image_id):
image_id,
self.local_path(volume))

# NOTE (leseb): Set the virtual size of the image
# the raw conversion overwrote the destination file
# (which had the correct size)
# with the fetched glance image size,
# thus the initial 'size' parameter is not honored
# this sets the size to the one asked in the first place by the user
# and then verify the final virtual size
image_utils.resize_image(self.local_path(volume), volume['size'])

data = image_utils.qemu_img_info(self.local_path(volume))
virt_size = data.virtual_size / units.GiB
if virt_size != volume['size']:
raise exception.ImageUnacceptable(
image_id=image_id,
reason=(_("Expected volume size was %d") % volume['size'])
+ (_(" but size is now %d") % virt_size))

def copy_volume_to_image(self, context, volume, image_service, image_meta):
"""Copy the volume to the specified image."""
image_utils.upload_volume(context,
Expand Down

0 comments on commit 824a3b4

Please sign in to comment.