~ubuntu-branches/ubuntu/raring/nova/raring-proposed

« back to all changes in this revision

Viewing changes to nova/virt/disk/mount/guestfs.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Adam Gandelman, Chuck Short
  • Date: 2012-11-23 09:04:58 UTC
  • mfrom: (1.1.66)
  • Revision ID: package-import@ubuntu.com-20121123090458-91565o7aev1i1h71
Tags: 2013.1~g1-0ubuntu1
[ Adam Gandelman ]
* debian/control: Ensure novaclient is upgraded with nova,
  require python-keystoneclient >= 1:2.9.0. (LP: #1073289)
* debian/patches/{ubuntu/*, rbd-security.patch}: Dropped, applied
  upstream.
* debian/control: Add python-testtools to Build-Depends.

[ Chuck Short ]
* New upstream version.
* Refreshed debian/patches/avoid_setuptools_git_dependency.patch.
* debian/rules: FTBFS if missing binaries.
* debian/nova-scheudler.install: Add missing rabbit-queues and
  nova-rpc-zmq-receiver.
* Remove nova-volume since it doesnt exist anymore, transition to cinder-*.
* debian/rules: install apport hook in the right place.
* debian/patches/ubuntu-show-tests.patch: Display test failures.
* debian/control: Add depends on genisoimage
* debian/control: Suggest guestmount.
* debian/control: Suggest websockify. (LP: #1076442)
* debian/nova.conf: Disable nova-volume service.
* debian/control: Depend on xen-system-* rather than the hypervisor.
* debian/control, debian/mans/nova-conductor.8, debian/nova-conductor.init,
  debian/nova-conductor.install, debian/nova-conductor.logrotate
  debian/nova-conductor.manpages, debian/nova-conductor.postrm
  debian/nova-conductor.upstart.in: Add nova-conductor service.
* debian/control: Add python-fixtures as a build deps.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 
2
 
 
3
# Copyright 2011 Red Hat, Inc.
 
4
#
 
5
# Licensed under the Apache License, Version 2.0 (the "License"); you may
 
6
# not use this file except in compliance with the License. You may obtain
 
7
# a copy of the License at
 
8
#
 
9
# http://www.apache.org/licenses/LICENSE-2.0
 
10
#
 
11
# Unless required by applicable law or agreed to in writing, software
 
12
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 
13
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
14
# License for the specific language governing permissions and limitations
 
15
# under the License.
 
16
"""Support for mounting images with libguestfs"""
 
17
 
 
18
import os
 
19
 
 
20
from nova import exception
 
21
from nova import utils
 
22
from nova.virt.disk.mount import api
 
23
 
 
24
 
 
25
class GuestFSMount(api.Mount):
 
26
    """libguestfs support for arbitrary images."""
 
27
    mode = 'guestfs'
 
28
    device_id_string = 'guest'
 
29
 
 
30
    def map_dev(self):
 
31
        self.mapped = True
 
32
        return True
 
33
 
 
34
    def unmap_dev(self):
 
35
        self.mapped = False
 
36
 
 
37
    def mnt_dev(self):
 
38
        try:
 
39
            partition = int(self.partition or 0)
 
40
        except ValueError:
 
41
            self.error = _('unsupported partition: %s') % self.partition
 
42
            return False
 
43
 
 
44
        args = ('guestmount', '--rw', '-a', self.image)
 
45
        if partition == -1:
 
46
            args += ('-i',)  # find the OS partition
 
47
        elif partition:
 
48
            args += ('-m', '/dev/sda%d' % partition)
 
49
        else:
 
50
            # We don't resort to -i for this case yet,
 
51
            # as some older versions of libguestfs
 
52
            # have problems identifying ttylinux images for example
 
53
            args += ('-m', '/dev/sda')
 
54
        args += (self.mount_dir,)
 
55
        # root access should not required for guestfs (if the user
 
56
        # has permissions to fusermount (by being part of the fuse
 
57
        # group for example)).  Also note the image and mount_dir
 
58
        # have appropriate creditials at this point for read/write
 
59
        # mounting by the nova user.  However currently there are
 
60
        # subsequent access issues by both the nova and root users
 
61
        # if the nova user mounts the image, as detailed here:
 
62
        # https://bugzilla.redhat.com/show_bug.cgi?id=765814
 
63
        _out, err = utils.trycmd(*args, discard_warnings=True,
 
64
                                 run_as_root=True)
 
65
        if err:
 
66
            self.error = _('Failed to mount filesystem: %s') % err
 
67
            # Be defensive and ensure this is unmounted,
 
68
            # as I'm not sure guestmount will never have
 
69
            # mounted when it returns EXIT_FAILURE.
 
70
            # This is required if discard_warnings=False above
 
71
            utils.trycmd('fusermount', '-u', self.mount_dir, run_as_root=True)
 
72
            return False
 
73
 
 
74
        # More defensiveness as there are edge cases where
 
75
        # guestmount can return success while not mounting
 
76
        try:
 
77
            if not os.listdir(self.mount_dir):
 
78
                # Assume we've just got the original empty temp dir
 
79
                err = _('unknown guestmount error')
 
80
                self.error = _('Failed to mount filesystem: %s') % err
 
81
                return False
 
82
        except OSError:
 
83
            # This is the usual path and means root has
 
84
            # probably mounted fine
 
85
            pass
 
86
 
 
87
        self.mounted = True
 
88
        return True
 
89
 
 
90
    def unmnt_dev(self):
 
91
        if not self.mounted:
 
92
            return
 
93
        umount_cmd = ['fusermount', '-u', self.mount_dir]
 
94
        try:
 
95
            # We make a few attempts to work around other
 
96
            # processes temporarily scanning the mount_dir etc.
 
97
            utils.execute(*umount_cmd, attempts=5, run_as_root=True)
 
98
        except exception.ProcessExecutionError:
 
99
            # If we still can't umount, then do a lazy umount
 
100
            # (in the background), so that mounts might eventually
 
101
            # be cleaned up. Note we'll wait 10s below for the umount to
 
102
            # complete, after which we'll raise an exception.
 
103
            umount_cmd.insert(1, '-z')
 
104
            utils.execute(*umount_cmd, run_as_root=True)
 
105
 
 
106
        # Unfortunately FUSE has an issue where it doesn't wait
 
107
        # for processes associated with the mount to terminate.
 
108
        # Therefore we do this manually here.  Note later versions
 
109
        # of guestmount have the --pid-file option to help with this.
 
110
        # Here we check every .2 seconds whether guestmount is finished
 
111
        # but do this for at most 10 seconds.
 
112
        wait_cmd = 'until ! ps -C guestmount -o args= | grep -qF "%s"; '
 
113
        wait_cmd += 'do sleep .2; done'
 
114
        wait_cmd %= self.mount_dir
 
115
        try:
 
116
            utils.execute('timeout', '10s', 'sh', '-c', wait_cmd)
 
117
            self.mounted = False
 
118
        except exception.ProcessExecutionError:
 
119
            msg = _("Failed to umount image at %s, guestmount was "
 
120
                    "still running after 10s") % (self.mount_dir)
 
121
            raise exception.NovaException(msg)