blob: f0bacb22f111415b0263b2f01f92a26b46f74a5b [file] [log] [blame]
#!/bin/bash
# Copyright 2020 The Fuchsia 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 -eu
SCRIPT_SRC_DIR="$(cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd)"
# Fuchsia command common functions.
# shellcheck disable=SC1090
source "${SCRIPT_SRC_DIR}/fuchsia-common.sh" || exit $?
FUCHSIA_SDK_PATH="$(get-fuchsia-sdk-dir)"
FUCHSIA_IMAGE_WORK_DIR="$(get-fuchsia-sdk-data-dir)"
FUCHSIA_BUCKET="$(get-fuchsia-property bucket)"
if [[ "${FUCHSIA_BUCKET}" == "" ]]; then
FUCHSIA_BUCKET="${DEFAULT_FUCHSIA_BUCKET}"
fi
FUCHSIA_SERVER_PORT="8083"
IMAGE_NAME="$(get-fuchsia-property image)"
if [[ "${IMAGE_NAME}" == "" ]]; then
IMAGE_NAME="generic-x64"
fi
usage () {
echo "Usage: $0"
echo " [--work-dir <directory to store image assets>]"
echo " Defaults to ${FUCHSIA_IMAGE_WORK_DIR}"
echo " [--bucket <fuchsia gsutil bucket>]"
echo " Defaults to ${FUCHSIA_BUCKET}"
echo " [--image <image name>]"
echo " Defaults to ${IMAGE_NAME}. Use --image list to list all available images."
echo " [--private-key <identity file>]"
echo " Uses additional private key when using ssh to access the device."
echo " [--server-port <port>]"
echo " Port number to use when serving the packages. Defaults to ${FUCHSIA_SERVER_PORT}."
echo " [--device-name <device hostname>]"
echo " Only serves packages to a device with the given device hostname. Cannot be used with --device-ip."
echo " [--device-ip <device ip>]"
echo " Only serves packages to a device with the given device ip address. Cannot be used with --device-name."
echo " [--kill]"
echo " Kills any existing package manager server"
echo " [--prepare]"
echo " Downloads any dependencies but does not start the package server"
echo " [-x] Enable debug."
}
PRIVATE_KEY_FILE=""
PREPARE_ONLY=""
DEVICE_NAME_FILTER="$(get-fuchsia-property device-name)"
DEVICE_IP_ADDR="$(get-fuchsia-property device-ip)"
# Parse command line
while (( "$#" )); do
case $1 in
--work-dir)
shift
FUCHSIA_IMAGE_WORK_DIR="${1:-.}"
;;
--bucket)
shift
FUCHSIA_BUCKET="${1}"
;;
--image)
shift
IMAGE_NAME="${1}"
;;
--private-key)
shift
PRIVATE_KEY_FILE="${1}"
;;
--server-port)
shift
FUCHSIA_SERVER_PORT="${1}"
;;
--device-name)
shift
DEVICE_NAME_FILTER="${1}"
;;
--device-ip)
shift
DEVICE_IP_ADDR="${1}"
;;
--kill)
kill-running-pm
exit 0
;;
--prepare)
PREPARE_ONLY="yes"
;;
-x)
set -x
;;
*)
# unknown option
usage
exit 1
;;
esac
shift
done
if [[ "${DEVICE_IP_ADDR}" != "" && "${DEVICE_NAME_FILTER}" != "" ]]; then
fx-error "Cannot use both --device-name and --device-ip".
exit 1
fi
if ! SDK_ID="$(get-sdk-version)"; then
fx-error "Could not get SDK version"
exit 1
fi
if [[ "${IMAGE_NAME}" == "list" ]]; then
if ! IMAGES="$(get-available-images "${SDK_ID}" "${FUCHSIA_BUCKET}")"; then
fx-error "Could not get list of available images for ${SDK_ID}"
exit 1
fi
echo "Valid images for this SDK version are: ${IMAGES}."
exit 1
fi
# The package tarball. We add the SDK ID to the filename to make them
# unique.
#
# Consider cleaning up old tarballs when getting a new one?
#
FUCHSIA_TARGET_PACKAGES=$(get-package-src-path "${SDK_ID}" "${IMAGE_NAME}")
# The package tarball, we add the SDK ID to make it unique, and note the
# .tar.gz extension for packages vs .tgz extension for images.
IMAGE_FILENAME="${SDK_ID}_${IMAGE_NAME}.tar.gz"
# Validate the image is found
if [[ ! -f "${FUCHSIA_IMAGE_WORK_DIR}/${IMAGE_FILENAME}" ]] ; then
if ! run-gsutil ls "${FUCHSIA_TARGET_PACKAGES}" >/dev/null 2>&1; then
echo "Packages for ${IMAGE_NAME} not found. Valid images for this SDK version are:"
if ! IMAGES="$(get-available-images "${SDK_ID}" "${FUCHSIA_BUCKET}")"; then
fx-error "Could not get list of available images for ${SDK_ID}"
exit 1
fi
echo "${IMAGES}"
exit 2
fi
if ! run-gsutil cp "${FUCHSIA_TARGET_PACKAGES}" "${FUCHSIA_IMAGE_WORK_DIR}/${IMAGE_FILENAME}"; then
fx-error "Could not copy image from ${FUCHSIA_TARGET_PACKAGES} to ${FUCHSIA_IMAGE_WORK_DIR}/${IMAGE_FILENAME}."
exit 2
fi
else
echo "Skipping download, packages tarball exists"
fi
# The checksum file contains the output from `md5`. This is used to detect content
# changes in the packages file.
CHECKSUM_FILE="${FUCHSIA_IMAGE_WORK_DIR}/packages/packages.md5"
# check that any existing contents of the image directory match the intended target device
if [[ -f "${CHECKSUM_FILE}" ]]; then
if [[ "$(run-md5 "${FUCHSIA_IMAGE_WORK_DIR}/${IMAGE_FILENAME}")" != "$(cat "${CHECKSUM_FILE}")" ]]; then
fx-warn "Removing old package files."
if ! rm -f "$(cut -d ' ' -f3 "${CHECKSUM_FILE}")"; then
fx-error "Could not clean up old image archive."
exit 2
fi
if ! rm -rf "${FUCHSIA_IMAGE_WORK_DIR}/packages"; then
fx-error "Could not clean up old image."
exit 2
fi
fi
else
# if the checksum file does not exist, something is inconsistent.
# so delete the entire directory to make sure we're starting clean.
# This also happens on a clean run, where the packages directory does not
# exist.
if ! rm -rf "${FUCHSIA_IMAGE_WORK_DIR}/packages"; then
fx-error "Could not clean up old packages."
exit 2
fi
fi
if ! mkdir -p "${FUCHSIA_IMAGE_WORK_DIR}/packages"; then
fx-error "Could not create packages directory."
exit 2
fi
# if the tarball is not untarred, do it.
if [[ ! -d "${FUCHSIA_IMAGE_WORK_DIR}/packages/amber-files" ]]; then
if ! tar xzf "${FUCHSIA_IMAGE_WORK_DIR}/${IMAGE_FILENAME}" --directory "${FUCHSIA_IMAGE_WORK_DIR}/packages"; then
fx-error "Could not extract image from ${FUCHSIA_IMAGE_WORK_DIR}/${IMAGE_FILENAME}."
exit 1
fi
run-md5 "${FUCHSIA_IMAGE_WORK_DIR}/${IMAGE_FILENAME}" > "${CHECKSUM_FILE}"
fi
# Exit out if we only need to prepare the downloads
if [[ "${PREPARE_ONLY}" == "yes" ]]; then
exit 0
fi
if [[ "${DEVICE_IP_ADDR}" != "" ]]; then
DEVICE_IP="${DEVICE_IP_ADDR}"
else
DEVICE_IP=$(get-device-ip-by-name "$FUCHSIA_SDK_PATH" "$DEVICE_NAME_FILTER")
fi
if [[ ! "$?" || -z "$DEVICE_IP" ]]; then
fx-error "Could not get device IP address"
exit 2
fi
# get the host address as seen by the device.
ssh_args=("${DEVICE_IP}" echo "\$SSH_CONNECTION")
if ! connection_str="$(ssh-cmd "${ssh_args[@]}")"; then
fx-error "unable to determine host address as seen from the target. Is the target up?"
exit 1
fi
HOST_IP="$(echo "$connection_str" | cut -d ' ' -f 1)"
if [[ ! "$?" || -z "$HOST_IP" ]]; then
fx-error "Could not get Host IP address"
exit 2
fi
# A simple heuristic for "is an ipv6 address", URL encase escape
# the address.
if [[ "${HOST_IP}" =~ : ]]; then
HOST_IP="${HOST_IP//%/%25}"
HOST_IP="[${HOST_IP}]"
fi
# kill existing pm if present
kill-running-pm
# Start the package server
echo "** Starting package server in the background**"
# `:port` syntax is valid for Go programs that intend to serve on every
# interface on a given port. For example, if $FUCHSIA_SERVER_PORT is 54321,
# this is similar to serving on [::]:54321 or 0.0.0.0:54321.
"${FUCHSIA_SDK_PATH}/tools/pm" serve -repo "${FUCHSIA_IMAGE_WORK_DIR}/packages/amber-files" -l ":${FUCHSIA_SERVER_PORT}"&
SSH_ARGS=()
if [[ "${PRIVATE_KEY_FILE}" != "" ]]; then
SSH_ARGS+=( "-i" "${PRIVATE_KEY_FILE}")
fi
SSH_ARGS+=( "${DEVICE_IP}" amber_ctl add_src -f "http://${HOST_IP}:${FUCHSIA_SERVER_PORT}/config.json" )
# Update the device to point to the server.
# Because the URL to config.json contains an IPv6 address, the address needs
# to be escaped in square brackets. This is not necessary for the ssh target,
# since that's just an address and not a full URL.
if ! ssh-cmd "${SSH_ARGS[@]}" ; then
fx-error "Error: could not update device"
exit 1
fi