summaryrefslogtreecommitdiffstats
path: root/dev-tools/xmount_container2raw.sh
blob: 637daff7bb31a2ebd4d3b4ced267ada9874a725b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

xmount_binary="xmount"
dnbd3_binary="dnbd3-server"
image_file_or_directory=""
do_cleanup=false
container_formats="vmdk,vdi,vhd,qcow2"

print_usage() {
    cat << EOF
    Converts container images (vmdk,vdi,vhd,qcow2) to raw images (on the fly
    via xmount).
Usage:
    $0 [options] image_file_or_directory

Options:

    -h --help       Shows this help message.

    -x --xmount     Path to xmount. (default: "$xmount_binary").

    -d --dnbd3      Path to dnbd3-server. (default: "$dnbd3_binary").

    -c --cleanup    Cleans up the image directory. Unmounts the images and
                    removes symlinks.

EOF
}
parse_command_line() {
    while true; do
        case "$1" in
            -h|--help)
                print_usage "$0"
                exit 0
                ;;
            -x|--xmount)
                shift
                xmount_binary="$1"
                shift
                ;;
            -d|--dnbd3)
                shift
                dnbd3_binary="$1"
                shift
                ;;
            -c|--cleanup)
                do_cleanup=true
                shift
                ;;
            '') # no more parameters
                break
                ;;
            *)
                if [ -z "$image_file_or_directory" ]; then
                    if [ -d "$1" ] || [ -f "$1" ]; then
                        image_file_or_directory="$(realpath "$1")"
                    else
                        echo "ERROR: \"$1\" is not a file or a directory."
                        exit 1
                    fi
                    shift
                else
                    echo "ERROR: unsupported argument: \"$1\""
                    print_usage "$0"
                    return 1
                fi
        esac
    done
}

cleanup_image() {
    local image="$1"
    local mountpoint="$(image_to_mountpoint "$image")"

    echo "umounting $mountpoint"
    if ! umount "$mountpoint";then
        echo "WARNING: umount failed, try with sudo"
        return 1
    fi
    rmdir "$mountpoint"
    local link_name="$(image_to_link_name "$image")"
    [ -L "$link_name" ] && unlink "$link_name"
}

cleanup() {
    if [ -d "$image_file_or_directory" ]; then
        local image
        shopt -s nullglob # skip unmatched container formats
        for image in "${image_file_or_directory}"/*.{$container_formats}.r*; do
            cleanup_image "$image"
        done
    else
        cleanup_image "$image_file_or_directory"
    fi
}

check_binaries() {
    echo $xmount_binary
    if ! hash "$xmount_binary" 2>/dev/null; then
        echo "xmount not found, " \
            "install it or try to set the --xmount option"
        exit 1
    fi
    if ! hash "$dnbd3_binary" 2>/dev/null; then
        echo "dnbd3-server not found," \
            " install it or try to set the --dnbd3 option"
        exit 1
    fi
}
image_to_mountpoint() {
    # convert [imagename].[container_type].[revision] to
    # [imagename].[container_type].[revision].xmount
    local image="$1"
    extension="${image#*.}"
    basepath="${image%.$extension}"
    echo "${basepath}.${extension}.xmount"
}
image_to_link_name() {
    # convert [imagename].[container_type].[revision] to
    # [imagename].[container_type].xmount.[revision]
    local image="$1"
    extension="${image#*.}"
    basepath="${image%.$extension}"
    revision="${extension#*.}"
    container_type="${extension%.*}"
    echo "${basepath}.${container_type}.xmount.${revision}"
}
convert_image() {
    local image="$1"
    [ -d "$image" ] && return 0
    local mountpoint="$(image_to_mountpoint "$image")"
    local link_name="$(image_to_link_name "$image")"

    echo "creating mountpoint: \"$mountpoint\""
    mkdir "$mountpoint" || return 1
    ${xmount_binary} -o nonempty --in qemu "$image" \
        --out raw "${mountpoint}"
    echo "creating link: \"$link_name\""
    ln -s --relative "${mountpoint}"/*.dd "$link_name"
}
convert() {
    if [ -d "$image_file_or_directory" ]; then
        local image
        shopt -s nullglob # skip unmatched container formats
        for image in "${image_file_or_directory}"/*.{vmdk,vdi,vhd,qcow2}.r*; do
            convert_image "$image"
        done
    else
        convert_image "$image_file_or_directory"
    fi
}

parse_command_line "$@"
if $do_cleanup; then
    cleanup
else
    check_binaries
    convert
fi