summaryrefslogtreecommitdiffstats
path: root/tools/daisy-img-modify.sh
blob: aad2994944f62b87b8d64a20f1c1ecda2936dc35 (plain)
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
#!/bin/bash

##############################################################################
# Copyright (c) 2016 ZTE Coreporation and others.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Apache License, Version 2.0
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################

# This script refers to the yardstick project.

usage()
{
    cat << EOF
USAGE: `basename $0` [-c sub-Command] [-a IP Address] [-g Gateway IP address] [-s image Size in GB]
                     [-w workdir]
OPTIONS:
  -c sub-command to modify the content
  -a IP address for the sub-command to set in the image
  -g gateway IP address for the sub-command to set in the image
  -s image size of gigabytes. If it is absent, the image size will not be changed.
  -w workdir for temporary usage, optional
  -h print this message and exit

EXAMPLE:
    sudo `basename $0` -c centos-img-modify.sh -a 10.20.11.2 -g 10.20.11.1 -s 100
EOF
}

while getopts "c:a:g:s:w:h" OPTION
do
    case $OPTION in
        c)
            cmd=${OPTARG}
            if [ ! -x $cmd ]; then
                echo "The $cmd does not exist or is not executable."
                usage
                exit 1
            fi
            ;;
        a)
            ipaddr=${OPTARG}
            ;;
        g)
            gwaddr=${OPTARG}
            ;;
        s)
            img_size=${OPTARG}
            ;;
        w)
            WORKDIR=${OPTARG}
            ;;
        h)
            usage
            exit 0
            ;;
        *)
            echo "${OPTION} is not a valid argument"
            usage
            exit 0
            ;;
    esac
done


set -e
set -x

die() {
    echo "error: $1" >&2
    exit 1
}

test $(id -u) -eq 0 || die "You need be root to run this script"

cmd=${cmd:-$(cd "$(dirname "$0")"; pwd)/centos-img-modify.sh}
test -x $cmd

if [[ -n $ipaddr ]]; then
    export ipaddr=$ipaddr
fi

if [[ -n $gwaddr ]]; then
    export gwaddr=$gwaddr
fi

mountdir="/mnt/daisy/centos"
workdir=${WORKDIR:-"/tmp/workdir/daisy"}
host=${HOST:-"cloud.centos.org"}
filename=CentOS-7-x86_64-GenericCloud-1608.qcow2
image_xz_path="centos/7/images/${filename}.xz"
image_xz_url=${IMAGE_XZ_URL:-"http://${host}/${image_xz_path}"}
sha256sum_path="centos/7/images/sha256sum.txt"
sha256sum_url=${SHA256SUM_URL:-"http://${host}/${sha256sum_path}"}
imgfile="${workdir}/centos7.qcow2"
raw_imgfile="${workdir}/centos7.raw"

# download and checksum base image, conditionally if local copy is outdated
download() {
    test -d $workdir || mkdir -p $workdir
    cd $workdir
    rm -f sha256sum.txt
    wget $sha256sum_url

    test -e $filename  &&  grep $filename$ sha256sum.txt | sha256sum -c
    if [ $? -ne 0 ]; then
        rm -f $filename
        rm -f ${filename}.xz
        wget -nc --progress=dot:giga $image_xz_url
        xz -d -k ${filename}.xz
        grep $filename$ sha256sum.txt | sha256sum -c
    fi

    for i in $(seq 0 9); do
        [[ -e /dev/loop$i ]] || mknod -m 660 /dev/loop$i b 7 $i
    done

    qemu-img convert $filename $raw_imgfile
    cd -
}

# install utils
install_utils()
{
    which kpartx ||
    if [ $? -ne 0 ]; then
        yum install -y kpartx
    fi

    which growpart ||
    if [ $? -ne 0 ]; then
        yum install -y cloud-utils-growpart
    fi

    which xfs_growfs ||
    if [ $? -ne 0 ]; then
        yum install -y xfsprogs
    fi
}

# Eliminate exceptions
eliminate()
{
    if [ -b /dev/mapper/$loopdevice ]; then
        umount /dev/mapper/$loopdevice || true
        dmsetup remove $loopdevice || true
    fi
    return 0
}

# resize image
resize() {
    install_utils

    # resize the image
    qemu-img resize $raw_imgfile ${img_size}G
    qemu-img info $raw_imgfile
    losetup --find --show $raw_imgfile
    loopdevice=$(kpartx -l $raw_imgfile | head -1 | cut -f1 -d ' ')
    kpartx -av $raw_imgfile
    sleep 2
    dmsetup ls
    fdisk -l /dev/${loopdevice:0:5} || true
    growpart /dev/${loopdevice:0:5} 1
    dmsetup clear $loopdevice
    kpartx -dv $raw_imgfile || eliminate
}

# mount image
setup() {
    mkdir -p $mountdir
    losetup --find --show $raw_imgfile
    loopdevice=$(kpartx -l $raw_imgfile | head -1 | cut -f1 -d ' ')
    kpartx -av $raw_imgfile
    sleep 2
    dmsetup ls
    fdisk -l /dev/${loopdevice:0:5} || true
    mount /dev/mapper/$loopdevice $mountdir
    mount -t proc none ${mountdir}/proc

    if [[ -n $img_size ]]; then
        xfs_growfs /dev/mapper/$loopdevice
    fi

    chroot $mountdir df -h
    cp $cmd $mountdir/$(basename $cmd)
}

# modify image running a script using in a chrooted environment
modify() {
    chroot $mountdir /$(basename $cmd)
    rm -f $mountdir/$(basename $cmd)

    umount $mountdir/proc
    umount $mountdir

    if dmsetup table | grep $loopdevice; then
       dmsetup clear $loopdevice || true
    fi

    qemu-img convert -c -o compat=0.10 -O qcow2 $raw_imgfile $imgfile
}

# cleanup (umount) the image
cleanup() {
    mount | grep $mountdir/proc && umount $mountdir/proc
    mount | grep $mountdir && umount $mountdir
    if [ -f $raw_imgfile ]; then
        kpartx -dv $raw_imgfile || eliminate
    fi
    rm -f $raw_imgfile
    rm -rf $mountdir
}

exitcode=""
error_trap()
{
    local rc=$?

    set +e

    if [ -z "$exitcode" ]; then
        exitcode=$rc
    fi

    dmesg -T | tail -50

    cleanup

    echo "Image build failed with $exitcode"

    exit $exitcode
}

main() {
    cleanup
    if [ -f $imgfile ]; then
        rm -rf $imgfile
    fi

    trap "error_trap" EXIT SIGTERM

    download
    if [[ -n $img_size ]]; then
        echo img_size=$img_size
        resize
    fi
    setup
    modify

    trap - EXIT SIGTERM
    cleanup

    echo "the modified image is found here: $imgfile"
}

main