Move shared disk presence logic from nodes into shared disk code
[autocluster.git] / autocluster
index 7afb74bc56bb93ad16fc9725da0eb70859aff016..3c8219f150cc338d394da426d31690e207a94449 100755 (executable)
@@ -52,6 +52,10 @@ EOF
     cat <<EOF
 
   commands:
+     base [ create | boot ] ...
+
+     cluster [ build | destroy | create | update_hosts | boot | configure ] ...
+
      create base
            create a base image
 
@@ -84,6 +88,39 @@ die () {
     fi
 }
 
+announce ()
+{
+    echo "######################################################################"
+    printf "# %-66s #\n" "$*"
+    echo "######################################################################"
+    echo ""
+}
+
+waitfor ()
+{
+    local file="$1"
+    local msg="$2"
+    local timeout="$3"
+
+    local tmpfile=$(mktemp)
+
+    cat <<EOF >"$tmpfile"
+spawn tail -n 10000 -f $file
+expect -timeout $timeout -re "$msg"
+EOF
+
+    export LANG=C
+    expect "$tmpfile"
+    rm -f "$tmpfile"
+
+    if ! grep -E "$msg" "$file" > /dev/null; then
+       echo "Failed to find \"$msg\" in \"$file\""
+       return 1
+    fi
+
+    return 0
+}
+
 ###############################
 
 # Indirectly call a function named by ${1}_${2}
@@ -466,10 +503,11 @@ common_nodelist_hacking ()
 create_cluster_hooks=
 cluster_created_hooks=
 
-create_cluster ()
+cluster_create ()
 {
     # Use $1.  If not set then use value from configuration file.
     CLUSTER="${1:-${CLUSTER}}"
+    announce "cluster create \"${CLUSTER}\""
     [ -n "$CLUSTER" ] || die "\$CLUSTER not set"
 
     sanity_check_cluster_name
@@ -497,6 +535,101 @@ cluster_created_hosts_message ()
 
 register_hook cluster_created_hooks cluster_created_hosts_message
 
+cluster_destroy ()
+{
+    announce "cluster destroy \"${CLUSTER}\""
+    [ -n "$CLUSTER" ] || die "\$CLUSTER not set"
+
+    vircmd destroy "$CLUSTER" || true
+}
+
+cluster_update_hosts ()
+{
+    announce "cluster update_hosts \"${CLUSTER}\""
+    [ -n "$CLUSTER" ] || die "\$CLUSTER not set"
+
+    [ -n "$hosts_file" ] || hosts_file="tmp/hosts.${CLUSTER}"
+    [ -r "$hosts_file" ] || die "Missing hosts file \"${hosts_file}\""
+
+    local pat="# autocluster ${CLUSTER}\$|[[:space:]]${CLUSTER}(n|base)[[:digit:]]+"
+
+    local t="/etc/hosts.${CLUSTER}"
+    grep -E "$pat" /etc/hosts >"$t" || true
+    if diff -B "$t" "$hosts_file" >/dev/null ; then
+       rm "$t"
+       return
+    fi
+
+    local old=/etc/hosts.old.autocluster
+    cp /etc/hosts "$old"
+    local new=/etc/hosts.new
+    grep -Ev "$pat" "$old" |
+    cat -s - "$hosts_file" >"$new"
+
+    mv "$new" /etc/hosts
+
+    echo "Made these changes to /etc/hosts:"
+    diff -u "$old" /etc/hosts || true
+}
+
+cluster_boot ()
+{
+    [ -n "$CLUSTER_PATTERN" ] || CLUSTER_PATTERN="$CLUSTER"
+    announce "cluster boot \"${CLUSTER_PATTERN}\""
+    [ -n "$CLUSTER_PATTERN" ] || die "\$CLUSTER_PATTERN not set"
+
+    vircmd start "$CLUSTER_PATTERN"
+
+    local nodes=$(vircmd dominfo "$CLUSTER_PATTERN" 2>/dev/null | \
+       sed -n -e 's/Name: *//p')
+
+    # Wait for each node
+    local i
+    for i in $nodes ; do
+       waitfor "${KVMLOG}/serial.$i" "login:" 300 || {
+           vircmd destroy "$CLUSTER_PATTERN"
+           die "Failed to create cluster"
+       }
+    done
+
+    # Move past the last line of log output
+    echo ""
+}
+
+cluster_configure ()
+{
+    announce "cluster configure \"${CLUSTER}\""
+    [ -n "$CLUSTER" ] || die "\$CLUSTER not set"
+
+    local n1="${CLUSTER}n1"
+    local ssh="ssh -o StrictHostKeyChecking=no"
+
+    case "$CLUSTER_TYPE" in
+       "build")
+           $ssh "$n1" ./scripts/install_packages.sh clusterfs build
+           $ssh "$n1" ./scripts/setup_cluster.sh build
+           ;;
+
+       "ad")
+           $ssh "$n1" ./scripts/install_packages.sh ad_server
+           $ssh "$n1" ./scripts/configure_cluster.sh ad_server
+           ;;
+
+       "samba")
+           [ -n "$CLUSTER_PATTERN" ] || CLUSTER_PATTERN="$CLUSTER"
+
+           local nodes=$(vircmd dominfo "$CLUSTER_PATTERN" 2>/dev/null | \
+               sed -n -e 's/Name: *//p')
+
+           for i in $nodes ; do
+               $ssh "$i" ./scripts/install_packages.sh clusterfs nas
+           done
+
+           $ssh "$n1" ./scripts/setup_cluster.sh clusterfs nas
+           ;;
+    esac
+}
+
 create_one_node ()
 {
     CLUSTER="$1"
@@ -557,7 +690,7 @@ guess_install_network ()
 }
 
 # create base image
