Statistics
| Branch: | Revision:

root / common.sh.in @ df47d312

History | View | Annotate | Download (8.9 kB)

1
#
2

    
3
# Copyright (C) 2007, 2008, 2009 Google Inc.
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
AWK="@AWK@"
21
MKDIR_P="@MKDIR_P@"
22
DUMP="@DUMP@"
23
RESTORE="@RESTORE@"
24
LOSETUP="@LOSETUP@"
25
KPARTX="@KPARTX@"
26
SFDISK="@SFDISK@"
27
QEMU_IMG="@QEMU_IMG@"
28
NTFSCLONE="@NTFSCLONE@"
29
XMLSTARLET="@XMLSTARLET@"
30
INSTALL_MBR="@INSTALL_MBR@"
31
PROGRESS_MONITOR="@PROGRESS_MONITOR@"
32

    
33
windows_support="@windows_support@"
34
progress_monitor_support="@progress_monitor_support@"
35

    
36
CLEANUP=( )
37

    
38
log_error() {
39
  echo "$@" >&2
40
}
41

    
42
debug() {
43
    [ "$IMAGE_DEBUG" == "1" -o "$IMAGE_DEBUG" == "yes" ] &&  $@ || :
44
}
45

    
46
get_api5_arguments() {
47
  GETOPT_RESULT=$*
48
  # Note the quotes around `$TEMP': they are essential!
49
  eval set -- "$GETOPT_RESULT"
50
  while true; do
51
    case "$1" in
52
      -i|-n) instance=$2; shift 2;;
53

    
54
      -o) old_name=$2; shift 2;;
55

    
56
      -b) blockdev=$2; shift 2;;
57

    
58
      -s) swapdev=$2; shift 2;;
59

    
60
      --) shift; break;;
61

    
62
      *)  log_error "Internal error!" >&2; exit 1;;
63
    esac
64
  done
65
  if [ -z "$instance" -o -z "$blockdev" ]; then
66
    log_error "Missing OS API Argument (-i, -n, or -b)"
67
    exit 1
68
  fi
69
  if [ "$SCRIPT_NAME" != "export" -a -z "$swapdev"  ]; then
70
    log_error "Missing OS API Argument -s (swapdev)"
71
    exit 1
72
  fi
73
  if [ "$SCRIPT_NAME" = "rename" -a -z "$old_name"  ]; then
74
    log_error "Missing OS API Argument -o (old_name)"
75
    exit 1
76
  fi
