Merge "libvirt: virtuozzo instance resize support"

This commit is contained in:
Jenkins 2016-06-29 04:33:32 +00:00 committed by Gerrit Code Review
commit 1cb9195aa8
12 changed files with 62 additions and 19 deletions

View File

@ -385,8 +385,10 @@ driver-impl-vmware=complete
driver-impl-hyperv=complete driver-impl-hyperv=complete
driver-impl-ironic=partial driver-impl-ironic=partial
driver-notes-ironic=Only certain ironic drivers support this driver-notes-ironic=Only certain ironic drivers support this
driver-impl-libvirt-vz-vm=missing driver-impl-libvirt-vz-vm=complete
driver-impl-libvirt-vz-ct=missing driver-notes-vz-vm=Resizing Virtuozzo instances implies guest filesystem resize also
driver-impl-libvirt-vz-ct=complete
driver-notes-vz-ct=Resizing Virtuozzo instances implies guest filesystem resize also
[operation.resume] [operation.resume]
title=Restore instance title=Restore instance

View File

@ -246,7 +246,8 @@ cp: CommandFilter, cp, root
sync: CommandFilter, sync, root sync: CommandFilter, sync, root
# nova/virt/libvirt/imagebackend.py: # nova/virt/libvirt/imagebackend.py:
ploop: CommandFilter, ploop, root ploop: RegExpFilter, ploop, root, ploop, restore-descriptor, .*
prl_disk_tool: RegExpFilter, prl_disk_tool, root, prl_disk_tool, resize, --size, .*M$, --resize_partition, --hdd, .*
# nova/virt/libvirt/utils.py: 'xend', 'status' # nova/virt/libvirt/utils.py: 'xend', 'status'
xend: CommandFilter, xend, root xend: CommandFilter, xend, root

View File

@ -18,6 +18,7 @@ import tempfile
import fixtures import fixtures
import mock import mock
from oslo_concurrency import processutils from oslo_concurrency import processutils
from oslo_utils import units
from nova import test from nova import test
from nova import utils from nova import utils
@ -176,6 +177,24 @@ class APITestCase(test.NoDBTestCase):
imgsize) imgsize)
self.assertFalse(mock_extendable.called) self.assertFalse(mock_extendable.called)
@mock.patch.object(api, 'can_resize_image', return_value=True)
@mock.patch.object(utils, 'execute')
def test_extend_ploop(self, mock_execute, mock_can_resize_image):
imgfile = tempfile.NamedTemporaryFile()
self.addCleanup(imgfile.close)
imgsize = 10 * units.Gi
imgsize_mb = str(imgsize // units.Mi) + 'M'
image = imgmodel.LocalFileImage(imgfile, imgmodel.FORMAT_PLOOP)
api.extend(image, imgsize)
mock_can_resize_image.assert_called_once_with(image.path,
imgsize)
mock_execute.assert_called_once_with('prl_disk_tool', 'resize',
'--size', imgsize_mb,
'--resize_partition',
'--hdd', imgfile,
run_as_root=True)
def test_extend_raw_success(self): def test_extend_raw_success(self):
imgfile = tempfile.NamedTemporaryFile() imgfile = tempfile.NamedTemporaryFile()
self.addCleanup(imgfile.close) self.addCleanup(imgfile.close)

View File

@ -1590,6 +1590,7 @@ class PloopTestCase(_ImageTestCase, test.NoDBTestCase):
'__call__') '__call__')
self.mox.StubOutWithMock(imagebackend.libvirt_utils, 'copy_image') self.mox.StubOutWithMock(imagebackend.libvirt_utils, 'copy_image')
self.mox.StubOutWithMock(self.utils, 'execute') self.mox.StubOutWithMock(self.utils, 'execute')
self.mox.StubOutWithMock(imagebackend.disk, 'extend')
return fn return fn
def test_cache(self): def test_cache(self):
@ -1619,9 +1620,9 @@ class PloopTestCase(_ImageTestCase, test.NoDBTestCase):
imagebackend.libvirt_utils.copy_image(self.TEMPLATE_PATH, img_path) imagebackend.libvirt_utils.copy_image(self.TEMPLATE_PATH, img_path)
self.utils.execute("ploop", "restore-descriptor", "-f", "raw", self.utils.execute("ploop", "restore-descriptor", "-f", "raw",
self.PATH, img_path) self.PATH, img_path)
self.utils.execute("ploop", "grow", '-s', "2K", image = imgmodel.LocalFileImage(self.PATH, imgmodel.FORMAT_PLOOP)
os.path.join(self.PATH, "DiskDescriptor.xml"), imagebackend.disk.extend(image, 2048)
run_as_root=True)
self.mox.ReplayAll() self.mox.ReplayAll()
image = self.image_class(self.INSTANCE, self.NAME) image = self.image_class(self.INSTANCE, self.NAME)

