#!/bin/bash
# Copyright 2013 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Prep the image for Google Compute services.
#
# Do NOT "set -e"

# Exit out early if we've run before.
declare -r RUNFILE=/var/run/google.onboot
if [ -f ${RUNFILE} ]; then
  exit 0
fi

PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin

declare -r LOGFILE=/var/log/google.log

if [ -x /usr/bin/logger ]; then
    declare -r LOGGER=/usr/bin/logger
else
    declare -r LOGGER=/bin/logger
fi

declare -r BOTO_SETUP_SCRIPT=/usr/share/google/boto/boot_setup.py
declare -r GOOGLE_ENVIRONMENT=/var/run/google.environment

function log() {
  echo $* | ${LOGGER} -t google -p daemon.info
  echo $* >> ${LOGFILE}
}

function set_interrupts() {
  if [[ -x /usr/share/google/set-interrupts ]]; then
    /usr/share/google/set-interrupts
  fi
}

function virtionet_irq_affinity() {
  if [[ -x /usr/share/google/virtionet-irq-affinity ]]; then
    /usr/share/google/virtionet-irq-affinity
  fi
}

function first_boot() {
  if [[ -x /usr/share/google/first-boot ]]; then
    /usr/share/google/first-boot
  fi
}

function get_metadata_value() {
  local readonly varname=$1
  /usr/share/google/get_metadata_value ${varname}
  return $?
}

function do_environment() {
  echo "INSTANCE_ID=$(get_metadata_value id)" > ${GOOGLE_ENVIRONMENT}
}

function do_init() {
  log "onboot initializing"

  do_environment

  # If it exists, run the boto bootstrap script. This will set things
  # up so that gsutil will just work with any provisioned service
  # account.
  if [ -x ${BOTO_SETUP_SCRIPT} ]; then
    log "Running Boto setup script at ${BOTO_SETUP_SCRIPT}"
    ${BOTO_SETUP_SCRIPT} >> ${LOGFILE} 2>&1
  fi

  return 0
}

function print_ssh_key_fingerprints() {
  log "SSH public key fingerprints"

  if [ -e /etc/ssh/ssh_host_rsa_key.pub ]; then
    log "RSA public key"
    ssh-keygen -lf /etc/ssh/ssh_host_rsa_key.pub
  else
    log "No RSA public key found."
  fi

  if [ -e /etc/ssh/ssh_host_dsa_key.pub ]; then
    log "DSA public key"
    ssh-keygen -lf /etc/ssh/ssh_host_dsa_key.pub
  else
    log "No DSA public key found."
  fi

  if [ -e /etc/ssh/ssh_host_ecdsa_key.pub ]; then
    log "ECDSA public key"
    ssh-keygen -lf /etc/ssh/ssh_host_ecdsa_key.pub
  else
    log "No ECDSA public key found."
  fi

  return 0
}

function check_for_connection() {
  local count=0
  local return_code=0

  log "Checking for metadata server connection."
  while true; do
    ((count++))
    MDS_TRIES=1 /usr/share/google/get_metadata_value "?recursive=True"
    return_code=$?
    case ${return_code} in
      # No error.  Connection is active.
      0) break;;
      # Failed to resolve host or connect to host.  Retry indefinitely.
      6|7) sleep 1.0
        log "Waiting for metadata server, attempt ${count}"
        # After 7 minutes, add a console message denoting a probable network
        # issue. On systems using dhclient there is an attempt to obtain an IP
        # for 60 seconds followed by a 5 minute wait period. After 7 minutes,
        # this cycle will have run through twice. After this period of time, it
        # is not known when a DHCP lease might be obtained and the network
        # interface fully operational.
        if ((count >= 7*60+1)); then
          log "There is likely a problem with the network."
        fi
        continue;;
      # A genuine error but a connection exists.
      *)
        log "Check for connection non-fatal error getting metadata ${return_code}"
        break;;
    esac
  done
  # Return the last return code we got.
  return ${return_code}
}

set_interrupts
virtionet_irq_affinity
check_for_connection
first_boot
do_init
print_ssh_key_fingerprints

if [ -x /sbin/initctl ]; then
  /sbin/initctl emit --no-wait google-onboot-has-run
fi

# Indicate that we've run already.
touch ${RUNFILE}
