[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [OSSTEST PATCH 3/3] anointments: Introduce anointment scheme, and mg-anoint script
CC: Roger Pau Monne <roger.pau@xxxxxxxxxx> Signed-off-by: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx> --- README.planner | 4 + mg-anoint | 347 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 351 insertions(+) create mode 100755 mg-anoint diff --git a/README.planner b/README.planner index b3b41a9..255460b 100644 --- a/README.planner +++ b/README.planner @@ -133,6 +133,10 @@ Types of task mg-execute-flight). They are automatically created and destroyed - see above. + * `anoint' tasks. These are not really ongoing tasks; but they + represent something that can `own' a flight. Each anointment kind + is represented by an `anoint' task. + * `xdbref' tasks. These are used to own resources whose allocation authority has been transferred to a separate database, eg a test database. The refkey is an indication of the other database. diff --git a/mg-anoint b/mg-anoint new file mode 100755 index 0000000..4bb8ab0 --- /dev/null +++ b/mg-anoint @@ -0,0 +1,347 @@ +#!/usr/bin/perl -w +# +# usage: +# +# ./mg-anoint prepare [PARAM...] REFKEY DESCRIPTION +# REFKEY should be 'SCOPE DETAILS...' +# PARAMs are: +# --keep=<number to keep> default is 3 +# --blessings=<allowable-blessing>,... default is just "real" +# +# ./mg-anoint destroy REFKEY +# +# ./mg-anoint anoint [ANOINT-OPTION...] REFKEY FLIGHT JOB +# ANOINT-OPTIONs are: +# --allow-blessed=BLESSING,... default is from `prepare' +# --allow-job-status=STATUS,... default is only `pass' +# +# ./mg-anoint retrieve REFKEY +# => FLIGHT JOB +# if nothing anointed yet, prints nothing and exits 0 +# if anointment not prepared, fails +# +# ./mg-anoint list +# => human-readable output + +# This is part of "osstest", an automated testing framework for Xen. +# Copyright (C) 2009-2013,2017 Citrix Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Each flavour of anointment is represented by a row in tasks: +# +# type anoint +# refkey <scope> <details...> +# the flavour, eg freebsd build <bsdbranch> <arch> +# username NULL +# comment <for human consumption> +# live t +# refinfo keep=<number-to-keep> blessings=<blessing>,... +# +# Each anointment is represented by a row in resources: +# +# restype 'share-flight' +# resname <flight> +# owntaskid <the anointment flavour taskid> +# shareix <initially, the anointment flavour taskid> +# subtask <job> + + +use strict qw(vars refs); +use DBI; +unshift @INC, qw(.); +use Osstest; +use Osstest::TestSupport; +use Osstest::Executive; +use IO::Handle; + +csreadconfig(); + +our @o; +sub pr_o () { print $_, "\n" or die $! foreach @o; } + +our $anointments_qtxt = <<END; + anointments AS ( + SELECT f.flight flight, + f.started started, + r.shareix shareix, + r.subtask job + FROM resources r + JOIN flights f + ON r.restype = 'share-flight' + AND r.resname = text(f.flight) + AND r.owntaskid = ? + AND f.started IS NOT NULL + ) +END + +our $task_q; +our $mostrecent_q; + +sub prep_queries { + $task_q = $dbh_tests->prepare(<<END); + SELECT taskid, refinfo FROM tasks WHERE type='anoint' AND refkey=? +END + + $mostrecent_q = $dbh_tests->prepare(<<END); + WITH $anointments_qtxt + SELECT * FROM anointments + ORDER BY started DESC LIMIT 1 +END +} + +sub cmd_prepare { + my %params = (keep => 3, + blessings => 'real'); + while (@ARGV && $ARGV[0] =~ m/^-/) { + $_= shift @ARGV; + last if m/^\-\-?$/; + if (m/^--(keep)=(\d+)$/) { + $params{$1} = $2 + 0; + } elsif (m/^--(blessings)=([-+0-9a-z,]+)$/) { + $params{$1} = $2; + } else { + die "unknown option $_ ?"; + } + } + die "usage: mg-anoint prepare [OPTIONS] 'SCOPE DETAILS...' DESCRIPTION" + unless @ARGV==2 || $ARGV[0] =~ m/ /; + my ($refkey, $description) = @ARGV; + my $dq = $dbh_tests->prepare(<<END); + DELETE FROM tasks WHERE type='anoint' AND refkey=? +END + my $iq = $dbh_tests->prepare(<<END); + INSERT INTO tasks (type,live, refkey,comment,refinfo) + VALUES ('anoint','t', ?,?,?) +END + my $refinfo = join ' ', map { "$_=$params{$_}" } sort keys %params; + db_retry($dbh_tests, [], sub { + @o = (); + $dq->execute($refkey); + $iq->execute($refkey, $description, $refinfo); + }); + pr_o(); +} + +sub cmd_destroy { + die unless @ARGV==1; + die if $ARGV[0] =~ m/^-/; + my ($refkey) = @ARGV; + my $rdq = $dbh_tests->prepare(<<END); + DELETE FROM resources + WHERE restype='share-flight' + AND owntaskid = (SELECT taskid + FROM tasks + WHERE type='anoint' + AND refkey=?) +END + my $tdq = $dbh_tests->prepare(<<END); + DELETE FROM tasks WHERE type='anoint' AND refkey=? +END + db_retry($dbh_tests, [], sub { + @o = (); + $rdq->execute($refkey); + $tdq->execute($refkey); + }); + pr_o(); +} + +sub cmd_anoint { + my $allow_blessed = ''; + my $allow_jobstatus = ''; + while (@ARGV && $ARGV[0] =~ m/^-/) { + $_= shift @ARGV; + last if m/^\-\-?$/; + if (m/^--allow-blessed=/) { + $allow_blessed = $'; + } elsif (m/^--allow-job-status=/) { + $allow_jobstatus = $'; + } else { + die "unknown option $_ ?"; + } + } + die unless @ARGV==3; + my ($refkey, $flight, $job) = @ARGV; + + prep_queries(); + + my $newflight_q = $dbh_tests->prepare(<<END); + SELECT * FROM flights WHERE flight=? +END + my $newjob_q = $dbh_tests->prepare(<<END); + SELECT status FROM jobs WHERE flight=? AND job=? +END + + my $count_q = $dbh_tests->prepare(<<END); + WITH $anointments_qtxt + SELECT count(*) FROM anointments +END + my $todelete_q = $dbh_tests->prepare(<<END); + WITH $anointments_qtxt + SELECT * + FROM anointments + ORDER BY started ASC + LIMIT ? +END + my $delete_res_q = $dbh_tests->prepare(<<END); + DELETE FROM resources + WHERE restype = 'share-flight' + AND owntaskid = ? + AND resname = ? + AND shareix = ? +END + my $insert_q = $dbh_tests->prepare(<<END); + INSERT INTO resources + (restype, resname,owntaskid,shareix,subtask) + VALUES ('share-flight', ?,?,?,?) +END + + db_retry($dbh_tests, [], sub { + @o = (); + $task_q->execute($refkey); + + # find the task row (ie, the anointment kind) + my ($task, $refinfo) = $task_q->fetchrow_array(); + die "no such anointment kind \`$refkey' (no prepare?)\n" + unless defined $task; + my %params; + foreach (split /\s+/, $refinfo) { + die unless m/=/; + $params{$`} = $'; + } + my %blessings; + $blessings{$_}++ foreach + grep /./, + (split /,/, $params{blessings}), + (split /,/, $allow_blessed); + + my %jobstatus; + $jobstatus{pass}++; + $jobstatus{$_}++ foreach grep /./, split /,/, $allow_jobstatus; + + # check the to-be-anointed flight's blessing + $newflight_q->execute($flight); + my $frow = $newflight_q->fetchrow_hashref(); + die "flight $flight missing" unless $frow; + die "flight $flight not started" unless defined $frow->{started}; + + # check the job status + $newjob_q->execute($flight, $job); + my ($jstatus) = $newjob_q->fetchrow_array(); + die "job $flight.$job missing" unless defined $jstatus; + die "job $flight.$job status $jstatus" unless $jobstatus{$jstatus}; + + push @o, "flight $flight blessed $frow->{blessing}". + " started ".show_abs_time($frow->{started}); + + die "flight $flight blessing $frow->{blessing}". + " (not $params{blessings} / $allow_blessed)" + unless $blessings{ $frow->{blessing} }; + + # check to-be-annointed flight is most recent + $mostrecent_q->execute($task); + my $mostrecent = $mostrecent_q->fetchrow_hashref(); + die "flight $flight not newer than $mostrecent->{flight}" + unless $frow->{started} > ($mostrecent->{started} // 0); + + # expire old anointments + $count_q->execute($task); + my ($current) = $count_q->fetchrow_array(); + my $want_delete = ($current+1) - $params{keep}; + push @o, "anointment $refkey: currently $current anointed"; + if ($want_delete > 0) { + $todelete_q->execute($task, $want_delete); + while (my $d = $todelete_q->fetchrow_hashref()) { + push @o, " expiring $d->{flight}.$d->{job} [/$d->{shareix}]". + " started ".show_abs_time($d->{started}); + $delete_res_q->execute($task, $d->{flight}, $d->{shareix}); + } + } + + # at last! + $insert_q->execute($flight,$task,$task,$job); + push @o, "anointed $flight.$job"; + }); + pr_o(); +} + +sub cmd_retrieve { + die unless @ARGV==1; + die if $ARGV[0] =~ m/^-/; + my ($refkey) = @ARGV; + + prep_queries(); + + db_retry($dbh_tests, [], sub { + @o = (); + $task_q->execute($refkey); + my ($task) = $task_q->fetchrow_array(); + die "no such anointment kind \`$refkey'" unless defined $task; + + $mostrecent_q->execute($task); + my $row = $mostrecent_q->fetchrow_hashref(); + if ($row) { + push @o, "$row->{flight} $row->{job}"; + } else { + print STDERR "warning: nothing anointed $refkey\n"; + } + }); + pr_o(); +}; + +sub cmd_list { + die "no options to list" if @ARGV; + + my $tq = $dbh_tests->prepare(<<END); + SELECT * + FROM tasks + WHERE type = 'anoint' + ORDER BY refkey +END + my $rq = $dbh_tests->prepare(<<END); + SELECT * + FROM resources + WHERE owntaskid = ? +END + + db_retry($dbh_tests, [], sub { + @o = (); + db_readonly_report(); + $tq->execute(); + while (my $t = $tq->fetchrow_hashref()) { + push @o, sprintf "%s [%s] (%s)", + $t->{refkey}, $t->{refinfo}, $t->{comment}; + push @o, " ! NOT LIVE" unless $t->{live}; + push @o, " ! username=$t->{username}" if defined $t->{username}; + $rq->execute($t->{taskid}); + while (my $r = $rq->fetchrow_hashref()) { + if ($r->{restype} eq 'share-flight') { + push @o, " $r->{resname}.$r->{subtask}"; + } else { + push @o, " ! $r->{restype}/$r->{resname}/$r->{subtask}"; + } + } + } + }); + pr_o(); +} + +die 'need operation' unless @ARGV; +die 'no global options understood' if $ARGV[0] =~ m/^-/; + +my $subcmd= shift @ARGV; +$subcmd =~ s/-/_/g; +my $subcmdproc = ${*::}{"cmd_$subcmd"}; +die "unknown subcommand" unless $subcmdproc; +$subcmdproc->(); -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |