Merge "libvirt: virtuozzo instance resize support"
This commit is contained in:
commit
1cb9195aa8
@ -385,8 +385,10 @@ driver-impl-vmware=complete
|
||||
driver-impl-hyperv=complete
|
||||
driver-impl-ironic=partial
|
||||
driver-notes-ironic=Only certain ironic drivers support this
|
||||
driver-impl-libvirt-vz-vm=missing
|
||||
driver-impl-libvirt-vz-ct=missing
|
||||
driver-impl-libvirt-vz-vm=complete
|
||||
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]
|
||||
title=Restore instance
|
||||
|
@ -246,7 +246,8 @@ cp: CommandFilter, cp, root
|
||||
sync: CommandFilter, sync, root
|
||||
|
||||
# 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'
|
||||
xend: CommandFilter, xend, root
|
||||
|
@ -18,6 +18,7 @@ import tempfile
|
||||
import fixtures
|
||||
import mock
|
||||
from oslo_concurrency import processutils
|
||||
from oslo_utils import units
|
||||
|
||||
from nova import test
|
||||
from nova import utils
|
||||
@ -176,6 +177,24 @@ class APITestCase(test.NoDBTestCase):
|
||||
imgsize)
|
||||
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):
|
||||
imgfile = tempfile.NamedTemporaryFile()
|
||||
self.addCleanup(imgfile.close)
|
||||
|
@ -1590,6 +1590,7 @@ class PloopTestCase(_ImageTestCase, test.NoDBTestCase):
|
||||
'__call__')
|
||||
self.mox.StubOutWithMock(imagebackend.libvirt_utils, 'copy_image')
|
||||
self.mox.StubOutWithMock(self.utils, 'execute')
|
||||
self.mox.StubOutWithMock(imagebackend.disk, 'extend')
|
||||
return fn
|
||||
|
||||
def test_cache(self):
|
||||
@ -1619,9 +1620,9 @@ class PloopTestCase(_ImageTestCase, test.NoDBTestCase):
|
||||
imagebackend.libvirt_utils.copy_image(self.TEMPLATE_PATH, img_path)
|
||||
self.utils.execute("ploop", "restore-descriptor", "-f", "raw",
|
||||
self.PATH, img_path)
|
||||
self.utils.execute("ploop", "grow", '-s', "2K",
|
||||
os.path.join(self.PATH, "DiskDescriptor.xml"),
|
||||
run_as_root=True)
|
||||
image = imgmodel.LocalFileImage(self.PATH, imgmodel.FORMAT_PLOOP)
|
||||
imagebackend.disk.extend(image, 2048)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
image = self.image_class(self.INSTANCE, self.NAME)
|
||||
|
@ -44,7 +44,7 @@ class LibvirtUtilsTestCase(test.NoDBTestCase):
|
||||
@mock.patch('nova.utils.execute')
|
||||
def test_copy_image_local(self, mock_execute):
|
||||
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')
|
||||
def test_copy_image_remote_ssh(self, mock_rem_fs_remove):
|
||||
|
@ -166,7 +166,7 @@ class RemoteFSTestCase(test.NoDBTestCase):
|
||||
remotefs.RsyncDriver().copy_file('1.2.3.4:/home/star_wars',
|
||||
'/home/favourite', None, None,
|
||||
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',
|
||||
'/home/favourite',
|
||||
'--compress',
|
||||
@ -178,7 +178,7 @@ class RemoteFSTestCase(test.NoDBTestCase):
|
||||
remotefs.RsyncDriver().copy_file('1.2.3.4:/home/star_wars',
|
||||
'/home/favourite', None, None,
|
||||
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',
|
||||
'/home/favourite',
|
||||
on_completion=None,
|
||||
@ -188,7 +188,7 @@ class RemoteFSTestCase(test.NoDBTestCase):
|
||||
def test_remote_copy_file_ssh(self, mock_execute):
|
||||
remotefs.SshDriver().copy_file('1.2.3.4:/home/SpaceOdyssey',
|
||||
'/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',
|
||||
'/home/favourite',
|
||||
on_completion=None,
|
||||
|
@ -33,6 +33,7 @@ if os.name != 'nt':
|
||||
from oslo_concurrency import processutils
|
||||
from oslo_log import log as logging
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils import units
|
||||
|
||||
import nova.conf
|
||||
from nova import exception
|
||||
@ -158,6 +159,16 @@ def extend(image, size):
|
||||
if not isinstance(image, imgmodel.LocalImage):
|
||||
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):
|
||||
return
|
||||
|
||||
|
@ -20,10 +20,12 @@ from nova import exception
|
||||
|
||||
FORMAT_RAW = "raw"
|
||||
FORMAT_QCOW2 = "qcow2"
|
||||
FORMAT_PLOOP = "ploop"
|
||||
|
||||
ALL_FORMATS = [
|
||||
FORMAT_RAW,
|
||||
FORMAT_QCOW2,
|
||||
FORMAT_PLOOP,
|
||||
]
|
||||
|
||||
|
||||
|
@ -1024,9 +1024,7 @@ class Ploop(Image):
|
||||
utils.execute('ploop', 'restore-descriptor', '-f', self.pcs_format,
|
||||
target, image_path)
|
||||
if size:
|
||||
dd_path = os.path.join(self.path, "DiskDescriptor.xml")
|
||||
utils.execute('ploop', 'grow', '-s', '%dK' % (size >> 10),
|
||||
dd_path, run_as_root=True)
|
||||
self.resize_image(size)
|
||||
|
||||
if not os.path.exists(self.path):
|
||||
if CONF.force_raw_images:
|
||||
@ -1063,9 +1061,8 @@ class Ploop(Image):
|
||||
create_ploop_image(base, self.path, size)
|
||||
|
||||
def resize_image(self, size):
|
||||
dd_path = os.path.join(self.path, "DiskDescriptor.xml")
|
||||
utils.execute('ploop', 'grow', '-s', '%dK' % (size >> 10), dd_path,
|
||||
run_as_root=True)
|
||||
image = imgmodel.LocalFileImage(self.path, imgmodel.FORMAT_PLOOP)
|
||||
disk.extend(image, size)
|
||||
|
||||
def snapshot_extract(self, target, out_format):
|
||||
img_path = os.path.join(self.path, "root.hds")
|
||||
|
@ -199,7 +199,8 @@ def copy_image(src, dest, host=None, receive=False,
|
||||
# sparse files. I.E. holes will not be written to DEST,
|
||||
# rather recreated efficiently. In addition, since
|
||||
# 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:
|
||||
if receive:
|
||||
src = "%s:%s" % (utils.safe_ip_format(host), src)
|
||||
|
@ -196,7 +196,8 @@ class SshDriver(RemoteFilesystemDriver):
|
||||
on_execute=on_execute, on_completion=on_completion)
|
||||
|
||||
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)
|
||||
|
||||
|
||||
@ -324,7 +325,8 @@ class RsyncDriver(RemoteFilesystemDriver):
|
||||
on_execute=on_execute, on_completion=on_completion)
|
||||
|
||||
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:
|
||||
args.append('--compress')
|
||||
utils.execute(*args,
|
||||
|
@ -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".
|
Loading…
Reference in New Issue
Block a user