~ubuntu-branches/ubuntu/precise/nova/precise-updates

« back to all changes in this revision

Viewing changes to nova/virt/disk/api.py

  • Committer: Package Import Robot
  • Author(s): Adam Gandelman
  • Date: 2012-08-27 14:50:40 UTC
  • mfrom: (79.1.3 precise-proposed)
  • Revision ID: package-import@ubuntu.com-20120827145040-vlkdab5i0smvnhei
Tags: 2012.1.3+stable-20120827-4d2a4afe-0ubuntu1
* New upstream snapshot, fixes FTBFS in -proposed. (LP: #1041120)
* Resynchronize with stable/essex (4d2a4afe):
  - [5d63601] Inappropriate exception handling on kvm live/block migration
    (LP: #917615)
  - [ae280ca] Deleted floating ips can cause instance delete to fail
    (LP: #1038266)

Show diffs side-by-side

added added

removed removed

Lines of Context:
144
144
class _DiskImage(object):
145
145
    """Provide operations on a disk image file."""
146
146
 
 
147
    tmp_prefix = 'openstack-disk-mount-tmp'
 
148
 
147
149
    def __init__(self, image, partition=None, use_cow=False, mount_dir=None):
148
150
        # These passed to each mounter
149
151
        self.image = image
164
166
        if not self.handlers:
165
167
            raise exception.Error(_('no capable image handler configured'))
166
168
 
 
169
        if mount_dir:
 
170
            # Note the os.path.ismount() shortcut doesn't
 
171
            # work with libguestfs due to permissions issues.
 
172
            device = self._device_for_path(mount_dir)
 
173
            if device:
 
174
                self._reset(device)
 
175
 
 
176
    @staticmethod
 
177
    def _device_for_path(path):
 
178
        device = None
 
179
        with open("/proc/mounts", 'r') as ifp:
 
180
            for line in ifp:
 
181
                fields = line.split()
 
182
                if fields[1] == path:
 
183
                    device = fields[0]
 
184
                    break
 
185
        return device
 
186
 
 
187
    def _reset(self, device):
 
188
        """Reset internal state for a previously mounted directory."""
 
189
        mounter_cls = self._handler_class(device=device)
 
190
        mounter = mounter_cls(image=self.image,
 
191
                              partition=self.partition,
 
192
                              mount_dir=self.mount_dir,
 
193
                              device=device)
 
194
        self._mounter = mounter
 
195
 
 
196
        mount_name = os.path.basename(self.mount_dir or '')
 
197
        self._mkdir = mount_name.startswith(self.tmp_prefix)
 
198
 
167
199
    @property
168
200
    def errors(self):
169
201
        """Return the collated errors from all operations."""
170
202
        return '\n--\n'.join([''] + self._errors)
171
203
 
172
204
    @staticmethod
173
 
    def _handler_class(mode):
174
 
        """Look up the appropriate class to use based on MODE."""
 
205
    def _handler_class(mode=None, device=None):
 
206
        """Look up the appropriate class to use based on MODE or DEVICE."""
175
207
        for cls in (loop.Mount, nbd.Mount, guestfs.Mount):
176
 
            if cls.mode == mode:
177
 
                return cls
178
 
        raise exception.Error(_("unknown disk image handler: %s") % mode)
 
208
            if mode and cls.mode == mode:
 
209
                return cls
 
210
            elif device and cls.device_id_string in device:
 
211
                return cls
 
212
        msg = _("no disk image handler for: %s") % mode or device
 
213
        raise exception.Error(msg)
179
214
 
180
215
    def mount(self):
181
216
        """Mount a disk image, using the object attributes.
189
224
            raise exception.Error(_('image already mounted'))
190
225
 
191
226
        if not self.mount_dir:
192
 
            self.mount_dir = tempfile.mkdtemp()
 
227
            self.mount_dir = tempfile.mkdtemp(prefix=self.tmp_prefix)
193
228
            self._mkdir = True
194
229
 
195
230
        try:
258
293
        raise exception.Error(img.errors)
259
294
 
260
295
 
261
 
def setup_container(image, container_dir=None, use_cow=False):
 
296
def setup_container(image, container_dir, use_cow=False):
262
297
    """Setup the LXC container.
263
298
 
264
299
    It will mount the loopback image to the container directory in order
265
300
    to create the root filesystem for the container.
266
 
 
267
 
    LXC does not support qcow2 images yet.
268
301
    """
269
302
    try:
270
303
        img = _DiskImage(image=image, use_cow=use_cow, mount_dir=container_dir)
271
 
        if img.mount():
272
 
            return img
273
 
        else:
 
304
        if not img.mount():
274
305
            raise exception.Error(img.errors)
275
306
    except Exception, exn:
276
307
        LOG.exception(_('Failed to mount filesystem: %s'), exn)
277
308
 
278
309
 
279
 
def destroy_container(img):
 
310
def destroy_container(container_dir):
280
311
    """Destroy the container once it terminates.
281
312
 
282
313
    It will umount the container that is mounted,
283
314
    and delete any  linked devices.
284
 
 
285
 
    LXC does not support qcow2 images yet.
286
315
    """
287
316
    try:
288
 
        if img:
289
 
            img.umount()
 
317
        img = _DiskImage(image=None, mount_dir=container_dir)
 
318
        img.umount()
290
319
    except Exception, exn:
291
320
        LOG.exception(_('Failed to remove container: %s'), exn)
292
321