~fcorrea/charms/trusty/glance/controlled-pause-action

« back to all changes in this revision

Viewing changes to charmhelpers/contrib/storage/linux/loopback.py

  • Committer: James Page
  • Date: 2015-10-22 13:20:02 UTC
  • Revision ID: james.page@ubuntu.com-20151022132002-w9dpfv19w7vqn7wc
Tags: 15.10
15.10 Charm release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
import os
 
3
import re
 
4
 
 
5
from subprocess import (
 
6
    check_call,
 
7
    check_output,
 
8
)
 
9
 
 
10
 
 
11
##################################################
 
12
# loopback device helpers.
 
13
##################################################
 
14
def loopback_devices():
 
15
    '''
 
16
    Parse through 'losetup -a' output to determine currently mapped
 
17
    loopback devices. Output is expected to look like:
 
18
 
 
19
        /dev/loop0: [0807]:961814 (/tmp/my.img)
 
20
 
 
21
    :returns: dict: a dict mapping {loopback_dev: backing_file}
 
22
    '''
 
23
    loopbacks = {}
 
24
    cmd = ['losetup', '-a']
 
25
    devs = [d.strip().split(' ') for d in
 
26
            check_output(cmd).splitlines() if d != '']
 
27
    for dev, _, f in devs:
 
28
        loopbacks[dev.replace(':', '')] = re.search('\((\S+)\)', f).groups()[0]
 
29
    return loopbacks
 
30
 
 
31
 
 
32
def create_loopback(file_path):
 
33
    '''
 
34
    Create a loopback device for a given backing file.
 
35
 
 
36
    :returns: str: Full path to new loopback device (eg, /dev/loop0)
 
37
    '''
 
38
    file_path = os.path.abspath(file_path)
 
39
    check_call(['losetup', '--find', file_path])
 
40
    for d, f in loopback_devices().iteritems():
 
41
        if f == file_path:
 
42
            return d
 
43
 
 
44
 
 
45
def ensure_loopback_device(path, size):
 
46
    '''
 
47
    Ensure a loopback device exists for a given backing file path and size.
 
48
    If it a loopback device is not mapped to file, a new one will be created.
 
49
 
 
50
    TODO: Confirm size of found loopback device.
 
51
 
 
52
    :returns: str: Full path to the ensured loopback device (eg, /dev/loop0)
 
53
    '''
 
54
    for d, f in loopback_devices().iteritems():
 
55
        if f == path:
 
56
            return d
 
57
 
 
58
    if not os.path.exists(path):
 
59
        cmd = ['truncate', '--size', size, path]
 
60
        check_call(cmd)
 
61
 
 
62
    return create_loopback(path)