Rework the blockdev handling
authorIustin Pop <iustin@google.com>
Wed, 18 Feb 2009 11:15:13 +0000 (11:15 +0000)
committerIustin Pop <iustin@google.com>
Wed, 18 Feb 2009 11:15:13 +0000 (11:15 +0000)
This (big) patch changes the block device handling to be the same in all
the commands. The create script is no longer generated, but instead
common.sh is.

The patch also comments out the PARTITION_STYLE entry in defaults,
otherwise we'll always use that.

Reviewed-by: ultrotter,imsnah

.gitignore
Makefile.am
common.sh [deleted file]
common.sh.in [new file with mode: 0644]
create [moved from create.in with 73% similarity]
defaults
export
import
rename

index ee576da..86141c4 100644 (file)
@@ -10,7 +10,7 @@
 /configure
 
 # built scripts
-/create
+/common.sh
 
 # archives
 /ganeti-instance-debootstrap-*.tar.gz
index 36b278f..de9dcf9 100644 (file)
@@ -2,20 +2,20 @@ osname=$(subst ganeti-instance-,,$(PACKAGE))
 
 osdir=$(OS_DIR)/$(osname)
 
-os_SCRIPTS = create
-dist_os_SCRIPTS = import export rename
-dist_os_DATA = ganeti_api_version common.sh
+dist_os_SCRIPTS = create import export rename
+dist_os_DATA = ganeti_api_version
+os_DATA = common.sh
 
 dist_doc_DATA = COPYING NEWS README
 
-EXTRA_DIST = create.in defaults
+EXTRA_DIST = common.sh.in defaults
 
 do_subst = sed \
        -e 's,[@]sysconfdir[@],$(sysconfdir),g' \
        -e 's,[@]localstatedir[@],$(localstatedir),g'
 
-create: create.in Makefile
+common.sh: common.sh.in Makefile
        $(do_subst) < $< > $@
        chmod +x $@
 
