From 2a05617d5f00c29f7004dcee99709930e6d2387a Mon Sep 17 00:00:00 2001 From: ale <ale@incal.net> Date: Tue, 30 Mar 2021 12:04:05 +0100 Subject: [PATCH] Switch to vmime for test VMs --- .gitlab-ci.yml | 10 +++-- scripts/floatup.py | 91 ++++++++++++++++++++++++++++++++++++++++++++++ test-driver | 20 ++++++++-- 3 files changed, 115 insertions(+), 6 deletions(-) create mode 100755 scripts/floatup.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d34eb70a..a6764a9a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -26,14 +26,16 @@ variables: ${APT_PROXY:+-e config.apt_proxy=${APT_PROXY}} $CREATE_ENV_VARS $BUILD_DIR - - bash -c 'sleep $(( $RANDOM % 5 ))' - - with-ssh-key ./test-driver init $BUILD_DIR + - with-ssh-key ./scripts/floatup.py ${LIBVIRT:+--ssh $LIBVIRT} --inventory $BUILD_DIR/hosts.yml --ram 3072 --image $VM_IMAGE up + - with-ssh-key ./test-driver init --no-vagrant $BUILD_DIR - with-ssh-key ./test-driver run $BUILD_DIR after_script: - - with-ssh-key ./test-driver cleanup $BUILD_DIR + - with-ssh-key ./scripts/floatup.py ${LIBVIRT:+--ssh $LIBVIRT} down + - with-ssh-key ./test-driver cleanup --no-vagrant $BUILD_DIR variables: CREATE_ENV_VARS: "" TEST_DIR: "" + VM_IMAGE: "buster" tags: [ai3] except: - schedules @@ -56,6 +58,7 @@ base_test: base_bullseye_test: <<: *base_test variables: + VM_IMAGE: "bullseye" CREATE_ENV_VARS: "-e config.float_debian_dist=bullseye -e inventory.group_vars.vagrant.ansible_python_interpreter=/usr/bin/python3" TEST_DIR: "test/base.ref" @@ -67,6 +70,7 @@ full_test: full_bullseye_test: <<: *base_test variables: + VM_IMAGE: "bullseye" CREATE_ENV_VARS: "-e config.float_debian_dist=bullseye -e inventory.group_vars.vagrant.ansible_python_interpreter=/usr/bin/python3" TEST_DIR: "test/full.ref" diff --git a/scripts/floatup.py b/scripts/floatup.py new file mode 100755 index 00000000..a9639036 --- /dev/null +++ b/scripts/floatup.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +# +# Read a hosts.yml float inventory, and manage a VM group derived by it. +# + +import argparse +import json +import os +import re +import shlex +import subprocess +import yaml + + +def parse_inventory(path, host_attrs): + with open(path) as fd: + inventory = yaml.safe_load(fd) + + hosts = [{'ip': v['ansible_host'], 'name': k} + for k, v in inventory['hosts'].items()] + for h in hosts: + h.update(host_attrs) + + # We know that the network is a /24. + net = re.sub(r'[0-9]+$', '.0/24', hosts[0]['ip']) + return { + 'network': net, + 'hosts': hosts, + } + + +def do_request(url, ssh_gw, payload): + data = json.dumps(payload) + cmd = "curl -s -X POST -H 'Content-Type: application/json' -d %s %s" % ( + shlex.quote(data), url) + if ssh_gw: + cmd = "ssh %s %s" % (ssh_gw, shlex.quote(cmd)) + return json.loads(subprocess.check_output(cmd, shell=True)) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + '--url', metavar='URL', default='http://127.0.0.1:4949', + help='URL of the vmine API server') + parser.add_argument( + '--ssh', metavar='USER@HOST', + help='proxy the vmine API request through SSH') + parser.add_argument( + '--state-file', metavar='FILE', default='.vmine_group', + help='state file to store the vmine group ID') + parser.add_argument( + '--inventory', metavar='FILE', default='hosts.yml', + help='float host inventory') + parser.add_argument( + '--image', metavar='NAME', + help='base image to use for the VMs') + parser.add_argument( + '--ram', type=int, + help='memory reservation for the VMs') + parser.add_argument( + '--ttl', metavar='DURATION', default='1h', + help='TTL for the virtual machines') + parser.add_argument( + 'cmd', + choices=['up', 'down']) + args = parser.parse_args() + + if args.cmd == 'up': + host_attrs = {} + if args.ram: + host_attrs['ram'] = args.ram + if args.image: + host_attrs['image'] = args.image + req = parse_inventory(args.inventory, host_attrs) + req['ttl'] = args.ttl + + resp = do_request(args.url + '/api/create-group', args.ssh, req) + with open(args.state_file) as fd: + fd.write(resp['group_id']) + + elif args.cmd == 'down': + with open(args.state_file) as fd: + group_id = fd.read().strip() + do_request(args.url + '/api/stop-group', args.ssh, + {'group_id': group_id}) + os.remove(args.state_file) + + +if __name__ == '__main__': + main() diff --git a/test-driver b/test-driver index afdd49c3..3d40130e 100755 --- a/test-driver +++ b/test-driver @@ -6,6 +6,7 @@ bin_dir=$(dirname "$0") bin_dir=${bin_dir:-.} bin_dir=$(cd "${bin_dir}" && pwd) float_dir="${bin_dir}" +use_vagrant=1 log() { echo " ***" >&2 @@ -57,8 +58,10 @@ save_logs() { } run_init() { - start_vagrant \ - || die "could not start VMs" + if [ $use_vagrant -eq 1 ]; then + start_vagrant \ + || die "could not start VMs" + fi wait_for_vms \ || die "could not reach the VMs with Ansible" @@ -73,7 +76,9 @@ run_init() { } run_cleanup() { - stop_vagrant + if [ $use_vagrant -eq 1 ]; then + stop_vagrant + fi } usage() { @@ -91,6 +96,11 @@ Commands: If DIR is specified, chdir there before running anything. +The 'init' and 'cleanup' commands understand a --no-vagrant option +(which must immediately follow the command) in which case Vagrant +will not be invoked at all, and the virtual machines will be expected +to be already up and running. + EOF exit 2 } @@ -98,6 +108,10 @@ EOF cmd="$1" shift +if [ "x$1" = "x--no-vagrant" ]; then + use_vagrant=0 ; shift +fi + if [ $# -gt 0 ]; then cd "$1" shift -- GitLab