| OLD | NEW |
| 1 #!/bin/bash | 1 #!/bin/bash |
| 2 | 2 |
| 3 # Copyright (c) 2009 The Chromium OS Authors. All rights reserved. | 3 # Copyright (c) 2009 The Chromium OS Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 # Script to convert the output of build_image.sh to a usb image. | 7 # Script to update an image onto a live running ChromiumOS instance. |
| 8 | 8 |
| 9 # Load common constants. This should be the first executable line. | 9 # Load common constants. This should be the first executable line. |
| 10 # The path to common.sh should be relative to your script's location. | 10 # The path to common.sh should be relative to your script's location. |
| 11 . "$(dirname "$0")/common.sh" | |
| 12 | 11 |
| 13 assert_outside_chroot | 12 . "$(dirname $0)/common.sh" |
| 13 . "$(dirname $0)/remote_access.sh" |
| 14 | 14 |
| 15 cd $(dirname "$0") | 15 DEFINE_boolean ignore_version ${FLAGS_TRUE} \ |
| 16 | |
| 17 DEFAULT_PRIVATE_KEY="$SRC_ROOT/platform/testing/testing_rsa" | |
| 18 | |
| 19 DEFINE_string ip "" "IP address of running Chromium OS instance" | |
| 20 DEFINE_boolean ignore_version $FLAGS_TRUE \ | |
| 21 "Ignore existing version on running instance and always update" | 16 "Ignore existing version on running instance and always update" |
| 22 DEFINE_boolean ignore_hostname $FLAGS_TRUE \ | 17 DEFINE_boolean ignore_hostname ${FLAGS_TRUE} \ |
| 23 "Ignore existing AU hostname on running instance use this hostname" | 18 "Ignore existing AU hostname on running instance use this hostname" |
| 24 DEFINE_string private_key "$DEFAULT_PRIVATE_KEY" \ | 19 DEFINE_boolean update_known_hosts ${FLAGS_FALSE} \ |
| 25 "Private key of root account on instance" | 20 "Update your known_hosts with the new remote instance's key" |
| 26 | |
| 27 FLAGS "$@" || exit 1 | |
| 28 eval set -- "${FLAGS_ARGV}" | |
| 29 | |
| 30 set -e | |
| 31 | |
| 32 if [ -z "$FLAGS_ip" ]; then | |
| 33 echo "Please specify the IP of the Chromium OS instance" | |
| 34 exit 1 | |
| 35 fi | |
| 36 | |
| 37 TMP=$(mktemp -d /tmp/image_to_live.XXXX) | |
| 38 TMP_PRIVATE_KEY=$TMP/private_key | |
| 39 TMP_KNOWN_HOSTS=$TMP/known_hosts | |
| 40 | 21 |
| 41 function kill_all_devservers { | 22 function kill_all_devservers { |
| 42 ! pkill -f 'python devserver.py' | 23 ! pkill -f 'python devserver.py' |
| 43 } | 24 } |
| 44 | 25 |
| 45 function cleanup { | 26 function cleanup { |
| 46 kill_all_devservers | 27 kill_all_devservers |
| 47 rm -rf $TMP | 28 rm -rf "${TMP}" |
| 48 } | |
| 49 | |
| 50 trap cleanup EXIT | |
| 51 | |
| 52 function remote_sh { | |
| 53 # Disable strict host checking so that we don't prompt the user when | |
| 54 # the host key file is removed and just go ahead and add it. | |
| 55 REMOTE_OUT=$(ssh -o StrictHostKeyChecking=no -o \ | |
| 56 UserKnownHostsFile=$TMP_KNOWN_HOSTS root@$FLAGS_ip "$@") | |
| 57 return ${PIPESTATUS[0]} | |
| 58 } | 29 } |
| 59 | 30 |
| 60 function remote_reboot_sh { | 31 function remote_reboot_sh { |
| 61 rm -f $TMP_KNOWN_HOSTS | 32 rm -f "${TMP_KNOWN_HOSTS}" |
| 62 remote_sh "$@" | 33 remote_sh "$@" |
| 63 } | 34 } |
| 64 | 35 |
| 65 function set_up_remote_access { | |
| 66 if [ -z "$SSH_AGENT_PID" ]; then | |
| 67 eval `ssh-agent` | |
| 68 fi | |
| 69 cp $FLAGS_private_key $TMP_PRIVATE_KEY | |
| 70 chmod 0400 $TMP_PRIVATE_KEY | |
| 71 ssh-add $TMP_PRIVATE_KEY | |
| 72 | |
| 73 # Verify the client is reachable before continuing | |
| 74 remote_sh "true" | |
| 75 } | |
| 76 | |
| 77 function start_dev_server { | 36 function start_dev_server { |
| 78 kill_all_devservers | 37 kill_all_devservers |
| 79 sudo -v | 38 sudo -v |
| 80 ./enter_chroot.sh "cd ../platform/dev; ./start-devserver.sh>/dev/null 2>&1" & | 39 ./enter_chroot.sh "cd ../platform/dev; ./start-devserver.sh>/dev/null 2>&1" & |
| 81 echo -n "Waiting on devserver to start" | 40 echo -n "Waiting on devserver to start" |
| 82 until netstat -anp 2>&1 | grep 8080 > /dev/null; do | 41 until netstat -anp 2>&1 | grep 8080 > /dev/null; do |
| 83 sleep .5 | 42 sleep .5 |
| 84 echo -n "." | 43 echo -n "." |
| 85 done | 44 done |
| 86 echo "" | 45 echo "" |
| 87 } | 46 } |
| 88 | 47 |
| 89 function prepare_update_metadata { | 48 function prepare_update_metadata { |
| 90 remote_sh "mount -norw,remount /" | 49 remote_sh "mount -norw,remount /" |
| 91 | 50 |
| 92 if [ $FLAGS_ignore_version -eq $FLAGS_TRUE ]; then | 51 if [[ ${FLAGS_ignore_version} -eq ${FLAGS_TRUE} ]]; then |
| 93 echo "Forcing update independent of the current version" | 52 echo "Forcing update independent of the current version" |
| 94 remote_sh "cat /etc/lsb-release |\ | 53 remote_sh "cat /etc/lsb-release |\ |
| 95 grep -v CHROMEOS_RELEASE_VERSION > /etc/lsb-release~;\ | 54 grep -v CHROMEOS_RELEASE_VERSION > /etc/lsb-release~;\ |
| 96 mv /etc/lsb-release~ /etc/lsb-release; \ | 55 mv /etc/lsb-release~ /etc/lsb-release; \ |
| 97 echo 'CHROMEOS_RELEASE_VERSION=0.0.0.0' >> /etc/lsb-release" | 56 echo 'CHROMEOS_RELEASE_VERSION=0.0.0.0' >> /etc/lsb-release" |
| 98 fi | 57 fi |
| 99 | 58 |
| 100 if [ $FLAGS_ignore_hostname -eq $FLAGS_TRUE ]; then | 59 if [ ${FLAGS_ignore_hostname} -eq ${FLAGS_TRUE} ]; then |
| 101 echo "Forcing update from $HOSTNAME" | 60 echo "Forcing update from ${HOSTNAME}" |
| 102 remote_sh "cat /etc/lsb-release |\ | 61 remote_sh "cat /etc/lsb-release |\ |
| 103 grep -v '^CHROMEOS_AUSERVER=' |\ | 62 grep -v '^CHROMEOS_AUSERVER=' |\ |
| 104 grep -v '^CHROMEOS_DEVSERVER=' > /etc/lsb-release~;\ | 63 grep -v '^CHROMEOS_DEVSERVER=' > /etc/lsb-release~;\ |
| 105 mv /etc/lsb-release~ /etc/lsb-release; \ | 64 mv /etc/lsb-release~ /etc/lsb-release; \ |
| 106 echo 'CHROMEOS_AUSERVER=http://$HOSTNAME:8080/update' >> \ | 65 echo 'CHROMEOS_AUSERVER=http://$HOSTNAME:8080/update' >> \ |
| 107 /etc/lsb-release; \ | 66 /etc/lsb-release; \ |
| 108 echo 'CHROMEOS_DEVSERVER=http://$HOSTNAME:8080' >> /etc/lsb-release" | 67 echo 'CHROMEOS_DEVSERVER=http://$HOSTNAME:8080' >> /etc/lsb-release" |
| 109 fi | 68 fi |
| 110 | 69 |
| 111 remote_sh "mount -noro,remount /" | 70 remote_sh "mount -noro,remount /" |
| 112 } | 71 } |
| 113 | 72 |
| 114 function run_auto_update { | 73 function run_auto_update { |
| 115 echo "Starting update and clear away prior" | 74 echo "Starting update" |
| 116 UPDATE_FILE=/var/log/softwareupdate.log | 75 local update_file=/var/log/softwareupdate.log |
| 117 # Clear it out so we don't see a prior run and make sure it | 76 # Clear it out so we don't see a prior run and make sure it |
| 118 # exists so the first tail below can't fail if it races the | 77 # exists so the first tail below can't fail if it races the |
| 119 # memento updater first write and wins. | 78 # memento updater first write and wins. |
| 120 remote_sh "rm -f $UPDATE_FILE; touch $UPDATE_FILE; \ | 79 remote_sh "rm -f ${update_file}; touch ${update_file}; \ |
| 121 /opt/google/memento_updater/memento_updater.sh</dev/null>&/dev/null&" | 80 /opt/google/memento_updater/memento_updater.sh</dev/null>&/dev/null&" |
| 122 | 81 |
| 123 local update_error | 82 local update_error |
| 124 local output_file | 83 local output_file |
| 125 local progress | 84 local progress |
| 126 | 85 |
| 127 update_error=1 | 86 update_error=1 |
| 128 output_file=$TMP/output | 87 output_file="${TMP}/output" |
| 129 | 88 |
| 130 while true; do | 89 while true; do |
| 131 # The softwareupdate.log gets pretty bit with download progress | 90 # The softwareupdate.log gets pretty bit with download progress |
| 132 # lines so only look in the last 100 lines for status. | 91 # lines so only look in the last 100 lines for status. |
| 133 remote_sh "tail -100 $UPDATE_FILE" | 92 remote_sh "tail -100 ${update_file}" |
| 134 echo "$REMOTE_OUT" > $output_file | 93 echo "${REMOTE_OUT}" > "${output_file}" |
| 135 progress=$(tail -4 $output_file | grep 0K | head -1) | 94 progress=$(tail -4 "${output_file}" | grep 0K | head -1) |
| 136 if [ -n "$progress" ]; then | 95 if [ -n "${progress}" ]; then |
| 137 echo "Image fetching progress: $progress" | 96 echo "Image fetching progress: ${progress}" |
| 138 fi | 97 fi |
| 139 if grep -q 'updatecheck status="noupdate"' $output_file; then | 98 if grep -q 'updatecheck status="noupdate"' "${output_file}"; then |
| 140 echo "devserver is claiming there is no update available." | 99 echo "devserver is claiming there is no update available." |
| 141 echo "Consider setting --ignore_version." | 100 echo "Consider setting --ignore_version." |
| 142 break | 101 break |
| 143 fi | 102 fi |
| 144 if grep -q 'Autoupdate applied. You should now reboot' $output_file; then | 103 if grep -q 'Autoupdate applied. You should now reboot' "${output_file}" |
| 104 then |
| 145 echo "Autoupdate was successful." | 105 echo "Autoupdate was successful." |
| 146 update_error=0 | 106 update_error=0 |
| 147 fi | 107 fi |
| 148 if grep -q 'Memento AutoUpdate terminating' $output_file; then | 108 if grep -q 'Memento AutoUpdate terminating' "${output_file}"; then |
| 149 break | 109 break |
| 150 fi | 110 fi |
| 151 # Sleep for a while so that ssh handling doesn't slow down the install | 111 # Sleep for a while so that ssh handling doesn't slow down the install |
| 152 sleep 2 | 112 sleep 2 |
| 153 done | 113 done |
| 154 | 114 |
| 155 return $update_error | 115 return ${update_error} |
| 156 } | 116 } |
| 157 | 117 |
| 158 function remote_reboot { | 118 function remote_reboot { |
| 159 echo "Rebooting." | 119 echo "Rebooting." |
| 160 remote_sh "touch /tmp/awaiting_reboot; reboot" | 120 remote_sh "touch /tmp/awaiting_reboot; reboot" |
| 161 local output_file | 121 local output_file |
| 162 output_file=$TMP/output | 122 output_file="${TMP}/output" |
| 163 | 123 |
| 164 while true; do | 124 while true; do |
| 165 REMOTE_OUT="" | 125 REMOTE_OUT="" |
| 166 # This may fail while the machine is done so generate output and a | 126 # This may fail while the machine is done so generate output and a |
| 167 # boolean result to distinguish between down/timeout and real failure | 127 # boolean result to distinguish between down/timeout and real failure |
| 168 ! remote_reboot_sh "echo 0; [ -e /tmp/awaiting_reboot ] && echo '1'; true" | 128 ! remote_sh_allow_changed_host_key \ |
| 169 echo "$REMOTE_OUT" > $output_file | 129 "echo 0; [ -e /tmp/awaiting_reboot ] && echo '1'; true" |
| 170 if grep -q "0" $output_file; then | 130 echo "${REMOTE_OUT}" > "${output_file}" |
| 171 if grep -q "1" $output_file; then | 131 if grep -q "0" "${output_file}"; then |
| 132 if grep -q "1" "${output_file}"; then |
| 172 echo "Not yet rebooted" | 133 echo "Not yet rebooted" |
| 173 else | 134 else |
| 174 echo "Rebooted and responding" | 135 echo "Rebooted and responding" |
| 175 break | 136 break |
| 176 fi | 137 fi |
| 177 fi | 138 fi |
| 178 sleep .5 | 139 sleep .5 |
| 179 done | 140 done |
| 180 } | 141 } |
| 181 | 142 |
| 182 set_up_remote_access | 143 function main() { |
| 144 assert_outside_chroot |
| 183 | 145 |
| 184 if remote_sh [ -e /tmp/memento_autoupdate_completed ]; then | 146 cd $(dirname "$0") |
| 185 echo "Machine has been updated but not yet rebooted. Rebooting it now." | 147 |
| 186 echo "Rerun this script if you still wish to update it." | 148 FLAGS "$@" || exit 1 |
| 149 eval set -- "${FLAGS_ARGV}" |
| 150 |
| 151 set -e |
| 152 |
| 153 trap cleanup EXIT |
| 154 |
| 155 TMP=$(mktemp -d /tmp/image_to_live.XXXX) |
| 156 |
| 157 remote_access_init |
| 158 |
| 159 if remote_sh [ -e /tmp/memento_autoupdate_completed ]; then |
| 160 echo "Machine has been updated but not yet rebooted. Rebooting it now." |
| 161 echo "Rerun this script if you still wish to update it." |
| 162 remote_reboot |
| 163 exit 1 |
| 164 fi |
| 165 |
| 166 start_dev_server |
| 167 |
| 168 prepare_update_metadata |
| 169 |
| 170 if ! run_auto_update; then |
| 171 echo "Update was not successful." |
| 172 exit |
| 173 fi |
| 174 |
| 187 remote_reboot | 175 remote_reboot |
| 188 exit 1 | |
| 189 fi | |
| 190 | 176 |
| 191 start_dev_server | 177 if [[ ${FLAGS_update_hostkey} -eq ${FLAGS_TRUE} ]]; then |
| 178 local known_hosts="${HOME}/.ssh/known_hosts" |
| 179 cp "${known_hosts}" "${known_hosts}~" |
| 180 grep -v "^${FLAGS_remote} " "${known_hosts}" > "${TMP}/new_known_hosts" |
| 181 cat "${TMP}/new_known_hosts" "${TMP_KNOWN_HOSTS}" > "${known_hosts}" |
| 182 chmod 0640 "${known_hosts}" |
| 183 echo "New updated in ${known_hosts}, backup made." |
| 184 fi |
| 192 | 185 |
| 193 prepare_update_metadata | 186 remote_sh "grep ^CHROMEOS_RELEASE_DESCRIPTION= /etc/lsb-release" |
| 187 local release_description=$(echo $REMOTE_OUT | cut -d '=' -f 2) |
| 188 echo "Update was successful and rebooted to $release_description" |
| 189 |
| 190 return 0 |
| 191 } |
| 194 | 192 |
| 195 if ! run_auto_update; then | 193 main $@ |
| 196 echo "Update was not successful." | |
| 197 exit | |
| 198 fi | |
| 199 | |
| 200 remote_reboot | |
| 201 | |
| 202 remote_sh "grep ^CHROMEOS_RELEASE_DESCRIPTION= /etc/lsb-release" | |
| 203 RELEASE_DESCRIPTION=$(echo $REMOTE_OUT | cut -d '=' -f 2) | |
| 204 echo "Update was successful and rebooted to $RELEASE_DESCRIPTION" | |
| OLD | NEW |