Move shared disk presence logic from nodes into shared disk code
[autocluster.git] / autocluster
index 1a8d1670cd9ee4b566ac3b0be4a1f76e451378db..3c8219f150cc338d394da426d31690e207a94449 100755 (executable)
@@ -52,10 +52,14 @@ EOF
     cat <<EOF
 
   commands:
+     base [ create | boot ] ...
+
+     cluster [ build | destroy | create | update_hosts | boot | configure ] ...
+
      create base
            create a base image
 
-     create cluster CLUSTERNAME
+     create cluster [ CLUSTERNAME ]
            create a full cluster
 
      create node CLUSTERNAME IP_OFFSET
@@ -69,9 +73,6 @@ EOF
 
      bootbase
            boot the base image
-
-     testproxy
-           test your proxy setup
 EOF
     exit 1
 }
@@ -87,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}
@@ -469,9 +503,12 @@ common_nodelist_hacking ()
 create_cluster_hooks=
 cluster_created_hooks=
 
-create_cluster ()
+cluster_create ()
 {
-    CLUSTER="$1"
+    # 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
 
@@ -498,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"
@@ -558,7 +690,7 @@ guess_install_network ()
 }
 
 # create base image
-create_base()
+base_create()
 {
     local NAME="$BASENAME"
     local DISK="${VIRTBASE}/${NAME}.${BASE_FORMAT}"
@@ -645,6 +777,7 @@ may not have matched anything at the end of the kickstart output."
 Install finished, base image $DISK created
 
 You may wish to run
+   chcon -t virt_content_t $DISK
    chattr +i $DISK
 To ensure that this image does not change
 
@@ -655,7 +788,7 @@ EOF
 
 ###############################
 # boot the base disk
-boot_base() {
+base_boot() {
     rm -rf tmp
     mkdir -p tmp
 
@@ -1154,11 +1287,24 @@ usage_config_options (){
     usage_smart_display load_config
 }
 
-list_releases () {
-    local releases=$(cd $installdir/releases && echo *.release)
-    releases="${releases//.release}"
-    releases="${releases// /\", \"}"
-    echo "\"$releases\""
+actions_init ()
+{
+    actions=""
+}
+
+actions_add ()
+{
+    actions="${actions}${actions:+ }$*"
+}
+
+actions_run ()
+{
+    [ -n "$actions" ] || usage
+
+    local a
+    for a in $actions ; do
+       $a
+    done
 }
 
 ######################################################################
@@ -1172,7 +1318,7 @@ load_config
 ############################
 # parse command line options
 long_opts=$(getopt_config_options)
-getopt_output=$(getopt -n autocluster -o "c:e:E:xh" -l help,dump,with-release: -l "$long_opts" -- "$@")
+getopt_output=$(getopt -n autocluster -o "c:e:E:xh" -l help,dump -l "$long_opts" -- "$@")
 [ $? != 0 ] && usage
 
 use_default_config=true
@@ -1186,7 +1332,6 @@ while true ; do
        -e) shift 2 ;;
        -E) shift 2 ;;
        --) shift ; break ;;
-       --with-release) shift 2 ;; # Don't set use_default_config=false!!!
        --dump|-x) shift ;;
        -h|--help) usage ;; # Usage should be shown here for real defaults.
        --*) shift 2 ;; # Assume other long opts are valid and take an arg.
@@ -1201,8 +1346,20 @@ eval set -- "$getopt_output"
 
 while true ; do
     case "$1" in
-       # force at least ./local_file to avoid accidental file from $PATH
-       -c) . "$(dirname $2)/$(basename $2)" ; shift 2 ;;
+       -c)
+           b=$(basename $2)
+           # force at least ./local_file to avoid accidental file
+           # from $PATH
+           . "$(dirname $2)/${b}"
+           # If $CLUSTER is unset then try to base it on the filename
+           if [ ! -n "$CLUSTER" ] ; then
+               case "$b" in
+                   *.autocluster)
+                       CLUSTER="${b%.autocluster}"
+               esac
+           fi
+           shift 2
+           ;;
        -e) no_sanity=1 ; run_hooks post_config_hooks ; eval "$2" ; exit ;;
        -E) eval "$2" ; shift 2 ;;
        -x) set -x; shift ;;
@@ -1240,21 +1397,49 @@ check_command expect
 
 [ $# -lt 1 ] && usage
 
-command="$1"
+t="$1"
 shift
 
-case $command in
+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)
-       type=$1
+       t="$1"
        shift
-       case $type in
+       case "$t" in
            base)
                [ $# != 0 ] && usage
-               create_base
+               base_create
                ;;
            cluster)
                [ $# != 1 ] && usage
-               create_cluster "$1"
+               cluster_create "$1"
                ;;
            node)
                [ $# != 2 ] && usage
@@ -1274,10 +1459,7 @@ case $command in
        diskimage unmount
        ;;
     bootbase)
-       boot_base;
-       ;;
-    testproxy)
-       test_proxy;
+       base_boot;
        ;;
     *)
        usage;