-CLEANFILES = create
+CLEANFILES = common.sh
diff --git a/common.sh b/common.sh
deleted file mode 100644 (file)
index 78787d6..0000000
--- a/common.sh
+++ /dev/null
@@ -1,92 +0,0 @@
-
-log_error() {
-  echo "$@" >&2
-}
-
-SCRIPT_NAME=$(basename $0)
-
-for dir in /lib/udev /sbin; do
-  if [ -f $dir/vol_id -a -x $dir/vol_id ]; then
-    VOL_ID=$dir/vol_id
-  fi
-done
-
-if [ -z "$VOL_ID" ]; then
-    log_error "vol_id not found, please install udev"
-    exit 1
-fi
-
-get_api5_arguments() {
-  GETOPT_RESULT=$*
-  # Note the quotes around `$TEMP': they are essential!
-  eval set -- "$GETOPT_RESULT"
-  while true; do
-    case "$1" in
-      -i|-n) instance=$2; shift 2;;
-
-      -o) old_name=$2; shift 2;;
-
-      -b) blockdev=$2; shift 2;;
-
-      -s) swapdev=$2; shift 2;;
-
-      --) shift; break;;
-
-      *)  log_error "Internal error!" >&2; exit 1;;
-    esac
-  done
-  if [ -z "$instance" -o -z "$blockdev" ]; then
-    log_error "Missing OS API Argument (-i, -n, or -b)"
-    exit 1
-  fi
-  if [ "$SCRIPT_NAME" != "export" -a -z "$swapdev"  ]; then
-    log_error "Missing OS API Argument -s (swapdev)"
-    exit 1
-  fi
-  if [ "$SCRIPT_NAME" = "rename" -a -z "$old_name"  ]; then
-    log_error "Missing OS API Argument -o (old_name)"
-    exit 1
-  fi
-}
-
-get_api10_arguments() {
-  if [ -z "$INSTANCE_NAME" -o -z "$HYPERVISOR" -o -z "$DISK_COUNT" ]; then
-    log_error "Missing OS API Variable:"
-    log_error "(INSTANCE_NAME HYPERVISOR or DISK_COUNT)"
-    exit 1
-  fi
-  instance=$INSTANCE_NAME
-  if [ $DISK_COUNT -lt 1 -o -z "$DISK_0_PATH" ]; then
-    log_error "At least one disk is needed"
-    exit 1
-  fi
-  if [ "$SCRIPT_NAME" = "export" ]; then
-    if [ -z "$EXPORT_DEVICE" ]; then
-      log_error "Missing OS API Variable EXPORT_DEVICE"
-    fi
-    blockdev=$EXPORT_DEVICE
-  elif [ "$SCRIPT_NAME" = "import" ]; then
-    if [ -z "$IMPORT_DEVICE" ]; then
-       log_error "Missing OS API Variable IMPORT_DEVICE"
-    fi
-    blockdev=$IMPORT_DEVICE
-  else
-    blockdev=$DISK_0_PATH
-  fi
-  if [ "$SCRIPT_NAME" = "rename" -a -z "$OLD_INSTANCE_NAME" ]; then
-    log_error "Missing OS API Variable OLD_INSTANCE_NAME"
-  fi
-  old_name=$OLD_INSTANCE_NAME
-}
-
-if [ -z "$OS_API_VERSION" -o "$OS_API_VERSION" = "5" ]; then
-  OS_API_VERSION=5
-  GETOPT_RESULT=`getopt -o o:n:i:b:s: -n '$0' -- "$@"`
-  if [ $? != 0 ] ; then log_error "Terminating..."; exit 1 ; fi
-  get_api5_arguments $GETOPT_RESULT
-elif [ "$OS_API_VERSION" = "10" ]; then
-  get_api10_arguments
-else
-  log_error "Unknown OS API VERSION $OS_API_VERSION"
-  exit 1
-fi
diff --git a/common.sh.in b/common.sh.in
new file mode 100644 (file)
index 0000000..d0a7593
--- /dev/null
@@ -0,0 +1,172 @@
+#
+
+# Copyright (C) 2007, 2008, 2009 Google Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+
+log_error() {
+  echo "$@" >&2
+}
+
+get_api5_arguments() {
+  GETOPT_RESULT=$*
+  # Note the quotes around `$TEMP': they are essential!
+  eval set -- "$GETOPT_RESULT"
+  while true; do
+    case "$1" in
+      -i|-n) instance=$2; shift 2;;
+
+      -o) old_name=$2; shift 2;;
+
+      -b) blockdev=$2; shift 2;;
+
+      -s) swapdev=$2; shift 2;;
+
+      --) shift; break;;
+
+      *)  log_error "Internal error!" >&2; exit 1;;
+    esac
+  done
+  if [ -z "$instance" -o -z "$blockdev" ]; then
+    log_error "Missing OS API Argument (-i, -n, or -b)"
+    exit 1
+  fi
+  if [ "$SCRIPT_NAME" != "export" -a -z "$swapdev"  ]; then
+    log_error "Missing OS API Argument -s (swapdev)"
+    exit 1
+  fi
+  if [ "$SCRIPT_NAME" = "rename" -a -z "$old_name"  ]; then
+    log_error "Missing OS API Argument -o (old_name)"
+    exit 1
+  fi
+}
+
+get_api10_arguments() {
+  if [ -z "$INSTANCE_NAME" -o -z "$HYPERVISOR" -o -z "$DISK_COUNT" ]; then
+    log_error "Missing OS API Variable:"
+    log_error "(INSTANCE_NAME HYPERVISOR or DISK_COUNT)"
+    exit 1
+  fi
+  instance=$INSTANCE_NAME
+  if [ $DISK_COUNT -lt 1 -o -z "$DISK_0_PATH" ]; then
+    log_error "At least one disk is needed"
+    exit 1
+  fi
+  if [ "$SCRIPT_NAME" = "export" ]; then
+    if [ -z "$EXPORT_DEVICE" ]; then
+      log_error "Missing OS API Variable EXPORT_DEVICE"
+    fi
+    blockdev=$EXPORT_DEVICE
+  elif [ "$SCRIPT_NAME" = "import" ]; then
+    if [ -z "$IMPORT_DEVICE" ]; then
+       log_error "Missing OS API Variable IMPORT_DEVICE"
+    fi
+    blockdev=$IMPORT_DEVICE
+  else
+    blockdev=$DISK_0_PATH
+  fi
+  if [ "$SCRIPT_NAME" = "rename" -a -z "$OLD_INSTANCE_NAME" ]; then
+    log_error "Missing OS API Variable OLD_INSTANCE_NAME"
+  fi
+  old_name=$OLD_INSTANCE_NAME
+}
+
+format_disk0() {
+  # Create one big partition, and make it bootable
+  # some versions of sfdisk need manual specification of 
+  # head/sectors for devices such as drbd which don't 
+  # report geometry
+  sfdisk -H 255 -S 63 --quiet --Linux "$1" <<EOF
+0,,L,*
+EOF
+}
+
+map_disk0() {
+  blockdev="$1"
+  block_base=`basename $blockdev`
+  filesystem_dev_base=`kpartx -l -p- $blockdev | \
+                       grep -m 1 "^$block_base.*$blockdev" | \
+                       awk '{print $1}'`
+  kpartx -a -p- $blockdev
+  echo "/dev/mapper/$filesystem_dev_base"
+}
+
+unmap_disk0() {
+  kpartx -d -p- $1
+}
+
+cleanup() {
+  if [ ${#CLEANUP[*]} -gt 0 ]; then
+    LAST_ELEMENT=$((${#CLEANUP[*]}-1))
+    REVERSE_INDEXES=$(seq ${LAST_ELEMENT} -1 0)
+    for i in $REVERSE_INDEXES; do
+      ${CLEANUP[$i]}
+    done
+  fi
+}
+
+DEFAULT_FILE="@sysconfdir@/default/ganeti-instance-debootstrap"
+if [ -f "$DEFAULT_FILE" ]; then
+    . "$DEFAULT_FILE"
+fi
+
+# note: we don't set a default mirror since debian and ubuntu have
+# different defaults, and it's better to use the default
+
+# only if the user want to specify a mirror in the defaults file we
+# will use it, this declaration is to make sure the variable is set
+: ${MIRROR:=""}
+: ${PROXY:=""}
+: ${SUITE:="lenny"}
+: ${ARCH:=""}
+: ${EXTRA_PKGS:=""}
+: ${CUSTOMIZE_DIR:="@sysconfdir@/ganeti/instance-debootstrap.d"}
+: ${GENERATE_CACHE:="yes"}
+: ${CLEAN_CACHE:="14"} # number of days to keep a cache file
+if [ -z "$OS_API_VERSION" -o "$OS_API_VERSION" = "5" ]; then
+  DEFAULT_PARTITION_STYLE="none"
+else
+  DEFAULT_PARTITION_STYLE="msdos"
+fi
+: ${PARTITION_STYLE:=$DEFAULT_PARTITION_STYLE} # disk partition style
+
+CACHE_DIR="@localstatedir@/cache/ganeti-instance-debootstrap"
+
+SCRIPT_NAME=$(basename $0)
+
+for dir in /lib/udev /sbin; do
+  if [ -f $dir/vol_id -a -x $dir/vol_id ]; then
+    VOL_ID=$dir/vol_id
+  fi
+done
+
+if [ -z "$VOL_ID" ]; then
+    log_error "vol_id not found, please install udev"
+    exit 1
+fi
+
+if [ -z "$OS_API_VERSION" -o "$OS_API_VERSION" = "5" ]; then
+  OS_API_VERSION=5
+  GETOPT_RESULT=`getopt -o o:n:i:b:s: -n '$0' -- "$@"`
+  if [ $? != 0 ] ; then log_error "Terminating..."; exit 1 ; fi
+  get_api5_arguments $GETOPT_RESULT
+elif [ "$OS_API_VERSION" = "10" ]; then
+  get_api10_arguments
+else
+  log_error "Unknown OS API VERSION $OS_API_VERSION"
+  exit 1
+fi
similarity index 73%
rename from create.in
rename to create
index 2a8f48c..da25b0e 100755 (executable)
--- a/create.in
+++ b/create
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-# Copyright (C) 2007 Google Inc.
+# Copyright (C) 2007, 2008, 2009 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 
 set -e
 
-CLEANUP=( )
+. common.sh
 
-cleanup() {
-  if [ ${#CLEANUP[*]} -gt 0 ]; then
-    LAST_ELEMENT=$((${#CLEANUP[*]}-1))
-    REVERSE_INDEXES=$(seq ${LAST_ELEMENT} -1 0)
-    for i in $REVERSE_INDEXES; do
-      ${CLEANUP[$i]}
-    done
-  fi
-}
+CLEANUP=( )
 
 trap cleanup EXIT
 
-DEFAULT_FILE="@sysconfdir@/default/ganeti-instance-debootstrap"
-if [ -f "$DEFAULT_FILE" ]; then
-    . "$DEFAULT_FILE"
-fi
-
-# note: we don't set a default mirror since debian and ubuntu have
-# different defaults, and it's better to use the default
-
-# only if the user want to specify a mirror in the defaults file we
-# will use it, this declaration is to make sure the variable is set
-: ${MIRROR:=""}
-: ${PROXY:=""}
-: ${SUITE:="lenny"}
-: ${ARCH:=""}
-: ${EXTRA_PKGS:=""}
-: ${CUSTOMIZE_DIR:="@sysconfdir@/ganeti/instance-debootstrap.d"}
-: ${GENERATE_CACHE:="yes"}
-: ${CLEAN_CACHE:="14"} # number of days to keep a cache file
-if [ -z "$OS_API_VERSION" -o "$OS_API_VERSION" = "5" ]; then
-  DEFAULT_PARTITION_STYLE="none"
-else
-  DEFAULT_PARTITION_STYLE="msdos"
-fi
-: ${PARTITION_STYLE:=$DEFAULT_PARTITION_STYLE} # disk partition style
-
-CACHE_DIR="@localstatedir@/cache/ganeti-instance-debootstrap"
-
 if [ "$GENERATE_CACHE" = "yes" -a ! -d "$CACHE_DIR" ]; then
   mkdir -p "$CACHE_DIR"
 fi
@@ -67,8 +32,6 @@ fi
 DPKG_ARCH=${ARCH:-`dpkg --print-architecture`}
 CACHE_FILE="$CACHE_DIR/cache-${SUITE}-${DPKG_ARCH}.tar"
 
-. common.sh
-
 # If the target device is not a real block device we'll first losetup it.
 # This is needed for file disks.
 if [ ! -b $blockdev ]; then
@@ -81,16 +44,9 @@ if [ "$PARTITION_STYLE" = "none" ]; then
   filesystem_dev=$blockdev
 elif [ "$PARTITION_STYLE" = "msdos" ]; then
   # Create one big partition, and make it bootable
-  sfdisk --quiet --Linux $blockdev <<EOF
-0,,L,*
-EOF
-  block_base=`basename $blockdev`
-  filesystem_dev_base=`kpartx -l -p- $blockdev | \
-                       grep -m 1 "^$block_base.*$blockdev" | \
-                       awk '{print $1}'`
-  kpartx -a -p- $blockdev
-  CLEANUP+=("kpartx -d -p- $blockdev")
-  filesystem_dev="/dev/mapper/$filesystem_dev_base"
+  format_disk0 $blockdev
+  filesystem_dev=$(map_disk0 $blockdev)
+  CLEANUP+=("unmap_disk0 $blockdev")
 else
   echo "Unknown partition style $PARTITION_STYLE"
   exit 1
index c065055..467e46e 100644 (file)
--- a/defaults
+++ b/defaults
@@ -60,4 +60,4 @@ CLEAN_CACHE="14"
 # (more styles may be added in the future)
 # The default is "msdos" from ganeti 2.0 onwards, but none if installing under
 # Ganeti 1.2 (os api version 5)
-PARTITION_STYLE="none"
+# PARTITION_STYLE="none"
diff --git a/export b/export
index e3d8595..82254bc 100755 (executable)
--- a/export
+++ b/export
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-# Copyright (C) 2007 Google Inc.
+# Copyright (C) 2007, 2008, 2009 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -21,9 +21,36 @@ set -e
 
 . common.sh
 
-vol_type=$($VOL_ID -t $blockdev)
+CLEANUP=( )
+
+trap cleanup EXIT
+
+# If the target device is not a real block device we'll first losetup it.
+# This is needed for file disks.
+if [ ! -b $blockdev ]; then
+  ORIGINAL_BLOCKDEV=$blockdev
+  blockdev=$(losetup -sf $blockdev)
+  CLEANUP+=("losetup -d $blockdev")
+fi
+
+if [ "$PARTITION_STYLE" = "none" ]; then
+  filesystem_dev=$blockdev
+elif [ "$PARTITION_STYLE" = "msdos" ]; then
+  filesystem_dev=$(map_disk0 $blockdev)
+  CLEANUP+=("unmap_disk0 $blockdev")
+else
+  echo "Unknown partition style $PARTITION_STYLE"
+  exit 1
+fi
+
+vol_type=$($VOL_ID -t $filesystem_dev)
 
 if [ "$vol_type" = "ext3" -o "$vol_type" = "ext2" ]; then
-  dump -0 -q -f - "$blockdev"
+  dump -0 -q -f - "$filesystem_dev"
 fi
 
+# execute cleanups
+cleanup
+trap - EXIT
+
+exit 0
diff --git a/import b/import
index 1047954..d89fb17 100755 (executable)
--- a/import
+++ b/import
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-# Copyright (C) 2007 Google Inc.
+# Copyright (C) 2007, 2008, 2009 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -21,26 +21,46 @@ set -e
 
 . common.sh
 
-mke2fs -Fjq $blockdev
-root_uuid=$($VOL_ID -u $blockdev )
+CLEANUP=( )
+
+trap cleanup EXIT
+
+# If the target device is not a real block device we'll first losetup it.
+# This is needed for file disks.
+if [ ! -b $blockdev ]; then
+  ORIGINAL_BLOCKDEV=$blockdev
+  blockdev=$(losetup -sf $blockdev)
+  CLEANUP+=("losetup -d $blockdev")
+fi
+
+if [ "$PARTITION_STYLE" = "none" ]; then
+  filesystem_dev=$blockdev
+elif [ "$PARTITION_STYLE" = "msdos" ]; then
+  # Create one big partition, and make it bootable
+  format_disk0 $blockdev
+  filesystem_dev=$(map_disk0 $blockdev)
+  CLEANUP+=("unmap_disk0 $blockdev")
+else
+  echo "Unknown partition style $PARTITION_STYLE"
+  exit 1
+fi
+
+mke2fs -Fjq $filesystem_dev
+root_uuid=$($VOL_ID -u $filesystem_dev )
+
 if [ -n "$swapdev" ]; then
   mkswap $swapdev
-  swap_uuid=$($VOL_ID -u $swapdev )
+  swap_uuid=$($VOL_ID -u $swapdev || true )
 fi
 
 TMPDIR=`mktemp -d` || exit 1
-trap "umount $TMPDIR; rmdir $TMPDIR" EXIT
+CLEANUP+=("rmdir $TMPDIR")
 
-# If it's not a block device try to mount it via loopback device.
-# This is needed for file disks.
-MOUNT_OPTIONS=""
-if [ ! -b $blockdev ]; then
-  MOUNT_OPTIONS="$MOUNT_OPTIONS -o loop"
-fi
-mount $MOUNT_OPTIONS $blockdev $TMPDIR
+mount $filesystem_dev $TMPDIR
+CLEANUP+=("umount $TMPDIR")
 
 ( cd $TMPDIR; restore -r -y -f - )
-rm -f $TMPDIR/etc/udev/rules.d/z25_persistent-net.rules
+rm -f $TMPDIR/etc/udev/rules.d/z*_persistent-net.rules
 
 # Fix /etc/fstab with the new volumes' UUIDs
 if [ -e $TMPDIR/etc/fstab ]; then
@@ -49,7 +69,7 @@ if [ -e $TMPDIR/etc/fstab ]; then
     SWAP_LINE="UUID=$swap_uuid  swap  swap  defaults  0  0"
     cat $TMPDIR/etc/fstab | \
       sed -re "s#^(/dev/sda|UUID=[a-f0-9-]+)\s+/\s+.*\$#$ROOT_LINE#" \
-          -re "s#^(/dev/sdb|UUID=[a-f0-9-]+)\s+swap\s+.*\$#$SWAP_LINE#" \
+          -e "s#^(/dev/sdb|UUID=[a-f0-9-]+)\s+swap\s+.*\$#$SWAP_LINE#" \
       > $TMPDIR/etc/fstab.new
   else
     cat $TMPDIR/etc/fstab | \
@@ -59,6 +79,8 @@ if [ -e $TMPDIR/etc/fstab ]; then
   mv $TMPDIR/etc/fstab.new  $TMPDIR/etc/fstab
 fi
 
-umount $TMPDIR
-rmdir $TMPDIR
+# execute cleanups
+cleanup
 trap - EXIT
+
+exit 0
diff --git a/rename b/rename
index 331e691..a49d2fa 100755 (executable)
--- a/rename
+++ b/rename
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-# Copyright (C) 2007 Google Inc.
+# Copyright (C) 2007, 2008, 2009 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -21,16 +21,33 @@ set -e
 
 . common.sh
 
+CLEANUP=( )
+
+trap cleanup EXIT
+
 TMPDIR=`mktemp -d` || exit 1
-trap "umount $TMPDIR; rmdir $TMPDIR" EXIT
+CLEANUP+=("rmdir $TMPDIR")
 
-# If it's not a block device try to mount it via loopback device.
+# If the target device is not a real block device we'll first losetup it.
 # This is needed for file disks.
-MOUNT_OPTIONS=""
 if [ ! -b $blockdev ]; then
-  MOUNT_OPTIONS="$MOUNT_OPTIONS -o loop"
+  ORIGINAL_BLOCKDEV=$blockdev
+  blockdev=$(losetup -sf $blockdev)
+  CLEANUP+=("losetup -d $blockdev")
+fi
+
+if [ "$PARTITION_STYLE" = "none" ]; then
+  filesystem_dev=$blockdev
+elif [ "$PARTITION_STYLE" = "msdos" ]; then
+  filesystem_dev=$(map_disk0 $blockdev)
+  CLEANUP+=("unmap_disk0 $blockdev")
+else
+  echo "Unknown partition style $PARTITION_STYLE"
+  exit 1
 fi
-mount $MOUNT_OPTIONS $blockdev $TMPDIR
+
+mount $filesystem_dev $TMPDIR
+CLEANUP+=("umount $TMPDIR")
 
 HNAME="$TMPDIR/etc/hostname"
 MNAME="$TMPDIR/etc/mailname"
@@ -52,8 +69,8 @@ if [ "`cat $MNAME`" = "$old_name" ]; then
        echo $instance > $MNAME
 fi
 
-umount $TMPDIR
-rmdir $TMPDIR
+# execute cleanups
+cleanup
 trap - EXIT
 
 exit 0