-create_base()
+base_create()
 {
     local NAME="$BASENAME"
     local DISK="${VIRTBASE}/${NAME}.${BASE_FORMAT}"
@@ -655,7 +788,7 @@ EOF
 
 ###############################
 # boot the base disk
-boot_base() {
+base_boot() {
     rm -rf tmp
     mkdir -p tmp
 
@@ -1154,6 +1287,26 @@ usage_config_options (){
     usage_smart_display load_config
 }
 
+actions_init ()
+{
+    actions=""
+}
+
+actions_add ()
+{
+    actions="${actions}${actions:+ }$*"
+}
+
+actions_run ()
+{
+    [ -n "$actions" ] || usage
+
+    local a
+    for a in $actions ; do
+       $a
+    done
+}
+
 ######################################################################
 
 post_config_hooks=
@@ -1248,17 +1401,45 @@ t="$1"
 shift
 
 case "$t" in
+    base)
+       actions_init
+       for t in "$@" ; do
+           case "$t" in
+               create|boot) actions_add "base_${t}" ;;
+               *) usage ;;
+           esac
+       done
+       actions_run
+       ;;
+
+    cluster)
+       actions_init
+       for t in "$@" ; do
+           case "$t" in
+               destroy|create|update_hosts|boot|configure)
+                   actions_add "cluster_${t}" ;;
+               build)
+                   for t in destroy create update_hosts boot configure ; do
+                       actions_add "cluster_${t}"
+                   done
+                   ;;
+               *) usage ;;
+           esac
+       done
+       actions_run
+       ;;
+
     create)
        t="$1"
        shift
        case "$t" in
            base)
                [ $# != 0 ] && usage
-               create_base
+               base_create
                ;;
            cluster)
                [ $# != 1 ] && usage
-               create_cluster "$1"
+               cluster_create "$1"
                ;;
            node)
                [ $# != 2 ] && usage
@@ -1278,7 +1459,7 @@ case "$t" in
        diskimage unmount
        ;;
     bootbase)
-       boot_base;
+       base_boot;
        ;;
     *)
        usage;