diff options
author | Pavel Raiskup <praiskup@redhat.com> | 2014-10-22 08:54:05 +0200 |
---|---|---|
committer | Pavel Raiskup <praiskup@redhat.com> | 2014-10-22 08:54:05 +0200 |
commit | 2422a081a5be0d5ac5afb122361bc283da67341f (patch) | |
tree | cb255582060af6547dd9318c56ba0e8c761846a1 /controller | |
parent | 922089746e1029de9be986672fcdeb6bc82e18d7 (diff) | |
download | postgresql-setup-tests-2422a081a5be0d5ac5afb122361bc283da67341f.tar.gz postgresql-setup-tests-2422a081a5be0d5ac5afb122361bc283da67341f.tar.xz postgresql-setup-tests-2422a081a5be0d5ac5afb122361bc283da67341f.zip |
big reorg: prepare for generalization
Try to split into three separate components -> controller, tester,
and 'tasks' (postgresql-tasks in our case). The controller
component is the main part which is able to run the task remotely.
Tester is more-like library for 'tasks' component (should be
reusable on the raw git level).
* controller: Almost separated component.
* postgresql-tasks: Likewise.
* tester: Likewise.
Diffstat (limited to 'controller')
-rw-r--r-- | controller/ansible/dummy-wrapper.yml | 7 | ||||
-rw-r--r-- | controller/ansible/fedora.yml | 64 | ||||
-rw-r--r-- | controller/ansible/include/additional-packages.yml | 6 | ||||
-rw-r--r-- | controller/ansible/include/beakerlib.yml | 1 | ||||
-rw-r--r-- | controller/ansible/include/download-results.yml | 5 | ||||
-rw-r--r-- | controller/ansible/include/prepare-testenv.yml | 3 | ||||
-rwxr-xr-x | controller/ansible/run_include | 19 | ||||
-rwxr-xr-x | controller/ansible_helpers/wait-for-ssh | 11 | ||||
-rw-r--r-- | controller/config/.gitignore | 2 | ||||
-rw-r--r-- | controller/config/config.sh.template | 36 | ||||
-rw-r--r-- | controller/config/hosts.template | 2 | ||||
-rw-r--r-- | controller/config/os/EXAMPLE.sh | 20 | ||||
-rwxr-xr-x | controller/controller (renamed from controller) | 5 | ||||
-rwxr-xr-x | controller/get_machine | 85 | ||||
-rw-r--r-- | controller/parse_credsfile | 14 | ||||
-rw-r--r-- | controller/private/os/EXAMPLE.yml | 7 | ||||
-rwxr-xr-x | controller/result_stats | 74 | ||||
-rw-r--r-- | controller/result_templates/html.tmpl | 42 | ||||
-rwxr-xr-x | controller/run_remote | 101 |
19 files changed, 503 insertions, 1 deletions
diff --git a/controller/ansible/dummy-wrapper.yml b/controller/ansible/dummy-wrapper.yml new file mode 100644 index 0000000..524b0ea --- /dev/null +++ b/controller/ansible/dummy-wrapper.yml @@ -0,0 +1,7 @@ +- name: "dummy-wrapper" + hosts: "{{ target }}" + remote_user: root + gather_facts: False + + tasks: + - include: "{{ include_file }}" diff --git a/controller/ansible/fedora.yml b/controller/ansible/fedora.yml new file mode 100644 index 0000000..cc64eac --- /dev/null +++ b/controller/ansible/fedora.yml @@ -0,0 +1,64 @@ +- name: self-standing testsuite + remote_user: root + gather_facts: False + hosts: localhost + vars_files: + - "{{ opt_credsfile }}" + + tasks: + - name: generate builder name + local_action: shell echo `dd if=/dev/urandom bs=1k count=10 | md5sum ; echo DBTESTS` + register: vm_name + + - debug: msg="osusername={{ os_username }}" + + - name: spin it up + local_action: nova_compute auth_url={{os_auth_url}} + flavor_id={{os_flavor_id}} image_id="{{ os_image_id }}" key_name={{ os_keypair }} + login_password={{os_nova_password}} login_tenant_name="{{os_tenant_name}}" + login_username={{os_username}} security_groups={{os_security_group}} + wait=yes name="{{vm_name.stdout}}" wait_for=600 + register: nova + + - debug: msg="{{ nova.info.addresses }}" + + # This is ugly as hell... Hopefully nothing will be changing. + - local_action: command echo "{{ nova.info.addresses[os_network_dev][1].addr }}" + register: machine_ip + + - debug: msg="{{ machine_ip.stdout }}" + + - name: wait for the host to be hot + local_action: wait_for host={{ machine_ip.stdout }} port=22 delay=5 timeout=600 + + - local_action: shell ../ansible_helpers/wait-for-ssh "root@{{ machine_ip.stdout }}" + + - name: add it to the special group + local_action: add_host hostname={{ machine_ip.stdout }} + groupname=temp_group + +- hosts: temp_group + user: root + gather_facts: False + tasks: + - copy: src={{ opt_workdir }}/{{ opt_testsuite_name }}.tar.gz + dest=/root/{{ opt_testsuite_name }}.tar.gz + + - include: include/beakerlib.yml + + - include: include/prepare-testenv.yml + + - include: include/additional-packages.yml + when: dtf_rpm_files_list is defined + + - shell: cd /root && tar -xf {{ opt_testsuite_name }}.tar.gz + + - shell: cd /root/{{ opt_testsuite_name }}&& ./run &>/var/tmp/dtf-run.overview + register: test_result + ignore_errors: yes + + - include: include/download-results.yml + + - name: stop the vm + shell: echo "not implemented yet" + when: test_result.rc == 0 diff --git a/controller/ansible/include/additional-packages.yml b/controller/ansible/include/additional-packages.yml new file mode 100644 index 0000000..f821255 --- /dev/null +++ b/controller/ansible/include/additional-packages.yml @@ -0,0 +1,6 @@ +- local_action: shell cat "{{ dtf_rpm_files_list }}" | xargs -n 100 + register: additional_packages + +- debug: msg="{{ additional_packages.stdout }}" + +- shell: yum install -y {{ additional_packages.stdout }} diff --git a/controller/ansible/include/beakerlib.yml b/controller/ansible/include/beakerlib.yml new file mode 100644 index 0000000..0461f25 --- /dev/null +++ b/controller/ansible/include/beakerlib.yml @@ -0,0 +1 @@ +- yum: conf_file=https://beaker-project.org/yum/beaker-server-Fedora.repo state=present name=beakerlib diff --git a/controller/ansible/include/download-results.yml b/controller/ansible/include/download-results.yml new file mode 100644 index 0000000..4404e08 --- /dev/null +++ b/controller/ansible/include/download-results.yml @@ -0,0 +1,5 @@ +- shell: cp -f /var/tmp/dtf-run.overview /var/tmp/dtf/ + +- shell: cd /var/tmp ; tar -czf dtf.tar.gz dtf + +- fetch: src=/var/tmp/dtf.tar.gz dest="{{ opt_workdir }}/" flat=yes diff --git a/controller/ansible/include/prepare-testenv.yml b/controller/ansible/include/prepare-testenv.yml new file mode 100644 index 0000000..a63e51a --- /dev/null +++ b/controller/ansible/include/prepare-testenv.yml @@ -0,0 +1,3 @@ +- yum: state=present name=postgresql-server + +- yum: state=present name=postgresql-upgrade diff --git a/controller/ansible/run_include b/controller/ansible/run_include new file mode 100755 index 0000000..4e84c7d --- /dev/null +++ b/controller/ansible/run_include @@ -0,0 +1,19 @@ +#!/bin/bash + +export ANSIBLE_HOST_KEY_CHECKING=False + +workdir="$(dirname "${BASH_SOURCE[0]}")" +workdir=$(readlink -f "$workdir") + +export playbook=$(readlink -f "$1") + +( set -x + cd "$workdir" + + ansible-playbook -i "$workdir/../config/hosts" \ + --extra-vars "include_file=$playbook" \ + --extra-vars "script_name=dummy" \ + --extra-vars "opt_workdir=/tmp/dtf-$(date +%H%M%S%N)" \ + --extra-vars "target=host" \ + "dummy-wrapper.yml" +) diff --git a/controller/ansible_helpers/wait-for-ssh b/controller/ansible_helpers/wait-for-ssh new file mode 100755 index 0000000..eb3880a --- /dev/null +++ b/controller/ansible_helpers/wait-for-ssh @@ -0,0 +1,11 @@ +#!/bin/bash -x + +where="$1" + +test -z "$where" && echo >&2 "no host specified" && exit 1 + +while [ 1 ]; do + ssh -o StrictHostKeyChecking=no -q $where exit &>/dev/null && exit 0 +done + +exit 1 diff --git a/controller/config/.gitignore b/controller/config/.gitignore new file mode 100644 index 0000000..57c4fcb --- /dev/null +++ b/controller/config/.gitignore @@ -0,0 +1,2 @@ +*.sh +hosts diff --git a/controller/config/config.sh.template b/controller/config/config.sh.template new file mode 100644 index 0000000..94cbe22 --- /dev/null +++ b/controller/config/config.sh.template @@ -0,0 +1,36 @@ +# OpenStack ID +# ------------ +# +# By default, based on DTF_OPENSTACK_ID content the corresponding OpenStack +# configuration is used. You may have multiple OpenStack instances configured - +# this option selects one. Based on the OpenStack ID (say 'EXAMPLE'), those +# configuration-like files are used: +# +# * private/os/'EXAMPLE'.yml +# File having OpenStack credentials in ansible variable file (YAML file +# with "key: value" lines). See the ./private/os/EXAMPLE.yml for +# variables you should set up. Keep this file secret. +# +# * config/os/'EXAMPLE'.sh +# This file must contain configuration for specific OpenStack instance. +# Usually information about available images, flavors, networking, etc. +# The template file config/os/EXAMPLE.sh may be used when configuring your +# testing environment. + +export DTF_OPENSTACK_ID=dropbear + +# Result Database +# --------------- +# Directory where the testsuite should keep its (persistent) results. Make sure +# that this directory is backed up. + +export DTF_DATABASE=/var/lib/dtf_results + +# Presenter place +# --------------- +# For now, only static results are available. DTF_PRESENTER_PLACE must contain +# rsync-compatible destination (it may be place accessible via ssh+rsync). It +# is expected that some httpd server is able to read the directory with results +# and publish them as static directory structure over http://. + +export DTF_PRESENTER_PLACE=user@example.org:/var/www/html/my_project/dtf diff --git a/controller/config/hosts.template b/controller/config/hosts.template new file mode 100644 index 0000000..6850700 --- /dev/null +++ b/controller/config/hosts.template @@ -0,0 +1,2 @@ +[host] +10.64.27.30 diff --git a/controller/config/os/EXAMPLE.sh b/controller/config/os/EXAMPLE.sh new file mode 100644 index 0000000..b5ba270 --- /dev/null +++ b/controller/config/os/EXAMPLE.sh @@ -0,0 +1,20 @@ +## THIS IS EXAMPLE OPENSTACK DTF CONFIGURATION ## + +# variable declarations, should be C&Ped +declare -A os_flavor_ids os_image_ids +export os_flavor_ids=[] +export os_image_ids=[] + +# connection info about particular OpenStack instance + +# which ssh keys should be uploaded to created VMs +export os_keypair="keypair-id" +# group of firewall rules to be set on VMs +export os_security_group=test_group +# the name of network connection as is presented by ansible +export os_network_dev=network_name + +# per-distribution dictionary with images/flavors +os_flavor_ids["fedora20"]="2" +os_image_ids["fedora20"]="0461eef2-5921-4c01-95a6-6edf96d41b89" + diff --git a/controller b/controller/controller index 7f628d6..e0cffe9 100755 --- a/controller +++ b/controller/controller @@ -7,7 +7,7 @@ # (still) local variables distro=fedora -distro_ver=20 +distro_ver=21 arch=x86_64 starttime=$(date -u +%Y%m%d_%H%M%S_%N) @@ -55,11 +55,14 @@ prereq_resultdir workdir=$(mktemp -d "/var/tmp/dtf_postgresql_setup-XXXXXX") +# cp /var/tmp/dtf_postgresql_setup-yK12r7/dtf.tar.gz "$workdir" ./run_remote \ --distro="$distro" \ --distro-version="$distro_ver" \ --workdir="$workdir" \ --openstack-instance="$DTF_OPENSTACK_ID" \ + "$(test -f additional_packages \ + && echo '--extra-rpms-file=additional_packages')" \ || die "can not perform run_remote" resultdir="$DTF_DATABASE/$distro/$distro_ver/$arch" diff --git a/controller/get_machine b/controller/get_machine new file mode 100755 index 0000000..7d4e619 --- /dev/null +++ b/controller/get_machine @@ -0,0 +1,85 @@ +#!/bin/bash + +die() { echo "$@" ; exit 1 ; } +info() { echo " * $@" ; } + +opt_openstack_instance=os1 +opt_distro=fedora +opt_distro_version=20 + +function show_help() +{ +cat <<EOHELP >&2 +Usage: $0 OPTION + +Script is aimed to help sysadmin. + +Options: + --distro=NAME Distro name, like fedora + --distro-version=VERSION E.g. 20 for Fedora 20 + --openstack-instance=ID +EOHELP +test -n "$1" && exit "$1" +} + +boot() +( + set -o pipefail + nova boot "$1" --poll \ + --image "$2" \ + --flavor "$3" \ + --security-groups "$os_security_group" \ + --key-name "$os_keypair" \ + | grep "| id " | cut -d\| -f 3 | xargs -n 1 +) + +get_ip() +( + id="$1" + set -o pipefail + nova show "$id" | grep ' network ' \ + | cut -d\| -f 3 | cut -d, -f2 | xargs -n 1 +) + + +longopts="distro:,distro-version:,openstack-instance:" +ARGS=$(getopt -o "" -l "help,$longopts" -n "$0" -- "$@") \ + || exit 1 +eval set -- "$ARGS" + +while true; do + case "$1" in + --distro|--distro-version|--openstack-instance) + opt=$(sed -e 's/^--//' -e 's/[^[a-zA-Z0-9]/_/g'<<<"$1") + eval "opt_$opt=\"${2,,}\"" + shift 2 + ;; + + --help) + show_help 0 + ;; + + --) + shift + break; + esac +done + +. ./parse_credsfile "$opt_openstack_instance" || exit 1 +. ./config/os/"$opt_openstack_instance.sh" || exit 1 + +image_version=$opt_distro$opt_distro_version +image=${os_image_ids[$image_version]} +flavor=${os_flavor_ids[$image_version]} + +test -z "$image" && die "no image for '$image_version'" +test -z "$flavor" && die "no flavor for '$image_version'" + +info "booting machine $image_version from $image" + +machine=$(boot "testing-$image" "$image" "$flavor") + +info "machine id: $machine" + +ip=$(get_ip "$machine") +info "ip: $ip" diff --git a/controller/parse_credsfile b/controller/parse_credsfile new file mode 100644 index 0000000..df2a6bf --- /dev/null +++ b/controller/parse_credsfile @@ -0,0 +1,14 @@ +credsfile="private/os/$1.yml" + +while read line; do + if [[ "$line" =~ ^([a-zA-Z0-9_]*):\ ?(.*)$ ]]; then + key="${BASH_REMATCH[1]}" + if test "$key" = os_nova_password; then + key=os_password + fi + eval set ${BASH_REMATCH[2]} + eval export "${key^^}"="\"$@\"" + fi +done < "$credsfile" + +# vi: syntax=sh diff --git a/controller/private/os/EXAMPLE.yml b/controller/private/os/EXAMPLE.yml new file mode 100644 index 0000000..d44cbac --- /dev/null +++ b/controller/private/os/EXAMPLE.yml @@ -0,0 +1,7 @@ +## THIS IS EXAMPLE OPENSTACK CREDENTIALS FILE ## +--- +os_auth_url: http://openstack-controller.example.com:5000/v2.0 +os_tenant_id: 8289c1553643c7adf3476fb6234562c0 +os_tenant_name: Example Develpoment Group +os_username: jdoe +os_nova_password: plainPasswordKeepSecrete diff --git a/controller/result_stats b/controller/result_stats new file mode 100755 index 0000000..a92d6d6 --- /dev/null +++ b/controller/result_stats @@ -0,0 +1,74 @@ +#!/bin/perl + +use strict; +use warnings; +use utf8; + +use Data::Dumper; +use File::Basename; +use Cwd; +use Encode 'encode_utf8'; + +# teplates +use Text::Xslate; + +# yaml (quick) parser +use YAML::Syck; + +our $srcdir = dirname(__FILE__); + +sub html_printer +{ + my $results = $_[0]; + my $task_ids = $_[1]; + + my $xslate = Text::Xslate->new(path => ["$srcdir/result_templates"]); + + my $content = $xslate->render("html.tmpl", { + results => $results, + task_ids => $task_ids, + }); + print encode_utf8($content); +} + +my $workdir = $ARGV[0]; + +my $data = []; + +my $task_ids = {}; + +# go through *each* result directory +my $olddir = getcwd; +for (`find "$workdir" -maxdepth 1 -type d -name 'result_*'`) { + chomp; + chdir $_; + + my $run_results = {}; + $run_results->{dirname} = basename($_); + $run_results->{tasks} = {}; + $run_results->{exit_status} = 0; + + # go through each task + for (`find -maxdepth 1 -type f -name '*.result'`) { + chomp; + + (my $task_id = $_) =~ s/\.result$//; + $task_id =~ s/.*\///; + $task_ids->{$task_id} = 1; + + my $yaml_file = $_; + open my $fd, '<', $yaml_file + or die "can't open yaml file '$yaml_file'"; + + my $config = YAML::Syck::LoadFile($fd); + if ($config->{exit_status} != 0) { + $run_results->{exit_status} = 1; + } + $run_results->{tasks}->{$task_id} = $config; + } + + push @{$data}, $run_results; +} +chdir $olddir; + +html_printer $data, $task_ids; diff --git a/controller/result_templates/html.tmpl b/controller/result_templates/html.tmpl new file mode 100644 index 0000000..8a09ad7 --- /dev/null +++ b/controller/result_templates/html.tmpl @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="UTF-8" /> +<meta name="keywords" content="" /> +<title>Results</title> +<link href="https://praiskup.fedorapeople.org/staticdata/patternfly-1.1/css/patternfly.css" rel="stylesheet" media="screen, print"> +</head> +<body> +<div class="table-responsive"> +<table class="table table-condensed table-hover"> +<thead> + <tr> + <th>Run time</th> +: for $task_ids.keys() -> $task_id { + <th><: $task_id :></th> +: } + </tr> +</thead><tbody> +: for $results -> $result { + : if ($result.exit_status) { + <tr class="danger"> + : } else { + <tr> + : } + <td><: $result.dirname :></td> + : for $task_ids.keys() -> $task_id { + : if (not defined($result.tasks[$task_id].exit_status)) { + <td>NOT AVAILABLE</td> + : } elsif ($result.tasks[$task_id].exit_status == 0) { + <td>OK</td> + : } else { + <td class="danger">FAIL</td> + : } + : } + <tr> +:} +</tbody> +</table> +</div> +</body> +</html> diff --git a/controller/run_remote b/controller/run_remote new file mode 100755 index 0000000..0f7ccc3 --- /dev/null +++ b/controller/run_remote @@ -0,0 +1,101 @@ +#!/bin/bash + +. config/config.sh || { + echo >&2 "sorry, but config/config.sh not found" + exit 1 +} + +longopts="verbose,help,force,testid:,listonly" + +run_playbook=${run_playbook-ansible/fedora.yml} + +opt_workdir=/var/tmp/dbt-results +opt_distro=fedora +opt_openstack_instance="$DTF_OPENSTACK_ID" +opt_distro_ver=20 +opt_extra_rpms= +opt_taskdir= + +die() { echo >&2 "$@" ; exit 1 ; } + +longopts="distro:,distro-version:,workdir:,openstack-instance:,extra-rpms-file:" +longopts+=",taskdir:" +ARGS=$(getopt -o "v" -l "$longopts" -n "getopt" -- "$@") \ + || exit 1 +eval set -- "$ARGS" + +while true; do + case "$1" in + --taskdir) + opt=$(sed -e 's/^--//' -e 's/[^[a-zA-Z0-9]/_/g'<<<"$1") + eval "opt_$opt=\"${2,,}\"" + shift 2 + ;; + + --distro) + opt_distro="$2" + shift 2 + ;; + + --distro-version) + opt_distro_ver="$2" + shift 2 + ;; + + --openstack-instance) + opt_openstack_instance="$2" + shift 2 + ;; + + --workdir) + # where the remote results are fetched into + opt_workdir="$2" + shift 2 + ;; + + --extra-rpms-file) + opt_extra_rpms="$(readlink -f "$2")" + shift 2 + ;; + + --) + shift + break + ;; + esac +done + +test -z "$opt_taskdir" && die "you must specify --taskdir" + +credsfile="$(readlink -f "./private/os/$opt_openstack_instance.yml")" +test -z "$credsfile" && die "--ansible-creds option must be specified" +test ! -f "$credsfile" && die "file $credsfile not found" + +config_os_file="$(readlink -f "./config/os/$opt_openstack_instance.sh")" +test ! -r "$config_os_file" && die "file $config_os_file not found" +. "$config_os_file" + +config_os_id="$opt_distro$opt_distro_ver" + +tarball() +( + testsuite_name="$(basename "$opt_taskdir")" + echo "$testsuite_name" + "$opt_taskdir/run" --dist | gzip > "$opt_workdir/$testsuite_name.tar.gz" +) + +testsuite_name="$(tarball)" || die "can not create dist tarball" + +export ANSIBLE_HOST_KEY_CHECKING=False +ansible-playbook "$run_playbook" \ + --extra-vars "opt_distro=$opt_distro" \ + --extra-vars "opt_distro_ver=$opt_distro_ver" \ + --extra-vars "opt_workdir=$opt_workdir" \ + --extra-vars "opt_credsfile=$credsfile" \ + --extra-vars "os_flavor_id=${os_flavor_ids[$config_os_id]}" \ + --extra-vars "os_image_id=${os_image_ids[$config_os_id]}" \ + --extra-vars "os_keypair=${os_keypair}" \ + --extra-vars "os_security_group=${os_security_group}" \ + --extra-vars "os_network_dev=${os_network_dev}" \ + --extra-vars "opt_testsuite_name=${testsuite_name}" \ + --extra-vars "${opt_extra_rpms:+dtf_rpm_files_list=$opt_extra_rpms}" |