blob: b8e4a777956eeeae2ec582dad67fda86335c97ec [file] [log] [blame]
#!/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})" &
}