191fe48d5SPhilipp Schuster#!/usr/bin/env 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 9ca96ff60SRob BradfordCTR_IMAGE_TAG="ghcr.io/cloud-hypervisor/cloud-hypervisor" 10*24f384d2SRavi kumar VeeramallyCTR_IMAGE_VERSION="20231220-0" 1170cfd1beSRuslan Mstoi: "${CTR_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" 260a1d6e1cSSamuel OrtizCTR_CLH_CARGO_BUILT_DIR="${CTR_CLH_ROOT_DIR}/build" 270a1d6e1cSSamuel OrtizCTR_CLH_CARGO_TARGET="${CTR_CLH_CARGO_BUILT_DIR}/cargo_target" 28db6f894eSSamuel OrtizCTR_CLH_INTEGRATION_WORKLOADS="/root/workloads" 29db6f894eSSamuel Ortiz 30cf1b5156SMichael Zhao# Container networking option 317889fc92SSebastien BoeufCTR_CLH_NET="bridge" 32cf1b5156SMichael Zhao 33db6f894eSSamuel Ortiz# Cargo paths 34db6f894eSSamuel Ortiz# Full path to the cargo registry dir on the host. This appears on the host 35db6f894eSSamuel Ortiz# because we want to persist the cargo registry across container invocations. 36db6f894eSSamuel Ortiz# Otherwise, any rust crates from crates.io would be downloaded again each time 37db6f894eSSamuel Ortiz# we build or test. 38db6f894eSSamuel OrtizCARGO_REGISTRY_DIR="${CLH_BUILD_DIR}/cargo_registry" 39db6f894eSSamuel Ortiz 40db6f894eSSamuel Ortiz# Full path to the cargo git registry on the host. This serves the same purpose 41db6f894eSSamuel Ortiz# as CARGO_REGISTRY_DIR, for crates downloaded from GitHub repos instead of 42db6f894eSSamuel Ortiz# crates.io. 43db6f894eSSamuel OrtizCARGO_GIT_REGISTRY_DIR="${CLH_BUILD_DIR}/cargo_git_registry" 44db6f894eSSamuel Ortiz 45db6f894eSSamuel Ortiz# Full path to the cargo target dir on the host. 46db6f894eSSamuel OrtizCARGO_TARGET_DIR="${CLH_BUILD_DIR}/cargo_target" 47db6f894eSSamuel Ortiz 48db6f894eSSamuel Ortiz# Send a decorated message to stdout, followed by a new line 49db6f894eSSamuel Ortiz# 50db6f894eSSamuel Ortizsay() { 511a5b94eeSRob Bradford [ -t 1 ] && [ -n "$TERM" ] && 521a5b94eeSRob Bradford echo "$(tput setaf 2)[$CLI_NAME]$(tput sgr0) $*" || 531a5b94eeSRob Bradford echo "[$CLI_NAME] $*" 54db6f894eSSamuel Ortiz} 55db6f894eSSamuel Ortiz 56db6f894eSSamuel Ortiz# Send a decorated message to stdout, without a trailing new line 57db6f894eSSamuel Ortiz# 58db6f894eSSamuel Ortizsay_noln() { 591a5b94eeSRob Bradford [ -t 1 ] && [ -n "$TERM" ] && 601a5b94eeSRob Bradford echo -n "$(tput setaf 2)[$CLI_NAME]$(tput sgr0) $*" || 611a5b94eeSRob Bradford echo "[$CLI_NAME] $*" 62db6f894eSSamuel Ortiz} 63db6f894eSSamuel Ortiz 64db6f894eSSamuel Ortiz# Send a text message to stderr 65db6f894eSSamuel Ortiz# 66db6f894eSSamuel Ortizsay_err() { 671a5b94eeSRob Bradford [ -t 2 ] && [ -n "$TERM" ] && 681a5b94eeSRob Bradford echo "$(tput setaf 1)[$CLI_NAME] $*$(tput sgr0)" 1>&2 || 691a5b94eeSRob Bradford echo "[$CLI_NAME] $*" 1>&2 70db6f894eSSamuel Ortiz} 71db6f894eSSamuel Ortiz 72db6f894eSSamuel Ortiz# Send a warning-highlighted text to stdout 73db6f894eSSamuel Ortizsay_warn() { 741a5b94eeSRob Bradford [ -t 1 ] && [ -n "$TERM" ] && 751a5b94eeSRob Bradford echo "$(tput setaf 3)[$CLI_NAME] $*$(tput sgr0)" || 761a5b94eeSRob Bradford echo "[$CLI_NAME] $*" 77db6f894eSSamuel Ortiz} 78db6f894eSSamuel Ortiz 79db6f894eSSamuel Ortiz# Exit with an error message and (optional) code 80db6f894eSSamuel Ortiz# Usage: die [-c <error code>] <error message> 81db6f894eSSamuel Ortiz# 82db6f894eSSamuel Ortizdie() { 83db6f894eSSamuel Ortiz code=1 84db6f894eSSamuel Ortiz [[ "$1" = "-c" ]] && { 85db6f894eSSamuel Ortiz code="$2" 86db6f894eSSamuel Ortiz shift 2 87db6f894eSSamuel Ortiz } 88db6f894eSSamuel Ortiz say_err "$@" 892805e7b1SRob Bradford exit "$code" 90db6f894eSSamuel Ortiz} 91db6f894eSSamuel Ortiz 92db6f894eSSamuel Ortiz# Exit with an error message if the last exit code is not 0 93db6f894eSSamuel Ortiz# 94db6f894eSSamuel Ortizok_or_die() { 95db6f894eSSamuel Ortiz code=$? 96db6f894eSSamuel Ortiz [[ $code -eq 0 ]] || die -c $code "$@" 97db6f894eSSamuel Ortiz} 98db6f894eSSamuel Ortiz 99db6f894eSSamuel Ortiz# Make sure the build/ dirs are available. Exit if we can't create them. 100db6f894eSSamuel Ortiz# Upon returning from this call, the caller can be certain the build/ dirs exist. 101db6f894eSSamuel Ortiz# 102db6f894eSSamuel Ortizensure_build_dir() { 103db6f894eSSamuel Ortiz for dir in "$CLH_BUILD_DIR" \ 104db6f894eSSamuel Ortiz "$CLH_INTEGRATION_WORKLOADS" \ 105db6f894eSSamuel Ortiz "$CLH_CTR_BUILD_DIR" \ 106db6f894eSSamuel Ortiz "$CARGO_TARGET_DIR" \ 107db6f894eSSamuel Ortiz "$CARGO_REGISTRY_DIR" \ 108db6f894eSSamuel Ortiz "$CARGO_GIT_REGISTRY_DIR"; do 109db6f894eSSamuel Ortiz mkdir -p "$dir" || die "Error: cannot create dir $dir" 1101a5b94eeSRob Bradford [ -x "$dir" ] && [ -w "$dir" ] || 111db6f894eSSamuel Ortiz { 112db6f894eSSamuel Ortiz say "Wrong permissions for $dir. Attempting to fix them ..." 113db6f894eSSamuel Ortiz chmod +x+w "$dir" 1141a5b94eeSRob Bradford } || 115db6f894eSSamuel Ortiz die "Error: wrong permissions for $dir. Should be +x+w" 116db6f894eSSamuel Ortiz done 117db6f894eSSamuel Ortiz} 118db6f894eSSamuel Ortiz 1192fc86ffeSSamuel Ortiz# Make sure we're using the latest dev container, by just pulling it. 1202fc86ffeSSamuel Ortizensure_latest_ctr() { 12155b8a218SRob Bradford if [ "$CTR_IMAGE_VERSION" = "local" ]; then 12255b8a218SRob Bradford build_container 12355b8a218SRob Bradford else 1242fc86ffeSSamuel Ortiz $DOCKER_RUNTIME pull "$CTR_IMAGE" 1252fc86ffeSSamuel Ortiz 12655b8a218SRob Bradford if [ $? -ne 0 ]; then 12755b8a218SRob Bradford build_container 12855b8a218SRob Bradford fi 12955b8a218SRob Bradford 13055b8a218SRob Bradford ok_or_die "Error pulling/building container image. Aborting." 13155b8a218SRob Bradford fi 1322fc86ffeSSamuel Ortiz} 1332fc86ffeSSamuel Ortiz 134296ada94SSamuel Ortiz# Fix main directory permissions after a container ran as root. 1350a1d6e1cSSamuel Ortiz# Since the container ran as root, any files it creates will be owned by root. 136296ada94SSamuel Ortiz# This fixes that by recursively changing the ownership of /cloud-hypervisor to the 1370a1d6e1cSSamuel Ortiz# current user. 1380a1d6e1cSSamuel Ortiz# 139296ada94SSamuel Ortizfix_dir_perms() { 1400a1d6e1cSSamuel Ortiz # Yes, running Docker to get elevated privileges, just to chown some files 1410a1d6e1cSSamuel Ortiz # is a dirty hack. 1420a1d6e1cSSamuel Ortiz $DOCKER_RUNTIME run \ 1430a1d6e1cSSamuel Ortiz --workdir "$CTR_CLH_ROOT_DIR" \ 1440a1d6e1cSSamuel Ortiz --rm \ 1450a1d6e1cSSamuel Ortiz --volume /dev:/dev \ 146eade9d8bSRob Bradford --volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \ 1470a1d6e1cSSamuel Ortiz "$CTR_IMAGE" \ 148296ada94SSamuel Ortiz chown -R "$(id -u):$(id -g)" "$CTR_CLH_ROOT_DIR" 1490a1d6e1cSSamuel Ortiz 1502805e7b1SRob Bradford return "$1" 1510a1d6e1cSSamuel Ortiz} 1522e1866a5SMuminul Islam# Process exported volumes argument, separate the volumes and make docker compatible 1532e1866a5SMuminul Islam# Sample input: --volumes /a:/a#/b:/b 1542e1866a5SMuminul Islam# Sample output: --volume /a:/a --volume /b:/b 1552e1866a5SMuminul Islam# 1562e1866a5SMuminul Islamprocess_volumes_args() { 1572e1866a5SMuminul Islam if [ -z "$arg_vols" ]; then 1582e1866a5SMuminul Islam return 1592e1866a5SMuminul Islam fi 1602e1866a5SMuminul Islam exported_volumes="" 1612e1866a5SMuminul Islam arr_vols=(${arg_vols//#/ }) 1621a5b94eeSRob Bradford for var in "${arr_vols[@]}"; do 1632e1866a5SMuminul Islam parts=(${var//:/ }) 1642e1866a5SMuminul Islam if [[ ! -e "${parts[0]}" ]]; then 1652e1866a5SMuminul Islam echo "The volume ${parts[0]} does not exist." 1662e1866a5SMuminul Islam exit 1 1672e1866a5SMuminul Islam fi 1682e1866a5SMuminul Islam exported_volumes="$exported_volumes --volume $var" 1692e1866a5SMuminul Islam done 1702e1866a5SMuminul Islam} 1712e94a86bSRuslan Mstoi 172db6f894eSSamuel Ortizcmd_help() { 173db6f894eSSamuel Ortiz echo "" 1742805e7b1SRob Bradford echo "Cloud Hypervisor $(basename "$0")" 17506a9c3b8SOmer Faruk Bayram echo "Usage: $(basename "$0") [flags] <command> [<command args>]" 17606a9c3b8SOmer Faruk Bayram echo "" 17706a9c3b8SOmer Faruk Bayram echo "Available flags": 17806a9c3b8SOmer Faruk Bayram echo "" 17906a9c3b8SOmer Faruk Bayram echo " --local Set the container image version being used to \"local\"." 180db6f894eSSamuel Ortiz echo "" 181db6f894eSSamuel Ortiz echo "Available commands:" 182db6f894eSSamuel Ortiz echo "" 183ad9374bdSSamuel Ortiz echo " build [--debug|--release] [--libc musl|gnu] [-- [<cargo args>]]" 184db6f894eSSamuel Ortiz echo " Build the Cloud Hypervisor binaries." 185db6f894eSSamuel Ortiz echo " --debug Build the debug binaries. This is the default." 186db6f894eSSamuel Ortiz echo " --release Build the release binaries." 187ad9374bdSSamuel Ortiz echo " --libc Select the C library Cloud Hypervisor will be built against. Default is gnu" 1882e1866a5SMuminul Islam echo " --volumes Hash separated volumes to be exported. Example --volumes /mnt:/mnt#/myvol:/myvol" 18927b5f8d7SMuminul Islam echo " --hypervisor Underlying hypervisor. Options kvm, mshv" 190db6f894eSSamuel Ortiz echo "" 1916eb47bdbSRob Bradford echo " tests [<test type (see below)>] [--libc musl|gnu] [-- [<test scripts args>] [-- [<test binary args>]]] " 192db6f894eSSamuel Ortiz echo " Run the Cloud Hypervisor tests." 193db6f894eSSamuel Ortiz echo " --unit Run the unit tests." 194db6f894eSSamuel Ortiz echo " --integration Run the integration tests." 19556b0c855SSebastien Boeuf echo " --integration-sgx Run the SGX integration tests." 19604dc4968SSebastien Boeuf echo " --integration-vfio Run the VFIO integration tests." 197934f9925SRob Bradford echo " --integration-windows Run the Windows guest integration tests." 198a1a0bc85SBo Chen echo " --integration-live-migration Run the live-migration integration tests." 199ef1983eeSBo Chen echo " --integration-rate-limiter Run the rate-limiter integration tests." 200ad9374bdSSamuel Ortiz echo " --libc Select the C library Cloud Hypervisor will be built against. Default is gnu" 2011cf73c83SBo Chen echo " --metrics Generate performance metrics" 2022e1866a5SMuminul Islam echo " --volumes Hash separated volumes to be exported. Example --volumes /mnt:/mnt#/myvol:/myvol" 20327b5f8d7SMuminul Islam echo " --hypervisor Underlying hypervisor. Options kvm, mshv" 204db6f894eSSamuel Ortiz echo " --all Run all tests." 205db6f894eSSamuel Ortiz echo "" 206db6f894eSSamuel Ortiz echo " build-container [--type]" 207db6f894eSSamuel Ortiz echo " Build the Cloud Hypervisor container." 208db6f894eSSamuel Ortiz echo "" 209275cb5c9SSamuel Ortiz echo " clean [<cargo args>]]" 210275cb5c9SSamuel Ortiz echo " Remove the Cloud Hypervisor artifacts." 211275cb5c9SSamuel Ortiz echo "" 2125a6b8d63SSamuel Ortiz echo " shell" 2135a6b8d63SSamuel Ortiz echo " Run the development container into an interactive, privileged BASH shell." 214972e96eaSWei Liu echo " --volumes Hash separated volumes to be exported. Example --volumes /mnt:/mnt#/myvol:/myvol" 2155a6b8d63SSamuel Ortiz echo "" 216db6f894eSSamuel Ortiz echo " help" 217db6f894eSSamuel Ortiz echo " Display this help message." 218db6f894eSSamuel Ortiz echo "" 219db6f894eSSamuel Ortiz} 220db6f894eSSamuel Ortiz 221db6f894eSSamuel Ortizcmd_build() { 222db6f894eSSamuel Ortiz build="debug" 223ad9374bdSSamuel Ortiz libc="gnu" 22427b5f8d7SMuminul Islam hypervisor="kvm" 22527b5f8d7SMuminul Islam features_build="" 226b339aa6bSMuminul Islam exported_device="/dev/kvm" 227db6f894eSSamuel Ortiz while [ $# -gt 0 ]; do 228db6f894eSSamuel Ortiz case "$1" in 2291a5b94eeSRob Bradford "-h" | "--help") { 2301a5b94eeSRob Bradford cmd_help 2311a5b94eeSRob Bradford exit 1 2321a5b94eeSRob Bradford } ;; 233db6f894eSSamuel Ortiz "--debug") { build="debug"; } ;; 234db6f894eSSamuel Ortiz "--release") { build="release"; } ;; 23588ed8524SVincent Batts "--runtime") 23688ed8524SVincent Batts shift 23788ed8524SVincent Batts DOCKER_RUNTIME="$1" 23888ed8524SVincent Batts export DOCKER_RUNTIME 23988ed8524SVincent Batts ;; 240ad9374bdSSamuel Ortiz "--libc") 241ad9374bdSSamuel Ortiz shift 2421a5b94eeSRob Bradford [[ "$1" =~ ^(musl|gnu)$ ]] || 243ad9374bdSSamuel Ortiz die "Invalid libc: $1. Valid options are \"musl\" and \"gnu\"." 244ad9374bdSSamuel Ortiz libc="$1" 245ad9374bdSSamuel Ortiz ;; 2462e1866a5SMuminul Islam "--volumes") 2472e1866a5SMuminul Islam shift 2482e1866a5SMuminul Islam arg_vols="$1" 2492e1866a5SMuminul Islam ;; 25027b5f8d7SMuminul Islam "--hypervisor") 25127b5f8d7SMuminul Islam shift 25227b5f8d7SMuminul Islam hypervisor="$1" 25327b5f8d7SMuminul Islam ;; 2545343e09eSFabiano Fidêncio "--features") 2555343e09eSFabiano Fidêncio shift 2565343e09eSFabiano Fidêncio features_build="--features $1" 2575343e09eSFabiano Fidêncio ;; 2581a5b94eeSRob Bradford "--") { 2591a5b94eeSRob Bradford shift 2601a5b94eeSRob Bradford break 2611a5b94eeSRob Bradford } ;; 262db6f894eSSamuel Ortiz *) 263db6f894eSSamuel Ortiz die "Unknown build argument: $1. Please use --help for help." 264db6f894eSSamuel Ortiz ;; 265db6f894eSSamuel Ortiz esac 266db6f894eSSamuel Ortiz shift 267db6f894eSSamuel Ortiz done 268b8342ebeSRob Bradford 269b8342ebeSRob Bradford ensure_build_dir 270b8342ebeSRob Bradford ensure_latest_ctr 271b8342ebeSRob Bradford 2722e1866a5SMuminul Islam process_volumes_args 273ca4857b5SMuminul Islam if [[ ! ("$hypervisor" = "kvm" || "$hypervisor" = "mshv") ]]; then 274ca4857b5SMuminul Islam die "Hypervisor value must be kvm or mshv" 27527b5f8d7SMuminul Islam fi 276b339aa6bSMuminul Islam if [[ "$hypervisor" = "mshv" ]]; then 277b339aa6bSMuminul Islam exported_device="/dev/mshv" 278b339aa6bSMuminul Islam fi 279ad9374bdSSamuel Ortiz target="$(uname -m)-unknown-linux-${libc}" 280ad9374bdSSamuel Ortiz 281db6f894eSSamuel Ortiz cargo_args=("$@") 282db6f894eSSamuel Ortiz [ $build = "release" ] && cargo_args+=("--release") 283ad9374bdSSamuel Ortiz cargo_args+=(--target "$target") 2840090ec2dSMichael Zhao 2859d42f48fSWei Liu rustflags="$RUSTFLAGS" 286b0324f85SSebastien Boeuf target_cc="" 2872805e7b1SRob Bradford if [ "$(uname -m)" = "aarch64" ] && [ "$libc" = "musl" ]; then 288*24f384d2SRavi kumar Veeramally rustflags="$rustflags -C link-args=-Wl,-Bstatic -C link-args=-lc" 2890090ec2dSMichael Zhao fi 290db6f894eSSamuel Ortiz 291db6f894eSSamuel Ortiz $DOCKER_RUNTIME run \ 292c8fa8092SSamuel Ortiz --user "$(id -u):$(id -g)" \ 293db6f894eSSamuel Ortiz --workdir "$CTR_CLH_ROOT_DIR" \ 294db6f894eSSamuel Ortiz --rm \ 295b339aa6bSMuminul Islam --volume $exported_device \ 296eade9d8bSRob Bradford --volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \ 2970090ec2dSMichael Zhao --env RUSTFLAGS="$rustflags" \ 298b0324f85SSebastien Boeuf --env TARGET_CC="$target_cc" \ 299db6f894eSSamuel Ortiz "$CTR_IMAGE" \ 3007dc9259cSFabiano Fidêncio cargo build --all $features_build \ 301db6f894eSSamuel Ortiz --target-dir "$CTR_CLH_CARGO_TARGET" \ 302ad9374bdSSamuel Ortiz "${cargo_args[@]}" && say "Binaries placed under $CLH_CARGO_TARGET/$target/$build" 303db6f894eSSamuel Ortiz} 304db6f894eSSamuel Ortiz 305275cb5c9SSamuel Ortizcmd_clean() { 306275cb5c9SSamuel Ortiz cargo_args=("$@") 307275cb5c9SSamuel Ortiz 308b8342ebeSRob Bradford ensure_build_dir 309b8342ebeSRob Bradford ensure_latest_ctr 310b8342ebeSRob Bradford 311275cb5c9SSamuel Ortiz $DOCKER_RUNTIME run \ 312c8fa8092SSamuel Ortiz --user "$(id -u):$(id -g)" \ 313275cb5c9SSamuel Ortiz --workdir "$CTR_CLH_ROOT_DIR" \ 314275cb5c9SSamuel Ortiz --rm \ 315eade9d8bSRob Bradford --volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \ 316275cb5c9SSamuel Ortiz "$CTR_IMAGE" \ 317275cb5c9SSamuel Ortiz cargo clean \ 318275cb5c9SSamuel Ortiz --target-dir "$CTR_CLH_CARGO_TARGET" \ 319275cb5c9SSamuel Ortiz "${cargo_args[@]}" 320275cb5c9SSamuel Ortiz} 321275cb5c9SSamuel Ortiz 322db6f894eSSamuel Ortizcmd_tests() { 323db6f894eSSamuel Ortiz unit=false 324db6f894eSSamuel Ortiz integration=false 32556b0c855SSebastien Boeuf integration_sgx=false 32604dc4968SSebastien Boeuf integration_vfio=false 327934f9925SRob Bradford integration_windows=false 328a1a0bc85SBo Chen integration_live_migration=false 329ef1983eeSBo Chen integration_rate_limiter=false 3301cf73c83SBo Chen metrics=false 331ad9374bdSSamuel Ortiz libc="gnu" 3322e1866a5SMuminul Islam arg_vols="" 33327b5f8d7SMuminul Islam hypervisor="kvm" 334b339aa6bSMuminul Islam exported_device="/dev/kvm" 335db6f894eSSamuel Ortiz while [ $# -gt 0 ]; do 336db6f894eSSamuel Ortiz case "$1" in 3371a5b94eeSRob Bradford "-h" | "--help") { 3381a5b94eeSRob Bradford cmd_help 3391a5b94eeSRob Bradford exit 1 3401a5b94eeSRob Bradford } ;; 341db6f894eSSamuel Ortiz "--unit") { unit=true; } ;; 342db6f894eSSamuel Ortiz "--integration") { integration=true; } ;; 34356b0c855SSebastien Boeuf "--integration-sgx") { integration_sgx=true; } ;; 34404dc4968SSebastien Boeuf "--integration-vfio") { integration_vfio=true; } ;; 345934f9925SRob Bradford "--integration-windows") { integration_windows=true; } ;; 346a1a0bc85SBo Chen "--integration-live-migration") { integration_live_migration=true; } ;; 347ef1983eeSBo Chen "--integration-rate-limiter") { integration_rate_limiter=true; } ;; 3481cf73c83SBo Chen "--metrics") { metrics=true; } ;; 349ad9374bdSSamuel Ortiz "--libc") 350ad9374bdSSamuel Ortiz shift 3511a5b94eeSRob Bradford [[ "$1" =~ ^(musl|gnu)$ ]] || 352ad9374bdSSamuel Ortiz die "Invalid libc: $1. Valid options are \"musl\" and \"gnu\"." 353ad9374bdSSamuel Ortiz libc="$1" 354ad9374bdSSamuel Ortiz ;; 3552e1866a5SMuminul Islam "--volumes") 3562e1866a5SMuminul Islam shift 3572e1866a5SMuminul Islam arg_vols="$1" 3582e1866a5SMuminul Islam ;; 35927b5f8d7SMuminul Islam "--hypervisor") 36027b5f8d7SMuminul Islam shift 36127b5f8d7SMuminul Islam hypervisor="$1" 36227b5f8d7SMuminul Islam ;; 3631a5b94eeSRob Bradford "--all") { 3641a5b94eeSRob Bradford cargo=true 3651a5b94eeSRob Bradford unit=true 3661a5b94eeSRob Bradford integration=true 3671a5b94eeSRob Bradford } ;; 3681a5b94eeSRob Bradford "--") { 3691a5b94eeSRob Bradford shift 3701a5b94eeSRob Bradford break 3711a5b94eeSRob Bradford } ;; 372db6f894eSSamuel Ortiz *) 373db6f894eSSamuel Ortiz die "Unknown tests argument: $1. Please use --help for help." 374db6f894eSSamuel Ortiz ;; 375db6f894eSSamuel Ortiz esac 376db6f894eSSamuel Ortiz shift 377db6f894eSSamuel Ortiz done 378ca4857b5SMuminul Islam if [[ ! ("$hypervisor" = "kvm" || "$hypervisor" = "mshv") ]]; then 379ca4857b5SMuminul Islam die "Hypervisor value must be kvm or mshv" 38027b5f8d7SMuminul Islam fi 381ca4857b5SMuminul Islam 382b339aa6bSMuminul Islam if [[ "$hypervisor" = "mshv" ]]; then 383b339aa6bSMuminul Islam exported_device="/dev/mshv" 384b339aa6bSMuminul Islam fi 385ca4857b5SMuminul Islam 386e436b382SMuminul Islam if [ ! -e "${exported_device}" ] ; then 387e436b382SMuminul Islam die "${exported_device} does not exist on the system" 388e436b382SMuminul Islam fi 389e436b382SMuminul Islam 3904552d07aSBo Chen set -- '--hypervisor' "$hypervisor" "$@" 391d79594aaSMuminul Islam 392b8342ebeSRob Bradford ensure_build_dir 393b8342ebeSRob Bradford ensure_latest_ctr 394b8342ebeSRob Bradford 3952e1866a5SMuminul Islam process_volumes_args 396ad9374bdSSamuel Ortiz target="$(uname -m)-unknown-linux-${libc}" 397ad9374bdSSamuel Ortiz 3988ba5682eSWei Liu rustflags="$RUSTFLAGS" 3998ba5682eSWei Liu target_cc="" 4008ba5682eSWei Liu if [ "$(uname -m)" = "aarch64" ] && [ "$libc" = "musl" ]; then 401*24f384d2SRavi kumar Veeramally rustflags="$rustflags -C link-args=-Wl,-Bstatic -C link-args=-lc" 4028ba5682eSWei Liu fi 4038ba5682eSWei Liu 4049cdcbb51SMuminul Islam if [[ "$unit" = true ]]; then 405ad9374bdSSamuel Ortiz say "Running unit tests for $target..." 406db6f894eSSamuel Ortiz $DOCKER_RUNTIME run \ 407db6f894eSSamuel Ortiz --workdir "$CTR_CLH_ROOT_DIR" \ 408db6f894eSSamuel Ortiz --rm \ 409b339aa6bSMuminul Islam --device $exported_device \ 4107fabca35SSebastien Boeuf --device /dev/net/tun \ 4117fabca35SSebastien Boeuf --cap-add net_admin \ 412eade9d8bSRob Bradford --volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \ 413ad9374bdSSamuel Ortiz --env BUILD_TARGET="$target" \ 4148ba5682eSWei Liu --env RUSTFLAGS="$rustflags" \ 4158ba5682eSWei Liu --env TARGET_CC="$target_cc" \ 416db6f894eSSamuel Ortiz "$CTR_IMAGE" \ 417d79594aaSMuminul Islam ./scripts/run_unit_tests.sh "$@" || fix_dir_perms $? || exit $? 418db6f894eSSamuel Ortiz fi 419db6f894eSSamuel Ortiz 420db6f894eSSamuel Ortiz if [ "$integration" = true ]; then 421ad9374bdSSamuel Ortiz say "Running integration tests for $target..." 422db6f894eSSamuel Ortiz $DOCKER_RUNTIME run \ 423db6f894eSSamuel Ortiz --workdir "$CTR_CLH_ROOT_DIR" \ 424db6f894eSSamuel Ortiz --rm \ 425db6f894eSSamuel Ortiz --privileged \ 426f21cd31bSSamuel Ortiz --security-opt seccomp=unconfined \ 427f21cd31bSSamuel Ortiz --ipc=host \ 428cf1b5156SMichael Zhao --net="$CTR_CLH_NET" \ 429a5b053f8SSamuel Ortiz --mount type=tmpfs,destination=/tmp \ 430db6f894eSSamuel Ortiz --volume /dev:/dev \ 431eade9d8bSRob Bradford --volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \ 432db6f894eSSamuel Ortiz --volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \ 433f21cd31bSSamuel Ortiz --env USER="root" \ 434c7e51e51SWei Liu --env BUILD_TARGET="$target" \ 4358ba5682eSWei Liu --env RUSTFLAGS="$rustflags" \ 4368ba5682eSWei Liu --env TARGET_CC="$target_cc" \ 43799a25510SRob Bradford --env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \ 438db6f894eSSamuel Ortiz "$CTR_IMAGE" \ 439a7aecb5eSOmer Faruk Bayram dbus-run-session ./scripts/run_integration_tests_"$(uname -m)".sh "$@" || fix_dir_perms $? || exit $? 440db6f894eSSamuel Ortiz fi 4410a1d6e1cSSamuel Ortiz 44256b0c855SSebastien Boeuf if [ "$integration_sgx" = true ]; then 44357f81d03SWei Liu say "Running SGX integration tests for $target..." 44456b0c855SSebastien Boeuf $DOCKER_RUNTIME run \ 44556b0c855SSebastien Boeuf --workdir "$CTR_CLH_ROOT_DIR" \ 44656b0c855SSebastien Boeuf --rm \ 44756b0c855SSebastien Boeuf --privileged \ 44856b0c855SSebastien Boeuf --security-opt seccomp=unconfined \ 44956b0c855SSebastien Boeuf --ipc=host \ 45056b0c855SSebastien Boeuf --net="$CTR_CLH_NET" \ 45156b0c855SSebastien Boeuf --mount type=tmpfs,destination=/tmp \ 45256b0c855SSebastien Boeuf --volume /dev:/dev \ 453eade9d8bSRob Bradford --volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \ 45456b0c855SSebastien Boeuf --volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \ 45556b0c855SSebastien Boeuf --env USER="root" \ 456c7e51e51SWei Liu --env BUILD_TARGET="$target" \ 4578ba5682eSWei Liu --env RUSTFLAGS="$rustflags" \ 4588ba5682eSWei Liu --env TARGET_CC="$target_cc" \ 45999a25510SRob Bradford --env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \ 46056b0c855SSebastien Boeuf "$CTR_IMAGE" \ 461d79594aaSMuminul Islam ./scripts/run_integration_tests_sgx.sh "$@" || fix_dir_perms $? || exit $? 46256b0c855SSebastien Boeuf fi 46356b0c855SSebastien Boeuf 46404dc4968SSebastien Boeuf if [ "$integration_vfio" = true ]; then 46504dc4968SSebastien Boeuf say "Running VFIO integration tests for $target..." 46604dc4968SSebastien Boeuf $DOCKER_RUNTIME run \ 46704dc4968SSebastien Boeuf --workdir "$CTR_CLH_ROOT_DIR" \ 46804dc4968SSebastien Boeuf --rm \ 46904dc4968SSebastien Boeuf --privileged \ 47004dc4968SSebastien Boeuf --security-opt seccomp=unconfined \ 47104dc4968SSebastien Boeuf --ipc=host \ 47204dc4968SSebastien Boeuf --net="$CTR_CLH_NET" \ 47304dc4968SSebastien Boeuf --mount type=tmpfs,destination=/tmp \ 47404dc4968SSebastien Boeuf --volume /dev:/dev \ 475eade9d8bSRob Bradford --volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \ 47604dc4968SSebastien Boeuf --volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \ 47704dc4968SSebastien Boeuf --env USER="root" \ 478c7e51e51SWei Liu --env BUILD_TARGET="$target" \ 4798ba5682eSWei Liu --env RUSTFLAGS="$rustflags" \ 4808ba5682eSWei Liu --env TARGET_CC="$target_cc" \ 48199a25510SRob Bradford --env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \ 48204dc4968SSebastien Boeuf "$CTR_IMAGE" \ 48304dc4968SSebastien Boeuf ./scripts/run_integration_tests_vfio.sh "$@" || fix_dir_perms $? || exit $? 48404dc4968SSebastien Boeuf fi 48504dc4968SSebastien Boeuf 486934f9925SRob Bradford if [ "$integration_windows" = true ]; then 48757f81d03SWei Liu say "Running Windows integration tests for $target..." 488934f9925SRob Bradford $DOCKER_RUNTIME run \ 489934f9925SRob Bradford --workdir "$CTR_CLH_ROOT_DIR" \ 490934f9925SRob Bradford --rm \ 491934f9925SRob Bradford --privileged \ 492934f9925SRob Bradford --security-opt seccomp=unconfined \ 493934f9925SRob Bradford --ipc=host \ 494934f9925SRob Bradford --net="$CTR_CLH_NET" \ 495934f9925SRob Bradford --mount type=tmpfs,destination=/tmp \ 496934f9925SRob Bradford --volume /dev:/dev \ 497eade9d8bSRob Bradford --volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \ 498934f9925SRob Bradford --volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \ 499934f9925SRob Bradford --env USER="root" \ 500c7e51e51SWei Liu --env BUILD_TARGET="$target" \ 5018ba5682eSWei Liu --env RUSTFLAGS="$rustflags" \ 5028ba5682eSWei Liu --env TARGET_CC="$target_cc" \ 50399a25510SRob Bradford --env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \ 504934f9925SRob Bradford "$CTR_IMAGE" \ 505944d0920SAnatol Belski ./scripts/run_integration_tests_windows_"$(uname -m)".sh "$@" || fix_dir_perms $? || exit $? 506934f9925SRob Bradford fi 507a1a0bc85SBo Chen 508a1a0bc85SBo Chen if [ "$integration_live_migration" = true ]; then 509a1a0bc85SBo Chen say "Running 'live migration' integration tests for $target..." 510a1a0bc85SBo Chen $DOCKER_RUNTIME run \ 511a1a0bc85SBo Chen --workdir "$CTR_CLH_ROOT_DIR" \ 512a1a0bc85SBo Chen --rm \ 513a1a0bc85SBo Chen --privileged \ 514a1a0bc85SBo Chen --security-opt seccomp=unconfined \ 515a1a0bc85SBo Chen --ipc=host \ 516a1a0bc85SBo Chen --net="$CTR_CLH_NET" \ 517a1a0bc85SBo Chen --mount type=tmpfs,destination=/tmp \ 518a1a0bc85SBo Chen --volume /dev:/dev \ 519eade9d8bSRob Bradford --volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \ 520a1a0bc85SBo Chen --volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \ 521a1a0bc85SBo Chen --env USER="root" \ 522c7e51e51SWei Liu --env BUILD_TARGET="$target" \ 5238ba5682eSWei Liu --env RUSTFLAGS="$rustflags" \ 5248ba5682eSWei Liu --env TARGET_CC="$target_cc" \ 52599a25510SRob Bradford --env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \ 526a1a0bc85SBo Chen "$CTR_IMAGE" \ 527a1a0bc85SBo Chen ./scripts/run_integration_tests_live_migration.sh "$@" || fix_dir_perms $? || exit $? 528a1a0bc85SBo Chen fi 5291cf73c83SBo Chen 530ef1983eeSBo Chen if [ "$integration_rate_limiter" = true ]; then 531ef1983eeSBo Chen say "Running 'rate limiter' integration tests for $target..." 532ef1983eeSBo Chen $DOCKER_RUNTIME run \ 533ef1983eeSBo Chen --workdir "$CTR_CLH_ROOT_DIR" \ 534ef1983eeSBo Chen --rm \ 535ef1983eeSBo Chen --privileged \ 536ef1983eeSBo Chen --security-opt seccomp=unconfined \ 537ef1983eeSBo Chen --ipc=host \ 538ef1983eeSBo Chen --net="$CTR_CLH_NET" \ 539ef1983eeSBo Chen --mount type=tmpfs,destination=/tmp \ 540ef1983eeSBo Chen --volume /dev:/dev \ 541ef1983eeSBo Chen --volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \ 542ef1983eeSBo Chen --volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \ 543ef1983eeSBo Chen --env USER="root" \ 544c7e51e51SWei Liu --env BUILD_TARGET="$target" \ 5458ba5682eSWei Liu --env RUSTFLAGS="$rustflags" \ 5468ba5682eSWei Liu --env TARGET_CC="$target_cc" \ 54799a25510SRob Bradford --env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \ 548ef1983eeSBo Chen "$CTR_IMAGE" \ 549ef1983eeSBo Chen ./scripts/run_integration_tests_rate_limiter.sh "$@" || fix_dir_perms $? || exit $? 550ef1983eeSBo Chen fi 551ef1983eeSBo Chen 5521cf73c83SBo Chen if [ "$metrics" = true ]; then 5531cf73c83SBo Chen say "Generating performance metrics for $target..." 5541cf73c83SBo Chen $DOCKER_RUNTIME run \ 5551cf73c83SBo Chen --workdir "$CTR_CLH_ROOT_DIR" \ 5561cf73c83SBo Chen --rm \ 5571cf73c83SBo Chen --privileged \ 5581cf73c83SBo Chen --security-opt seccomp=unconfined \ 5591cf73c83SBo Chen --ipc=host \ 5601cf73c83SBo Chen --net="$CTR_CLH_NET" \ 5611cf73c83SBo Chen --mount type=tmpfs,destination=/tmp \ 5621cf73c83SBo Chen --volume /dev:/dev \ 563eade9d8bSRob Bradford --volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \ 5641cf73c83SBo Chen --volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \ 5651cf73c83SBo Chen --env USER="root" \ 566c7e51e51SWei Liu --env BUILD_TARGET="$target" \ 5678ba5682eSWei Liu --env RUSTFLAGS="$rustflags" \ 5688ba5682eSWei Liu --env TARGET_CC="$target_cc" \ 569b56da6eeSsmit-gardhariya --env RUST_BACKTRACE="${RUST_BACKTRACE}" \ 57099a25510SRob Bradford --env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \ 5711cf73c83SBo Chen "$CTR_IMAGE" \ 5721cf73c83SBo Chen ./scripts/run_metrics.sh "$@" || fix_dir_perms $? || exit $? 5731cf73c83SBo Chen fi 5741cf73c83SBo Chen 575296ada94SSamuel Ortiz fix_dir_perms $? 576db6f894eSSamuel Ortiz} 577db6f894eSSamuel Ortiz 57855b8a218SRob Bradfordbuild_container() { 579b8342ebeSRob Bradford ensure_build_dir 580b8342ebeSRob Bradford 581db6f894eSSamuel Ortiz BUILD_DIR=/tmp/cloud-hypervisor/container/ 582db6f894eSSamuel Ortiz 583db6f894eSSamuel Ortiz mkdir -p $BUILD_DIR 5842805e7b1SRob Bradford cp "$CLH_DOCKERFILE" $BUILD_DIR 585db6f894eSSamuel Ortiz 5862805e7b1SRob Bradford [ "$(uname -m)" = "aarch64" ] && TARGETARCH="arm64" 5872805e7b1SRob Bradford [ "$(uname -m)" = "x86_64" ] && TARGETARCH="amd64" 5888bf0bac5SHenry Wang 589db6f894eSSamuel Ortiz $DOCKER_RUNTIME build \ 59055b8a218SRob Bradford --target dev \ 591db6f894eSSamuel Ortiz -t $CTR_IMAGE \ 592db6f894eSSamuel Ortiz -f $BUILD_DIR/Dockerfile \ 5938bf0bac5SHenry Wang --build-arg TARGETARCH=$TARGETARCH \ 594db6f894eSSamuel Ortiz $BUILD_DIR 595db6f894eSSamuel Ortiz} 596db6f894eSSamuel Ortiz 59755b8a218SRob Bradfordcmd_build-container() { 59855b8a218SRob Bradford while [ $# -gt 0 ]; do 59955b8a218SRob Bradford case "$1" in 60055b8a218SRob Bradford "-h" | "--help") { 60155b8a218SRob Bradford cmd_help 60255b8a218SRob Bradford exit 1 60355b8a218SRob Bradford } ;; 60455b8a218SRob Bradford "--") { 60555b8a218SRob Bradford shift 60655b8a218SRob Bradford break 60755b8a218SRob Bradford } ;; 60855b8a218SRob Bradford *) 60955b8a218SRob Bradford die "Unknown build-container argument: $1. Please use --help for help." 61055b8a218SRob Bradford ;; 61155b8a218SRob Bradford esac 61255b8a218SRob Bradford shift 61355b8a218SRob Bradford done 61455b8a218SRob Bradford 61555b8a218SRob Bradford build_container 61655b8a218SRob Bradford} 61755b8a218SRob Bradford 6185a6b8d63SSamuel Ortizcmd_shell() { 619972e96eaSWei Liu while [ $# -gt 0 ]; do 620972e96eaSWei Liu case "$1" in 6211a5b94eeSRob Bradford "-h" | "--help") { 6221a5b94eeSRob Bradford cmd_help 6231a5b94eeSRob Bradford exit 1 6241a5b94eeSRob Bradford } ;; 625972e96eaSWei Liu "--volumes") 626972e96eaSWei Liu shift 627972e96eaSWei Liu arg_vols="$1" 628972e96eaSWei Liu ;; 6291a5b94eeSRob Bradford "--") { 6301a5b94eeSRob Bradford shift 6311a5b94eeSRob Bradford break 6321a5b94eeSRob Bradford } ;; 6331a5b94eeSRob Bradford *) ;; 6341a5b94eeSRob Bradford 635972e96eaSWei Liu esac 636972e96eaSWei Liu shift 637972e96eaSWei Liu done 638b8342ebeSRob Bradford ensure_build_dir 639b8342ebeSRob Bradford ensure_latest_ctr 640972e96eaSWei Liu process_volumes_args 6415a6b8d63SSamuel Ortiz say_warn "Starting a privileged shell prompt as root ..." 6425a6b8d63SSamuel Ortiz say_warn "WARNING: Your $CLH_ROOT_DIR folder will be bind-mounted in the container under $CTR_CLH_ROOT_DIR" 6435a6b8d63SSamuel Ortiz $DOCKER_RUNTIME run \ 6445a6b8d63SSamuel Ortiz -ti \ 6455a6b8d63SSamuel Ortiz --workdir "$CTR_CLH_ROOT_DIR" \ 6465a6b8d63SSamuel Ortiz --rm \ 6475a6b8d63SSamuel Ortiz --privileged \ 6485a6b8d63SSamuel Ortiz --security-opt seccomp=unconfined \ 6495a6b8d63SSamuel Ortiz --ipc=host \ 650cf1b5156SMichael Zhao --net="$CTR_CLH_NET" \ 6515a6b8d63SSamuel Ortiz --tmpfs /tmp:exec \ 6525a6b8d63SSamuel Ortiz --volume /dev:/dev \ 653eade9d8bSRob Bradford --volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \ 6545a6b8d63SSamuel Ortiz --volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \ 6555a6b8d63SSamuel Ortiz --env USER="root" \ 6565a6b8d63SSamuel Ortiz --entrypoint bash \ 6575a6b8d63SSamuel Ortiz "$CTR_IMAGE" 6585a6b8d63SSamuel Ortiz 6595a6b8d63SSamuel Ortiz fix_dir_perms $? 6605a6b8d63SSamuel Ortiz} 6615a6b8d63SSamuel Ortiz 6622e94a86bSRuslan Mstoiif [ $# = 0 ]; then 6632e94a86bSRuslan Mstoi cmd_help 6642e94a86bSRuslan Mstoi say_err "Please specify command to run!" 6652e94a86bSRuslan Mstoi exit 1 6662e94a86bSRuslan Mstoifi 6672e94a86bSRuslan Mstoi 668db6f894eSSamuel Ortiz# Parse main command line args. 669db6f894eSSamuel Ortiz# 670db6f894eSSamuel Ortizwhile [ $# -gt 0 ]; do 671db6f894eSSamuel Ortiz case "$1" in 6721a5b94eeSRob Bradford -h | --help) { 6731a5b94eeSRob Bradford cmd_help 6741a5b94eeSRob Bradford exit 1 6751a5b94eeSRob Bradford } ;; 67655b8a218SRob Bradford --local) { 67755b8a218SRob Bradford CTR_IMAGE_VERSION="local" 67855b8a218SRob Bradford CTR_IMAGE="${CTR_IMAGE_TAG}:${CTR_IMAGE_VERSION}" 67955b8a218SRob Bradford } ;; 680db6f894eSSamuel Ortiz -*) 681db6f894eSSamuel Ortiz die "Unknown arg: $1. Please use \`$0 help\` for help." 682db6f894eSSamuel Ortiz ;; 683db6f894eSSamuel Ortiz *) 684db6f894eSSamuel Ortiz break 685db6f894eSSamuel Ortiz ;; 686db6f894eSSamuel Ortiz esac 687db6f894eSSamuel Ortiz shift 688db6f894eSSamuel Ortizdone 689db6f894eSSamuel Ortiz 690db6f894eSSamuel Ortiz# $1 is now a command name. Check if it is a valid command and, if so, 691db6f894eSSamuel Ortiz# run it. 692db6f894eSSamuel Ortiz# 693db6f894eSSamuel Ortizdeclare -f "cmd_$1" >/dev/null 694db6f894eSSamuel Ortizok_or_die "Unknown command: $1. Please use \`$0 help\` for help." 695db6f894eSSamuel Ortiz 696db6f894eSSamuel Ortizcmd=cmd_$1 697db6f894eSSamuel Ortizshift 698db6f894eSSamuel Ortiz 699db6f894eSSamuel Ortiz$cmd "$@" 700