View File

@ -44,7 +44,7 @@ class LibvirtUtilsTestCase(test.NoDBTestCase):
@mock.patch('nova.utils.execute') @mock.patch('nova.utils.execute')
def test_copy_image_local(self, mock_execute): def test_copy_image_local(self, mock_execute):
libvirt_utils.copy_image('src', 'dest') libvirt_utils.copy_image('src', 'dest')
mock_execute.assert_called_once_with('cp', 'src', 'dest') mock_execute.assert_called_once_with('cp', '-r', 'src', 'dest')
@mock.patch('nova.virt.libvirt.volume.remotefs.SshDriver.copy_file') @mock.patch('nova.virt.libvirt.volume.remotefs.SshDriver.copy_file')
def test_copy_image_remote_ssh(self, mock_rem_fs_remove): def test_copy_image_remote_ssh(self, mock_rem_fs_remove):

View File

@ -166,7 +166,7 @@ class RemoteFSTestCase(test.NoDBTestCase):
remotefs.RsyncDriver().copy_file('1.2.3.4:/home/star_wars', remotefs.RsyncDriver().copy_file('1.2.3.4:/home/star_wars',
'/home/favourite', None, None, '/home/favourite', None, None,
compression=True) compression=True)
mock_execute.assert_called_once_with('rsync', '--sparse', mock_execute.assert_called_once_with('rsync', '-r', '--sparse',
'1.2.3.4:/home/star_wars', '1.2.3.4:/home/star_wars',
'/home/favourite', '/home/favourite',
'--compress', '--compress',
@ -178,7 +178,7 @@ class RemoteFSTestCase(test.NoDBTestCase):
remotefs.RsyncDriver().copy_file('1.2.3.4:/home/star_wars', remotefs.RsyncDriver().copy_file('1.2.3.4:/home/star_wars',
'/home/favourite', None, None, '/home/favourite', None, None,
compression=False) compression=False)
mock_execute.assert_called_once_with('rsync', '--sparse', mock_execute.assert_called_once_with('rsync', '-r', '--sparse',
'1.2.3.4:/home/star_wars', '1.2.3.4:/home/star_wars',
'/home/favourite', '/home/favourite',
on_completion=None, on_completion=None,
@ -188,7 +188,7 @@ class RemoteFSTestCase(test.NoDBTestCase):
def test_remote_copy_file_ssh(self, mock_execute): def test_remote_copy_file_ssh(self, mock_execute):
remotefs.SshDriver().copy_file('1.2.3.4:/home/SpaceOdyssey', remotefs.SshDriver().copy_file('1.2.3.4:/home/SpaceOdyssey',
'/home/favourite', None, None, True) '/home/favourite', None, None, True)
mock_execute.assert_called_once_with('scp', mock_execute.assert_called_once_with('scp', '-r',
'1.2.3.4:/home/SpaceOdyssey', '1.2.3.4:/home/SpaceOdyssey',
'/home/favourite', '/home/favourite',
on_completion=None, on_completion=None,

View File

@ -33,6 +33,7 @@ if os.name != 'nt':
from oslo_concurrency import processutils from oslo_concurrency import processutils
from oslo_log import log as logging from oslo_log import log as logging
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from oslo_utils import units
import nova.conf import nova.conf
from nova import exception from nova import exception
@ -158,6 +159,16 @@ def extend(image, size):
if not isinstance(image, imgmodel.LocalImage): if not isinstance(image, imgmodel.LocalImage):
return return
if (image.format == imgmodel.FORMAT_PLOOP):
if not can_resize_image(image.path, size):
return
utils.execute('prl_disk_tool', 'resize',
'--size', '%dM' % (size // units.Mi),
'--resize_partition',
'--hdd', image.path, run_as_root=True)
return
if not can_resize_image(image.path, size): if not can_resize_image(image.path, size):
return return

View File

@ -20,10 +20,12 @@ from nova import exception
FORMAT_RAW = "raw" FORMAT_RAW = "raw"
FORMAT_QCOW2 = "qcow2" FORMAT_QCOW2 = "qcow2"
FORMAT_PLOOP = "ploop"
ALL_FORMATS = [ ALL_FORMATS = [
FORMAT_RAW, FORMAT_RAW,
FORMAT_QCOW2, FORMAT_QCOW2,
FORMAT_PLOOP,
] ]

View File

@ -1024,9 +1024,7 @@ class Ploop(Image):
utils.execute('ploop', 'restore-descriptor', '-f', self.pcs_format, utils.execute('ploop', 'restore-descriptor', '-f', self.pcs_format,
target, image_path) target, image_path)
if size: if size:
dd_path = os.path.join(self.path, "DiskDescriptor.xml") self.resize_image(size)
utils.execute('ploop', 'grow', '-s', '%dK' % (size >> 10),
dd_path, run_as_root=True)
if not os.path.exists(self.path): if not os.path.exists(self.path):
if CONF.force_raw_images: if CONF.force_raw_images:
@ -1063,9 +1061,8 @@ class Ploop(Image):
create_ploop_image(base, self.path, size) create_ploop_image(base, self.path, size)
def resize_image(self, size): def resize_image(self, size):
dd_path = os.path.join(self.path, "DiskDescriptor.xml") image = imgmodel.LocalFileImage(self.path, imgmodel.FORMAT_PLOOP)
utils.execute('ploop', 'grow', '-s', '%dK' % (size >> 10), dd_path, disk.extend(image, size)
run_as_root=True)
def snapshot_extract(self, target, out_format): def snapshot_extract(self, target, out_format):
img_path = os.path.join(self.path, "root.hds") img_path = os.path.join(self.path, "root.hds")

View File

@ -199,7 +199,8 @@ def copy_image(src, dest, host=None, receive=False,
# sparse files. I.E. holes will not be written to DEST, # sparse files. I.E. holes will not be written to DEST,
# rather recreated efficiently. In addition, since # rather recreated efficiently. In addition, since
# coreutils 8.11, holes can be read efficiently too. # coreutils 8.11, holes can be read efficiently too.
execute('cp', src, dest) # we add '-r' argument because ploop disks are directories
execute('cp', '-r', src, dest)
else: else:
if receive: if receive:
src = "%s:%s" % (utils.safe_ip_format(host), src) src = "%s:%s" % (utils.safe_ip_format(host), src)

View File

@ -196,7 +196,8 @@ class SshDriver(RemoteFilesystemDriver):
on_execute=on_execute, on_completion=on_completion) on_execute=on_execute, on_completion=on_completion)
def copy_file(self, src, dst, on_execute, on_completion, compression): def copy_file(self, src, dst, on_execute, on_completion, compression):
utils.execute('scp', src, dst, # As far as ploop disks are in fact directories we add '-r' argument
utils.execute('scp', '-r', src, dst,
on_execute=on_execute, on_completion=on_completion) on_execute=on_execute, on_completion=on_completion)
@ -324,7 +325,8 @@ class RsyncDriver(RemoteFilesystemDriver):
on_execute=on_execute, on_completion=on_completion) on_execute=on_execute, on_completion=on_completion)
def copy_file(self, src, dst, on_execute, on_completion, compression): def copy_file(self, src, dst, on_execute, on_completion, compression):
args = ['rsync', '--sparse', src, dst] # As far as ploop disks are in fact directories we add '-r' argument
args = ['rsync', '-r', '--sparse', src, dst]
if compression: if compression:
args.append('--compress') args.append('--compress')
utils.execute(*args, utils.execute(*args,

View File

@ -0,0 +1,7 @@
---
features:
- Virtuozzo ploop disks can be resized now during "nova resize".
upgrade:
- You must update the rootwrap configuration for the compute service
if you use ploop images, so that "ploop grow" filter is changed
to "prl_disk_tool resize".