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

« back to all changes in this revision

Viewing changes to nova/virt/disk/mount/api.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 virtual image files"""
 
17
 
 
18
import os
 
19
 
 
20
from nova.openstack.common import log as logging
 
21
from nova import utils
 
22
 
 
23
LOG = logging.getLogger(__name__)
 
24
 
 
25
 
 
26
class Mount(object):
 
27
    """Standard mounting operations, that can be overridden by subclasses.
 
28
 
 
29
    The basic device operations provided are get, map and mount,
 
30
    to be called in that order.
 
31
    """
 
32
 
 
33
    mode = device_id_string = None  # to be overridden in subclasses
 
34
 
 
35
    def __init__(self, image, mount_dir, partition=None, device=None):
 
36
 
 
37
        # Input
 
38
        self.image = image
 
39
        self.partition = partition
 
40
        self.mount_dir = mount_dir
 
41
 
 
42
        # Output
 
43
        self.error = ""
 
44
 
 
45
        # Internal
 
46
        self.linked = self.mapped = self.mounted = self.automapped = False
 
47
        self.device = self.mapped_device = device
 
48
 
 
49
        # Reset to mounted dir if possible
 
50
        self.reset_dev()
 
51
 
 
52
    def reset_dev(self):
 
53
        """Reset device paths to allow unmounting."""
 
54
        if not self.device:
 
55
            return
 
56
 
 
57
        self.linked = self.mapped = self.mounted = True
 
58
 
 
59
        device = self.device
 
60
        if os.path.isabs(device) and os.path.exists(device):
 
61
            if device.startswith('/dev/mapper/'):
 
62
                device = os.path.basename(device)
 
63
                device, self.partition = device.rsplit('p', 1)
 
64
                self.device = os.path.join('/dev', device)
 
65
 
 
66
    def get_dev(self):
 
67
        """Make the image available as a block device in the file system."""
 
68
        self.device = None
 
69
        self.linked = True
 
70
        return True
 
71
 
 
72
    def unget_dev(self):
 
73
        """Release the block device from the file system namespace."""
 
74
        self.linked = False
 
75
 
 
76
    def map_dev(self):
 
77
        """Map partitions of the device to the file system namespace."""
 
78
        assert(os.path.exists(self.device))
 
79
        automapped_path = '/dev/%sp%s' % (os.path.basename(self.device),
 
80
                                              self.partition)
 
81
 
 
82
        if self.partition == -1:
 
83
            self.error = _('partition search unsupported with %s') % self.mode
 
84
        elif self.partition and not os.path.exists(automapped_path):
 
85
            map_path = '/dev/mapper/%sp%s' % (os.path.basename(self.device),
 
86
                                              self.partition)
 
87
            assert(not os.path.exists(map_path))
 
88
 
 
89
            # Note kpartx can output warnings to stderr and succeed
 
90
            # Also it can output failures to stderr and "succeed"
 
91
            # So we just go on the existence of the mapped device
 
92
            _out, err = utils.trycmd('kpartx', '-a', self.device,
 
93
                                     run_as_root=True, discard_warnings=True)
 
94
 
 
95
            # Note kpartx does nothing when presented with a raw image,
 
96
            # so given we only use it when we expect a partitioned image, fail
 
97
            if not os.path.exists(map_path):
 
98
                if not err:
 
99
                    err = _('partition %s not found') % self.partition
 
100
                self.error = _('Failed to map partitions: %s') % err
 
101
            else:
 
102
                self.mapped_device = map_path
 
103
                self.mapped = True
 
104
        elif self.partition and os.path.exists(automapped_path):
 
105
            # Note auto mapping can be enabled with the 'max_part' option
 
106
            # to the nbd or loop kernel modules. Beware of possible races
 
107
            # in the partition scanning for _loop_ devices though
 
108
            # (details in bug 1024586), which are currently uncatered for.
 
109
            self.mapped_device = automapped_path
 
110
            self.mapped = True
 
111
            self.automapped = True
 
112
        else:
 
113
            self.mapped_device = self.device
 
114
            self.mapped = True
 
115
 
 
116
        return self.mapped
 
117
 
 
118
    def unmap_dev(self):
 
119
        """Remove partitions of the device from the file system namespace."""
 
120
        if not self.mapped:
 
121
            return
 
122
        if self.partition and not self.automapped:
 
123
            utils.execute('kpartx', '-d', self.device, run_as_root=True)
 
124
        self.mapped = False
 
125
        self.automapped = False
 
126
 
 
127
    def mnt_dev(self):
 
128
        """Mount the device into the file system."""
 
129
        _out, err = utils.trycmd('mount', self.mapped_device, self.mount_dir,
 
130
                                 run_as_root=True)
 
131
        if err:
 
132
            self.error = _('Failed to mount filesystem: %s') % err
 
133
            return False
 
134
 
 
135
        self.mounted = True
 
136
        return True
 
137
 
 
138
    def unmnt_dev(self):
 
139
        """Unmount the device from the file system."""
 
140
        if not self.mounted:
 
141
            return
 
142
        utils.execute('umount', self.mapped_device, run_as_root=True)
 
143
        self.mounted = False
 
144
 
 
145
    def do_mount(self):
 
146
        """Call the get, map and mnt operations."""
 
147
        status = False
 
148
        try:
 
149
            status = self.get_dev() and self.map_dev() and self.mnt_dev()
 
150
        finally:
 
151
            if not status:
 
152
                self.do_umount()
 
153
        return status
 
154
 
 
155
    def do_umount(self):
 
156
        """Call the unmnt, unmap and unget operations."""
 
157
        if self.mounted:
 
158
            self.unmnt_dev()
 
159
        if self.mapped:
 
160
            self.unmap_dev()
 
161
        if self.linked:
 
162
            self.unget_dev()