From b47476bd694d7af388e07938dea5f46ba074324a Mon Sep 17 00:00:00 2001 From: Ava Hahn Date: Tue, 21 Jan 2025 14:25:05 -0800 Subject: [PATCH] vm flag and wip vsh rework Signed-off-by: Ava Hahn --- README.md | 31 ++++++++- nginx.sh | 68 ++++++++++++-------- test.sh | 188 +++++++++++++++++++++++++++++++++--------------------- util.sh | 36 +++++++++++ virt.sh | 138 +++++++++++++-------------------------- 5 files changed, 266 insertions(+), 195 deletions(-) create mode 100644 util.sh diff --git a/README.md b/README.md index 20c495a..d5133bc 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,12 @@ This is a set of scripts that roughly does the following: ## Prerequisites - SECRET.sh must contain the following - - USERN= - - PASSP= +```sh +USERN= # username on your VMs +PASSP= # password for said user +VM_PARALLEL= # number of CPU cores a VM has +HOST_PARALLEL= # number of CPU cores to build with locally on the hypervisor +``` - sshpass, virsh, libvirt, etc - cloned repos of nginx, nginx-tests, and nginx-otel @@ -53,3 +57,26 @@ Invoke `test.sh` with some or all of the following flags: Logs are in logging directory shown. They are split out into files per VM per phase. User may set test_log_dir to provide their own logging directory. + +When running, you may view the combined status using a command like one of the following. +The logging dir will be specified in the first second of output from the test.sh script. +```sh +tail -f /on* +tail -f /sync* +tail -f /build_nginx* +tail -f /build_otel* +tail -f /test_nginx* +tail -f /test_otel* +tail -f /off* +``` + +Additionally, virt.sh and nginx.sh can be sourced in a shell profile so that their +functions can be used at terminal prompt. For example, sourcing virt.sh will provide +the `vsh` function which turns on a VM, opens an SSH connection to it, and then turns it off again. Functions such as `vms_avail`, `vms_on`, and `vms_off` may also be of use. + +In the future, routines will be added to nginx.sh that automate several local development and testing processes. + +# Contributions +Any contributions which make the procedures defined in these scripts portable across +shells and platforms is welcomed. Any additional feature add for any enclosed script +is also welcomed. diff --git a/nginx.sh b/nginx.sh index 2117332..110b171 100644 --- a/nginx.sh +++ b/nginx.sh @@ -1,23 +1,38 @@ #!/bin/bash -# gets executed ON REMOTE HOST -#function current_dir_is_nginx_repo() { -# local tok -# tok=$(basename -s .git `git config --get remote.origin.url` 2> /dev/null) -# if [[ "$tok" == "nginx" ]]; then -# ret="true" -# return 0 -# else -# ret="false" -# return 0 -# fi -#} +dirn=$(dirname "$0") +source $dirn/common.sh + +if [[ ! -f $dirn/SECRET.sh ]]; then + error "need to create SECRET.sh... see Readme" + exit 1 +fi + +source $dirn/SECRET.sh + +# function that helps set parallelism in builds +# needs to strictly return 3 on VMs and strictly +# return a lot more on the hypervisor host. + +function num_jobs() { + if [ ! $VM_PARALLEL ]; then + log "VM_PARALLEL not defined, defaulting to 3" + VM_PARALLEL=3 + fi + + if [ ! $HOST_PARALLEL ]; then + log "HOST_PARALLEL not defined, defaulting to 22" + HOST_PARALLEL=22 + fi + + which virsh >/dev/null && echo $HOST_PARALLEL || echo $VM_PARALLEL +} # The following functions are all run on a VM # Through an SSH connection. Make sure not to # use any external functions in them. -function build_nginx_remote() { +function build_nginx() { auto/configure \ --with-threads \ --with-http_ssl_module \ @@ -38,31 +53,30 @@ function build_nginx_remote() { --with-stream_realip_module \ --with-stream_ssl_preread_module \ --with-debug && \ - make -j3 - return $? + make -j$(num_jobs) } -function test_nginx_remote() { - TEST_NGINX_VERBOSE=1 TEST_NGINX_CATLOG=1 prove -vw -j 3 . - return $? +function test_nginx() { + TEST_NGINX_VERBOSE=1 \ + TEST_NGINX_CATLOG=1 \ + prove -vw -j$(num_jobs) . } -function clean_nginx_remote() { +function clean_nginx() { make clean - return $? } -function build_otel_remote() { - mkdir -p build && cd build && \ - cmake -DNGX_OTEL_NGINX_BUILD_DIR=../../nginx/objs .. && \ - make -j3 - return $? +function build_otel() { + mkdir -p build && \ + cd build && \ + cmake -DNGX_OTEL_NGINX_BUILD_DIR=../../nginx/objs .. && \ + make -j$(num_jobs) } -function test_otel_remote() { +function test_otel() { echo "UNIMPLEMENTED!" } -function clean_otel_remote() { +function clean_otel() { rm -rf build } diff --git a/test.sh b/test.sh index 3ef8744..b3ed7f7 100755 --- a/test.sh +++ b/test.sh @@ -5,17 +5,26 @@ source $dirn/common.sh source $dirn/virt.sh source $dirn/nginx.sh +if [[ ! $(vms_avail) ]]; then + log "no VMs available!" + exit 1 +fi + nginx_dir="" otel_dir="" tests_dir="" +vm_list="" while [ $# -gt 0 ]; do case $1 in -h | --help) log "test.sh: build and test code on many libvirt VMs at once" log " -h, --help: show this help text" - log " -n , --nginx : specify an nginx directory" - log " -o , --otel : specify an nginx-otel directory" - log " -t , --tests : specify an nginx-tests directory" + log " -n , --nginx : specify an nginx directory" + log " -o , --otel : specify an nginx-otel directory" + log " -t , --tests : specify an nginx-tests directory" + log " --vm : (optional) specify a VM to operate on" + log " may be specified multiple times, or none" + log " defaults to all available VMs" exit 0 ;; @@ -43,6 +52,17 @@ while [ $# -gt 0 ]; do tests_dir=$2 ;; + --vm) + [ $2 ] || ( \ + log "VM must be specified" && \ + exit 1 ) + [[ $vms_available == *"$2"* ]] || ( \ + log "VM not available" && \ + exit 1 ) + [ $vm_list ] && vm_list+="\n" + vm_list+=$2 + ;; + *) log "unknown argument: $1" exit 1 @@ -52,9 +72,13 @@ while [ $# -gt 0 ]; do shift done -vm_nginx_dir=$(basename $nginx_dir) -vm_otel_dir=$(basename $otel_dir) -vm_tests_dir=$(basename $tests_dir) +[ $nginx_dir ] && vm_nginx_dir=$(basename $nginx_dir) +[ $otel_dir ] && vm_otel_dir=$(basename $otel_dir) +[ $tests_dir ] && vm_tests_dir=$(basename $tests_dir) + +if [ ! $vm_list ]; then + vm_list=$(vms_avail) +fi section "script init..." if [[ ! -d $test_log_dir ]]; then @@ -70,76 +94,93 @@ log "nginx code dir: $nginx_dir" log "nginx test dir: $tests_dir" log "otel code dir: $otel_dir" -function syncs() { - sync_dir_to_vm $1 $nginx_dir - sync_dir_to_vm $1 $tests_dir - sync_dir_to_vm $1 $otel_dir +function sync_all_to_remote() { + # test inverse because function can only return false + # when a command fails + + ([[ ! $nginx_dir ]] || sync_dir_to_vm $1 $nginx_dir) && \ + ([[ ! $tests_dir ]] || sync_dir_to_vm $1 $tests_dir) && \ + ([[ ! $otel_dir ]] || sync_dir_to_vm $1 $otel_dir ) } -function build_nginx() { - vm_shell $1 \ - "echo 'BEGIN BUILD'; set -ex; \ - $(typeset -f build_nginx_remote); \ - cd $vm_nginx_dir; \ - build_nginx_remote;" - return $? +function build_nginx_remote() { + vm_cmd $1 \ + "set -ex; + $(typeset WHT) + $(typeset END) + $(typeset -f log) + $(typeset -f num_jobs) + $(typeset -f build_nginx) + cd $vm_nginx_dir; + build_nginx" } -function build_otel() { - vm_shell $1 \ - "echo 'BEGIN BUILD'; set -ex; \ - $(typeset -f build_otel_remote); \ - cd $vm_otel_dir; \ - build_otel_remote;" - return $? +function build_otel_remote() { + vm_cmd $1 \ + "set -ex; + $(typeset WHT) + $(typeset END) + $(typeset -f log) + $(typeset -f num_jobs) + $(typeset -f build_otel) + cd $vm_otel_dir; + build_otel" } -function test_nginx() { - vm_shell $1 \ - "echo 'BEGIN TESTS'; set -ex; \ - $(typeset -f test_nginx_remote); \ - cd $vm_tests_dir; \ - test_nginx_remote;" - return $? +function test_nginx_remote() { + vm_cmd $1 \ + "set -ex; + $(typeset WHT) + $(typeset END) + $(typeset -f log) + $(typeset -f num_jobs) + $(typeset -f test_nginx) + cd $vm_tests_dir; + test_nginx" } -function test_otel() { - vm_shell $1 \ - "echo 'BEGIN TESTS'; set -ex; \ - $(typeset -f test_otel_remote); \ - cd $vm_otel_dir; \ - test_otel_remote;" - return $? +function test_otel_remote() { + vm_cmd $1 \ + "set -ex; + $(typeset WHT) + $(typeset END) + $(typeset -f log) + $(typeset -f num_jobs) + $(typeset -f test_otel) + cd $vm_otel_dir; + test_otel" } -function clean_nginx() { - vm_shell $1 \ - "set -ex; \ - $(typeset -f clean_nginx_remote); \ - cd $vm_nginx_dir; \ - clean_nginx_remote;" - return $? +function clean_nginx_remote() { + vm_cmd $1 \ + "set -ex; + $(typeset -f clean_nginx) + cd $vm_nginx_dir; + clean_nginx" } -function clean_otel() { - vm_shell $1 \ - "set -ex; \ - $(typeset -f clean_otel_remote); \ - cd $vm_otel_dir; \ - clean_otel_remote;" - return $? +function clean_otel_remote() { + vm_cmd $1 \ + "set -ex; + $(typeset -f clean_otel) + cd $vm_otel_dir; + clean_otel" } function cleanup() { section "cleanup!" log "cleaning build directories" if ! parallel_invoke_and_wait \ - clean_nginx "$vm_list" "$test_log_dir/clean_nginx"; then + clean_nginx_remote \ + "$vm_list" \ + "$test_log_dir/clean_nginx_"; then error "Failed to clean NGINX build directory" fi if ! parallel_invoke_and_wait \ - clean_otel "$vm_list" "$test_log_dir/clean_otel"; then + clean_otel_remote \ + "$vm_list" \ + "$test_log_dir/clean_otel_"; then error "Failed to clean otel build directory" fi @@ -151,14 +192,6 @@ function cleanup() { } section "launching VMs" -vms_avail -if [[ "$ret" == "" ]]; then - log "no VMs available!" - exit 1 -fi -vm_list=$ret -ret="" - if ! parallel_invoke_and_wait \ turn_on_vm_and_wait \ "$vm_list" \ @@ -170,50 +203,61 @@ fi section "syncing code to VMs" if ! parallel_invoke_and_wait \ - syncs "$vm_list" "$test_log_dir/sync_"; then + sync_all_to_remote \ + "$vm_list" \ + "$test_log_dir/sync_"; then error "Failed to sync files to VMs" cleanup exit 1 fi -if [ $nginx_dir ]; then +if [ "$nginx_dir" ]; then section "building NGINX" if ! parallel_invoke_and_wait \ - build_nginx "$vm_list" "$test_log_dir/build_nginx_"; then + build_nginx_remote \ + "$vm_list" \ + "$test_log_dir/build_nginx_"; then error "NGINX build failures detected" cleanup exit 1 fi fi -if [ $otel_dir ]; then +if [ "$otel_dir" ]; then section "building NGINX Otel module" if ! parallel_invoke_and_wait \ - build_otel "$vm_list" "$test_log_dir/build_otel_"; then + build_otel_remote \ + "$vm_list" \ + "$test_log_dir/build_otel_"; then error "Otel build failures detected" cleanup exit 1 fi fi -if [ $tests_dir ]; then - if [ $nginx_dir ]; then +if [ "$tests_dir" ]; then + if [ "$nginx_dir" ]; then section "testing NGINX" if ! parallel_invoke_and_wait \ - test_nginx "$vm_list" "$test_log_dir/test_nginx_"; then + test_nginx_remote \ + "$vm_list" \ + "$test_log_dir/test_nginx_"; then error "NGINX test failures detected" cleanup exit 1 fi fi - if [ $otel_dir ]; then + if [ "$otel_dir" ]; then section "testing NGINX Otel module" if ! parallel_invoke_and_wait \ - test_otel "$vm_list" "$test_log_dir/test_otel_"; then + test_otel_remote \ + "$vm_list" \ + "$test_log_dir/test_otel_"; then error "Otel test failures detected" cleanup exit 1 + fi fi fi diff --git a/util.sh b/util.sh new file mode 100644 index 0000000..d3a8332 --- /dev/null +++ b/util.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +dirn=$(dirname "$0") +source $dirn/common.sh +source $dirn/virt.sh +source $dirn/nginx.sh + +# this file exists to provide logic that requires functionality from one or +# more modules in the rest of the code. It can be sourced directly. + +function vsh() { + if ! turn_on_vm_and_wait $1; then + exit 1 + fi + + sshpass -p $PASSP \ + ssh -o PreferredAuthentications=password \ + -o StrictHostKeyChecking=no \ + $USERN@$(get_vm_ip $1) \ + "cat > /tmp/u.sh <