Fix license and copyright
[snf-image] / snf-image-host / snf-image-update-helper.in
1 #!/bin/bash
2
3 # Copyright (C) 2011 GRNET S.A. 
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 # 02110-1301, USA.
19
20 set -e
21 set -o pipefail
22
23 . @osdir@/common.sh
24
25 usage() {
26     local rc="$1"
27
28     cat <<EOF
29
30 Usage: $0 [options]
31
32 This script runs a debootstrap and creates a small Debian image populated with
33 the snf-image-helper package. This needs to be done before the first use of
34 ganeti's \`snf-image' guest OS type.
35
36 OPTIONS:
37     -c CACHE_FILE
38         Use this cache file, instead of the default
39         [default: $HELPER_CACHE_FILE]
40
41     -d DIRECTORY
42         Use this directory to host the created files, instead of the default
43         [default: $HELPER_DIR]
44
45     -h  Print this message
46
47     -p PACKAGE
48         Install this deb package in the helper image, instead of the default
49         [default: $HELPER_PKG]
50
51     -y  Assume Yes to all queries and do not prompt
52
53 EOF
54
55     exit "$rc"
56 }
57
58 while getopts "c:d:hp:y" opt; do
59     case $opt in
60         c) HELPER_CACHE_FILE="$OPTARG"
61             ;;
62         d) HELPER_DIR="$OPTARG"
63             ;;
64         h) usage 0
65             ;;
66         p) HELPER_PKG="$OPTARG"
67             ;;
68         y) NO_PROMPT="yes"
69             ;;
70         ?) log_error "Use \`-h' for help"; exit 1
71             ;;
72     esac
73 done
74
75 echo
76 echo "This is the update helper image script for snf-image."
77 echo "If you don't know what to do, use \`-h'."
78 echo
79
80 if [ ! -d "$HELPER_DIR" -o ! -w "$HELPER_DIR" ]; then
81     log_error "ERROR:"
82     log_error "Helper directory \`$HELPER_DIR' does not exist or the script" \
83     "has no write permission on it."
84     exit 1
85 fi
86
87 if [ ! -r "$HELPER_PKG" ]; then
88     log_error "ERROR:"
89     log_error "Helper package \`$HELPER_PKG' does not exist or is not " \
90     "readable by the script."
91     exit 1
92 fi
93
94 cat >&1 <<EOF
95 This program will overwrite the following files if present:
96   \`$HELPER_DIR/initrd'
97   \`$HELPER_DIR/kernel'
98   \`$HELPER_DIR/image'
99 EOF
100
101 while [[ 1 ]]; do
102     echo -n "Do you want to continue [y/N]? "
103     if [ "x$NO_PROMPT" = "xyes" ]; then
104         echo "y";
105         break;
106     fi
107
108     read answer
109     [ "$(echo -n "$answer" | tr [A-Z] [a-z])" = "y" ] && break
110     if [ -z "$answer" -o "$(echo -n "$answer" | tr [A-Z] [a-z])" = "n" ]; then
111         log_error "Abort."
112         exit 1
113     fi
114 done
115
116 rm -f "$HELPER_DIR/initrd" "$HELPER_DIR/kernel" "$HELPER_DIR/image"
117
118 echo -n "Allocating space for helper disk image..."
119 helper_img=$(mktemp "$HELPER_DIR/image.XXXXXX")
120
121 dd if=/dev/zero of="$helper_img" bs=1k count=400000 &> /dev/null
122 echo "done"
123
124 echo "Creating partitions..."
125 blockdev=$("$LOSETUP" -sf $helper_img)
126 add_cleanup "$LOSETUP" -d "$blockdev"
127
128 sleep 1 # sometimes losetup returns and the device is still busy..
129
130 format_disk0 "$blockdev" "extdump"  2>&1 | sed -e 's/^/CFDISK: /g'
131
132 root_dev=$(map_disk0 "$blockdev")-1
133 add_cleanup unmap_disk0 "$blockdev"
134
135 echo Creating and configuring filesystem...
136 mkfs.ext3 "$root_dev" 2>&1 | sed -e 's/^/MKFS.EXT3: /g'
137 # The helper vm should never do filesystem checks...
138 tune2fs -i 0 -c 0 "$root_dev" 2>&1 | sed -e 's/^/TUNE2FS: /g'
139
140 target=$(mktemp -d)
141 add_cleanup rmdir "$target"
142
143 mount "$root_dev" "$target"
144 add_cleanup umount "$root_dev"
145
146 echo -n "Checking for cached root filesystem file \`$HELPER_CACHE_FILE'..." 
147 if [  -f "$HELPER_CACHE_FILE" ]; then
148     echo "found"
149     tar xf "$HELPER_CACHE_FILE" -C "$target"
150 else
151     echo "not found"
152     echo "Debootstraping to create a new root filesystem:"
153
154     # Create a policy-rc.d file to deny init script execution
155     mkdir -p "$target/usr/sbin"
156     cat > "$target/usr/sbin/policy-rc.d" <<EOF
157 #!/bin/sh
158 exit 101
159 EOF
160     chmod +x "$target/usr/sbin/policy-rc.d"
161
162     debootstrap --arch amd64 --include "$HELPER_EXTRA_PKGS" \
163         --variant=minbase stable "$target" "$HELPER_MIRROR" 2>&1 | \
164         sed -e 's/^/DEBOOTSTRAP: /g'
165
166     rm "$target/usr/sbin/policy-rc.d"
167     
168     # remove the downloaded debs, as they are no longer needed
169     find "$target/var/cache/apt/archives" -type f -name '*.deb' -print0 | \
170         xargs -r0 rm -f
171
172     tmp_cache=$(mktemp "$HELPER_CACHE_FILE.XXXXXX")
173     tar cf "$tmp_cache" --one-file-system -C "$target" . || \
174         { rm "$tmp_cache"; false; }
175     mv -f "$tmp_cache" "$HELPER_CACHE_FILE"
176 fi
177
178 echo -n "Configuring the helper image..."
179 echo snf-image-helper > "$target/etc/hostname"
180
181 cat > "$target/etc/fstab" <<EOF
182 # /etc/fstab: static file system information.
183 #
184 # <file system>   <mount point>   <type>  <options>       <dump>  <pass>
185 /dev/sda1         /               ext3    defaults        0       1
186 proc              /proc           proc    defaults        0       0
187 EOF
188 echo "done"
189
190 echo -n "Extracting kernel..."
191 if [ ! -L "$target/vmlinuz" -o ! -L "$target/vmlinuz" ]; then
192     echo -e "\033[1;31mfailed\033[0m"
193     log_error "vmlinuz or initrd.img link in root is missing."
194     log_error "I don't know how to find a usable kernel/initrd pair."
195     exit 1
196 fi
197 echo "done"
198
199 kernel=$(readlink -en "$target/vmlinuz")
200 initrd=$(readlink -en "$target/initrd.img")
201
202 echo "Moving $(basename "$kernel") and $(basename "$initrd") to \`$HELPER_DIR'"
203 mv "$kernel" "$initrd" "$HELPER_DIR"
204
205 kernel=$(basename "$kernel")
206 initrd=$(basename "$initrd")
207
208 (cd "$HELPER_DIR"; ln -fs "$kernel" kernel; ln -fs "$initrd" initrd)
209
210 rm "$target/vmlinuz" "$target/initrd.img"
211
212 echo "Installing snf-image-helper pkg in the new image..."
213 cp "$HELPER_PKG" "$target/tmp/"
214 pkg_name=$(basename "$HELPER_PKG")
215 add_cleanup rm "$target/tmp/$pkg_name"
216 chroot "$target" dpkg -i "/tmp/$pkg_name" 2>&1 | sed -e 's/^/DPKG: /g'
217
218 cat > "$target/etc/rc.local" <<EOF
219 #!/bin/sh -e
220 #
221 # rc.local
222 #
223 # This script is executed at the end of each multiuser runlevel.
224 # Make sure that the script will "exit 0" on success or any other
225 # value on error.
226 #
227 # In order to enable or disable this script just change the execution
228 # bits.
229 #
230 # By default this script does nothing.
231
232 if ! grep -q snf_image_activate_helper /proc/cmdline; then
233     echo "WARNING: NOT calling snf-image-helper, add snf_image_activate_helper"
234     echo "to the kernel command line if you want to do so."
235 else
236     /usr/bin/snf-image-helper --force
237 fi
238
239 exit 0
240 EOF
241
242 chmod +x "$target/etc/rc.local"
243
244 echo "done"
245
246 cleanup
247
248 mv "$helper_img" "$HELPER_DIR/image"
249
250 trap - EXIT
251
252 echo "Files in \`$HELPER_DIR' were updated successfully"
253 exit 0
254
255 # vim: set sta sts=4 shiftwidth=4 sw=4 et ai :