xref: /cloud-hypervisor/scripts/dev_cli.sh (revision c8fa8092c5d2ffab48af9c5dea92a0f7765c5e4c)
1db6f894eSSamuel Ortiz#!/bin/bash
2db6f894eSSamuel Ortiz
3db6f894eSSamuel Ortiz# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4db6f894eSSamuel Ortiz# Copyright © 2020 Intel Corporation
5db6f894eSSamuel Ortiz# SPDX-License-Identifier: Apache-2.0
6db6f894eSSamuel Ortiz
7db6f894eSSamuel OrtizCLI_NAME="Cloud Hypervisor"
8db6f894eSSamuel Ortiz
9db6f894eSSamuel OrtizCTR_IMAGE_TAG="cloudhypervisor/dev"
10db6f894eSSamuel OrtizCTR_IMAGE_VERSION="v1"
11db6f894eSSamuel OrtizCTR_IMAGE="${CTR_IMAGE_TAG}:${CTR_IMAGE_VERSION}"
12db6f894eSSamuel Ortiz
13db6f894eSSamuel OrtizDOCKER_RUNTIME="docker"
14db6f894eSSamuel Ortiz
15db6f894eSSamuel Ortiz# Host paths
16db6f894eSSamuel OrtizCLH_SCRIPTS_DIR=$(cd "$(dirname "$0")" && pwd)
17db6f894eSSamuel OrtizCLH_ROOT_DIR=$(cd "${CLH_SCRIPTS_DIR}/.." && pwd)
18db6f894eSSamuel OrtizCLH_BUILD_DIR="${CLH_ROOT_DIR}/build"
19db6f894eSSamuel OrtizCLH_CARGO_TARGET="${CLH_BUILD_DIR}/cargo_target"
20db6f894eSSamuel OrtizCLH_DOCKERFILE="${CLH_SCRIPTS_DIR}/../resources/Dockerfile"
21db6f894eSSamuel OrtizCLH_CTR_BUILD_DIR="/tmp/cloud-hypervisor/ctr-build"
22db6f894eSSamuel OrtizCLH_INTEGRATION_WORKLOADS="${HOME}/workloads"
23db6f894eSSamuel Ortiz
24db6f894eSSamuel Ortiz# Container paths
25db6f894eSSamuel OrtizCTR_CLH_ROOT_DIR="/cloud-hypervisor"
26db6f894eSSamuel OrtizCTR_CLH_CARGO_TARGET="${CTR_CLH_ROOT_DIR}/build/cargo_target"
27db6f894eSSamuel OrtizCTR_CLH_INTEGRATION_WORKLOADS="/root/workloads"
28db6f894eSSamuel Ortiz
29db6f894eSSamuel Ortiz# Cargo paths
30db6f894eSSamuel Ortiz# Full path to the cargo registry dir on the host. This appears on the host
31db6f894eSSamuel Ortiz# because we want to persist the cargo registry across container invocations.
32db6f894eSSamuel Ortiz# Otherwise, any rust crates from crates.io would be downloaded again each time
33db6f894eSSamuel Ortiz# we build or test.
34db6f894eSSamuel OrtizCARGO_REGISTRY_DIR="${CLH_BUILD_DIR}/cargo_registry"
35db6f894eSSamuel Ortiz
36db6f894eSSamuel Ortiz# Full path to the cargo git registry on the host. This serves the same purpose
37db6f894eSSamuel Ortiz# as CARGO_REGISTRY_DIR, for crates downloaded from GitHub repos instead of
38db6f894eSSamuel Ortiz# crates.io.
39db6f894eSSamuel OrtizCARGO_GIT_REGISTRY_DIR="${CLH_BUILD_DIR}/cargo_git_registry"
40db6f894eSSamuel Ortiz
41db6f894eSSamuel Ortiz# Full path to the cargo target dir on the host.
42db6f894eSSamuel OrtizCARGO_TARGET_DIR="${CLH_BUILD_DIR}/cargo_target"
43db6f894eSSamuel Ortiz
44db6f894eSSamuel Ortiz# Send a decorated message to stdout, followed by a new line
45db6f894eSSamuel Ortiz#
46db6f894eSSamuel Ortizsay() {
47db6f894eSSamuel Ortiz    [ -t 1 ] && [ -n "$TERM" ] \
48db6f894eSSamuel Ortiz        && echo "$(tput setaf 2)[$CLI_NAME]$(tput sgr0) $*" \
49db6f894eSSamuel Ortiz        || echo "[$CLI_NAME] $*"
50db6f894eSSamuel Ortiz}
51db6f894eSSamuel Ortiz
52db6f894eSSamuel Ortiz# Send a decorated message to stdout, without a trailing new line
53db6f894eSSamuel Ortiz#
54db6f894eSSamuel Ortizsay_noln() {
55db6f894eSSamuel Ortiz    [ -t 1 ] && [ -n "$TERM" ] \
56db6f894eSSamuel Ortiz        && echo -n "$(tput setaf 2)[$CLI_NAME]$(tput sgr0) $*" \
57db6f894eSSamuel Ortiz        || echo "[$CLI_NAME] $*"
58db6f894eSSamuel Ortiz}
59db6f894eSSamuel Ortiz
60db6f894eSSamuel Ortiz# Send a text message to stderr
61db6f894eSSamuel Ortiz#
62db6f894eSSamuel Ortizsay_err() {
63db6f894eSSamuel Ortiz    [ -t 2 ] && [ -n "$TERM" ] \
64db6f894eSSamuel Ortiz        && echo "$(tput setaf 1)[$CLI_NAME] $*$(tput sgr0)" 1>&2 \
65db6f894eSSamuel Ortiz        || echo "[$CLI_NAME] $*" 1>&2
66db6f894eSSamuel Ortiz}
67db6f894eSSamuel Ortiz
68db6f894eSSamuel Ortiz# Send a warning-highlighted text to stdout
69db6f894eSSamuel Ortizsay_warn() {
70db6f894eSSamuel Ortiz    [ -t 1 ] && [ -n "$TERM" ] \
71db6f894eSSamuel Ortiz        && echo "$(tput setaf 3)[$CLI_NAME] $*$(tput sgr0)" \
72db6f894eSSamuel Ortiz        || echo "[$CLI_NAME] $*"
73db6f894eSSamuel Ortiz}
74db6f894eSSamuel Ortiz
75db6f894eSSamuel Ortiz# Exit with an error message and (optional) code
76db6f894eSSamuel Ortiz# Usage: die [-c <error code>] <error message>
77db6f894eSSamuel Ortiz#
78db6f894eSSamuel Ortizdie() {
79db6f894eSSamuel Ortiz    code=1
80db6f894eSSamuel Ortiz    [[ "$1" = "-c" ]] && {
81db6f894eSSamuel Ortiz        code="$2"
82db6f894eSSamuel Ortiz        shift 2
83db6f894eSSamuel Ortiz    }
84db6f894eSSamuel Ortiz    say_err "$@"
85db6f894eSSamuel Ortiz    exit $code
86db6f894eSSamuel Ortiz}
87db6f894eSSamuel Ortiz
88db6f894eSSamuel Ortiz# Exit with an error message if the last exit code is not 0
89db6f894eSSamuel Ortiz#
90db6f894eSSamuel Ortizok_or_die() {
91db6f894eSSamuel Ortiz    code=$?
92db6f894eSSamuel Ortiz    [[ $code -eq 0 ]] || die -c $code "$@"
93db6f894eSSamuel Ortiz}
94db6f894eSSamuel Ortiz
95db6f894eSSamuel Ortiz# Make sure the build/ dirs are available. Exit if we can't create them.
96db6f894eSSamuel Ortiz# Upon returning from this call, the caller can be certain the build/ dirs exist.
97db6f894eSSamuel Ortiz#
98db6f894eSSamuel Ortizensure_build_dir() {
99db6f894eSSamuel Ortiz    for dir in "$CLH_BUILD_DIR" \
100db6f894eSSamuel Ortiz		   "$CLH_INTEGRATION_WORKLOADS" \
101db6f894eSSamuel Ortiz		   "$CLH_CTR_BUILD_DIR" \
102db6f894eSSamuel Ortiz		   "$CARGO_TARGET_DIR" \
103db6f894eSSamuel Ortiz		   "$CARGO_REGISTRY_DIR" \
104db6f894eSSamuel Ortiz		   "$CARGO_GIT_REGISTRY_DIR"; do
105db6f894eSSamuel Ortiz        mkdir -p "$dir" || die "Error: cannot create dir $dir"
106db6f894eSSamuel Ortiz        [ -x "$dir" ] && [ -w "$dir" ] || \
107db6f894eSSamuel Ortiz            {
108db6f894eSSamuel Ortiz                say "Wrong permissions for $dir. Attempting to fix them ..."
109db6f894eSSamuel Ortiz                chmod +x+w "$dir"
110db6f894eSSamuel Ortiz            } || \
111db6f894eSSamuel Ortiz            die "Error: wrong permissions for $dir. Should be +x+w"
112db6f894eSSamuel Ortiz    done
113db6f894eSSamuel Ortiz}
114db6f894eSSamuel Ortiz
115db6f894eSSamuel Ortizcmd_help() {
116db6f894eSSamuel Ortiz    echo ""
117db6f894eSSamuel Ortiz    echo "Cloud Hypervisor $(basename $0)"
118db6f894eSSamuel Ortiz    echo "Usage: $(basename $0) <command> [<command args>]"
119db6f894eSSamuel Ortiz    echo ""
120db6f894eSSamuel Ortiz    echo "Available commands:"
121db6f894eSSamuel Ortiz    echo ""
122db6f894eSSamuel Ortiz    echo "    build [--debug|--release] [-- [<cargo args>]]"
123db6f894eSSamuel Ortiz    echo "        Build the Cloud Hypervisor binaries."
124db6f894eSSamuel Ortiz    echo "        --debug               Build the debug binaries. This is the default."
125db6f894eSSamuel Ortiz    echo "        --release             Build the release binaries."
126db6f894eSSamuel Ortiz    echo ""
127705f2715SSamuel Ortiz    echo "    tests [--unit|--cargo|--all] [-- [<cargo test args>]]"
128db6f894eSSamuel Ortiz    echo "        Run the Cloud Hypervisor tests."
129db6f894eSSamuel Ortiz    echo "        --unit               Run the unit tests."
130db6f894eSSamuel Ortiz    echo "        --cargo              Run the cargo tests."
131db6f894eSSamuel Ortiz    echo "        --integration        Run the integration tests."
132db6f894eSSamuel Ortiz    echo "        --all                Run all tests."
133db6f894eSSamuel Ortiz    echo ""
134db6f894eSSamuel Ortiz    echo "    build-container [--type]"
135db6f894eSSamuel Ortiz    echo "        Build the Cloud Hypervisor container."
136db6f894eSSamuel Ortiz    echo "        --dev                Build dev container. This is the default."
137db6f894eSSamuel Ortiz    echo ""
138275cb5c9SSamuel Ortiz    echo "    clean [<cargo args>]]"
139275cb5c9SSamuel Ortiz    echo "        Remove the Cloud Hypervisor artifacts."
140275cb5c9SSamuel Ortiz    echo ""
141db6f894eSSamuel Ortiz    echo "    help"
142db6f894eSSamuel Ortiz    echo "        Display this help message."
143db6f894eSSamuel Ortiz    echo ""
144db6f894eSSamuel Ortiz}
145db6f894eSSamuel Ortiz
146db6f894eSSamuel Ortizcmd_build() {
147db6f894eSSamuel Ortiz    build="debug"
148db6f894eSSamuel Ortiz
149db6f894eSSamuel Ortiz    while [ $# -gt 0 ]; do
150db6f894eSSamuel Ortiz	case "$1" in
151db6f894eSSamuel Ortiz            "-h"|"--help")  { cmd_help; exit 1;     } ;;
152db6f894eSSamuel Ortiz            "--debug")      { build="debug";      } ;;
153db6f894eSSamuel Ortiz            "--release")    { build="release";    } ;;
154db6f894eSSamuel Ortiz            "--")           { shift; break;         } ;;
155db6f894eSSamuel Ortiz            *)
156db6f894eSSamuel Ortiz		die "Unknown build argument: $1. Please use --help for help."
157db6f894eSSamuel Ortiz		;;
158db6f894eSSamuel Ortiz	esac
159db6f894eSSamuel Ortiz	shift
160db6f894eSSamuel Ortiz    done
161db6f894eSSamuel Ortiz
162db6f894eSSamuel Ortiz    cargo_args=("$@")
163db6f894eSSamuel Ortiz    [ $build = "release" ] && cargo_args+=("--release")
164db6f894eSSamuel Ortiz
165db6f894eSSamuel Ortiz    $DOCKER_RUNTIME run \
166*c8fa8092SSamuel Ortiz	   --user "$(id -u):$(id -g)" \
167db6f894eSSamuel Ortiz	   --workdir "$CTR_CLH_ROOT_DIR" \
168db6f894eSSamuel Ortiz	   --rm \
169db6f894eSSamuel Ortiz	   --volume /dev:/dev \
170db6f894eSSamuel Ortiz	   --volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" \
171db6f894eSSamuel Ortiz	   "$CTR_IMAGE" \
172db6f894eSSamuel Ortiz	   cargo build \
173db6f894eSSamuel Ortiz	         --target-dir "$CTR_CLH_CARGO_TARGET" \
174db6f894eSSamuel Ortiz	         "${cargo_args[@]}"
175db6f894eSSamuel Ortiz
176db6f894eSSamuel Ortiz    ret=$?
177db6f894eSSamuel Ortiz
178db6f894eSSamuel Ortiz    # If `cargo build` was successful, let's copy the binaries to a more
179db6f894eSSamuel Ortiz    # accessible location.
180db6f894eSSamuel Ortiz    [ $ret -eq 0 ] && {
181db6f894eSSamuel Ortiz        cargo_bin_dir="$CLH_CARGO_TARGET/$build"
182db6f894eSSamuel Ortiz        say "Binaries placed under $cargo_bin_dir"
183db6f894eSSamuel Ortiz    }
184db6f894eSSamuel Ortiz}
185db6f894eSSamuel Ortiz
186275cb5c9SSamuel Ortizcmd_clean() {
187275cb5c9SSamuel Ortiz    cargo_args=("$@")
188275cb5c9SSamuel Ortiz
189275cb5c9SSamuel Ortiz    $DOCKER_RUNTIME run \
190*c8fa8092SSamuel Ortiz	   --user "$(id -u):$(id -g)" \
191275cb5c9SSamuel Ortiz	   --workdir "$CTR_CLH_ROOT_DIR" \
192275cb5c9SSamuel Ortiz	   --rm \
193275cb5c9SSamuel Ortiz	   --volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" \
194275cb5c9SSamuel Ortiz	   "$CTR_IMAGE" \
195275cb5c9SSamuel Ortiz	   cargo clean \
196275cb5c9SSamuel Ortiz	         --target-dir "$CTR_CLH_CARGO_TARGET" \
197275cb5c9SSamuel Ortiz	         "${cargo_args[@]}"
198275cb5c9SSamuel Ortiz    }
199275cb5c9SSamuel Ortiz
200db6f894eSSamuel Ortizcmd_tests() {
201db6f894eSSamuel Ortiz    unit=false
202db6f894eSSamuel Ortiz    cargo=false
203db6f894eSSamuel Ortiz    integration=false
204db6f894eSSamuel Ortiz
205db6f894eSSamuel Ortiz    while [ $# -gt 0 ]; do
206db6f894eSSamuel Ortiz	case "$1" in
207db6f894eSSamuel Ortiz            "-h"|"--help")    { cmd_help; exit 1;     } ;;
208db6f894eSSamuel Ortiz            "--unit")         { unit=true;      } ;;
209db6f894eSSamuel Ortiz            "--cargo")        { cargo=true;    } ;;
210db6f894eSSamuel Ortiz	    "--integration")  { integration=true;    } ;;
211db6f894eSSamuel Ortiz	    "--all")          { cargo=true; unit=true; integration=true;  } ;;
212db6f894eSSamuel Ortiz            "--")             { shift; break;         } ;;
213db6f894eSSamuel Ortiz            *)
214db6f894eSSamuel Ortiz		die "Unknown tests argument: $1. Please use --help for help."
215db6f894eSSamuel Ortiz		;;
216db6f894eSSamuel Ortiz	esac
217db6f894eSSamuel Ortiz	shift
218db6f894eSSamuel Ortiz    done
219db6f894eSSamuel Ortiz
220db6f894eSSamuel Ortiz    if [ "$unit" = true ] ;  then
221db6f894eSSamuel Ortiz	say "Running unit tests..."
222db6f894eSSamuel Ortiz	$DOCKER_RUNTIME run \
223db6f894eSSamuel Ortiz	       --workdir "$CTR_CLH_ROOT_DIR" \
224db6f894eSSamuel Ortiz	       --rm \
225db6f894eSSamuel Ortiz	       --privileged \
226db6f894eSSamuel Ortiz	       --volume /dev:/dev \
227db6f894eSSamuel Ortiz	       --volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" \
228db6f894eSSamuel Ortiz	       "$CTR_IMAGE" \
22904cb35e3SRob Bradford	       ./scripts/run_unit_tests.sh "$@" || exit $?
230db6f894eSSamuel Ortiz    fi
231db6f894eSSamuel Ortiz
232db6f894eSSamuel Ortiz    if [ "$cargo" = true ] ;  then
233db6f894eSSamuel Ortiz	say "Running cargo tests..."
234db6f894eSSamuel Ortiz	$DOCKER_RUNTIME run \
235*c8fa8092SSamuel Ortiz	       --user "$(id -u):$(id -g)" \
236db6f894eSSamuel Ortiz	       --workdir "$CTR_CLH_ROOT_DIR" \
237db6f894eSSamuel Ortiz	       --rm \
238db6f894eSSamuel Ortiz	       --volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" \
239db6f894eSSamuel Ortiz	       "$CTR_IMAGE" \
24004cb35e3SRob Bradford	       ./scripts/run_cargo_tests.sh || exit $?
241db6f894eSSamuel Ortiz    fi
242db6f894eSSamuel Ortiz
243db6f894eSSamuel Ortiz    if [ "$integration" = true ] ;  then
244db6f894eSSamuel Ortiz	say "Running integration tests..."
245db6f894eSSamuel Ortiz	$DOCKER_RUNTIME run \
246db6f894eSSamuel Ortiz	       --workdir "$CTR_CLH_ROOT_DIR" \
247db6f894eSSamuel Ortiz	       --rm \
248db6f894eSSamuel Ortiz	       --privileged \
249a5b053f8SSamuel Ortiz	       --mount type=tmpfs,destination=/tmp \
250db6f894eSSamuel Ortiz	       --volume /dev:/dev \
251db6f894eSSamuel Ortiz	       --volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" \
252db6f894eSSamuel Ortiz	       --volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \
253db6f894eSSamuel Ortiz	       "$CTR_IMAGE" \
25404cb35e3SRob Bradford	       ./scripts/run_integration_tests.sh "$@" || exit $?
255db6f894eSSamuel Ortiz    fi
256db6f894eSSamuel Ortiz}
257db6f894eSSamuel Ortiz
258db6f894eSSamuel Ortizcmd_build-container() {
259db6f894eSSamuel Ortiz    container_type="dev"
260db6f894eSSamuel Ortiz
261db6f894eSSamuel Ortiz    while [ $# -gt 0 ]; do
262db6f894eSSamuel Ortiz	case "$1" in
263db6f894eSSamuel Ortiz            "-h"|"--help")  { cmd_help; exit 1;     } ;;
264db6f894eSSamuel Ortiz            "--dev")        { container_type="dev"; } ;;
265db6f894eSSamuel Ortiz            "--")           { shift; break;         } ;;
266db6f894eSSamuel Ortiz            *)
267db6f894eSSamuel Ortiz		die "Unknown build-container argument: $1. Please use --help for help."
268db6f894eSSamuel Ortiz		;;
269db6f894eSSamuel Ortiz	esac
270db6f894eSSamuel Ortiz	shift
271db6f894eSSamuel Ortiz    done
272db6f894eSSamuel Ortiz
273db6f894eSSamuel Ortiz    BUILD_DIR=/tmp/cloud-hypervisor/container/
274db6f894eSSamuel Ortiz
275db6f894eSSamuel Ortiz    mkdir -p $BUILD_DIR
276db6f894eSSamuel Ortiz    cp $CLH_DOCKERFILE $BUILD_DIR
277db6f894eSSamuel Ortiz
278db6f894eSSamuel Ortiz    $DOCKER_RUNTIME build \
279db6f894eSSamuel Ortiz	   --target $container_type \
280db6f894eSSamuel Ortiz	   -t $CTR_IMAGE \
281db6f894eSSamuel Ortiz	   -f $BUILD_DIR/Dockerfile \
282db6f894eSSamuel Ortiz	   $BUILD_DIR
283db6f894eSSamuel Ortiz}
284db6f894eSSamuel Ortiz
285db6f894eSSamuel Ortiz# Parse main command line args.
286db6f894eSSamuel Ortiz#
287db6f894eSSamuel Ortizwhile [ $# -gt 0 ]; do
288db6f894eSSamuel Ortiz    case "$1" in
289db6f894eSSamuel Ortiz        -h|--help)              { cmd_help; exit 1;     } ;;
290db6f894eSSamuel Ortiz        -y|--unattended)        { OPT_UNATTENDED=true;  } ;;
291db6f894eSSamuel Ortiz        -*)
292db6f894eSSamuel Ortiz            die "Unknown arg: $1. Please use \`$0 help\` for help."
293db6f894eSSamuel Ortiz            ;;
294db6f894eSSamuel Ortiz        *)
295db6f894eSSamuel Ortiz            break
296db6f894eSSamuel Ortiz            ;;
297db6f894eSSamuel Ortiz    esac
298db6f894eSSamuel Ortiz    shift
299db6f894eSSamuel Ortizdone
300db6f894eSSamuel Ortiz
301db6f894eSSamuel Ortiz# $1 is now a command name. Check if it is a valid command and, if so,
302db6f894eSSamuel Ortiz# run it.
303db6f894eSSamuel Ortiz#
304db6f894eSSamuel Ortizdeclare -f "cmd_$1" > /dev/null
305db6f894eSSamuel Ortizok_or_die "Unknown command: $1. Please use \`$0 help\` for help."
306db6f894eSSamuel Ortiz
307db6f894eSSamuel Ortizcmd=cmd_$1
308db6f894eSSamuel Ortizshift
309db6f894eSSamuel Ortiz
310db6f894eSSamuel Ortizensure_build_dir
311db6f894eSSamuel Ortiz
312db6f894eSSamuel Ortiz$cmd "$@"
313