Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/bin/bash | |
|
gauravsh
2011/01/04 21:35:29
slight nit: I know this is a bikeshedding issue an
thieule
2011/01/04 23:24:33
Done.
| |
| 2 | |
| 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | |
|
gauravsh
2011/01/04 21:35:29
2011
thieule
2011/01/04 23:24:33
Done.
| |
| 4 # Use of this source code is governed by a BSD-style license that can be | |
| 5 # found in the LICENSE file. | |
| 6 | |
| 7 # Script to preserve the on-disk file layout of the specified image and | |
| 8 # the latest shipping image. This is accomplished by copying the new rootfs | |
| 9 # over a template rootfs (aka the latest shipping image) to preserve as much | |
| 10 # of the metadata from the shipping rootfs as possible. This will ensure | |
| 11 # minimal disk shuffling when applying the auto-update. | |
| 12 # | |
| 13 # Note: This script does not recompute the rootfs hash. | |
| 14 | |
| 15 # Load common library. This should be the first executable line. | |
| 16 # The path to common.sh should be relative to your script's location. | |
| 17 . "$(dirname "$0")/common.sh" | |
| 18 | |
| 19 load_shflags | |
| 20 | |
| 21 # Flags. | |
| 22 DEFINE_string app_id "{87efface-864d-49a5-9bb3-4b050a7c227a}" \ | |
| 23 "App ID to use when pinging the Omaha server for the latest version." | |
| 24 DEFINE_string hardware_id "IEC MARIO PONY 6101" \ | |
| 25 "The Hardware ID of the latest shipping image to use as a template." | |
| 26 DEFINE_string image "" \ | |
| 27 "The image that needs to be aligned to the latest shipping image." | |
| 28 | |
| 29 IMAGE_SEARCH_STRING= | |
| 30 RELEASE_URL= | |
| 31 RELEASE_ALT_URL= | |
| 32 | |
| 33 # Sets up environment variables specific to the board | |
| 34 initialize() { | |
| 35 if [ "${FLAGS_hardware_id}" = "IEC MARIO PONY 6101" ]; then | |
| 36 IMAGE_SEARCH_STRING="*SSD_MP_SIGNED.bin" | |
| 37 RELEASE_URL="http://chromeos-images/chromeos-official/dev-channel/x86-mario" | |
| 38 RELEASE_ALT_URL="${RELEASE_URL}-rc" | |
| 39 else | |
| 40 die "Hardware ID \"${FLAGS_hardware_id}\" not supported" | |
| 41 fi | |
| 42 } | |
| 43 | |
| 44 # Gets the latest shipping version for the specified Hardware ID by pinging | |
| 45 # the Omaha server. The latest shipping version is returned in |VERSION|. | |
| 46 # Args: VERSION | |
| 47 get_latest_shipping_version() { | |
| 48 info "Pinging Omaha for the latest shipping version." | |
| 49 local auserver_url="https://tools.google.com/service/update2" | |
| 50 local au_request_file=$(mktemp "/tmp/align_rootfs_au_request.XXXX") | |
| 51 add_cleanup_action "sudo rm -f \"${au_request_file}\"" | |
| 52 cat > "${au_request_file}" << EOF | |
| 53 <?xml version="1.0" encoding="UTF-8"?> | |
| 54 <o:gupdate xmlns:o="http://www.google.com/update2/request" | |
| 55 version="ChromeOSUpdateEngine-0.1.0.0" | |
| 56 updaterversion="ChromeOSUpdateEngine-0.1.0.0" protocol="2.0" ismachine="1"> | |
| 57 <o:os version="Indy" platform="Chrome OS" sp="ForcedUpdate_i686"></o:os> | |
| 58 <o:app appid="${FLAGS_app_id}" | |
| 59 version="0.0.0.0" lang="en-US" track="dev-channel" | |
|
petkov
2011/01/04 20:56:55
you need to parametrize the channel at some point
thieule
2011/01/04 23:24:33
Done.
| |
| 60 hardware_class="${FLAGS_hardware_id}" delta_okay="true"> | |
| 61 <o:updatecheck></o:updatecheck> | |
| 62 </o:app> | |
| 63 </o:gupdate> | |
| 64 EOF | |
| 65 | |
| 66 eval $1=$(wget -q --header="Content-Type: text/xml" \ | |
|
petkov
2011/01/04 20:56:55
i didn't even know you could do that... why don't
gauravsh
2011/01/04 21:35:29
I would vote for something like that too - much cl
thieule
2011/01/04 23:24:33
Done.
| |
| 67 --post-file="${au_request_file}" -O - ${auserver_url} | \ | |
|
petkov
2011/01/04 20:56:55
no need for \ at the end
thieule
2011/01/04 23:24:33
Done.
| |
| 68 sed 's/.*\(ChromeOSVersion="\)\([0-9\.]*\)"\(.*\)/\2/') | |
| 69 } | |
| 70 | |
| 71 # Downloads the image from the specified |URL| using ${IMAGE_SEARCH_STRING} as | |
| 72 # a wildcard match and write the image to |OUTPUT_FILE|. | |
| 73 # Args: URL OUTPUT_FILE | |
| 74 download_image() { | |
| 75 # Since we don't know the exact name, we'll just download recursively based | |
| 76 # on a wildcard. Then we'll rename that download file to the desired output | |
| 77 # file. It's important that the IMAGE_SEARCH_STRING matches only one file. | |
| 78 local url=$1 | |
| 79 local output_file=$2 | |
| 80 local retcode=0 | |
| 81 | |
| 82 local download_dir=$(mktemp -d "/tmp/align_rootfs_download_dir.XXXX") | |
| 83 add_cleanup_action "sudo rm -rf \"${download_dir}\"" | |
| 84 | |
| 85 wget -A "${IMAGE_SEARCH_STRING}" --progress=bar -r -l1 -nd \ | |
| 86 -P "${download_dir}" ${url} || retcode=$? | |
| 87 if [ ${retcode} -eq 0 ]; then | |
| 88 mv -f "${download_dir}"/* "${output_file}" | |
| 89 else | |
| 90 return ${retcode} | |
| 91 fi | |
| 92 } | |
| 93 | |
| 94 # Retrieves the latest shipping image and saves it to |IMAGE|. | |
| 95 # Args: VERSION IMAGE | |
| 96 get_shipping_image() { | |
| 97 # The image may reside in one of two URLs. We don't know exactly which one | |
| 98 # so we'll have to try both. | |
| 99 local version=$1 | |
| 100 local image=$2 | |
| 101 local url="${RELEASE_URL}/${version}" | |
| 102 download_image "${url}" "${image}" || retcode=$? | |
| 103 if [ ${retcode} -gt 0 ]; then | |
| 104 url="${RELEASE_ALT_URL}/${version}" | |
| 105 download_image "${url}" "${image}" | |
| 106 fi | |
| 107 } | |
| 108 | |
| 109 # Copies the rootfs from |SRC_IMAGE| to the |DST_ROOT_FS| and preserves as | |
| 110 # much of the file system metadata in |DST_ROOT_FS| as possible. | |
| 111 # Args: SRC_IMAGE DST_ROOT_FS | |
| 112 copy_root_fs() { | |
| 113 local src_image=$1 | |
| 114 local dst_root_fs=$2 | |
| 115 | |
| 116 # Mount the src and dst rootfs. | |
| 117 local src_root_fs_dir=$(mktemp -d "/tmp/align_root_fs_src_mount_dir.XXXX") | |
|
gauravsh
2011/01/04 21:35:29
just a suggestion: since you already including com
thieule
2011/01/04 23:24:33
Unfortunately, in this case, I need to be able to
| |
| 118 add_cleanup_action "sudo rm -rf \"${src_root_fs_dir}\"" | |
| 119 mount_image_partition_ro "${src_image}" 3 "${src_root_fs_dir}" | |
| 120 add_cleanup_action "sudo umount -d \"${src_root_fs_dir}\"" | |
| 121 | |
| 122 local dst_root_fs_dir=$(mktemp -d "/tmp/align_root_fs_dst_mount_dir.XXXX") | |
| 123 add_cleanup_action "sudo rm -rf \"${dst_root_fs_dir}\"" | |
| 124 sudo mount -o loop "${dst_root_fs}" "${dst_root_fs_dir}" -o loop | |
| 125 add_cleanup_action "sudo umount -d \"${dst_root_fs_dir}\"" | |
| 126 | |
| 127 # Temporarily make immutable files on the dst rootfs mutable. | |
| 128 # We'll need to track these files in ${immutable_files} so we can make them | |
| 129 # mutable again. | |
| 130 local immutable_files=() | |
| 131 sudo find "${dst_root_fs_dir}" -xdev -type f | | |
| 132 while read -r file; do | |
| 133 immutable=$(sudo lsattr "${file}" | cut -d' ' -f1 | grep -q i ; echo $?) | |
| 134 if [ $immutable -eq 0 ]; then | |
| 135 immutable_files=("${immutable_files[@]}" "${file}") | |
| 136 sudo chattr -i "${file}" | |
| 137 fi | |
| 138 done | |
| 139 | |
| 140 # Copy files from the src rootfs over top of dst rootfs. | |
| 141 # Use the --inplace flag to preserve as much of the file system metadata | |
| 142 # as possible. | |
| 143 sudo rsync -v -a -H -A -x --force --inplace --numeric-ids --delete \ | |
| 144 "${src_root_fs_dir}"/ "${dst_root_fs_dir}" | |
| 145 | |
| 146 # Make immutable files immutable again. | |
| 147 for file in ${immutable_files[*]} ; do | |
| 148 sudo chattr +i "${file}" | |
| 149 done | |
| 150 | |
| 151 # Unmount the src and dst root fs so that we can replace the rootfs later. | |
| 152 perform_latest_cleanup_action | |
|
adlr
2011/01/04 19:04:48
this is called twice here, but add_cleanup_action
thieule
2011/01/04 23:24:33
Done.
| |
| 153 perform_latest_cleanup_action | |
| 154 } | |
| 155 | |
| 156 # Zeroes the rootfs free space in the specified image. | |
| 157 # Args: IMAGE | |
| 158 zero_root_fs_free_space() { | |
| 159 local image=$1 | |
| 160 local root_fs_dir=$(mktemp -d "/tmp/align_rootfs_zero_free_space_dir.XXXX") | |
| 161 add_cleanup_action "sudo rmdir -rf \"${root_fs_dir}\"" | |
| 162 mount_image_partition "${image}" 3 "${root_fs_dir}" | |
| 163 add_cleanup_action "sudo umount -d \"${root_fs_dir}\"" | |
| 164 | |
| 165 info "Zeroing free space in rootfs" | |
| 166 sudo dd if=/dev/zero of="${root_fs_dir}/filler" oflag=sync bs=4096 || true | |
| 167 sudo rm -f "${root_fs_dir}/filler" | |
| 168 sudo sync | |
| 169 | |
| 170 perform_latest_cleanup_action | |
| 171 perform_latest_cleanup_action | |
| 172 } | |
| 173 | |
| 174 main() { | |
| 175 trap cleanup INT TERM EXIT | |
|
gauravsh
2011/01/04 21:35:29
the trap also gets set in common.sh which gets ove
thieule
2011/01/04 23:24:33
Done.
| |
| 176 | |
| 177 # Parse command line. | |
| 178 FLAGS "$@" || exit 1 | |
| 179 eval set -- "${FLAGS_ARGV}" | |
| 180 | |
| 181 # Only now can we die on error. shflags functions leak non-zero error codes, | |
| 182 # so will die prematurely if 'set -e' is specified before now. | |
| 183 set -e | |
| 184 | |
| 185 # Make sure we have the required parameters. | |
| 186 if [ -z "${FLAGS_hardware_id}" ]; then | |
|
gauravsh
2011/01/04 21:35:29
since now you have a default value for the hardwar
thieule
2011/01/04 23:24:33
Done.
| |
| 187 die "--hardware_id is required." | |
| 188 fi | |
| 189 | |
| 190 if [ -z "${FLAGS_image}" ]; then | |
| 191 die "--image is required." | |
| 192 fi | |
| 193 | |
| 194 if [ ! -f "${FLAGS_image}" ]; then | |
| 195 die "Cannot find the specified image." | |
| 196 fi | |
| 197 | |
| 198 # Initialize some variables specific to the board. | |
| 199 initialize | |
| 200 | |
| 201 # Download the latest shipping image. | |
| 202 local latest_shipping_version= | |
| 203 get_latest_shipping_version latest_shipping_version | |
| 204 local latest_shipping_image=$(mktemp "/tmp/align_rootfs_shipping_image.XXXX") | |
| 205 add_cleanup_action "sudo rm -f \"${latest_shipping_image}\"" | |
| 206 info "Downloading image (${latest_shipping_version})" | |
| 207 get_shipping_image "${latest_shipping_version}" "${latest_shipping_image}" | |
| 208 | |
| 209 # Make sure the two rootfs are the same size. | |
| 210 # If they are not, then there is nothing for us to do. | |
| 211 # Note: Exit with a zero code so we do not break the build workflow. | |
| 212 local shipping_root_fs_size=$(partsize "${latest_shipping_image}" 3) | |
| 213 local new_root_fs_size=$(partsize "${FLAGS_image}" 3) | |
| 214 if [ ${shipping_root_fs_size} -ne ${new_root_fs_size} ]; then | |
| 215 warn "The latest shipping rootfs and the new rootfs are not the same size." | |
| 216 exit 0 | |
| 217 fi | |
| 218 | |
| 219 # Extract the rootfs from the shipping image and use this as a template | |
| 220 # for the new image. | |
| 221 temp_root_fs=$(mktemp "/tmp/align_rootfs_temp_rootfs.XXXX") | |
| 222 add_cleanup_action "sudo rm -f \"${temp_root_fs}\"" | |
| 223 info "Extracting rootfs from shipping image" | |
| 224 extract_image_partition "${latest_shipping_image}" 3 "${temp_root_fs}" | |
| 225 enable_rw_mount "${temp_root_fs}" | |
| 226 | |
| 227 # Perform actual copy of the two root file systems. | |
| 228 info "Copying rootfs" | |
| 229 copy_root_fs "${FLAGS_image}" "${temp_root_fs}" | |
| 230 | |
| 231 # Replace the rootfs in the new image with the aligned version. | |
| 232 info "Replacing rootfs" | |
| 233 replace_image_partition "${FLAGS_image}" 3 "${temp_root_fs}" | |
| 234 | |
| 235 # Zero rootfs free space. | |
| 236 zero_root_fs_free_space "${FLAGS_image}" | |
| 237 | |
| 238 trap - EXIT | |
|
gauravsh
2011/01/04 21:35:29
do you need these 2 lines - cleanup should happen
thieule
2011/01/04 23:24:33
Done.
| |
| 239 | |
| 240 cleanup | |
| 241 } | |
| 242 | |
| 243 main "$@" | |
| OLD | NEW |