~openstack-charmers-next/charms/trusty/ceph-mon/trunk

169 by James Page
Switch to using charm-store for amulet tests
1
# Copyright 2014-2015 Canonical Limited.
2
#
173 by James Page
Resync charmhelpers for licensing change
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
6
#
7
#  http://www.apache.org/licenses/LICENSE-2.0
8
#
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
# See the License for the specific language governing permissions and
13
# limitations under the License.
169 by James Page
Switch to using charm-store for amulet tests
14
15
import os
16
import re
17
from subprocess import (
18
    check_call,
19
    check_output,
20
)
21
22
import six
23
24
25
##################################################
26
# loopback device helpers.
27
##################################################
28
def loopback_devices():
29
    '''
30
    Parse through 'losetup -a' output to determine currently mapped
31
    loopback devices. Output is expected to look like:
32
33
        /dev/loop0: [0807]:961814 (/tmp/my.img)
34
35
    :returns: dict: a dict mapping {loopback_dev: backing_file}
36
    '''
37
    loopbacks = {}
38
    cmd = ['losetup', '-a']
39
    devs = [d.strip().split(' ') for d in
40
            check_output(cmd).splitlines() if d != '']
41
    for dev, _, f in devs:
42
        loopbacks[dev.replace(':', '')] = re.search('\((\S+)\)', f).groups()[0]
43
    return loopbacks
44
45
46
def create_loopback(file_path):
47
    '''
48
    Create a loopback device for a given backing file.
49
50
    :returns: str: Full path to new loopback device (eg, /dev/loop0)
51
    '''
52
    file_path = os.path.abspath(file_path)
53
    check_call(['losetup', '--find', file_path])
54
    for d, f in six.iteritems(loopback_devices()):
55
        if f == file_path:
56
            return d
57
58
59
def ensure_loopback_device(path, size):
60
    '''
61
    Ensure a loopback device exists for a given backing file path and size.
62
    If it a loopback device is not mapped to file, a new one will be created.
63
64
    TODO: Confirm size of found loopback device.
65
66
    :returns: str: Full path to the ensured loopback device (eg, /dev/loop0)
67
    '''
68
    for d, f in six.iteritems(loopback_devices()):
69
        if f == path:
70
            return d
71
72
    if not os.path.exists(path):
73
        cmd = ['truncate', '--size', size, path]
74
        check_call(cmd)
75
76
    return create_loopback(path)
77
78
79
def is_mapped_loopback_device(device):
80
    """
81
    Checks if a given device name is an existing/mapped loopback device.
82
    :param device: str: Full path to the device (eg, /dev/loop1).
83
    :returns: str: Path to the backing file if is a loopback device
84
    empty string otherwise
85
    """
86
    return loopback_devices().get(device, "")