Fix rebuild.sh for aarch64, add --reuse/--reuse_resync

1. Move some GCP-specific logic under the GCP if conditional
2. Do not use the x86 login (--x86_user) on the target ARM
   board; use the ARM login (--arm_user).
3. Add a --reuse option that bypasses setting up (for a GCP instance)
   and syncing the source (for a GCP instance and an ARM board).  Useful
   whem making changes to the already-checked-out files for
   experimentation. Default is false.
4. Add a --reuse_resync, which is like --reuse except that it cleans and
   resyncs the sources from the provided manifest prior to building it.
   This is useful for GCP instances, which can be slow to delete and
   re-create for every build attemp.  Option --reuse_resync overrides
   option --reuse when both are specified.  Default is false.

Example uses:

To rebuild crosvm for ARM, using an ARM board accessible at 192.168.0.6
and user cf:

cd $(gettop)
./device/google/cuttlefish_vmm/rebuild.sh \
	--custom_manifest=device/google/cuttlefish_vmm/aarch64-linux-gnu/manifest.xml \
	--x86_instance="" \
	--arm_system=192.168.0.6 --arm_user=cf

To rebuilt crosvm for x86_64, using a freshly-created GCP instance,
using the defaults from the shell script (and assuming you have gcloud
set up and are properly authenticated):

cd $(gettop)
./device/google/cuttlefish_vmm/rebuild.sh \
	--custom_manifest=device/google/cuttlefish_vmm/aarch64-linux-gnu/manifest.xml \
	--arm_system=""

To do the same as the above, but reusing the instance:

cd $(gettop)
./device/google/cuttlefish_vmm/rebuild.sh \
	--custom_manifest=device/google/cuttlefish_vmm/aarch64-linux-gnu/manifest.xml \
	--arm_system="" \
	--reuse

To reuse the instance, but do a clean checkout of the code:

cd $(gettop)
./device/google/cuttlefish_vmm/rebuild.sh \
	--custom_manifest=device/google/cuttlefish_vmm/aarch64-linux-gnu/manifest.xml \
	--arm_system="" \
	--reuse_resync

Test: built x86_64 and aarch64 crosvm with and without --reuse and
      --reuse_resync
Bug: 148642775 Clean up the crosvm build

Change-Id: I5f3f744b858e876ab856b00b00e4c62f824f5a02
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/rebuild.sh b/rebuild.sh
index 07a8db6..a123fd9 100755
--- a/rebuild.sh
+++ b/rebuild.sh
@@ -26,6 +26,8 @@
 DEFINE_string x86_user cuttlefish_crosvm_builder \
   "User name to use on GCE when doing the build"
 DEFINE_string zone "$(gcloud config get-value compute/zone)" "Zone to use" "z"
+DEFINE_boolean reuse false "Set to true to reuse a previously-set-up instance."
+DEFINE_boolean reuse_resync false "Reuse a previously-set-up instance, but clean and re-sync the sources. Overrides --reuse if both are specified."
 
 SSH_FLAGS=(${INTERNAL_IP})
 
@@ -43,6 +45,7 @@
   fail=0
   source_files=("${DIR}"/rebuild_gce.sh)
   gce_flags=()
+  arm_flags=()
   if [[ -n "${FLAGS_custom_manifest}" ]]; then
     if [[ ! -f "${FLAGS_custom_manifest}" ]]; then
       echo custom manifest not found: ${FLAGS_custom_manifest} 1>&1
@@ -50,33 +53,57 @@
     fi
     source_files+=("${FLAGS_custom_manifest}")
     gce_flags+=("CUSTOM_MANIFEST=/home/${FLAGS_x86_user}/$(basename "${FLAGS_custom_manifest}")")
+    arm_flags+=("CUSTOM_MANIFEST=/home/${FLAGS_arm_user}/$(basename "${FLAGS_custom_manifest}")")
   fi
-  if [[ -z "${FLAGS_project}" ]]; then
-    echo Must specify project 1>&2
-    fail=1
+  local _prepare_source=(install_packages prepare_source);
+  local _reuse=0
+  if [ ${FLAGS_reuse} -eq ${FLAGS_TRUE} ]; then
+    # neither install packages, nor sync sources; skip to building them
+    _prepare_source=()
+    _reuse=1
   fi
-  if [[ -z "${FLAGS_zone}" ]]; then
-    echo Must specify zone 1>&2
-    fail=1
-  fi
-  if [[ "${fail}" -ne 0 ]]; then
-    exit "${fail}"
+  if [ ${FLAGS_reuse_resync} -eq ${FLAGS_TRUE} ]; then
+    # do not install packages but clean and sync sources afresh
+    _prepare_source=(resync_source);
+    _reuse=1
   fi
   if [[ -n "${FLAGS_x86_instance}" ]]; then
+    if [[ -z "${FLAGS_project}" ]]; then
+      echo Must specify project 1>&2
+      fail=1
+    fi
+    if [[ -z "${FLAGS_zone}" ]]; then
+      echo Must specify zone 1>&2
+      fail=1
+    fi
+    if [[ "${fail}" -ne 0 ]]; then
+      exit "${fail}"
+    fi
     project_zone_flags=(--project="${FLAGS_project}" --zone="${FLAGS_zone}")
