From c0e7cafff16c934adf80aecbfea8c8f04c10da1a Mon Sep 17 00:00:00 2001 From: Sahid Orentino Ferdjaoui Date: Thu, 4 Sep 2014 13:48:44 +0000 Subject: [PATCH] disk/vfs: introduce new option to setup Introduces new option mount=True|False which prevents mounting devices when setuping an instance of vfs. Related-bug: #1358316 Change-Id: I8d2d0b44890fa5277dc9d902d12d6f9ac883f155 --- nova/tests/unit/virt/disk/vfs/test_guestfs.py | 14 ++++++++ nova/tests/unit/virt/disk/vfs/test_localfs.py | 34 +++++++++++++++++++ nova/virt/disk/vfs/api.py | 2 +- nova/virt/disk/vfs/guestfs.py | 13 ++++--- nova/virt/disk/vfs/localfs.py | 21 ++++++------ 5 files changed, 68 insertions(+), 16 deletions(-) diff --git a/nova/tests/unit/virt/disk/vfs/test_guestfs.py b/nova/tests/unit/virt/disk/vfs/test_guestfs.py index 72acd433456d..392b81e26714 100644 --- a/nova/tests/unit/virt/disk/vfs/test_guestfs.py +++ b/nova/tests/unit/virt/disk/vfs/test_guestfs.py @@ -14,6 +14,8 @@ import sys +import mock + from nova import exception from nova import test from nova.tests.unit.virt.disk.vfs import fakeguestfs @@ -269,3 +271,15 @@ class VirtDiskVFSGuestFSTest(test.NoDBTestCase): self.assertIsNotNone(vfs.handle) self.assertTrue('ext3', vfs.get_image_fs()) vfs.teardown() + + @mock.patch.object(vfsimpl.VFSGuestFS, 'setup_os') + def test_setup_mount(self, setup_os): + vfs = vfsimpl.VFSGuestFS("img.qcow2", imgfmt='qcow2') + vfs.setup() + self.assertTrue(setup_os.called) + + @mock.patch.object(vfsimpl.VFSGuestFS, 'setup_os') + def test_setup_mount_false(self, setup_os): + vfs = vfsimpl.VFSGuestFS("img.qcow2", imgfmt='qcow2') + vfs.setup(mount=False) + self.assertFalse(setup_os.called) diff --git a/nova/tests/unit/virt/disk/vfs/test_localfs.py b/nova/tests/unit/virt/disk/vfs/test_localfs.py index 3b790c3096a7..ae034a9db049 100644 --- a/nova/tests/unit/virt/disk/vfs/test_localfs.py +++ b/nova/tests/unit/virt/disk/vfs/test_localfs.py @@ -12,6 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. +import tempfile + import mock from oslo.config import cfg from oslo_concurrency import processutils @@ -415,3 +417,35 @@ class VirtDiskVFSLocalFSTest(test.NoDBTestCase): 'value', '-s', 'TYPE', '/dev/xyz', run_as_root=True) + + @mock.patch.object(tempfile, 'mkdtemp') + @mock.patch.object(nova.virt.disk.mount.nbd, 'NbdMount') + def test_setup_mount(self, NbdMount, mkdtemp): + vfs = vfsimpl.VFSLocalFS("img.qcow2", imgfmt='qcow2') + + mounter = mock.MagicMock() + mkdtemp.return_value = 'tmp/' + NbdMount.return_value = mounter + + vfs.setup() + + self.assertTrue(mkdtemp.called) + NbdMount.assert_called_once_with( + 'img.qcow2', 'tmp/', None) + mounter.do_mount.assert_called_once_with() + + @mock.patch.object(tempfile, 'mkdtemp') + @mock.patch.object(nova.virt.disk.mount.nbd, 'NbdMount') + def test_setup_mount_false(self, NbdMount, mkdtemp): + vfs = vfsimpl.VFSLocalFS("img.qcow2", imgfmt='qcow2') + + mounter = mock.MagicMock() + mkdtemp.return_value = 'tmp/' + NbdMount.return_value = mounter + + vfs.setup(mount=False) + + self.assertTrue(mkdtemp.called) + NbdMount.assert_called_once_with( + 'img.qcow2', 'tmp/', None) + self.assertFalse(mounter.do_mount.called) diff --git a/nova/virt/disk/vfs/api.py b/nova/virt/disk/vfs/api.py index 12937f2e284d..57d6e762b4d7 100644 --- a/nova/virt/disk/vfs/api.py +++ b/nova/virt/disk/vfs/api.py @@ -76,7 +76,7 @@ class VFS(object): self.imgfmt = imgfmt self.partition = partition - def setup(self): + def setup(self, mount=True): """Performs any one-time setup. Perform any one-time setup tasks to make the virtual filesystem diff --git a/nova/virt/disk/vfs/guestfs.py b/nova/virt/disk/vfs/guestfs.py index 2176bc8881c4..21fa23af7e67 100644 --- a/nova/virt/disk/vfs/guestfs.py +++ b/nova/virt/disk/vfs/guestfs.py @@ -69,6 +69,7 @@ class VFSGuestFS(vfs.VFS): _("libguestfs is not installed (%s)") % e) self.handle = None + self.mount = False def inspect_capabilities(self): """Determines whether guestfs is well configured.""" @@ -163,7 +164,7 @@ class VFSGuestFS(vfs.VFS): else: raise exception.NovaException(msg) - def setup(self): + def setup(self, mount=True): LOG.debug("Setting up appliance for %(imgfile)s %(imgfmt)s", {'imgfile': self.imgfile, 'imgfmt': self.imgfmt}) try: @@ -197,9 +198,10 @@ class VFSGuestFS(vfs.VFS): self.handle.add_drive_opts(self.imgfile, format=self.imgfmt) self.handle.launch() - self.setup_os() - - self.handle.aug_init("/", 0) + if mount: + self.setup_os() + self.handle.aug_init("/", 0) + self.mount = True except RuntimeError as e: # explicitly teardown instead of implicit close() # to prevent orphaned VMs in cases when an implicit @@ -220,7 +222,8 @@ class VFSGuestFS(vfs.VFS): try: try: - self.handle.aug_close() + if self.mount: + self.handle.aug_close() except RuntimeError as e: LOG.warning(_LW("Failed to close augeas %s"), e) diff --git a/nova/virt/disk/vfs/localfs.py b/nova/virt/disk/vfs/localfs.py index fb0b54d02081..a2e5add76ad1 100644 --- a/nova/virt/disk/vfs/localfs.py +++ b/nova/virt/disk/vfs/localfs.py @@ -60,22 +60,23 @@ class VFSLocalFS(vfs.VFS): self.imgdir = imgdir self.mount = None - def setup(self): + def setup(self, mount=True): self.imgdir = tempfile.mkdtemp(prefix="openstack-vfs-localfs") try: if self.imgfmt == "raw": LOG.debug("Using LoopMount") - mount = loop.LoopMount(self.imgfile, - self.imgdir, - self.partition) - else: - LOG.debug("Using NbdMount") - mount = nbd.NbdMount(self.imgfile, + mnt = loop.LoopMount(self.imgfile, self.imgdir, self.partition) - if not mount.do_mount(): - raise exception.NovaException(mount.error) - self.mount = mount + else: + LOG.debug("Using NbdMount") + mnt = nbd.NbdMount(self.imgfile, + self.imgdir, + self.partition) + if mount: + if not mnt.do_mount(): + raise exception.NovaException(mnt.error) + self.mount = mnt except Exception as e: with excutils.save_and_reraise_exception(): LOG.debug("Failed to mount image %(ex)s)", {'ex': e})