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:
Daniel P. Berrange 2014-10-29 18:10:37 +00:00
parent 79af02046d
commit 0ea510f556
11 changed files with 150 additions and 67 deletions

View File

@ -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")

View File

@ -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))

View File

@ -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)

View File

@ -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()

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)