blob: 81354f20b650ea08d1ef02ea0520538b9bc86004 [file] [log] [blame] [edit]
#!/bin/bash
# Copyright 2024 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
color_cyan="\033[0;36m"
color_plain="\033[0m"
color_yellow="\033[0;33m"
# validate number of arguments
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
echo "This script requires 1 mandatory and 1 optional parameters, server address and optionally number of instances to invoke"
exit 1
fi
# map arguments to variables
# $1: ARM server address
# $2: Instance number (Optional, default is 1)
server=$1
if [ "$#" -eq 2 ]; then
num_instances=$2
else
num_instances=1
fi
# set img_dir and cvd_host_tool_dir
img_dir=${ANDROID_PRODUCT_OUT:-$PWD}
cvd_host_tool_dir=${ANDROID_HOST_OUT:+"$ANDROID_HOST_OUT/../linux_musl-arm64"}
cvd_host_tool_dir=${cvd_host_tool_dir:-$PWD}
# upload artifacts into ARM server
cvd_home_dir=cvd_home
ssh $server -t "mkdir -p ~/.cvd_artifact; mkdir -p ~/$cvd_home_dir"
if [ -f $img_dir/required_images ]; then
rsync -aSvch --recursive $img_dir --files-from=$img_dir/required_images $server:~/$cvd_home_dir --info=progress2
else
rsync -aSvch --recursive $img_dir/bootloader $img_dir/*.img $server:~/$cvd_home_dir --info=progress2
fi
# upload cvd-host_package.tar.gz into ARM server
temp_dir=/tmp/cvd_dist
rm -rf $temp_dir
mkdir -p $temp_dir
if [ -d $cvd_host_tool_dir/cvd-host_package ]; then
echo "Use contents in cvd-host_package dir"
pushd $cvd_host_tool_dir/cvd-host_package > /dev/null
tar -cf $temp_dir/cvd-host_package.tar ./*
popd > /dev/null
pigz -R $temp_dir/cvd-host_package.tar
elif [ -f $cvd_host_tool_dir/cvd-host_package.tar.gz ]; then
echo "Use contents in cvd-host_package.tar.gz"
# re-compress with rsyncable option
# TODO(b/275312073): remove this if toxbox supports rsyncable
pigz -d -c $cvd_host_tool_dir/cvd-host_package.tar.gz | pigz -R > $temp_dir/cvd-host_package.tar.gz
else
echo "There is neither cvd-host_package dir nor cvd-host_package.tar.gz"
exit 1
fi
rsync -avch $temp_dir/cvd-host_package.tar.gz $server:~/$cvd_home_dir --info=progress2
# run docker instance
container_id=$(ssh $server -t "docker run --rm --privileged -P -d cuttlefish")
container_id=${container_id//$'\r'} # to remove trailing ^M
echo -e "${color_cyan}Booting container $container_id${color_plain}"
# set trap to stop docker instance
trap cleanup SIGINT
cleanup() {
echo -e "${color_yellow}SIGINT: stopping the launch instances${color_plain}"
ssh $server "docker kill $container_id"
}
# extract Host Orchestrator Port
docker_inspect=$(ssh $server "docker inspect --format='{{json .NetworkSettings.Ports }}' $container_id")
docker_host_orchestrator_port_parser_script='
import sys, json;
json_raw=input()
data = json.loads(json_raw)
for k in data:
original_port = int(k.split("/")[0])
assigned_port = int(data[k][0]["HostPort"])
if original_port == 2443:
print(assigned_port)
break
'
docker_host_orchestrator_port=$(echo $docker_inspect | python -c "$docker_host_orchestrator_port_parser_script")
host_orchestrator_url=https://localhost:$docker_host_orchestrator_port
echo -e "Extracting host orchestrator port in docker instance"
# create user artifact directory
create_user_artifacts_dir_script="ssh $server curl -s -k -X POST ${host_orchestrator_url}/userartifacts | jq -r '.name'"
user_artifacts_dir=$($create_user_artifacts_dir_script)
while [ -z "$user_artifacts_dir" ]; do
echo -e "Failed to create user_artifacts_dir, retrying"
sleep 1
user_artifacts_dir=$($create_user_artifacts_dir_script)
done
echo -e "Succeeded to create user_artifacts_dir"
# upload artifacts and cvd-host_pachage.tar.gz into docker instance
ssh $server \
"for filename in \$(ls $cvd_home_dir); do \
absolute_path=\$HOME/$cvd_home_dir/\$filename && \
size=\$(stat -c%s \$absolute_path) && \
echo Uploading \$filename\\(size:\$size\\) ... && \
curl -s -k --location -X PUT $host_orchestrator_url/userartifacts/$user_artifacts_dir \
-H 'Content-Type: multipart/form-data' \
-F chunk_number=1 \
-F chunk_total=1 \
-F chunk_size_bytes=\$size \
-F file=@\$absolute_path; \
done"
echo -e "Done"
# start Cuttlefish instance on top of docker instance
echo -e "Starting Cuttlefish"
ssh $server "curl -s -k -X POST $host_orchestrator_url/cvds \
-H 'Content-Type: application/json' \
-d '{\"cvd\": {\"build_source\": {\"user_build_source\": {\"artifacts_dir\": \"$user_artifacts_dir\"}}}, \"additional_instances_num\": $(($num_instances-1))}'
"
# Web UI port is 3443 instead 1443 because there could be a running operator or host orchestrator in this machine as well.
web_ui_port=3443
echo -e "Web UI port: $web_ui_port. ${color_cyan}Please point your browser to https://localhost:$web_ui_port for the UI${color_plain}"
# sets up SSH port forwarding to the remote server for various ports and launch cvd instance
for instance_num in $(seq 1 $num_instances); do
device_name="cvd_$instance_num"
adb_port=$((6520+$instance_num-1))
echo -e "$device_name is using adb port $adb_port. Try ${color_cyan}adb connect 127.0.0.1:${adb_port}${color_plain} if you want to connect to this device"
done
docker_port_parser_script='
import sys, json;
web_ui_port = int(sys.argv[1])
max_instances = 100
num_instance = int(sys.argv[2])
json_raw=input()
data = json.loads(json_raw)
for k in data:
original_port = int(k.split("/")[0])
assigned_port = int(data[k][0]["HostPort"])
if original_port == 1443:
original_port = web_ui_port
elif original_port in (1080, 2080, 2443): # Do not expose other operator or host orchestrator port beyond ARM server
continue
elif original_port >= 6520 and original_port <= 6520 + max_instances:
if original_port - 6520 >= num_instance:
continue
print(f"-L {original_port}:127.0.0.1:{assigned_port}", end=" ")
'
ports_forwarding=$(echo $docker_inspect | python -c "$docker_port_parser_script" $web_ui_port $num_instances)
echo -e $ports_forwarding
echo "Set up ssh ports forwarding: $ports_forwarding"
echo -e "${color_yellow}Please stop the running instances by ctrl+c${color_plain}"
ssh $server $ports_forwarding "docker logs -f $container_id"