virt: convert disk mount API to use nova.virt.image.model
Convert the nova.virt.disk.mount classes to use the nova.virt.image.model classes instead of manually passing a filename and image format as parameters. Related-Bug: #1257674 Change-Id: Ibabcf48c95185ba443ef7575590eae6a63e0f8e5
This commit is contained in:
parent
79af02046d
commit
0ea510f556
|
@ -1892,3 +1892,7 @@ class EnumFieldUnset(Invalid):
|
||||||
|
|
||||||
class InvalidImageFormat(Invalid):
|
class InvalidImageFormat(Invalid):
|
||||||
msg_fmt = _("Invalid image format '%(format)s'")
|
msg_fmt = _("Invalid image format '%(format)s'")
|
||||||
|
|
||||||
|
|
||||||
|
class UnsupportedImageModel(Invalid):
|
||||||
|
msg_fmt = _("Image model '%(image)s' is not supported")
|
||||||
|
|
|
@ -18,6 +18,7 @@ import fixtures
|
||||||
|
|
||||||
from nova import test
|
from nova import test
|
||||||
from nova.virt.disk.mount import loop
|
from nova.virt.disk.mount import loop
|
||||||
|
from nova.virt.image import model as imgmodel
|
||||||
|
|
||||||
|
|
||||||
def _fake_noop(*args, **kwargs):
|
def _fake_noop(*args, **kwargs):
|
||||||
|
@ -33,9 +34,15 @@ def _fake_trycmd_losetup_fails(*args, **kwards):
|
||||||
|
|
||||||
|
|
||||||
class LoopTestCase(test.NoDBTestCase):
|
class LoopTestCase(test.NoDBTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(LoopTestCase, self).setUp()
|
||||||
|
|
||||||
|
self.file = imgmodel.LocalFileImage("/some/file.qcow2",
|
||||||
|
imgmodel.FORMAT_QCOW2)
|
||||||
|
|
||||||
def test_get_dev(self):
|
def test_get_dev(self):
|
||||||
tempdir = self.useFixture(fixtures.TempDir()).path
|
tempdir = self.useFixture(fixtures.TempDir()).path
|
||||||
l = loop.LoopMount(None, tempdir)
|
l = loop.LoopMount(self.file, tempdir)
|
||||||
self.useFixture(fixtures.MonkeyPatch('nova.utils.trycmd',
|
self.useFixture(fixtures.MonkeyPatch('nova.utils.trycmd',
|
||||||
_fake_trycmd_losetup_works))
|
_fake_trycmd_losetup_works))
|
||||||
self.useFixture(fixtures.MonkeyPatch('nova.utils.execute',
|
self.useFixture(fixtures.MonkeyPatch('nova.utils.execute',
|
||||||
|
@ -55,7 +62,7 @@ class LoopTestCase(test.NoDBTestCase):
|
||||||
|
|
||||||
def test_inner_get_dev_fails(self):
|
def test_inner_get_dev_fails(self):
|
||||||
tempdir = self.useFixture(fixtures.TempDir()).path
|
tempdir = self.useFixture(fixtures.TempDir()).path
|
||||||
l = loop.LoopMount(None, tempdir)
|
l = loop.LoopMount(self.file, tempdir)
|
||||||
self.useFixture(fixtures.MonkeyPatch('nova.utils.trycmd',
|
self.useFixture(fixtures.MonkeyPatch('nova.utils.trycmd',
|
||||||
_fake_trycmd_losetup_fails))
|
_fake_trycmd_losetup_fails))
|
||||||
|
|
||||||
|
@ -72,7 +79,7 @@ class LoopTestCase(test.NoDBTestCase):
|
||||||
|
|
||||||
def test_get_dev_timeout(self):
|
def test_get_dev_timeout(self):
|
||||||
tempdir = self.useFixture(fixtures.TempDir()).path
|
tempdir = self.useFixture(fixtures.TempDir()).path
|
||||||
l = loop.LoopMount(None, tempdir)
|
l = loop.LoopMount(self.file, tempdir)
|
||||||
self.useFixture(fixtures.MonkeyPatch('time.sleep', _fake_noop))
|
self.useFixture(fixtures.MonkeyPatch('time.sleep', _fake_noop))
|
||||||
self.useFixture(fixtures.MonkeyPatch('nova.utils.trycmd',
|
self.useFixture(fixtures.MonkeyPatch('nova.utils.trycmd',
|
||||||
_fake_trycmd_losetup_fails))
|
_fake_trycmd_losetup_fails))
|
||||||
|
@ -89,7 +96,7 @@ class LoopTestCase(test.NoDBTestCase):
|
||||||
|
|
||||||
def test_unget_dev(self):
|
def test_unget_dev(self):
|
||||||
tempdir = self.useFixture(fixtures.TempDir()).path
|
tempdir = self.useFixture(fixtures.TempDir()).path
|
||||||
l = loop.LoopMount(None, tempdir)
|
l = loop.LoopMount(self.file, tempdir)
|
||||||
self.useFixture(fixtures.MonkeyPatch('nova.utils.execute',
|
self.useFixture(fixtures.MonkeyPatch('nova.utils.execute',
|
||||||
_fake_noop))
|
_fake_noop))
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import fixtures
|
||||||
|
|
||||||
from nova import test
|
from nova import test
|
||||||
from nova.virt.disk.mount import nbd
|
from nova.virt.disk.mount import nbd
|
||||||
|
from nova.virt.image import model as imgmodel
|
||||||
|
|
||||||
ORIG_EXISTS = os.path.exists
|
ORIG_EXISTS = os.path.exists
|
||||||
ORIG_LISTDIR = os.listdir
|
ORIG_LISTDIR = os.listdir
|
||||||
|
@ -67,24 +68,26 @@ class NbdTestCase(test.NoDBTestCase):
|
||||||
_fake_detect_nbd_devices)
|
_fake_detect_nbd_devices)
|
||||||
self.useFixture(fixtures.MonkeyPatch('os.listdir',
|
self.useFixture(fixtures.MonkeyPatch('os.listdir',
|
||||||
_fake_listdir_nbd_devices))
|
_fake_listdir_nbd_devices))
|
||||||
|
self.file = imgmodel.LocalFileImage("/some/file.qcow2",
|
||||||
|
imgmodel.FORMAT_QCOW2)
|
||||||
|
|
||||||
def test_nbd_no_devices(self):
|
def test_nbd_no_devices(self):
|
||||||
tempdir = self.useFixture(fixtures.TempDir()).path
|
tempdir = self.useFixture(fixtures.TempDir()).path
|
||||||
self.stubs.Set(nbd.NbdMount, '_detect_nbd_devices',
|
self.stubs.Set(nbd.NbdMount, '_detect_nbd_devices',
|
||||||
_fake_detect_nbd_devices_none)
|
_fake_detect_nbd_devices_none)
|
||||||
n = nbd.NbdMount(None, tempdir)
|
n = nbd.NbdMount(self.file, tempdir)
|
||||||
self.assertIsNone(n._allocate_nbd())
|
self.assertIsNone(n._allocate_nbd())
|
||||||
|
|
||||||
def test_nbd_no_free_devices(self):
|
def test_nbd_no_free_devices(self):
|
||||||
tempdir = self.useFixture(fixtures.TempDir()).path
|
tempdir = self.useFixture(fixtures.TempDir()).path
|
||||||
n = nbd.NbdMount(None, tempdir)
|
n = nbd.NbdMount(self.file, tempdir)
|
||||||
self.useFixture(fixtures.MonkeyPatch('os.path.exists',
|
self.useFixture(fixtures.MonkeyPatch('os.path.exists',
|
||||||
_fake_exists_all_used))
|
_fake_exists_all_used))
|
||||||
self.assertIsNone(n._allocate_nbd())
|
self.assertIsNone(n._allocate_nbd())
|
||||||
|
|
||||||
def test_nbd_not_loaded(self):
|
def test_nbd_not_loaded(self):
|
||||||
tempdir = self.useFixture(fixtures.TempDir()).path
|
tempdir = self.useFixture(fixtures.TempDir()).path
|
||||||
n = nbd.NbdMount(None, tempdir)
|
n = nbd.NbdMount(self.file, tempdir)
|
||||||
|
|
||||||
# Fake out os.path.exists
|
# Fake out os.path.exists
|
||||||
def fake_exists(path):
|
def fake_exists(path):
|
||||||
|
@ -101,7 +104,7 @@ class NbdTestCase(test.NoDBTestCase):
|
||||||
|
|
||||||
def test_nbd_allocation(self):
|
def test_nbd_allocation(self):
|
||||||
tempdir = self.useFixture(fixtures.TempDir()).path
|
tempdir = self.useFixture(fixtures.TempDir()).path
|
||||||
n = nbd.NbdMount(None, tempdir)
|
n = nbd.NbdMount(self.file, tempdir)
|
||||||
self.useFixture(fixtures.MonkeyPatch('os.path.exists',
|
self.useFixture(fixtures.MonkeyPatch('os.path.exists',
|
||||||
_fake_exists_no_users))
|
_fake_exists_no_users))
|
||||||
self.useFixture(fixtures.MonkeyPatch('random.shuffle', _fake_noop))
|
self.useFixture(fixtures.MonkeyPatch('random.shuffle', _fake_noop))
|
||||||
|
@ -111,7 +114,7 @@ class NbdTestCase(test.NoDBTestCase):
|
||||||
|
|
||||||
def test_nbd_allocation_one_in_use(self):
|
def test_nbd_allocation_one_in_use(self):
|
||||||
tempdir = self.useFixture(fixtures.TempDir()).path
|
tempdir = self.useFixture(fixtures.TempDir()).path
|
||||||
n = nbd.NbdMount(None, tempdir)
|
n = nbd.NbdMount(self.file, tempdir)
|
||||||
self.useFixture(fixtures.MonkeyPatch('random.shuffle', _fake_noop))
|
self.useFixture(fixtures.MonkeyPatch('random.shuffle', _fake_noop))
|
||||||
|
|
||||||
# Fake out os.path.exists
|
# Fake out os.path.exists
|
||||||
|
@ -135,12 +138,12 @@ class NbdTestCase(test.NoDBTestCase):
|
||||||
tempdir = self.useFixture(fixtures.TempDir()).path
|
tempdir = self.useFixture(fixtures.TempDir()).path
|
||||||
self.stubs.Set(nbd.NbdMount, '_detect_nbd_devices',
|
self.stubs.Set(nbd.NbdMount, '_detect_nbd_devices',
|
||||||
_fake_detect_nbd_devices_none)
|
_fake_detect_nbd_devices_none)
|
||||||
n = nbd.NbdMount(None, tempdir)
|
n = nbd.NbdMount(self.file, tempdir)
|
||||||
self.assertFalse(n._inner_get_dev())
|
self.assertFalse(n._inner_get_dev())
|
||||||
|
|
||||||
def test_inner_get_dev_qemu_fails(self):
|
def test_inner_get_dev_qemu_fails(self):
|
||||||
tempdir = self.useFixture(fixtures.TempDir()).path
|
tempdir = self.useFixture(fixtures.TempDir()).path
|
||||||
n = nbd.NbdMount(None, tempdir)
|
n = nbd.NbdMount(self.file, tempdir)
|
||||||
self.useFixture(fixtures.MonkeyPatch('os.path.exists',
|
self.useFixture(fixtures.MonkeyPatch('os.path.exists',
|
||||||
_fake_exists_no_users))
|
_fake_exists_no_users))
|
||||||
|
|
||||||
|
@ -155,7 +158,7 @@ class NbdTestCase(test.NoDBTestCase):
|
||||||
|
|
||||||
def test_inner_get_dev_qemu_timeout(self):
|
def test_inner_get_dev_qemu_timeout(self):
|
||||||
tempdir = self.useFixture(fixtures.TempDir()).path
|
tempdir = self.useFixture(fixtures.TempDir()).path
|
||||||
n = nbd.NbdMount(None, tempdir)
|
n = nbd.NbdMount(self.file, tempdir)
|
||||||
self.useFixture(fixtures.MonkeyPatch('os.path.exists',
|
self.useFixture(fixtures.MonkeyPatch('os.path.exists',
|
||||||
_fake_exists_no_users))
|
_fake_exists_no_users))
|
||||||
|
|
||||||
|
@ -195,7 +198,7 @@ class NbdTestCase(test.NoDBTestCase):
|
||||||
|
|
||||||
def test_inner_get_dev_works(self):
|
def test_inner_get_dev_works(self):
|
||||||
tempdir = self.useFixture(fixtures.TempDir()).path
|
tempdir = self.useFixture(fixtures.TempDir()).path
|
||||||
n = nbd.NbdMount(None, tempdir)
|
n = nbd.NbdMount(self.file, tempdir)
|
||||||
self.useFixture(fixtures.MonkeyPatch('random.shuffle', _fake_noop))
|
self.useFixture(fixtures.MonkeyPatch('random.shuffle', _fake_noop))
|
||||||
self.useFixture(fixtures.MonkeyPatch('os.path.exists',
|
self.useFixture(fixtures.MonkeyPatch('os.path.exists',
|
||||||
self.fake_exists_one))
|
self.fake_exists_one))
|
||||||
|
@ -219,13 +222,13 @@ class NbdTestCase(test.NoDBTestCase):
|
||||||
# This test is just checking we don't get an exception when we unget
|
# This test is just checking we don't get an exception when we unget
|
||||||
# something we don't have
|
# something we don't have
|
||||||
tempdir = self.useFixture(fixtures.TempDir()).path
|
tempdir = self.useFixture(fixtures.TempDir()).path
|
||||||
n = nbd.NbdMount(None, tempdir)
|
n = nbd.NbdMount(self.file, tempdir)
|
||||||
self.useFixture(fixtures.MonkeyPatch('nova.utils.execute', _fake_noop))
|
self.useFixture(fixtures.MonkeyPatch('nova.utils.execute', _fake_noop))
|
||||||
n.unget_dev()
|
n.unget_dev()
|
||||||
|
|
||||||
def test_get_dev(self):
|
def test_get_dev(self):
|
||||||
tempdir = self.useFixture(fixtures.TempDir()).path
|
tempdir = self.useFixture(fixtures.TempDir()).path
|
||||||
n = nbd.NbdMount(None, tempdir)
|
n = nbd.NbdMount(self.file, tempdir)
|
||||||
self.useFixture(fixtures.MonkeyPatch('random.shuffle', _fake_noop))
|
self.useFixture(fixtures.MonkeyPatch('random.shuffle', _fake_noop))
|
||||||
self.useFixture(fixtures.MonkeyPatch('nova.utils.execute', _fake_noop))
|
self.useFixture(fixtures.MonkeyPatch('nova.utils.execute', _fake_noop))
|
||||||
self.useFixture(fixtures.MonkeyPatch('os.path.exists',
|
self.useFixture(fixtures.MonkeyPatch('os.path.exists',
|
||||||
|
@ -252,7 +255,7 @@ class NbdTestCase(test.NoDBTestCase):
|
||||||
self.stubs.Set(nbd.NbdMount, '_inner_get_dev', fake_get_dev_fails)
|
self.stubs.Set(nbd.NbdMount, '_inner_get_dev', fake_get_dev_fails)
|
||||||
|
|
||||||
tempdir = self.useFixture(fixtures.TempDir()).path
|
tempdir = self.useFixture(fixtures.TempDir()).path
|
||||||
n = nbd.NbdMount(None, tempdir)
|
n = nbd.NbdMount(self.file, tempdir)
|
||||||
self.useFixture(fixtures.MonkeyPatch('random.shuffle', _fake_noop))
|
self.useFixture(fixtures.MonkeyPatch('random.shuffle', _fake_noop))
|
||||||
self.useFixture(fixtures.MonkeyPatch('time.sleep', _fake_noop))
|
self.useFixture(fixtures.MonkeyPatch('time.sleep', _fake_noop))
|
||||||
self.useFixture(fixtures.MonkeyPatch('nova.utils.execute', _fake_noop))
|
self.useFixture(fixtures.MonkeyPatch('nova.utils.execute', _fake_noop))
|
||||||
|
@ -318,7 +321,7 @@ class NbdTestCase(test.NoDBTestCase):
|
||||||
pid_exists))
|
pid_exists))
|
||||||
|
|
||||||
def get_a_device():
|
def get_a_device():
|
||||||
n = nbd.NbdMount(None, tempdir)
|
n = nbd.NbdMount(self.file, tempdir)
|
||||||
n.get_dev()
|
n.get_dev()
|
||||||
chosen_devices.append(n.device)
|
chosen_devices.append(n.device)
|
||||||
|
|
||||||
|
|
|
@ -23,13 +23,14 @@ from nova import test
|
||||||
from nova import utils
|
from nova import utils
|
||||||
from nova.virt.disk import api
|
from nova.virt.disk import api
|
||||||
from nova.virt.disk.mount import api as mount
|
from nova.virt.disk.mount import api as mount
|
||||||
|
from nova.virt.image import model as imgmodel
|
||||||
|
|
||||||
|
|
||||||
class FakeMount(object):
|
class FakeMount(object):
|
||||||
device = None
|
device = None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def instance_for_format(imgfile, mountdir, partition, imgfmt):
|
def instance_for_format(image, mountdir, partition):
|
||||||
return FakeMount()
|
return FakeMount()
|
||||||
|
|
||||||
def get_dev(self):
|
def get_dev(self):
|
||||||
|
@ -115,10 +116,11 @@ class APITestCase(test.NoDBTestCase):
|
||||||
imgsize = 10
|
imgsize = 10
|
||||||
device = "/dev/sdh"
|
device = "/dev/sdh"
|
||||||
use_cow = True
|
use_cow = True
|
||||||
|
image = imgmodel.LocalFileImage(imgfile, imgmodel.FORMAT_QCOW2)
|
||||||
|
|
||||||
self.flags(resize_fs_using_block_device=True)
|
self.flags(resize_fs_using_block_device=True)
|
||||||
mounter = FakeMount.instance_for_format(
|
mounter = FakeMount.instance_for_format(
|
||||||
imgfile, None, None, 'qcow2')
|
image, None, None)
|
||||||
mounter.device = device
|
mounter.device = device
|
||||||
|
|
||||||
self.mox.StubOutWithMock(api, 'can_resize_image')
|
self.mox.StubOutWithMock(api, 'can_resize_image')
|
||||||
|
@ -133,8 +135,7 @@ class APITestCase(test.NoDBTestCase):
|
||||||
api.can_resize_image(imgfile, imgsize).AndReturn(True)
|
api.can_resize_image(imgfile, imgsize).AndReturn(True)
|
||||||
utils.execute('qemu-img', 'resize', imgfile, imgsize)
|
utils.execute('qemu-img', 'resize', imgfile, imgsize)
|
||||||
api.is_image_extendable(imgfile, use_cow).AndReturn(True)
|
api.is_image_extendable(imgfile, use_cow).AndReturn(True)
|
||||||
mount.Mount.instance_for_format(
|
mount.Mount.instance_for_format(image, None, None).AndReturn(mounter)
|
||||||
imgfile, None, None, 'qcow2').AndReturn(mounter)
|
|
||||||
mounter.get_dev().AndReturn(True)
|
mounter.get_dev().AndReturn(True)
|
||||||
api.resize2fs(mounter.device, run_as_root=True, check_exit_code=[0])
|
api.resize2fs(mounter.device, run_as_root=True, check_exit_code=[0])
|
||||||
mounter.unget_dev()
|
mounter.unget_dev()
|
||||||
|
|
|
@ -23,6 +23,7 @@ from nova import test
|
||||||
from nova.tests.unit import utils as tests_utils
|
from nova.tests.unit import utils as tests_utils
|
||||||
import nova.utils
|
import nova.utils
|
||||||
from nova.virt.disk.vfs import localfs as vfsimpl
|
from nova.virt.disk.vfs import localfs as vfsimpl
|
||||||
|
from nova.virt.image import model as imgmodel
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
@ -432,7 +433,9 @@ class VirtDiskVFSLocalFSTest(test.NoDBTestCase):
|
||||||
|
|
||||||
self.assertTrue(mkdtemp.called)
|
self.assertTrue(mkdtemp.called)
|
||||||
NbdMount.assert_called_once_with(
|
NbdMount.assert_called_once_with(
|
||||||
'img.qcow2', 'tmp/', None)
|
imgmodel.LocalFileImage('img.qcow2',
|
||||||
|
imgmodel.FORMAT_QCOW2),
|
||||||
|
'tmp/', None)
|
||||||
mounter.do_mount.assert_called_once_with()
|
mounter.do_mount.assert_called_once_with()
|
||||||
|
|
||||||
@mock.patch.object(tempfile, 'mkdtemp')
|
@mock.patch.object(tempfile, 'mkdtemp')
|
||||||
|
@ -448,5 +451,7 @@ class VirtDiskVFSLocalFSTest(test.NoDBTestCase):
|
||||||
|
|
||||||
self.assertTrue(mkdtemp.called)
|
self.assertTrue(mkdtemp.called)
|
||||||
NbdMount.assert_called_once_with(
|
NbdMount.assert_called_once_with(
|
||||||
'img.qcow2', 'tmp/', None)
|
imgmodel.LocalFileImage('img.qcow2',
|
||||||
|
imgmodel.FORMAT_QCOW2),
|
||||||
|
'tmp/', None)
|
||||||
self.assertFalse(mounter.do_mount.called)
|
self.assertFalse(mounter.do_mount.called)
|
||||||
|
|
|
@ -131,7 +131,7 @@ class TestDiskImage(test.NoDBTestCase):
|
||||||
mountdir = '/mnt/fake_rootfs'
|
mountdir = '/mnt/fake_rootfs'
|
||||||
fakemount = FakeMount(image, mountdir, None)
|
fakemount = FakeMount(image, mountdir, None)
|
||||||
|
|
||||||
def fake_instance_for_format(imgfile, mountdir, partition, imgfmt):
|
def fake_instance_for_format(image, mountdir, partition):
|
||||||
return fakemount
|
return fakemount
|
||||||
|
|
||||||
self.stubs.Set(mount.Mount, 'instance_for_format',
|
self.stubs.Set(mount.Mount, 'instance_for_format',
|
||||||
|
@ -149,7 +149,7 @@ class TestDiskImage(test.NoDBTestCase):
|
||||||
mountdir = '/mnt/fake_rootfs'
|
mountdir = '/mnt/fake_rootfs'
|
||||||
fakemount = FakeMount(image, mountdir, None)
|
fakemount = FakeMount(image, mountdir, None)
|
||||||
|
|
||||||
def fake_instance_for_format(imgfile, mountdir, partition, imgfmt):
|
def fake_instance_for_format(image, mountdir, partition):
|
||||||
return fakemount
|
return fakemount
|
||||||
|
|
||||||
self.stubs.Set(mount.Mount, 'instance_for_format',
|
self.stubs.Set(mount.Mount, 'instance_for_format',
|
||||||
|
@ -169,7 +169,7 @@ class TestDiskImage(test.NoDBTestCase):
|
||||||
mountdir = '/mnt/fake_rootfs'
|
mountdir = '/mnt/fake_rootfs'
|
||||||
fakemount = FakeMount(image, mountdir, None)
|
fakemount = FakeMount(image, mountdir, None)
|
||||||
|
|
||||||
def fake_instance_for_format(imgfile, mountdir, partition, imgfmt):
|
def fake_instance_for_format(image, mountdir, partition):
|
||||||
return fakemount
|
return fakemount
|
||||||
|
|
||||||
self.stubs.Set(mount.Mount, 'instance_for_format',
|
self.stubs.Set(mount.Mount, 'instance_for_format',
|
||||||
|
@ -200,8 +200,8 @@ class TestVirtDisk(test.NoDBTestCase):
|
||||||
def proc_mounts(self, mount_point):
|
def proc_mounts(self, mount_point):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def fake_instance_for_format(imgfile, mountdir, partition, imgfmt):
|
def fake_instance_for_format(image, mountdir, partition):
|
||||||
return FakeMount(imgfile, mountdir, partition)
|
return FakeMount(image, mountdir, partition)
|
||||||
|
|
||||||
self.stubs.Set(os.path, 'exists', lambda _: True)
|
self.stubs.Set(os.path, 'exists', lambda _: True)
|
||||||
self.stubs.Set(disk_api._DiskImage, '_device_for_path', proc_mounts)
|
self.stubs.Set(disk_api._DiskImage, '_device_for_path', proc_mounts)
|
||||||
|
|
|
@ -42,6 +42,7 @@ from nova.i18n import _LW
|
||||||
from nova import utils
|
from nova import utils
|
||||||
from nova.virt.disk.mount import api as mount
|
from nova.virt.disk.mount import api as mount
|
||||||
from nova.virt.disk.vfs import api as vfs
|
from nova.virt.disk.vfs import api as vfs
|
||||||
|
from nova.virt.image import model as imgmodel
|
||||||
from nova.virt import images
|
from nova.virt import images
|
||||||
|
|
||||||
|
|
||||||
|
@ -173,7 +174,12 @@ def get_disk_size(path):
|
||||||
|
|
||||||
|
|
||||||
def extend(image, size, use_cow=False):
|
def extend(image, size, use_cow=False):
|
||||||
"""Increase image to size."""
|
"""Increase image to size.
|
||||||
|
|
||||||
|
:param image: path to disk image file
|
||||||
|
:param size: image size in bytes
|
||||||
|
:param use_cow: whether the disk is a qcow2 file
|
||||||
|
"""
|
||||||
if not can_resize_image(image, size):
|
if not can_resize_image(image, size):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -200,7 +206,9 @@ def extend(image, size, use_cow=False):
|
||||||
# in case of non-raw disks we can't just resize the image, but
|
# in case of non-raw disks we can't just resize the image, but
|
||||||
# rather the mounted device instead
|
# rather the mounted device instead
|
||||||
mounter = mount.Mount.instance_for_format(
|
mounter = mount.Mount.instance_for_format(
|
||||||
image, None, None, 'qcow2')
|
imgmodel.LocalFileImage(image,
|
||||||
|
imgmodel.FORMAT_QCOW2),
|
||||||
|
None, None)
|
||||||
if mounter.get_dev():
|
if mounter.get_dev():
|
||||||
safe_resize2fs(mounter.device,
|
safe_resize2fs(mounter.device,
|
||||||
run_as_root=True,
|
run_as_root=True,
|
||||||
|
@ -270,11 +278,24 @@ class _DiskImage(object):
|
||||||
tmp_prefix = 'openstack-disk-mount-tmp'
|
tmp_prefix = 'openstack-disk-mount-tmp'
|
||||||
|
|
||||||
def __init__(self, image, partition=None, use_cow=False, mount_dir=None):
|
def __init__(self, image, partition=None, use_cow=False, mount_dir=None):
|
||||||
|
"""Create a new _DiskImage object instance
|
||||||
|
|
||||||
|
:param image: the path to the disk image file
|
||||||
|
:param partition: the partition number within the image
|
||||||
|
:param use_cow: whether the disk is in qcow2 format
|
||||||
|
:param mount_dir: the directory to mount the image on
|
||||||
|
"""
|
||||||
|
|
||||||
# These passed to each mounter
|
# These passed to each mounter
|
||||||
self.image = image
|
|
||||||
self.partition = partition
|
self.partition = partition
|
||||||
self.mount_dir = mount_dir
|
self.mount_dir = mount_dir
|
||||||
self.use_cow = use_cow
|
|
||||||
|
if use_cow:
|
||||||
|
self.image = imgmodel.LocalFileImage(image,
|
||||||
|
imgmodel.FORMAT_QCOW2)
|
||||||
|
else:
|
||||||
|
self.image = imgmodel.LocalFileImage(image,
|
||||||
|
imgmodel.FORMAT_RAW)
|
||||||
|
|
||||||
# Internal
|
# Internal
|
||||||
self._mkdir = False
|
self._mkdir = False
|
||||||
|
@ -328,14 +349,10 @@ class _DiskImage(object):
|
||||||
self.mount_dir = tempfile.mkdtemp(prefix=self.tmp_prefix)
|
self.mount_dir = tempfile.mkdtemp(prefix=self.tmp_prefix)
|
||||||
self._mkdir = True
|
self._mkdir = True
|
||||||
|
|
||||||
imgfmt = "raw"
|
|
||||||
if self.use_cow:
|
|
||||||
imgfmt = "qcow2"
|
|
||||||
|
|
||||||
mounter = mount.Mount.instance_for_format(self.image,
|
mounter = mount.Mount.instance_for_format(self.image,
|
||||||
self.mount_dir,
|
self.mount_dir,
|
||||||
self.partition,
|
self.partition)
|
||||||
imgfmt)
|
|
||||||
if mounter.do_mount():
|
if mounter.do_mount():
|
||||||
self._mounter = mounter
|
self._mounter = mounter
|
||||||
return self._mounter.device
|
return self._mounter.device
|
||||||
|
|
|
@ -19,8 +19,10 @@ import time
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_utils import importutils
|
from oslo_utils import importutils
|
||||||
|
|
||||||
|
from nova import exception
|
||||||
from nova.i18n import _, _LI, _LW
|
from nova.i18n import _, _LI, _LW
|
||||||
from nova import utils
|
from nova import utils
|
||||||
|
from nova.virt.image import model as imgmodel
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -37,42 +39,79 @@ class Mount(object):
|
||||||
mode = None # to be overridden in subclasses
|
mode = None # to be overridden in subclasses
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def instance_for_format(imgfile, mountdir, partition, imgfmt):
|
def instance_for_format(image, mountdir, partition):
|
||||||
LOG.debug("Instance for format imgfile=%(imgfile)s "
|
"""Get a Mount instance for the image type
|
||||||
"mountdir=%(mountdir)s partition=%(partition)s "
|
|
||||||
"imgfmt=%(imgfmt)s",
|
:param image: instance of nova.virt.image.model.Image
|
||||||
{'imgfile': imgfile, 'mountdir': mountdir,
|
:param mountdir: path to mount the image at
|
||||||
'partition': partition, 'imgfmt': imgfmt})
|
:param partition: partition number to mount
|
||||||
if imgfmt == "raw":
|
"""
|
||||||
LOG.debug("Using LoopMount")
|
LOG.debug("Instance for format image=%(image)s "
|
||||||
return importutils.import_object(
|
"mountdir=%(mountdir)s partition=%(partition)s",
|
||||||
"nova.virt.disk.mount.loop.LoopMount",
|
{'image': image, 'mountdir': mountdir,
|
||||||
imgfile, mountdir, partition)
|
'partition': partition})
|
||||||
|
|
||||||
|
if isinstance(image, imgmodel.LocalFileImage):
|
||||||
|
if image.format == imgmodel.FORMAT_RAW:
|
||||||
|
LOG.debug("Using LoopMount")
|
||||||
|
return importutils.import_object(
|
||||||
|
"nova.virt.disk.mount.loop.LoopMount",
|
||||||
|
image, mountdir, partition)
|
||||||
|
else:
|
||||||
|
LOG.debug("Using NbdMount")
|
||||||
|
return importutils.import_object(
|
||||||
|
"nova.virt.disk.mount.nbd.NbdMount",
|
||||||
|
image, mountdir, partition)
|
||||||
else:
|
else:
|
||||||
LOG.debug("Using NbdMount")
|
# TODO(berrange) we could mount images of
|
||||||
return importutils.import_object(
|
# type LocalBlockImage directly without
|
||||||
"nova.virt.disk.mount.nbd.NbdMount",
|
# involving loop or nbd devices
|
||||||
imgfile, mountdir, partition)
|
#
|
||||||
|
# We could also mount RBDImage directly
|
||||||
|
# using kernel RBD block dev support.
|
||||||
|
#
|
||||||
|
# This is left as an enhancement for future
|
||||||
|
# motivated developers todo, since raising
|
||||||
|
# an exception is on par with what this
|
||||||
|
# code did historically
|
||||||
|
raise exception.UnsupportedImageModel(
|
||||||
|
image.__class__.__name__)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def instance_for_device(imgfile, mountdir, partition, device):
|
def instance_for_device(image, mountdir, partition, device):
|
||||||
LOG.debug("Instance for device imgfile=%(imgfile)s "
|
"""Get a Mount instance for the device type
|
||||||
|
|
||||||
|
:param image: instance of nova.virt.image.model.Image
|
||||||
|
:param mountdir: path to mount the image at
|
||||||
|
:param partition: partition number to mount
|
||||||
|
:param device: mounted device path
|
||||||
|
"""
|
||||||
|
|
||||||
|
LOG.debug("Instance for device image=%(image)s "
|
||||||
"mountdir=%(mountdir)s partition=%(partition)s "
|
"mountdir=%(mountdir)s partition=%(partition)s "
|
||||||
"device=%(device)s",
|
"device=%(device)s",
|
||||||
{'imgfile': imgfile, 'mountdir': mountdir,
|
{'image': image, 'mountdir': mountdir,
|
||||||
'partition': partition, 'device': device})
|
'partition': partition, 'device': device})
|
||||||
|
|
||||||
if "loop" in device:
|
if "loop" in device:
|
||||||
LOG.debug("Using LoopMount")
|
LOG.debug("Using LoopMount")
|
||||||
return importutils.import_object(
|
return importutils.import_object(
|
||||||
"nova.virt.disk.mount.loop.LoopMount",
|
"nova.virt.disk.mount.loop.LoopMount",
|
||||||
imgfile, mountdir, partition, device)
|
image, mountdir, partition, device)
|
||||||
else:
|
else:
|
||||||
LOG.debug("Using NbdMount")
|
LOG.debug("Using NbdMount")
|
||||||
return importutils.import_object(
|
return importutils.import_object(
|
||||||
"nova.virt.disk.mount.nbd.NbdMount",
|
"nova.virt.disk.mount.nbd.NbdMount",
|
||||||
imgfile, mountdir, partition, device)
|
image, mountdir, partition, device)
|
||||||
|
|
||||||
def __init__(self, image, mount_dir, partition=None, device=None):
|
def __init__(self, image, mount_dir, partition=None, device=None):
|
||||||
|
"""Create a new Mount instance
|
||||||
|
|
||||||
|
:param image: instance of nova.virt.image.model.Image
|
||||||
|
:param mount_dir: path to mount the image at
|
||||||
|
:param partition: partition number to mount
|
||||||
|
:param device: mounted device path
|
||||||
|
"""
|
||||||
|
|
||||||
# Input
|
# Input
|
||||||
self.image = image
|
self.image = image
|
||||||
|
|
|
@ -27,7 +27,8 @@ class LoopMount(api.Mount):
|
||||||
mode = 'loop'
|
mode = 'loop'
|
||||||
|
|
||||||
def _inner_get_dev(self):
|
def _inner_get_dev(self):
|
||||||
out, err = utils.trycmd('losetup', '--find', '--show', self.image,
|
out, err = utils.trycmd('losetup', '--find', '--show',
|
||||||
|
self.image.path,
|
||||||
run_as_root=True)
|
run_as_root=True)
|
||||||
if err:
|
if err:
|
||||||
self.error = _('Could not attach image to loopback: %s') % err
|
self.error = _('Could not attach image to loopback: %s') % err
|
||||||
|
|
|
@ -83,8 +83,9 @@ class NbdMount(api.Mount):
|
||||||
# NOTE(mikal): qemu-nbd will return an error if the device file is
|
# NOTE(mikal): qemu-nbd will return an error if the device file is
|
||||||
# already in use.
|
# already in use.
|
||||||
LOG.debug('Get nbd device %(dev)s for %(imgfile)s',
|
LOG.debug('Get nbd device %(dev)s for %(imgfile)s',
|
||||||
{'dev': device, 'imgfile': self.image})
|
{'dev': device, 'imgfile': self.image.path})
|
||||||
_out, err = utils.trycmd('qemu-nbd', '-c', device, self.image,
|
_out, err = utils.trycmd('qemu-nbd', '-c', device,
|
||||||
|
self.image.path,
|
||||||
run_as_root=True)
|
run_as_root=True)
|
||||||
if err:
|
if err:
|
||||||
self.error = _('qemu-nbd error: %s') % err
|
self.error = _('qemu-nbd error: %s') % err
|
||||||
|
|
|
@ -24,6 +24,7 @@ from nova import utils
|
||||||
from nova.virt.disk.mount import loop
|
from nova.virt.disk.mount import loop
|
||||||
from nova.virt.disk.mount import nbd
|
from nova.virt.disk.mount import nbd
|
||||||
from nova.virt.disk.vfs import api as vfs
|
from nova.virt.disk.vfs import api as vfs
|
||||||
|
from nova.virt.image import model as imgmodel
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -65,14 +66,18 @@ class VFSLocalFS(vfs.VFS):
|
||||||
try:
|
try:
|
||||||
if self.imgfmt == "raw":
|
if self.imgfmt == "raw":
|
||||||
LOG.debug("Using LoopMount")
|
LOG.debug("Using LoopMount")
|
||||||
mnt = loop.LoopMount(self.imgfile,
|
mnt = loop.LoopMount(
|
||||||
self.imgdir,
|
imgmodel.LocalFileImage(self.imgfile,
|
||||||
self.partition)
|
imgmodel.FORMAT_RAW),
|
||||||
|
self.imgdir,
|
||||||
|
self.partition)
|
||||||
else:
|
else:
|
||||||
LOG.debug("Using NbdMount")
|
LOG.debug("Using NbdMount")
|
||||||
mnt = nbd.NbdMount(self.imgfile,
|
mnt = nbd.NbdMount(
|
||||||
self.imgdir,
|
imgmodel.LocalFileImage(self.imgfile,
|
||||||
self.partition)
|
imgmodel.FORMAT_QCOW2),
|
||||||
|
self.imgdir,
|
||||||
|
self.partition)
|
||||||
if mount:
|
if mount:
|
||||||
if not mnt.do_mount():
|
if not mnt.do_mount():
|
||||||
raise exception.NovaException(mnt.error)
|
raise exception.NovaException(mnt.error)
|
||||||
|
|
Loading…
Reference in New Issue