| Index: image_to_live.sh
|
| diff --git a/image_to_live.sh b/image_to_live.sh
|
| deleted file mode 100755
|
| index a61726a35e63dba24f75116b7de5666ba6bd575e..0000000000000000000000000000000000000000
|
| --- a/image_to_live.sh
|
| +++ /dev/null
|
| @@ -1,467 +0,0 @@
|
| -#!/bin/bash
|
| -
|
| -# Copyright (c) 2009-2010 The Chromium OS Authors. All rights reserved.
|
| -# Use of this source code is governed by a BSD-style license that can be
|
| -# found in the LICENSE file.
|
| -
|
| -# Script to update an image onto a live running ChromiumOS instance.
|
| -
|
| -# --- BEGIN COMMON.SH BOILERPLATE ---
|
| -# Load common CrOS utilities. Inside the chroot this file is installed in
|
| -# /usr/lib/crosutils. Outside the chroot we find it relative to the script's
|
| -# location.
|
| -find_common_sh() {
|
| - local common_paths=(/usr/lib/crosutils $(dirname "$(readlink -f "$0")"))
|
| - local path
|
| -
|
| - SCRIPT_ROOT=
|
| - for path in "${common_paths[@]}"; do
|
| - if [ -r "${path}/common.sh" ]; then
|
| - SCRIPT_ROOT=${path}
|
| - break
|
| - fi
|
| - done
|
| -}
|
| -
|
| -find_common_sh
|
| -. "${SCRIPT_ROOT}/common.sh" || (echo "Unable to load common.sh" && exit 1)
|
| -# --- END COMMON.SH BOILERPLATE ---
|
| -
|
| -. "${SCRIPT_ROOT}/remote_access.sh" || die "Unable to load remote_access.sh"
|
| -
|
| -# Flags to control image_to_live.
|
| -DEFINE_boolean ignore_hostname ${FLAGS_TRUE} \
|
| - "Ignore existing AU hostname on running instance use this hostname."
|
| -DEFINE_boolean ignore_version ${FLAGS_TRUE} \
|
| - "Ignore existing version on running instance and always update."
|
| -DEFINE_string server_log "dev_server.log" \
|
| - "Path to log for the devserver."
|
| -DEFINE_boolean update "${FLAGS_TRUE}" \
|
| - "Perform update of root partition."
|
| -DEFINE_boolean update_known_hosts ${FLAGS_FALSE} \
|
| - "Update your known_hosts with the new remote instance's key."
|
| -DEFINE_string update_log "update_engine.log" \
|
| - "Path to log for the update_engine."
|
| -DEFINE_string update_url "" "Full url of an update image."
|
| -DEFINE_boolean verify ${FLAGS_TRUE} "Verify image on device after update."
|
| -
|
| -# Flags for devserver.
|
| -DEFINE_string archive_dir "" \
|
| - "Update using the test image in the image.zip in this directory." a
|
| -DEFINE_string board "" "Override the board reported by the target"
|
| -DEFINE_integer devserver_port 8080 \
|
| - "Port to use for devserver."
|
| -DEFINE_boolean for_vm ${FLAGS_FALSE} "Image is for a vm."
|
| -DEFINE_string image "" \
|
| - "Update with this image path that is in this source checkout." i
|
| -DEFINE_string payload "" \
|
| - "Update with this update payload, ignoring specified images."
|
| -DEFINE_string proxy_port "" \
|
| - "Have the client request from this proxy instead of devserver."
|
| -DEFINE_string src_image "" \
|
| - "Create a delta update by passing in the image on the remote machine."
|
| -DEFINE_boolean update_stateful ${FLAGS_TRUE} \
|
| - "Perform update of stateful partition e.g. /var /usr/local."
|
| -
|
| -# Flags for stateful update.
|
| -DEFINE_string stateful_update_flag "" \
|
| - "Flag to pass to stateful update e.g. old, clean, etc." s
|
| -
|
| -UPDATER_BIN="/usr/bin/update_engine_client"
|
| -UPDATER_IDLE="UPDATE_STATUS_IDLE"
|
| -UPDATER_NEED_REBOOT="UPDATE_STATUS_UPDATED_NEED_REBOOT"
|
| -UPDATER_UPDATE_CHECK="UPDATE_STATUS_CHECKING_FOR_UPDATE"
|
| -UPDATER_DOWNLOADING="UPDATE_STATUS_DOWNLOADING"
|
| -
|
| -IMAGE_PATH=""
|
| -
|
| -function kill_all_devservers {
|
| - # Using ! here to avoid exiting with set -e is insufficient, so use
|
| - # || true instead.
|
| - sudo pkill -f devserver\.py || true
|
| -}
|
| -
|
| -function cleanup {
|
| - if [ -z "${FLAGS_update_url}" ]; then
|
| - kill_all_devservers
|
| - fi
|
| - cleanup_remote_access
|
| - rm -rf "${TMP}"
|
| -}
|
| -
|
| -function remote_reboot_sh {
|
| - rm -f "${TMP_KNOWN_HOSTS}"
|
| - remote_sh "$@"
|
| -}
|
| -
|
| -# Returns the hostname of this machine.
|
| -# It tries to find the ipaddress using ifconfig, however, it will
|
| -# default to $HOSTNAME on failure. We try to use the ip address first as
|
| -# some targets may have dns resolution issues trying to contact back
|
| -# to us.
|
| -function get_hostname {
|
| - local hostname
|
| - # Try to parse ifconfig for ip address. Use sudo, because not all distros
|
| - # allow a common user to call ifconfig.
|
| - # TODO(zbehan): What if target is not connected via eth0? Update over wifi?
|
| - # Dedicated usb NIC? Perhaps this detection should be done in the target,
|
| - # which will get the return address in one way or another. Or maybe we should
|
| - # just open a ssh tunnel and use localhost.
|
| - hostname=$(/sbin/ifconfig eth0 |
|
| - grep 'inet addr' |
|
| - cut -f2 -d':' |
|
| - cut -f1 -d' ')
|
| -
|
| - # Fallback to $HOSTNAME if that failed
|
| - [ -z "${hostname}" ] && hostname=${HOSTNAME}
|
| -
|
| - echo ${hostname}
|
| -}
|
| -
|
| -# Reinterprets path from outside the chroot for use inside.
|
| -# Returns "" if "" given.
|
| -# $1 - The path to reinterpret.
|
| -function reinterpret_path_for_chroot() {
|
| - if [ -z "${1}" ]; then
|
| - echo ""
|
| - else
|
| - local path_abs_path=$(readlink -f "${1}")
|
| - local gclient_root_abs_path=$(readlink -f "${GCLIENT_ROOT}")
|
| -
|
| - # Strip the repository root from the path.
|
| - local relative_path=$(echo ${path_abs_path} \
|
| - | sed s:${gclient_root_abs_path}/::)
|
| -
|
| - if [ "${relative_path}" = "${path_abs_path}" ]; then
|
| - die "Error reinterpreting path. Path ${1} is not within source tree."
|
| - fi
|
| -
|
| - # Prepend the chroot repository path.
|
| - echo "/home/${USER}/trunk/${relative_path}"
|
| - fi
|
| -}
|
| -
|
| -function start_dev_server {
|
| - kill_all_devservers
|
| - local devserver_flags="--pregenerate_update"
|
| - # Parse devserver flags.
|
| - if [ -n "${FLAGS_image}" ]; then
|
| - devserver_flags="${devserver_flags} \
|
| - --image $(reinterpret_path_for_chroot ${FLAGS_image})"
|
| - IMAGE_PATH="${FLAGS_image}"
|
| - elif [ -n "${FLAGS_archive_dir}" ]; then
|
| - devserver_flags="${devserver_flags} \
|
| - --archive_dir $(reinterpret_path_for_chroot ${FLAGS_archive_dir}) -t"
|
| - IMAGE_PATH="${FLAGS_archive_dir}/chromiumos_test_image.bin"
|
| - else
|
| - # IMAGE_PATH should be the newest image and learn the board from
|
| - # the target.
|
| - learn_board
|
| - IMAGE_PATH="$(${SCRIPTS_DIR}/get_latest_image.sh --board="${FLAGS_board}")"
|
| - IMAGE_PATH="${IMAGE_PATH}/chromiumos_image.bin"
|
| - devserver_flags="${devserver_flags} \
|
| - --image $(reinterpret_path_for_chroot ${IMAGE_PATH})"
|
| - fi
|
| -
|
| - if [ -n "${FLAGS_payload}" ]; then
|
| - devserver_flags="${devserver_flags} \
|
| - --payload $(reinterpret_path_for_chroot ${FLAGS_payload})"
|
| - fi
|
| -
|
| - if [ -n "${FLAGS_proxy_port}" ]; then
|
| - devserver_flags="${devserver_flags} \
|
| - --proxy_port ${FLAGS_proxy_port}"
|
| - fi
|
| -
|
| - [ ${FLAGS_for_vm} -eq ${FLAGS_TRUE} ] && \
|
| - devserver_flags="${devserver_flags} --for_vm"
|
| -
|
| - devserver_flags="${devserver_flags} \
|
| - --src_image=\"$(reinterpret_path_for_chroot ${FLAGS_src_image})\""
|
| -
|
| - info "Starting devserver with flags ${devserver_flags}"
|
| - ./enter_chroot.sh -- sudo sh -c "start_devserver ${devserver_flags} \
|
| - --client_prefix=ChromeOSUpdateEngine \
|
| - --board=${FLAGS_board} \
|
| - --port=${FLAGS_devserver_port} > ${FLAGS_server_log} 2>&1" &
|
| -
|
| - info "Waiting on devserver to start"
|
| - info "note: be patient as the server generates the update before starting."
|
| - until netstat -anp 2>&1 | grep 0.0.0.0:${FLAGS_devserver_port} > /dev/null; do
|
| - sleep 5
|
| - echo -n "."
|
| - if ! pgrep -f start_devserver > /dev/null; then
|
| - echo "Devserver failed, see dev_server.log."
|
| - exit 1
|
| - fi
|
| - done
|
| - echo ""
|
| -}
|
| -
|
| -# Copies stateful update script which fetches the newest stateful update
|
| -# from the dev server and prepares the update. chromeos_startup finishes
|
| -# the update on next boot.
|
| -function run_stateful_update {
|
| - local dev_url=$(get_devserver_url)
|
| - local stateful_url=""
|
| - local stateful_update_args=""
|
| -
|
| - # Parse stateful update flag.
|
| - if [ -n "${FLAGS_stateful_update_flag}" ]; then
|
| - stateful_update_args="${stateful_update_args} \
|
| - --stateful_change ${FLAGS_stateful_update_flag}"
|
| - fi
|
| -
|
| - # Assume users providing an update url are using an archive_dir path.
|
| - if [ -n "${FLAGS_update_url}" ]; then
|
| - stateful_url=$(echo ${dev_url} | sed -e "s/update/static\/archive/")
|
| - else
|
| - stateful_url=$(echo ${dev_url} | sed -e "s/update/static/")
|
| - fi
|
| -
|
| - info "Starting stateful update using URL ${stateful_url}"
|
| -
|
| - # Copy over update script and run update.
|
| - local chroot_path="${SCRIPTS_DIR}/../../chroot"
|
| - local stateful_update_script="/usr/bin/stateful_update"
|
| -
|
| - remote_cp_to "${chroot_path}/${stateful_update_script}" "/tmp"
|
| - remote_sh "/tmp/stateful_update ${stateful_update_args} ${stateful_url}"
|
| -}
|
| -
|
| -function get_update_args {
|
| - if [ -z ${1} ]; then
|
| - die "No url provided for update."
|
| - fi
|
| - local update_args="--omaha_url ${1}"
|
| - if [[ ${FLAGS_ignore_version} -eq ${FLAGS_TRUE} ]]; then
|
| - info "Forcing update independent of the current version"
|
| - update_args="--update ${update_args}"
|
| - fi
|
| -
|
| - echo "${update_args}"
|
| -}
|
| -
|
| -function get_devserver_url {
|
| - local devserver_url=""
|
| - local port=${FLAGS_devserver_port}
|
| -
|
| - if [[ -n ${FLAGS_proxy_port} ]]; then
|
| - port=${FLAGS_proxy_port}
|
| - fi
|
| -
|
| - if [ ${FLAGS_ignore_hostname} -eq ${FLAGS_TRUE} ]; then
|
| - if [ -z ${FLAGS_update_url} ]; then
|
| - devserver_url="http://$(get_hostname):${port}/update"
|
| - else
|
| - devserver_url="${FLAGS_update_url}"
|
| - fi
|
| - fi
|
| - echo "${devserver_url}"
|
| -}
|
| -
|
| -function truncate_update_log {
|
| - remote_sh "> /var/log/update_engine.log"
|
| -}
|
| -
|
| -function get_update_log {
|
| - remote_sh "cat /var/log/update_engine.log"
|
| - echo "${REMOTE_OUT}" > "${FLAGS_update_log}"
|
| -}
|
| -
|
| -# Returns ${1} reported by the update client e.g. PROGRESS, CURRENT_OP.
|
| -function get_update_var {
|
| - remote_sh "${UPDATER_BIN} --status 2> /dev/null |
|
| - grep ${1} |
|
| - cut -f 2 -d ="
|
| - echo "${REMOTE_OUT}"
|
| -}
|
| -
|
| -# Returns the current status / progress of the update engine.
|
| -# This is expected to run in its own thread.
|
| -function status_thread {
|
| - local timeout=5
|
| -
|
| - info "Devserver handling ping. Check ${FLAGS_server_log} for more info."
|
| - sleep ${timeout}
|
| -
|
| - local current_state=""
|
| - local next_state="$(get_update_var CURRENT_OP)"
|
| -
|
| - # For current status, only print out status changes.
|
| - # For download, show progress.
|
| - # Finally if no status change print out .'s to keep dev informed.
|
| - while [ "${current_state}" != "${UPDATER_NEED_REBOOT}" ] && \
|
| - [ "${current_state}" != "${UPDATER_IDLE}" ]; do
|
| - if [ "${current_state}" != "${next_state}" ]; then
|
| - info "State of updater has changed to: ${next_state}"
|
| - elif [ "${next_state}" = "${UPDATER_DOWNLOADING}" ]; then
|
| - echo "Download progress $(get_update_var PROGRESS)"
|
| - else
|
| - echo -n "."
|
| - fi
|
| -
|
| - sleep ${timeout}
|
| - current_state="${next_state}"
|
| - next_state="$(get_update_var CURRENT_OP)"
|
| - done
|
| -}
|
| -
|
| -# Pings the update_engine to see if it responds or a max timeout is reached.
|
| -# Returns 1 if max timeout is reached.
|
| -function wait_until_update_engine_is_ready {
|
| - local wait_timeout=1
|
| - local max_timeout=60
|
| - local time_elapsed=0
|
| - while ! get_update_var CURRENT_OP > /dev/null; do
|
| - sleep ${wait_timeout}
|
| - time_elapsed=$(( time_elapsed + wait_timeout ))
|
| - echo -n "."
|
| - if [ ${time_elapsed} -gt ${max_timeout} ]; then
|
| - return 1
|
| - fi
|
| - done
|
| -}
|
| -
|
| -function run_auto_update {
|
| - # Truncate the update log so our log file is clean.
|
| - truncate_update_log
|
| -
|
| - local update_args="$(get_update_args "$(get_devserver_url)")"
|
| - info "Waiting to initiate contact with the update_engine."
|
| - wait_until_update_engine_is_ready || die "Could not contact update engine."
|
| -
|
| - info "Starting update using args ${update_args}"
|
| -
|
| - # Sets up a secondary thread to track the update progress.
|
| - status_thread &
|
| - local status_thread_pid=$!
|
| - trap "kill ${status_thread_pid} && cleanup" EXIT
|
| -
|
| - # Actually run the update. This is a blocking call.
|
| - remote_sh "${UPDATER_BIN} ${update_args}"
|
| -
|
| - # Clean up secondary thread.
|
| - ! kill ${status_thread_pid} 2> /dev/null
|
| - trap cleanup EXIT
|
| -
|
| - # We get the log file now.
|
| - get_update_log
|
| -
|
| - local update_status="$(get_update_var CURRENT_OP)"
|
| - if [ "${update_status}" = ${UPDATER_NEED_REBOOT} ]; then
|
| - info "Autoupdate was successful."
|
| - return 0
|
| - else
|
| - warn "Autoupdate was unsuccessful. Status returned was ${update_status}."
|
| - return 1
|
| - fi
|
| -}
|
| -
|
| -function verify_image {
|
| - info "Verifying image."
|
| - "${SCRIPTS_DIR}/mount_gpt_image.sh" --from "$(dirname "${IMAGE_PATH}")" \
|
| - --image "$(basename ${IMAGE_PATH})" \
|
| - --read_only
|
| -
|
| - local lsb_release=$(cat /tmp/m/etc/lsb-release)
|
| - info "Verifying image with release:"
|
| - echo ${lsb_release}
|
| -
|
| - "${SCRIPTS_DIR}/mount_gpt_image.sh" --unmount
|
| -
|
| - remote_sh "cat /etc/lsb-release"
|
| - info "Remote image reports:"
|
| - echo ${REMOTE_OUT}
|
| -
|
| - if [ "${lsb_release}" = "${REMOTE_OUT}" ]; then
|
| - info "Update was successful and image verified as ${lsb_release}."
|
| - return 0
|
| - else
|
| - warn "Image verification failed."
|
| - return 1
|
| - fi
|
| -}
|
| -
|
| -function find_root_dev {
|
| - remote_sh "rootdev -s"
|
| - echo ${REMOTE_OUT}
|
| -}
|
| -
|
| -function main() {
|
| - assert_outside_chroot
|
| -
|
| - cd "${SCRIPTS_DIR}"
|
| -
|
| - FLAGS "$@" || exit 1
|
| - eval set -- "${FLAGS_ARGV}"
|
| -
|
| - set -e
|
| -
|
| - if [ ${FLAGS_verify} -eq ${FLAGS_TRUE} ] && \
|
| - [ -n "${FLAGS_update_url}" ]; then
|
| - warn "Verify is not compatible with setting an update url."
|
| - FLAGS_verify=${FLAGS_FALSE}
|
| - fi
|
| -
|
| - trap cleanup EXIT
|
| -
|
| - TMP=$(mktemp -d /tmp/image_to_live.XXXX)
|
| -
|
| - remote_access_init
|
| -
|
| - if [ "$(get_update_var CURRENT_OP)" != "${UPDATER_IDLE}" ]; then
|
| - warn "Machine is in a bad state. Rebooting it now."
|
| - remote_reboot
|
| - fi
|
| -
|
| - local initial_root_dev=$(find_root_dev)
|
| -
|
| - if [ -z "${FLAGS_update_url}" ]; then
|
| - # Start local devserver if no update url specified.
|
| - start_dev_server
|
| - fi
|
| -
|
| - if [ ${FLAGS_update} -eq ${FLAGS_TRUE} ] && ! run_auto_update; then
|
| - warn "Dumping update_engine.log for debugging and/or bug reporting."
|
| - tail -n 200 "${FLAGS_update_log}" >&2
|
| - die "Update was not successful."
|
| - fi
|
| -
|
| - if [ ${FLAGS_update_stateful} -eq ${FLAGS_TRUE} ] && \
|
| - ! run_stateful_update; then
|
| - die "Stateful update was not successful."
|
| - fi
|
| -
|
| - remote_reboot
|
| -
|
| - if [[ ${FLAGS_update_hostkey} -eq ${FLAGS_TRUE} ]]; then
|
| - local known_hosts="${HOME}/.ssh/known_hosts"
|
| - cp "${known_hosts}" "${known_hosts}~"
|
| - grep -v "^${FLAGS_remote} " "${known_hosts}" > "${TMP}/new_known_hosts"
|
| - cat "${TMP}/new_known_hosts" "${TMP_KNOWN_HOSTS}" > "${known_hosts}"
|
| - chmod 0640 "${known_hosts}"
|
| - info "New updated in ${known_hosts}, backup made."
|
| - fi
|
| -
|
| - remote_sh "grep ^CHROMEOS_RELEASE_DESCRIPTION= /etc/lsb-release"
|
| - if [ ${FLAGS_verify} -eq ${FLAGS_TRUE} ]; then
|
| - verify_image
|
| -
|
| - if [ "${initial_root_dev}" == "$(find_root_dev)" ]; then
|
| - # At this point, the software version didn't change, but we didn't
|
| - # switch partitions either. Means it was an update to the same version
|
| - # that failed.
|
| - die "The root partition did NOT change. The update failed."
|
| - fi
|
| - else
|
| - local release_description=$(echo ${REMOTE_OUT} | cut -d '=' -f 2)
|
| - info "Update was successful and rebooted to $release_description"
|
| - fi
|
| -
|
| - print_time_elapsed
|
| -
|
| - exit 0
|
| -}
|
| -
|
| -main $@
|
|
|