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 update an image onto a live running ChromiumOS instance. | 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 | 11 |
12 . "$(dirname $0)/common.sh" | 12 . "$(dirname $0)/common.sh" |
13 . "$(dirname $0)/remote_access.sh" | 13 . "$(dirname $0)/remote_access.sh" |
14 | 14 |
15 DEFINE_boolean ignore_version ${FLAGS_TRUE} \ | 15 DEFINE_boolean ignore_version ${FLAGS_TRUE} \ |
16 "Ignore existing version on running instance and always update" | 16 "Ignore existing version on running instance and always update" |
17 DEFINE_boolean ignore_hostname ${FLAGS_TRUE} \ | 17 DEFINE_boolean ignore_hostname ${FLAGS_TRUE} \ |
18 "Ignore existing AU hostname on running instance use this hostname" | 18 "Ignore existing AU hostname on running instance use this hostname" |
19 DEFINE_boolean update_known_hosts ${FLAGS_FALSE} \ | 19 DEFINE_boolean update_known_hosts ${FLAGS_FALSE} \ |
20 "Update your known_hosts with the new remote instance's key" | 20 "Update your known_hosts with the new remote instance's key" |
21 DEFINE_boolean verbose ${FLAGS_FALSE} \ | 21 DEFINE_boolean verbose ${FLAGS_FALSE} \ |
22 "Whether to output verbose information for debugging." | 22 "Whether to output verbose information for debugging." |
23 DEFINE_integer devserver_port 8080 \ | 23 DEFINE_integer devserver_port 8080 \ |
24 "Port to use for devserver" | 24 "Port to use for devserver" |
25 DEFINE_string update_url "" "Full url of an update image" | 25 DEFINE_string update_url "" "Full url of an update image" |
26 | 26 |
| 27 UPDATER_BIN='/usr/bin/update_engine_client' |
| 28 UPDATER_IDLE='UPDATE_STATUS_IDLE' |
| 29 UPDATER_NEED_REBOOT='UPDATE_STATUS_UPDATED_NEED_REBOOT' |
| 30 |
27 function kill_all_devservers { | 31 function kill_all_devservers { |
28 echo "Killing dev server." | |
29 # Using ! here to avoid exiting with set -e is insufficient, so use | 32 # Using ! here to avoid exiting with set -e is insufficient, so use |
30 # || true instead. | 33 # || true instead. |
31 sudo pkill -f devserver\.py || true | 34 sudo pkill -f devserver\.py || true |
32 } | 35 } |
33 | 36 |
34 function cleanup { | 37 function cleanup { |
35 if [ -z "${FLAGS_update_url}" ]; then | 38 if [ -z "${FLAGS_update_url}" ]; then |
36 kill_all_devservers | 39 kill_all_devservers |
37 fi | 40 fi |
38 cleanup_remote_access | 41 cleanup_remote_access |
39 rm -rf "${TMP}" | 42 rm -rf "${TMP}" |
40 } | 43 } |
41 | 44 |
42 function remote_reboot_sh { | 45 function remote_reboot_sh { |
43 rm -f "${TMP_KNOWN_HOSTS}" | 46 rm -f "${TMP_KNOWN_HOSTS}" |
44 remote_sh "$@" | 47 remote_sh "$@" |
45 } | 48 } |
46 | 49 |
47 function start_dev_server { | 50 function start_dev_server { |
48 kill_all_devservers | 51 kill_all_devservers |
49 if [ ${FLAGS_verbose} -eq ${FLAGS_FALSE} ]; then | 52 if [ ${FLAGS_verbose} -eq ${FLAGS_FALSE} ]; then |
50 ./enter_chroot.sh "sudo ./start_devserver ${FLAGS_devserver_port} \ | 53 ./enter_chroot.sh "sudo ./start_devserver ${FLAGS_devserver_port} \ |
51 > dev_server.log 2>&1" & | 54 --client_prefix=ChromeOSUpdateEngine > dev_server.log 2>&1" & |
52 else | 55 else |
53 ./enter_chroot.sh "sudo ./start_devserver ${FLAGS_devserver_port}" & | 56 ./enter_chroot.sh "sudo ./start_devserver ${FLAGS_devserver_port} \ |
| 57 --client_prefix=ChromeOSUpdateEngine &" |
54 fi | 58 fi |
55 echo -n "Waiting on devserver to start" | 59 echo -n "Waiting on devserver to start" |
56 until netstat -anp 2>&1 | grep 0.0.0.0:${FLAGS_devserver_port} > /dev/null | 60 until netstat -anp 2>&1 | grep 0.0.0.0:${FLAGS_devserver_port} > /dev/null |
57 do | 61 do |
58 sleep .5 | 62 sleep .5 |
59 echo -n "." | 63 echo -n "." |
60 done | 64 done |
61 echo "" | 65 echo "" |
62 } | 66 } |
63 | 67 |
64 # Copys stateful update script which fetches the newest stateful update | 68 # Copys stateful update script which fetches the newest stateful update |
65 # from the dev server and prepares the update. chromeos_startup finishes | 69 # from the dev server and prepares the update. chromeos_startup finishes |
66 # the update on next boot. | 70 # the update on next boot. |
67 function copy_stateful_update { | 71 function copy_stateful_update { |
68 echo "Starting stateful update." | 72 info "Starting stateful update." |
69 local dev_dir="$(dirname $0)/../platform/dev" | 73 local dev_dir="$(dirname $0)/../platform/dev" |
70 | 74 |
71 # Copy over update script and run update. | 75 # Copy over update script and run update. |
72 remote_cp_to "$dev_dir/stateful_update" "/tmp" | 76 remote_cp_to "$dev_dir/stateful_update" "/tmp" |
73 remote_sh "/tmp/stateful_update" | 77 remote_sh "/tmp/stateful_update" |
74 } | 78 } |
75 | 79 |
76 function prepare_update_metadata { | 80 function get_update_args { |
77 remote_sh "mount -norw,remount /" | 81 if [ -z ${1} ]; then |
78 | 82 die "No url provided for update." |
| 83 fi |
| 84 local update_args="--omaha_url ${1}" |
79 if [[ ${FLAGS_ignore_version} -eq ${FLAGS_TRUE} ]]; then | 85 if [[ ${FLAGS_ignore_version} -eq ${FLAGS_TRUE} ]]; then |
80 echo "Forcing update independent of the current version" | 86 info "Forcing update independent of the current version" |
81 remote_sh "cat /etc/lsb-release |\ | 87 update_args="--update ${update_args}" |
82 grep -v CHROMEOS_RELEASE_VERSION > /etc/lsb-release~;\ | |
83 mv /etc/lsb-release~ /etc/lsb-release; \ | |
84 echo 'CHROMEOS_RELEASE_VERSION=0.0.0.0' >> /etc/lsb-release" | |
85 fi | 88 fi |
86 | 89 |
| 90 echo "${update_args}" |
| 91 } |
| 92 |
| 93 function get_devserver_url { |
| 94 local devserver_url="" |
87 if [ ${FLAGS_ignore_hostname} -eq ${FLAGS_TRUE} ]; then | 95 if [ ${FLAGS_ignore_hostname} -eq ${FLAGS_TRUE} ]; then |
88 if [ -z ${FLAGS_update_url} ]; then | 96 if [ -z ${FLAGS_update_url} ]; then |
89 devserver_url="http://$HOSTNAME:${FLAGS_devserver_port}/update" | 97 devserver_url="http://$HOSTNAME:${FLAGS_devserver_port}/update" |
90 else | 98 else |
91 devserver_url="${FLAGS_update_url}" | 99 devserver_url="${FLAGS_update_url}" |
92 fi | 100 fi |
93 echo "Forcing update from ${devserver_url}" | 101 fi |
94 remote_sh "cat /etc/lsb-release |\ | 102 echo "${devserver_url}" |
95 grep -v '^CHROMEOS_AUSERVER=' |\ | 103 } |
96 grep -v '^CHROMEOS_DEVSERVER=' > /etc/lsb-release~;\ | 104 |
97 mv /etc/lsb-release~ /etc/lsb-release; \ | 105 function get_update_status { |
98 echo 'CHROMEOS_AUSERVER=${devserver_url}' >> \ | 106 remote_sh "${UPDATER_BIN} -status | |
99 /etc/lsb-release; \ | 107 grep CURRENT_OP | |
100 echo 'CHROMEOS_DEVSERVER=${devserver_url}' >> /etc/lsb-release" | 108 cut -f 2 -d =" |
| 109 echo "${REMOTE_OUT}" |
| 110 } |
| 111 |
| 112 function run_auto_update { |
| 113 local update_args="$(get_update_args "$(get_devserver_url)")" |
| 114 info "Starting update using args ${update_args}" |
| 115 remote_sh "${UPDATER_BIN} ${update_args}" |
| 116 |
| 117 local update_status="$(get_update_status)" |
| 118 if [ "${update_status}" = ${UPDATER_NEED_REBOOT} ]; then |
| 119 info "Autoupdate was successful." |
| 120 return 0 |
| 121 else |
| 122 warn "Autoupdate was unsuccessful. Status returned was ${update_status}." |
| 123 return 1 |
101 fi | 124 fi |
102 } | 125 } |
103 | 126 |
104 function run_auto_update { | |
105 echo "Starting update" | |
106 local update_file=/var/log/softwareupdate.log | |
107 # Clear it out so we don't see a prior run and make sure it | |
108 # exists so the first tail below can't fail if it races the | |
109 # memento updater first write and wins. | |
110 remote_sh "rm -f /tmp/memento_autoupdate_completed; rm -f ${update_file}; \ | |
111 touch ${update_file}; \ | |
112 /opt/google/memento_updater/memento_updater.sh --force_update < /dev/null\ | |
113 >&/dev/null&" | |
114 | |
115 local update_error | |
116 local output_file | |
117 local progress | |
118 | |
119 update_error=1 | |
120 output_file="${TMP}/output" | |
121 | |
122 while true; do | |
123 # The softwareupdate.log gets pretty bit with download progress | |
124 # lines so only look in the last 100 lines for status. | |
125 remote_sh "tail -100 ${update_file}" | |
126 echo "${REMOTE_OUT}" > "${output_file}" | |
127 progress=$(tail -4 "${output_file}" | grep 0K | head -1) | |
128 if [ -n "${progress}" ]; then | |
129 echo "Image fetching progress: ${progress}" | |
130 fi | |
131 if grep -q 'updatecheck status="noupdate"' "${output_file}"; then | |
132 echo "devserver is claiming there is no update available." | |
133 echo "Consider setting --ignore_version." | |
134 break | |
135 fi | |
136 if grep -q 'Autoupdate applied. You should now reboot' "${output_file}" | |
137 then | |
138 echo "Autoupdate was successful." | |
139 update_error=0 | |
140 fi | |
141 if grep -q 'Memento AutoUpdate terminating' "${output_file}"; then | |
142 break | |
143 fi | |
144 # Sleep for a while so that ssh handling doesn't slow down the install | |
145 sleep 2 | |
146 done | |
147 | |
148 return ${update_error} | |
149 } | |
150 | |
151 function remote_reboot { | 127 function remote_reboot { |
152 echo "Rebooting." | 128 info "Rebooting." |
153 remote_sh "touch /tmp/awaiting_reboot; reboot" | 129 remote_sh "touch /tmp/awaiting_reboot; reboot" |
154 local output_file | 130 local output_file |
155 output_file="${TMP}/output" | 131 output_file="${TMP}/output" |
156 | 132 |
157 while true; do | 133 while true; do |
158 REMOTE_OUT="" | 134 REMOTE_OUT="" |
159 # This may fail while the machine is down so generate output and a | 135 # This may fail while the machine is down so generate output and a |
160 # boolean result to distinguish between down/timeout and real failure | 136 # boolean result to distinguish between down/timeout and real failure |
161 ! remote_sh_allow_changed_host_key \ | 137 ! remote_sh_allow_changed_host_key \ |
162 "echo 0; [ -e /tmp/awaiting_reboot ] && echo '1'; true" | 138 "echo 0; [ -e /tmp/awaiting_reboot ] && echo '1'; true" |
163 echo "${REMOTE_OUT}" > "${output_file}" | 139 echo "${REMOTE_OUT}" > "${output_file}" |
164 if grep -q "0" "${output_file}"; then | 140 if grep -q "0" "${output_file}"; then |
165 if grep -q "1" "${output_file}"; then | 141 if grep -q "1" "${output_file}"; then |
166 echo "Not yet rebooted" | 142 info "Not yet rebooted" |
167 else | 143 else |
168 echo "Rebooted and responding" | 144 info "Rebooted and responding" |
169 break | 145 break |
170 fi | 146 fi |
171 fi | 147 fi |
172 sleep .5 | 148 sleep .5 |
173 done | 149 done |
174 } | 150 } |
175 | 151 |
176 function main() { | 152 function main() { |
177 assert_outside_chroot | 153 assert_outside_chroot |
178 | 154 |
179 cd $(dirname "$0") | 155 cd $(dirname "$0") |
180 | 156 |
181 FLAGS "$@" || exit 1 | 157 FLAGS "$@" || exit 1 |
182 eval set -- "${FLAGS_ARGV}" | 158 eval set -- "${FLAGS_ARGV}" |
183 | 159 |
184 set -e | 160 set -e |
185 | 161 |
186 trap cleanup EXIT | 162 trap cleanup EXIT |
187 | 163 |
188 TMP=$(mktemp -d /tmp/image_to_live.XXXX) | 164 TMP=$(mktemp -d /tmp/image_to_live.XXXX) |
189 | 165 |
190 remote_access_init | 166 remote_access_init |
191 | 167 |
192 if remote_sh [ -e /tmp/memento_autoupdate_completed ]; then | 168 if [ "$(get_update_status)" = "${UPDATER_NEED_REBOOT}" ]; then |
193 echo "Machine has been updated but not yet rebooted. Rebooting it now." | 169 warn "Machine has been updated but not yet rebooted. Rebooting it now." |
194 echo "Rerun this script if you still wish to update it." | 170 warn "Rerun this script if you still wish to update it." |
195 remote_reboot | 171 remote_reboot |
196 exit 1 | 172 exit 1 |
197 fi | 173 fi |
198 | 174 |
199 if [ -z "${FLAGS_update_url}" ]; then | 175 if [ -z "${FLAGS_update_url}" ]; then |
200 # only start local devserver if no update url specified. | 176 # only start local devserver if no update url specified. |
201 start_dev_server | 177 start_dev_server |
202 fi | 178 fi |
203 | 179 |
204 prepare_update_metadata | |
205 | |
206 if ! run_auto_update; then | 180 if ! run_auto_update; then |
207 echo "Update was not successful." | 181 die "Update was not successful." |
208 exit 1 | |
209 fi | 182 fi |
210 | 183 |
211 if ! copy_stateful_update; then | 184 if ! copy_stateful_update; then |
212 echo "Stateful update was not successful." | 185 warn "Stateful update was not successful." |
213 fi | 186 fi |
214 | 187 |
215 remote_reboot | 188 remote_reboot |
216 | 189 |
217 if [[ ${FLAGS_update_hostkey} -eq ${FLAGS_TRUE} ]]; then | 190 if [[ ${FLAGS_update_hostkey} -eq ${FLAGS_TRUE} ]]; then |
218 local known_hosts="${HOME}/.ssh/known_hosts" | 191 local known_hosts="${HOME}/.ssh/known_hosts" |
219 cp "${known_hosts}" "${known_hosts}~" | 192 cp "${known_hosts}" "${known_hosts}~" |
220 grep -v "^${FLAGS_remote} " "${known_hosts}" > "${TMP}/new_known_hosts" | 193 grep -v "^${FLAGS_remote} " "${known_hosts}" > "${TMP}/new_known_hosts" |
221 cat "${TMP}/new_known_hosts" "${TMP_KNOWN_HOSTS}" > "${known_hosts}" | 194 cat "${TMP}/new_known_hosts" "${TMP_KNOWN_HOSTS}" > "${known_hosts}" |
222 chmod 0640 "${known_hosts}" | 195 chmod 0640 "${known_hosts}" |
223 echo "New updated in ${known_hosts}, backup made." | 196 info "New updated in ${known_hosts}, backup made." |
224 fi | 197 fi |
225 | 198 |
226 remote_sh "grep ^CHROMEOS_RELEASE_DESCRIPTION= /etc/lsb-release" | 199 remote_sh "grep ^CHROMEOS_RELEASE_DESCRIPTION= /etc/lsb-release" |
227 local release_description=$(echo $REMOTE_OUT | cut -d '=' -f 2) | 200 local release_description=$(echo ${REMOTE_OUT} | cut -d '=' -f 2) |
228 echo "Update was successful and rebooted to $release_description" | 201 info "Update was successful and rebooted to $release_description" |
229 | 202 |
230 return 0 | 203 return 0 |
231 } | 204 } |
232 | 205 |
233 main $@ | 206 main $@ |
OLD | NEW |