| #!/bin/bash |
| # Copyright (c) 2012 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. |
| # Set PROGram name |
| PROG=$(basename $0) |
| ######################################################################## |
| #+ |
| #+ NAME |
| #+ $PROG - ChromeOS channel image mover |
| #+ |
| #+ SYNOPSIS |
| #+ $PROG [-n] <version> <from-channel> <to-channel> [<board>] [<key>] \ |
| #+ [<newkey>] |
| #+ $PROG [--help | -man] |
| #+ $PROG [--usage | -?] |
| #+ |
| #+ DESCRIPTION |
| #+ $PROG takes an image from one channel and creates a copy (with symlinks) |
| #+ to be signed in a new target directory (stable,beta). |
| #+ |
| #+ Run from anywhere with GS credentials |
| #+ |
| #+ If you don't specify a <board>, then all boards will be processed. |
| #+ |
| #+ If you specify a <key>, then only instructions matching that keyset will |
| #+ be processed. Otherwise, all active keysets will be processed. If you |
| #+ use a short name like "mp" or "premp", the short board name will be auto- |
| #+ matically prepended to it. |
| #+ |
| #+ If, instead, you want to change the key used to sign the images, specify |
| #+ the <newkey> option. Then any images that were signed with <key> will be |
| #+ changed to be signed with <newkey>. |
| #+ |
| #+ EXAMPLES |
| #+ |
| #+ FILES |
| #+ |
| #+ SEE ALSO |
| #+ stdlib.sh - function definitions for TimeStamp, etc. |
| #+ |
| #+ BUGS/TODO |
| #+ |
| #- AUTHOR & DT : djmm Wed Jul 21 15:02:45 PDT 2010 |
| #- |
| ######################################################################## |
| # If NO ARGUMENTS should return *usage*, uncomment the following line: |
| usage=${1-yes} |
| |
| # This construct allows $PROG to be a symlink or simply PATH'd to. |
| symlink=$(readlink $0) |
| # Set up basic env and standard functions. |
| . "$(dirname "${symlink:-$0}")"/channelsign-lib.sh || exit 1 |
| |
| # Set some default options. |
| DRYRUN=false |
| looseargs=() |
| for arg in ${LOOSEARGS}; do |
| case ${arg} in |
| -n) DRYRUN=true ;; |
| *) looseargs+=( "${arg}" ) ;; |
| esac |
| done |
| if ${DRYRUN}; then |
| echo "DRYRUN MODE: Nothing will be uploaded" |
| echo |
| fi |
| if [[ ${#looseargs[@]} -lt 3 ]]; then |
| exec ${PROG} -? |
| fi |
| |
| # BEGIN script. |
| TimeStamp begin |
| |
| VERSION=${looseargs[0]} |
| FROMCHANNEL=${looseargs[1]/-channel/}-channel |
| TOCHANNEL=${looseargs[2]/-channel/}-channel |
| BOARD=${looseargs[3]} |
| |
| expand_key_name() { |
| local key=$1 |
| |
| if [[ -z ${key} ]]; then |
| return |
| fi |
| |
| case ${key} in |
| premp|mp|mp-v[0-9]*) |
| # If they specify "mp", automatically prepend the board name so |
| # we get something like "stumpy-mp". |
| echo "${BOARD#*-}-${key}" |
| ;; |
| *) |
| echo "${key}" |
| ;; |
| esac |
| } |
| ORIG_KEY=${looseargs[4]} |
| ORIG_NEWKEY=${looseargs[5]} |
| KEY=$(expand_key_name "${ORIG_KEY}") |
| NEWKEY=$(expand_key_name "${ORIG_NEWKEY}") |
| |
| if [[ -n ${ORIG_KEY} ]]; then |
| echo "Looking for images signed by key ${KEY} (derived from ${ORIG_KEY})" |
| fi |
| if [[ -n ${ORIG_NEWKEY} ]]; then |
| echo " Resigning with key ${NEWKEY} (derived from ${ORIG_NEWKEY})" |
| fi |
| |
| GSBASE=gs://chromeos-releases |
| TBSBASE="${GSBASE}/tobesigned" |
| |
| echo "Waiting for GoogleStorage..." |
| # Get list of instructions files only to process |
| FILELIST=$( |
| gsutil ls "${GSBASE}/${FROMCHANNEL}/${BOARD:-*}/${VERSION}/C*.instructions" |
| ) |
| FROMCHANNEL=$(echo ${FILELIST} | awk -F/ 'NR<2 {print $4}') |
| |
| if [[ -z ${FROMCHANNEL} ]]; then |
| Exit 1 "Couldn't determine source channel. Fail." |
| fi |
| |
| if [[ ${TOCHANNEL} == "${FROMCHANNEL}" ]]; then |
| if [[ ${KEY} == "${NEWKEY}" ]]; then |
| Exit 1 "Source channel = destination channel && old key == new key! Fail." |
| fi |
| fi |
| |
| GSUTIL=$(FindGSUTIL) || Exit 1 "Unable to find gsutil executable!" |
| |
| # GS copy |
| # Take a FROM arg and a TO arg |
| GSCp() { |
| local lfrom=$1 |
| local lto=$2 |
| local cmd=( "${GSUTIL}" cp "${lfrom}" "${lto}" ) |
| |
| if ${DRYRUN}; then |
| if [[ ${lto} == gs:* ]]; then |
| echo "DRYRUN: ${cmd[*]}" |
| else |
| # If source is local, we're downloading a file, so still do that. |
| "${cmd[@]}" |
| fi |
| else |
| "${cmd[@]}" |
| fi |
| } |
| |
| LOCALSIGN="/tmp/${PROG}-tbs.$$" |
| DumpRunTimeEnv > "${LOCALSIGN}" |
| |
| # Working off of instructions files only, derive file names for all other |
| # operations |
| for f in ${FILELIST}; do |
| echo |
| |
| # Set the TO filename |
| TARGET=${f/${FROMCHANNEL}/${TOCHANNEL}} |
| |
| # Get a local insructions file name |
| LOCALI="/tmp/$(basename ${TARGET})" |
| rm -f "${LOCALI}" |
| GSCp ${f} "${LOCALI}" |
| |
| # Make relevant changes to local instructions file |
| sed -i "s/channel = .*/channel = ${TOCHANNEL/-channel/}/g" "${LOCALI}" |
| keyset=$(awk '$1 == "keyset" { print $NF }' "${LOCALI}") |
| if [[ -n ${KEY} ]]; then |
| if [[ ${keyset} != ${KEY} ]]; then |
| echo " - skipping instructions: ${KEY} != ${keyset}" |
| continue |
| fi |
| if [[ -n ${NEWKEY} ]]; then |
| echo " - changing keyset from ${KEY} to ${NEWKEY}" |
| sed -i "/keyset *=/s:=.*:= ${NEWKEY}:g" "${LOCALI}" |
| fi |
| fi |
| archive=$(awk '$1 == "archive" { print $NF }' "${LOCALI}") |
| if [[ -z ${archive} ]]; then |
| archive=${f%.instructions}.zip |
| fi |
| |
| TBS_BOARD=${BOARD:-$(echo "${f}" | cut -d/ -f5)} |
| if [[ ${TOCHANNEL} == "${FROMCHANNEL}" ]]; then |
| # We're just changing keys in the same channel, so update the insn only. |
| TARGET="${TARGET%.instructions}-${NEWKEY}.instructions" |
| GSCp "${LOCALI}" "${TARGET}" |
| else |
| # Copy it and other bits up to TOCHANNEL |
| GSCp "${LOCALI}" "${TARGET}" |
| GSCp "${f%/*}/${archive}" "${TARGET%/*}/${archive}" |
| GSCp "$(dirname "${f}")/ChromeOS-test*.tar.xz" \ |
| "$(dirname "${TARGET}")/" |
| GSCp "$(dirname "${f}")/stateful.tgz" \ |
| "$(dirname "${TARGET}")/" |
| fi |
| |
| TOBESIGNED="${TBSBASE}/30,${TOCHANNEL},${TBS_BOARD},${VERSION},${TARGET##*/}" |
| GSCp "${LOCALSIGN}" "${TOBESIGNED}" |
| done |
| |
| # Cleanup |
| rm -f "${LOCALI}" "${LOCALSIGN}" |
| |
| # END script. |
| TimeStamp end |