-    delete_instances=("${FLAGS_x86_instance}")
-    gcloud compute instances delete -q \
-      "${project_zone_flags[@]}" \
-      "${delete_instances[@]}" || \
-        echo Not running
-    gcloud compute instances create \
-      "${project_zone_flags[@]}" \
-      --boot-disk-size=200GB \
-      --machine-type=n1-standard-4 \
-      --image-family="${FLAGS_source_image_family}" \
-      --image-project="${FLAGS_source_image_project}" \
-      "${FLAGS_x86_instance}"
-    wait_for_instance "${FLAGS_x86_instance}"
+    if [ ${_reuse} -eq 0 ]; then
+      delete_instances=("${FLAGS_x86_instance}")
+      gcloud compute instances delete -q \
+        "${project_zone_flags[@]}" \
+        "${delete_instances[@]}" || \
+          echo Not running
+      gcloud compute instances create \
+        "${project_zone_flags[@]}" \
+        --boot-disk-size=200GB \
+        --machine-type=n1-standard-4 \
+        --image-family="${FLAGS_source_image_family}" \
+        --image-project="${FLAGS_source_image_project}" \
+        "${FLAGS_x86_instance}"
+      wait_for_instance "${FLAGS_x86_instance}"
+    fi
+    local _status=$(gcloud compute instances list \
+                    --project="${FLAGS_project}" \
+                    --zones="${FLAGS_zone}" \
+                    --filter="name=('${FLAGS_x86_instance}')" \
+                    --format=flattened | awk '/status:/ {print $2}')
+    if [ "${_status}" != "RUNNING" ] ; then
+      echo "Instance ${FLAGS_x86_instance} is not running."
+      exit 1;
+    fi
     # beta for the --internal-ip flag that may be passed via SSH_FLAGS
     gcloud beta compute scp "${SSH_FLAGS[@]}" \
       "${project_zone_flags[@]}" \
@@ -85,7 +112,7 @@
     gcloud compute ssh "${SSH_FLAGS[@]}" \
       "${project_zone_flags[@]}" \
       "${FLAGS_x86_user}@${FLAGS_x86_instance}" -- \
-        ./rebuild_gce.sh "${gce_flags[@]}" prepare_source x86_64_build
+        ./rebuild_gce.sh "${gce_flags[@]}" ${_prepare_source[@]} x86_64_build
     gcloud beta compute scp --recurse "${SSH_FLAGS[@]}" \
       "${project_zone_flags[@]}" \
       "${FLAGS_x86_user}@${FLAGS_x86_instance}":x86_64-linux-gnu \
@@ -98,9 +125,8 @@
     scp \
       "${source_files[@]}" \
       "${FLAGS_arm_user}@${FLAGS_arm_system}:"
-    # We're using the source tarball from the x86_64 build
     ssh -t "${FLAGS_arm_user}@${FLAGS_arm_system}" -- \
-        ./rebuild_gce.sh "${gce_flags[@]}" prepare_source arm64_build
+        ./rebuild_gce.sh "${arm_flags[@]}" ${_prepare_source[@]} arm64_build
     scp -r "${FLAGS_arm_user}@${FLAGS_arm_system}":aarch64-linux-gnu \
       "${ANDROID_BUILD_TOP}/device/google/cuttlefish_vmm"
   fi
diff --git a/rebuild_gce.sh b/rebuild_gce.sh
index 6cfe64c..4744d6d 100755
--- a/rebuild_gce.sh
+++ b/rebuild_gce.sh
@@ -94,16 +94,9 @@
   fi
 }
 
-prepare_source() {
-  if [ "$(ls -A $SOURCE_DIR)" ]; then
-    echo "${SOURCE_DIR} is non empty. Run this from an empty directory if you wish to fetch the source." 1>&2
-    exit 2
-  fi
-
+fetch_source() {
   echo "Fetching source..."
 
-  # Needed so we can use git
-  install_packages
   mkdir -p "${SOURCE_DIR}"
   cd "${SOURCE_DIR}"
 
@@ -121,6 +114,20 @@
   repo sync
 }
 
+prepare_source() {
+  if [ "$(ls -A $SOURCE_DIR)" ]; then
+    echo "${SOURCE_DIR} is non empty. Run this from an empty directory if you wish to fetch the source." 1>&2
+    exit 2
+  fi
+  fetch_source
+}
+
+resync_source() {
+  echo "Deleting source directory..."
+  rm -rf "${SOURCE_DIR}"
+  fetch_source
+}
+
 compile_minijail() {
   echo "Compiling Minijail..."
 
@@ -287,6 +294,8 @@
     CUSTOM_MANIFEST=*) CUSTOM_MANIFEST="${i/CUSTOM_MANIFEST=/}" ;;
     arm64_build) $i ;;
     arm64_retry) $i ;;
+    install_packages) $i ;;
+    resync_source) $i ;;
     prepare_source) $i ;;
     x86_64_build) $i ;;
     x86_64_retry) $i ;;