77
}
78

    
79
get_api10_arguments() {
80
  if [ -z "$INSTANCE_NAME" -o -z "$HYPERVISOR" -o -z "$DISK_COUNT" ]; then
81
    log_error "Missing OS API Variable:"
82
    log_error "(INSTANCE_NAME HYPERVISOR or DISK_COUNT)"
83
    exit 1
84
  fi
85
  instance=$INSTANCE_NAME
86
  if [ $DISK_COUNT -lt 1 -o -z "$DISK_0_PATH" ]; then
87
    log_error "At least one disk is needed"
88
    exit 1
89
  fi
90
  if [ "$SCRIPT_NAME" = "export" ]; then
91
    if [ -z "$EXPORT_DEVICE" ]; then
92
      log_error "Missing OS API Variable EXPORT_DEVICE"
93
    fi
94
    blockdev=$EXPORT_DEVICE
95
  elif [ "$SCRIPT_NAME" = "import" ]; then
96
    if [ -z "$IMPORT_DEVICE" ]; then
97
       log_error "Missing OS API Variable IMPORT_DEVICE"
98
    fi
99
    blockdev=$IMPORT_DEVICE
100
  else
101
    blockdev=$DISK_0_PATH
102
  fi
103
  if [ "$SCRIPT_NAME" = "rename" -a -z "$OLD_INSTANCE_NAME" ]; then
104
    log_error "Missing OS API Variable OLD_INSTANCE_NAME"
105
  fi
106
  old_name=$OLD_INSTANCE_NAME
107
}
108

    
109
get_api20_parameters() {
110
  if [ -z "$OSP_IMG_ID" -o -z "$OSP_IMG_FORMAT" -o -z "$OSP_IMG_PASSWD" ]; then
111
    log_error "Missing OS API Parameter:"
112
    log_error "(OSP_IMG_ID or OSP_IMG_FORMAT or OSP_IMG_PASSWD)"
113
    exit 1
114
  fi
115
  IMG_ID=$OSP_IMG_ID
116
  IMG_FORMAT=$OSP_IMG_FORMAT
117
  IMG_PASSWD=$OSP_IMG_PASSWD
118
}
119

    
120
mount_disk0() {
121
    local target=$1
122
    mount $root_dev $target
123
    CLEANUP+=("umount $target")
124
    if [ -n "${boot_dev}" ] ; then
125
        $MKDIR_P $target/boot
126
        mount $boot_dev $target/boot
127
        CLEANUP+=("umount $target/boot")
128
    fi
129
    # sync the file systems before unmounting to ensure everything is flushed
130
    # out
131
    CLEANUP+=("sync")
132
}
133

    
134
map_disk0() {
135
    blockdev="$1"
136
    filesystem_dev_base=`$KPARTX -l -p- $blockdev | \
137
                            grep -m 1 -- "-1.*$blockdev" | \
138
                            $AWK '{print $1}'`
139
    if [ -z "$filesystem_dev_base" ]; then
140
        log_error "Cannot interpret kpartx output and get partition mapping"
141
        exit 1
142
    fi
143
    $KPARTX -a -p- $blockdev > /dev/null
144
    filesystem_dev="/dev/mapper/${filesystem_dev_base/%-1/}"
145
    if [ ! -b "/dev/mapper/$filesystem_dev_base" ]; then
146
        log_error "Can't find kpartx mapped partition: /dev/mapper/$filesystem_dev_base"
147
        exit 1
148
    fi
149
    echo "$filesystem_dev"
150
}
151

    
152
map_partition() {
153
    filesystem_dev="$1"
154
    partition="$2"
155
    if [ "${SWAP}" = "yes" -a "${BOOT}" = "yes" ] ; then
156
        boot_dev="${filesystem_dev}-1"
157
        swap_dev="${filesystem_dev}-2"
158
        root_dev="${filesystem_dev}-3"
159
    elif [ "${SWAP}" = "no" -a "${BOOT}" = "yes" ] ; then
160
        boot_dev="${filesystem_dev}-1"
161
        root_dev="${filesystem_dev}-2"
162
    elif [ "${SWAP}" = "yes" -a "${BOOT}" = "no" ] ; then
163
        swap_dev="${filesystem_dev}-1"
164
        root_dev="${filesystem_dev}-2"
165
    elif [ "${SWAP}" = "no" -a "${BOOT}" = "no" ] ; then
166
        root_dev="${filesystem_dev}-1"
167
    fi
168
    echo "$(eval "echo \${$(echo ${partition}_dev)"})"
169
}
170

    
171
unmap_disk0() {
172
  $KPARTX -d -p- $1
173
}
174

    
175
cleanup() {
176
  # if something fails here, it souldn't call cleanup again...
177
  trap - EXIT
178

    
179
  if [ ${#CLEANUP[*]} -gt 0 ]; then
180
    LAST_ELEMENT=$((${#CLEANUP[*]}-1))
181
    REVERSE_INDEXES=$(seq ${LAST_ELEMENT} -1 0)
182
    for i in $REVERSE_INDEXES; do
183
        # If something fails here, it's better to retry it for a few times
184
        # before we give up with an error. This is needed for kpartx when
185
        # dealing with ntfs partitions mounted through fuse. umount is not
186
        # synchronous and may return while the partition is still busy. A
187
        # premature attempt to delete partition mappings through kpartx on a
188
        # device that hosts previously mounted ntfs partition may fail with an 
189
        # `device-mapper: remove ioctl failed: Device or resource busy'
190
        # error. A sensible workaround for this is to wait for a while and then
191
        # try again.
192
        local cmd=${CLEANUP[$i]}
193
        $cmd || for interval in 0.25 0.5 1 2 4; do
194
            echo "Command $cmd failed!"
195
            echo "I'll wait for $interval secs and will retry..."
196
            sleep $interval
197
            $cmd && break
198
        done
199
        test $? -eq 1 && { echo "Giving Up..."; exit 1; }
200
    done
201
  fi
202
  echo "Clean UP executed"
203
}
204

    
205
trap cleanup EXIT
206

    
207
DEFAULT_FILE="@defaultdir@/ganeti-instance-image"
208
if [ -f "$DEFAULT_FILE" ]; then
209
    . "$DEFAULT_FILE"
210
fi
211

    
212
# note: we don't set a default mirror since debian and ubuntu have
213
# different defaults, and it's better to use the default
214

    
215
# only if the user want to specify a mirror in the defaults file we
216
# will use it, this declaration is to make sure the variable is set
217
: ${CDINSTALL:="no"}
218
: ${BOOT:="no"}
219
: ${SWAP:="yes"}
220
: ${SWAP_SIZE:="${INSTANCE_BE_memory}"}
221
: ${FILESYSTEM:="ext3"}
222
: ${KERNEL_ARGS=""}
223
: ${OVERLAY=""}
224
: ${IMAGE_NAME:=""}
225
: ${IMAGE_TYPE:="dump"}
226
: ${NOMOUNT:="no"}
227
: ${ARCH:=""}
228
: ${CUSTOMIZE_DIR:="@sysconfdir@/ganeti/instance-image/hooks"}
229
: ${VARIANTS_DIR:="@sysconfdir@/ganeti/instance-image/variants"}
230
: ${NETWORKS_DIR:="@sysconfdir@/ganeti/instance-image/networks"}
231
: ${OVERLAYS_DIR:="@sysconfdir@/ganeti/instance-image/overlays"}
232
: ${IMAGE_DIR:="@localstatedir@/cache/ganeti-instance-image"}
233
: ${IMAGE_DEBUG:="no"}
234
: ${TOOLS_DIR:="@osdir@/@osname@/tools"}
235

    
236
SCRIPT_NAME=$(basename $0)
237
KERNEL_PATH="$INSTANCE_HV_kernel_path"
238

    
239
if [ -f /sbin/blkid -a -x /sbin/blkid ]; then
240
    VOL_ID="/sbin/blkid -c /dev/null -o value -s UUID"
241
    VOL_TYPE="/sbin/blkid -c /dev/null -o value -s TYPE"
242
else
243
    for dir in /lib/udev /sbin; do
244
        if [ -f $dir/vol_id -a -x $dir/vol_id ]; then
245
            VOL_ID="$dir/vol_id -u"
246
            VOL_TYPE="$dir/vol_id -t"
247
        fi
248
    done
249
fi
250

    
251
if [ -z "$VOL_ID" ]; then
252
    log_error "vol_id or blkid not found, please install udev or util-linux"
253
    exit 1
254
fi
255

    
256

    
257
if [ -z "$OS_API_VERSION" -o "$OS_API_VERSION" = "5" ]; then
258
  OS_API_VERSION=5
259
  GETOPT_RESULT=`getopt -o o:n:i:b:s: -n '$0' -- "$@"`
260
  if [ $? != 0 ] ; then log_error "Terminating..."; exit 1 ; fi
261
  get_api5_arguments $GETOPT_RESULT
262
elif [ "$OS_API_VERSION" = "10" -o "$OS_API_VERSION" = "15" ]; then
263
  get_api10_arguments
264
elif [ "$OS_API_VERSION" = "20" ]; then
265
  get_api10_arguments
266
  get_api20_parameters
267
  IMAGE_NAME=$IMG_ID
268
  IMAGE_TYPE=$IMG_FORMAT
269
else
270
  log_error "Unknown OS API VERSION $OS_API_VERSION"
271
  exit 1
272
fi
273

    
274
if [ -n "$OS_VARIANT" ]; then
275
  if [ ! -d "$VARIANTS_DIR" ]; then
276
    log_error "OS Variants directory $VARIANTS_DIR doesn't exist"
277
    exit 1
278
  fi
279
  VARIANT_CONFIG="$VARIANTS_DIR/$OS_VARIANT.conf"
280
  if [ -f "$VARIANT_CONFIG" ]; then
281
    . "$VARIANT_CONFIG"
282
  else
283
    if grep -qxF "$OS_VARIANT" variants.list; then
284
      log_error "ERROR: instance-image configuration error"
285
      log_error "  Published variant $OS_VARIANT is missing its config file"
286
      log_error "  Please create $VARIANT_CONFIG or unpublish the variant"
287
      log_error "  (by removing $OS_VARIANT from variants.list)"
288
    else
289
      log_error "Unofficial variant $OS_VARIANT is unsupported"
290
      log_error "Most probably this is a user error, forcing a wrong name"
291
      log_error "To support this variant please create file $VARIANT_CONFIG"
292
    fi
293
    exit 1
294
  fi
295
fi
296