| #!/bin/sh |
| |
| # Copyright (c) 2013 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. |
| |
| # Check uber shopfloor server, fetch and parse board config. |
| # |
| # Channel image URLs and checksums are sent out through stdout for shell |
| # to eval. The format: |
| # |
| # SRC_{CHANNEL}_URL=http://shopfloor_server:port/pathto/gzimage |
| # SRC_{CHANNEL}_CHECKSUM=plain_image_binarysha1_base64 |
| # |
| # For memento updater compatibility, images should be generated by script |
| # make_factory_package.sh. |
| # |
| # Example: |
| # SHOPFLOOR="http://SF_SERVER:SF_PORT" |
| # BOARD="testboard" |
| # result=$(ping_shopfloor) |
| # rc="$?" |
| # if [ "$rc" = "0" ]; then |
| # eval "$result" |
| # fi |
| # if [ "$SHOPFLOOR_INSTALL" = "1" ]; then |
| # do_install |
| # ... |
| # |
| |
| sf_log() { |
| echo "$(date) $*" >&2 |
| } |
| |
| ping_shopfloor() { |
| local channel_hash="" |
| local channel_file="" |
| local channel_name="" |
| local config_file="default.conf" |
| local line="" |
| local resource_url="" |
| local wget_output="" |
| local wget_rc="0" |
| local channels="" |
| local cleanup_files="" |
| |
| # Get config file name from BOARD |
| if [ -n "$BOARD" ]; then |
| config_file="${BOARD}.conf" |
| fi |
| |
| # Get resource URL from SHOPFLOOR or OMAHA |
| if [ -n "$SHOPFLOOR" ]; then |
| resource_url="$SHOPFLOOR/res" |
| elif [ -n "$OMAHA" ]; then |
| resource_url="${OMAHA%/update}/res" |
| else |
| sf_log "ping_shopfloor: SHOPFLOOR and OMAHA not found." |
| return 1 |
| fi |
| |
| # Try to get resource map from Umpire. ETH_INTERFACE is passed from |
| # factory_install.sh. |
| local sn="$(vpd -i RO_VPD -g serial_number)" || sn="" |
| local mlb_sn="$(vpd -i RO_VPD -g mlb_serial_number)" || mlb_sn="" |
| local board="${BOARD}" |
| local mac_addr="$(ip link show ${ETH_INTERFACE} | grep link/ether | |
| tr -s ' '| cut -d ' ' -f 3)" |
| local resourcemap_rc="0" |
| local resourcemap="" |
| local mac="mac.${ETH_INTERFACE}=${mac_addr};" |
| local values="sn=${sn}; mlb_sn=${mlb_sn}; board=${board}; ${mac}" |
| local empty_values="firmware=; ec=; stage=;" |
| local x_umpire_dut_header="X-Umpire-DUT: ${values} ${empty_values}" |
| local target="${resource_url%/res}/resourcemap" |
| sf_log "ping_shopfloor: ${x_umpire_dut_header}" |
| |
| resourcemap="$(wget -O - --header "${x_umpire_dut_header}" "${target}")" || |
| resourcemap_rc="$?" |
| |
| if [ "$resourcemap_rc" != "0" ]; then |
| sf_log "ping_shopfloor: could not fetch resourcemap." |
| else |
| sf_log "ping_shopfloor: got resourcemap: ${resourcemap}" |
| config_file="$(echo "${resourcemap}" | grep download_conf | |
| cut -d ':' -f 2 | tr -d ' ')" |
| sf_log "ping_shopfloor: config_file: ${config_file}" |
| fi |
| |
| # Ping shopfloor by fetching the config file |
| wget_output="$(mktemp "/tmp/conf_XXXXXXXX")" |
| cleanup_files="$wget_output" |
| wget -O $wget_output "$resource_url/$config_file" 2>/dev/null || |
| wget_rc="$?" |
| |
| if [ "$wget_rc" != "0" ]; then |
| sf_log "ping_shopfloor: could not fetch $resource_url/$config_file" |
| [ -f "$cleanup_files" ] && rm $cleanup_files |
| return 1 |
| fi |
| |
| # Fix shell read line without \n |
| echo >>"$wget_output" |
| |
| # Parse channels and skip comments in a subprocess |
| channels="$(mktemp "/tmp/sf_XXXXXXXX")" |
| cleanup_files="$cleanup_files $channels" |
| while IFS= read line; do |
| # Remove leading whitespaces |
| line=$(echo $line | sed -e 's/^[ \t]*//') |
| # Skip comment and empty lines |
| [ -n "$(echo $line | grep -E '^#')" -o -z "$line" ] && continue |
| # Split channel, file, and hash |
| channel_name=$(echo $line | cut -d':' -f1) |
| channel_file=$(echo $line | cut -d':' -f2) |
| channel_hash=$(echo $line | cut -d':' -f3) |
| if [ -z "$channel_name" -o -z "$channel_file" -o -z "$channel_hash" ]; then |
| sf_log "ping_shopfloor: not a channel $resource_url/$config_file ($line)" |
| [ -n "$cleanup_files" ] && rm $cleanup_files |
| return 1 |
| fi |
| echo "SRC_${channel_name}_URL=$resource_url/$channel_file" >> "$channels" |
| echo "SRC_${channel_name}_CHECKSUM=$channel_hash" >> "$channels" |
| done <"$wget_output" |
| |
| if [ "$?" != "0" ]; then |
| [ -n "$cleanup_files" ] && rm $cleanup_files |
| return 1 |
| fi |
| |
| cat "$channels" |
| echo "SHOPFLOOR_INSTALL=1" |
| |
| [ -n "$cleanup_files" ] && rm $cleanup_files |
| return 0 |
| } |
| |
| # Bring up network |
| bringup_network() { |
| # Probe USB Ethernet devices. |
| local module |
| local module_name |
| local result=1 |
| for module in /lib/modules/*/kernel/drivers/net/usb/*; do |
| module_name="$(basename "${module%.ko}")" |
| modprobe ${module_name} |
| done |
| |
| # Try to bring up network and get an IP address on each Ethernet device. |
| for iface in $(ifconfig -a | grep -Eo 'eth[0-9]+'); do |
| ifconfig ${iface} up || true |
| udhcpc -t 3 -f -q -n -i ${iface} -s /etc/udhcpc.script && result=0 |
| done |
| return ${result} |
| } |
| |
| # Try to register into Overlord server if available. |
| register_to_overlord() { |
| local omaha_url="$1" |
| local tty_file="$2" |
| local log_file="$3" |
| local machine_id="" |
| |
| local server="${omaha_url#*://}" |
| server="${server%%:*}" |
| server="${server%% }" |
| server="${server## }" |
| [ -n "${server}" ] || return 1 |
| |
| # Build machine ID by MAC addresses. |
| local eth="$(netstat -r | grep '^default ')" |
| machine_id="$(ip link show ${eth##* } | grep 'link/ether' | |
| sed 's/.*ether //;s/ brd .*//' | tr '\n' ',' | sed 's/,$//')" |
| [ -n "${machine_id}" ] || machine_id="UnknownMachineId.$(uuidgen 2>/dev/null)" |
| |
| local header_tty="$(mktemp)" header_log="$(mktemp)" |
| local header='{"name":"register", |
| "params":{"sid":"%s","mid":"%s","format":%s,"mode":4}}\r\n' |
| printf "${header}" "Console" "${machine_id}" "1" >"${header_tty}" |
| printf "${header}" "DebugLog" "${machine_id}" "0" >"${header_log}" |
| |
| # nc@busybox may have problem in receiving data from pipe (due to buffer size |
| # and timeout), so we should write the command into a scripting file and let |
| # busybox create the pipe internally. |
| local tty_piper="$(mktemp)" log_piper="$(mktemp)" |
| echo "tail -n +0 -qF ${header_tty} ${tty_file}" >"${tty_piper}" |
| echo "tail -n +0 -qF ${header_log} ${log_file}" >"${log_piper}" |
| chmod a+rx "${tty_piper}" "${log_piper}" |
| local connect_cmd="while true; do busybox nc ${server} 4455 -e %s; |
| sleep 10; done" |
| |
| if [ -n "${tty_file}" ]; then |
| setsid sh -c "$(printf "${connect_cmd}" ${tty_piper})" & |
| fi |
| setsid sh -c "$(printf "${connect_cmd}" ${log_piper})" & |
| } |