]> xenbits.xensource.com Git - people/iwj/osstest.git/commitdiff
wip reorg rename JobDB, key management, etc.
authorIan Jackson <iwj@woking.cam.xci-test.com>
Tue, 16 Oct 2012 15:19:21 +0000 (16:19 +0100)
committerIan Jackson <iwj@woking.cam.xci-test.com>
Tue, 16 Oct 2012 15:19:21 +0000 (16:19 +0100)
17 files changed:
.gitignore
Osstest.pm
Osstest/DhcpWatch/leases.pm [new file with mode: 0644]
Osstest/JobDB/Executive.pm
Osstest/JobDB/Standalone.pm
Osstest/TestSupport.pm
README
config.pl
cri-common
cri-getconfig [new file with mode: 0644]
sg-run-job
standalone-reset
tcl/JobDB-Executive.tcl [new file with mode: 0644]
tcl/JobDB-Standalone.tcl [new file with mode: 0644]
tcl/JobDb-Executive.tcl [deleted file]
tcl/JobDb-Standalone.tcl [deleted file]
ts-hosts-allocate

index 0959ae178f922a74d8fe27ae1529ee96e089d98f..cfbad6fcf4e2c54949d496e1801df4022ad70c90 100644 (file)
@@ -24,3 +24,5 @@ data-tree-lock
 tree-bisect
 standalone.db
 logs
+id_rsa_osstest
+id_rsa_osstest.pub
index d1de7c854b665d9719fb4c03132e2c42faf5f38b..4b709d325164bdb569e912fc13b74467008eeab8 100644 (file)
@@ -17,11 +17,9 @@ BEGIN {
                       csreadconfig
                       getmethod
                       postfork
-
                       $dbh_tests db_retry db_begin_work                      
-get_filecontents ensuredir get_filecontents_core_quiet system_checked
+                      ensuredir get_filecontents_core_quiet system_checked
                       nonempty
-
                       );
     %EXPORT_TAGS = ( );
 
@@ -37,15 +35,15 @@ our $dbh_tests;
 
 our %c = qw(
 
-   JobDb Standalone
-   HostDb Static
+   JobDB Standalone
+   HostDB Static
 
    Stash logs
    Images images
    Logs logs
    Results results
 
-   HostProp_DhcpWatchMethod leases dhcp3 /var/lib/dhcp3/dhcpd.leases
+   TestHostKeypairPath id_rsa_osstest
 );
 
 #---------- general setup and config reading ----------
@@ -66,6 +64,12 @@ sub readglobalconfig () {
     return if $readglobalconfig_done;
     $readglobalconfig_done=1;
 
+    $c{HostProp_DhcpWatchMethod} = 'leases dhcp3 /var/lib/dhcp3/dhcpd.leases';
+    $c{AuthorizedKeysFiles} = '';
+    $c{AuthorizedKeysAppend} = '';
+
+    my $cfgvar_re = '[A-Z][0-9a-zA-Z-_]*';
+
     my $cfgfile = $ENV{'OSSTEST_CONFIG'} || "$ENV{'HOME'}/.osstest/config";
     if (!open C, '<', "$cfgfile") {
        die "$cfgfile $!" unless $!==&ENOENT;
@@ -76,9 +80,18 @@ sub readglobalconfig () {
            s/\s+$//;
            next if m/^\#/;
            next unless m/\S/;
-           if (m/^([A-Z][0-9a-zA-Z-_]*)\s+(\S.*)$/) {
+           if (m/^($cfgvar_re)\s+(\S.*)$/) {
                $c{$1} = $2;
-           } elsif (m/^([A-Z][0-9a-zA-Z-_]*)=(.*)$/) {
+           } elsif (m/^($cfgvar_re)=\s*\<\<\'(.*)\'\s*$/) {
+               my ($vn,$delim) = ($1,$2);
+               my $val = '';
+               $!=0; while (<C>) {
+                   last if $_ eq "$delim\n";
+                   $val .= $_;
+               }
+               die $! unless length $_;
+               $c{$vn} = $val;
+           } elsif (m/^($cfgvar_re)=(.*)$/) {
                eval "\$c{$1} = ( $2 ); 1;" or die $@;
            } else {
                die "bad syntax";
@@ -97,8 +110,8 @@ sub readglobalconfig () {
     # 2. <~/path> </path> <./path> are replaced with contents of specified file
     # 3. <[> and <]> are replaced with < and >
 
-    $mjobdb = getmethod("Osstest::JobDB::$c{JobDb}");
-    $mhostdb = getmethod("Osstest::HostDB::$c{HostDb}");
+    $mjobdb = getmethod("Osstest::JobDB::$c{JobDB}");
+    $mhostdb = getmethod("Osstest::HostDB::$c{HostDB}");
 
     $c{TestHostDomain} ||= $c{DnsDomain};
 }
@@ -159,7 +172,7 @@ sub db_retry ($$$;$$) {
     return $r;
 }
 
-sub postfork () {
+sub jobdb_postfork () {
     $mjobdb->postfork();
 }
 
@@ -186,18 +199,6 @@ sub get_filecontents_core_quiet ($) { # ENOENT => undef
     return $data;
 }
 
-sub get_filecontents ($;$) {
-    my ($path, $ifnoent) = @_;  # $ifnoent=undef => is error
-    my $data= get_filecontents_core_quiet($path);
-    if (!defined $data) {
-        die "$path does not exist" unless defined $ifnoent;
-        logm("read $path absent.");
-        return $ifnoent;
-    }
-    logm("read $path ok.");
-    return $data;
-}
-
 sub ensuredir ($) {
     my ($dir)= @_;
     mkdir($dir) or $!==&EEXIST or die "$dir $!";
diff --git a/Osstest/DhcpWatch/leases.pm b/Osstest/DhcpWatch/leases.pm
new file mode 100644 (file)
index 0000000..6f3822c
--- /dev/null
@@ -0,0 +1,155 @@
+
+package Osstest::DhcpWatch::leases;
+
+use strict;
+use warnings;
+
+use Osstest;
+use Osstest::TestSupport;
+
+BEGIN {
+    use Exporter ();
+    our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
+    $VERSION     = 1.00;
+    @ISA         = qw(Exporter);
+    @EXPORT      = qw();
+    %EXPORT_TAGS = ( );
+
+    @EXPORT_OK   = qw();
+}
+
+sub new {
+    my ($class, $ho, $meth, $format, $source) = @_;
+    die "$format (@_) ?" unless $format eq 'dhcp3';
+    return bless {
+       Format => $format,
+       Source => $source,
+    }, $class;
+}
+
+sub check_ip ($$) {
+    my ($mo, $gho) = @_;
+
+    my $leases;
+    my $leasesfn = $mo->{Source};
+
+    if ($leasesfn =~ m,/,) {
+       $leases= new IO::File $leasesfn, 'r';
+       if (!defined $leases) { return "open $leasesfn: $!"; }
+    } else {
+       $leases= new IO::Socket::INET(PeerAddr => $leasesfn);
+    }
+
+    my $lstash= "dhcpleases-$gho->{Guest}";
+    my $inlease;
+    my $props;
+    my $best;
+    my @warns;
+
+    my $copy= new IO::File "$stash/$lstash.new", 'w';
+    $copy or die "$lstash.new $!";
+
+    my $saveas= sub {
+        my ($fn,$keep) = @_;
+
+        while (<$leases>) { print $copy $_ or die $!; }
+        die $! unless $leases->eof;
+
+        my $rename= sub {
+            my ($src,$dst) = @_;
+            rename "$stash/$src", "$stash/$dst"
+                or $!==&ENOENT
+                or die "rename $fn.$keep $!";
+        };
+        while (--$keep>0) {
+            $rename->("$fn.$keep", "$fn.".($keep+1));
+        }
+        if ($keep>=0) {
+            die if $keep;
+            $rename->("$fn", "$fn.$keep");
+        }
+        $copy->close();
+        rename "$stash/$lstash.new", "$stash/$fn" or die "$lstash.new $fn $!";
+        logm("warning: $_") foreach grep { defined } @warns[0..5];
+        logm("$fn: rotated and stashed current leases");
+    };
+
+    my $badleases= sub {
+        my ($m) = @_;
+        $m= "$leasesfn:$.: unknown syntax";
+        $saveas->("$lstash.bad", 7);
+        return $m;
+    };
+
+    while (<$leases>) {
+        print $copy $_ or die $!;
+
+        chomp; s/^\s+//; s/\s+$//;
+        next if m/^\#/;  next unless m/\S/;
+        if (m/^lease\s+([0-9.]+)\s+\{$/) {
+            return $badleases->("lease inside lease") if defined $inlease;
+            $inlease= $1;
+            $props= { };
+            next;
+        }
+        if (!m/^\}$/) {
+            s/^( hardware \s+ ethernet |
+                 binding \s+ state
+               ) \s+//x
+               or
+            s/^( [-a-z0-9]+
+               ) \s+//x
+               or
+              return $badleases->("unknown syntax");
+            my $prop= $1;
+            s/\s*\;$// or return $badleases->("missing semicolon");
+            $props->{$prop}= $_;
+            next;
+        }
+        return $badleases->("end lease not inside lease")
+            unless defined $inlease;
+
+        $props->{' addr'}= $inlease;
+        undef $inlease;
+
+        # got a lease in $props
+
+        # ignore old leases
+        next if exists $props->{'binding state'} &&
+            lc $props->{'binding state'} ne 'active';
+
+        # ignore leases we don't understand
+        my @missing= grep { !defined $props->{$_} }
+            ('binding state', 'hardware ethernet', 'ends');
+        if (@missing) {
+            push @warns, "$leasesfn:$.: lease without \`$_'"
+                foreach @missing;
+            next;
+        }
+
+        # ignore leases for other hosts
+        next unless lc $props->{'hardware ethernet'} eq lc $gho->{Ether};
+
+        $props->{' ends'}= $props->{'ends'};
+        $props->{' ends'} =~
+            s/^[0-6]\s+(\S+)\s+(\d+)\:(\d+\:\d+)$/
+                sprintf "%s %02d:%s", $1,$2,$3 /e
+                or return $badleases->("unexpected syntax for ends");
+
+        next if $best &&
+            $best->{' ends'} gt $props->{' ends'};
+        $best= $props;
+    }
+
+    if (!$best) {
+        $saveas->("$lstash.nolease", 3);
+        return "no active lease";
+    }
+    $gho->{Ip}= $best->{' addr'};
+
+    report_once($gho, 'guest_check_ip', 
+               "guest $gho->{Name}: $gho->{Ether} $gho->{Ip}");
+    return undef;
+}
+
+1;
index 65623727126abae30225a7083c4f02679dba9852..79f51fd13f1ef8ae2e95e909107e2fe671b8dbab 100644 (file)
@@ -114,7 +114,7 @@ sub host_check_allocated ($$) { #method
     die if $ho->{SharedOthers} && !$ho->{SharedReady};
 }
 
-sub postfork ($) { #method
+sub jobdb_postfork ($) { #method
     my ($jd) = @_;
     $dbh_tests->{InactiveDestroy}= 1;  undef $dbh_tests;
 }
index 3a72668337beb54948872abe5a8c301136c4bb01..9dc5777d5d1fce1c717fc6605d6b5b5c705c6b39 100644 (file)
@@ -18,7 +18,7 @@ BEGIN {
 }
 
 augmentconfigdefaults(
-    JobDbStandaloneFilename => 'standalone.db',
+    JobDBStandaloneFilename => 'standalone.db',
 );
 
 sub new { return bless {}, $_[0]; };
@@ -27,7 +27,7 @@ sub begin_work { }
 sub dbfl_check { }
 
 sub open ($) {
-    my $dbi = "dbi:SQLite:dbname=$c{JobDbStandaloneFilename}";
+    my $dbi = "dbi:SQLite:dbname=$c{JobDBStandaloneFilename}";
     
     my $dbh= DBI->connect($dbi, '','', {
         AutoCommit => 1,
@@ -65,6 +65,6 @@ sub host_check_allocated ($$) { #method
     my ($jd, $ho) = @_;
 }
 
-sub postfork ($) { }
+sub jobdb_postfork ($) { }
 
 1;
index ab2937366df73269337296659672533fadd2e35d..3b575e300de38af48d9ba7a33874fb32ad84ec93 100644 (file)
@@ -21,7 +21,7 @@ BEGIN {
                       tsreadconfig %r $flight $job $stash
                       ts_get_host_guest
 
-                      fail broken logm $logm_handle
+                      fail broken logm $logm_handle get_filecontents
 
                       store_runvar get_runvar get_runvar_maybe
                       get_runvar_default need_runvars flight_otherjob
@@ -174,6 +174,18 @@ END
                          : "($flight.$job not marked $newst)");
 }
 
+sub get_filecontents ($;$) {
+    my ($path, $ifnoent) = @_;  # $ifnoent=undef => is error
+    my $data= get_filecontents_core_quiet($path);
+    if (!defined $data) {
+        die "$path does not exist" unless defined $ifnoent;
+        logm("read $path absent.");
+        return $ifnoent;
+    }
+    logm("read $path ok.");
+    return $data;
+}
+
 #---------- runvars ----------
 
 sub store_runvar ($$) {
@@ -601,9 +613,9 @@ sub dhcp_watch_host_setup ($) {
 }
 
 sub guest_check_ip ($) {
-    my ($ho) = @_;
+    my ($gho) = @_;
     guest_find_ether($gho);
-    $ho->{DhcpWatch}->guest_check_ip($ho);
+    $gho->{DhcpWatch}->check_ip($gho);
 }
 
 #---------- power cycling ----------
diff --git a/README b/README
index 5d400bee267a7a9adda1218a98f442f48076c3b7..5cf3d1f210f39239056c5c82992c2db45cf86236 100644 (file)
--- a/README
+++ b/README
@@ -18,7 +18,7 @@ or
 
 Config settings relevant only to standalone mode
 
-JobDbStandaloneFilename
+JobDBStandaloneFilename
    Database file to use to record the "jobs" and their run variables.
    Default: ./standalone.db (sqlite3)
 
@@ -37,6 +37,15 @@ HostProp_DhcpWatchMethod
       where <format> is dhcp3
             <source> is filename (with slash) or <host>:<port>
 
+AuthorizedKeysFiles
+     :-separated list of files to concatenate into authorized_keys
+AuthorizedKeysAppend
+     literal text to add
+The keys in ~/.ssh/id_{rsa,dsa}.pub and ~/.ssh/authorized_keys
+(if they exist) are copied anyway.
+
+TestHostKeypairPath
+
 ========================================
 
 General config settings
@@ -64,8 +73,8 @@ WebspaceLog
 
 Other config settings which might be interesting
 
-JobDb
-HostDb
+JobDB
+HostDB
    Class name tails for the job and host databases.
 
 ExecutiveDbnamePat
index 9c4381723a9b1de544c9a905f4e79626070b1fd3..bf71b88d5da1c725dc42e573679b9c4b99a2b22a 100644 (file)
--- a/config.pl
+++ b/config.pl
@@ -65,14 +65,4 @@ $c{Preseed}= <<END;
 d-i clock-setup/ntp-server string ntp.uk.xensource.com
 END
 
-$c{TestHostKeypairPath}= '/export/home/osstest/.ssh/id_rsa_osstest';
-
-$c{AuthorizedKeysFiles}= '';
-$c{AuthorizedKeysAppend}= <<'END';
-ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq8eHHFJ+XHYgpHxfSdciq0b3tYPdMhHf9CgtwdKGSqCyDyocbn1jX6P0Z535K/JcVaxvaRQbGDl9FZ25neQw6lysE8pGf+G353mgLAE7Lw6xKqlTXDcR0GpKHiZUyY8Ck5AJlGF2MO0cDEzMBx+xkOahDBvAozikUcDHJsTNP+UUIGoRaPeQK0DfgprPkoaLzXFDiZvEoBtYcUUieuNygJt+QVM+ovyTXC68wg5Xb5Ou2PopmDaVMX6/A1HxziTWc3XdhOF5ocuRF/kfWpZL223Auuu/xvNQDly13DhuVlQiU3gRIP7BSCwCdsQC/K68Q6SgfBklKRiqHquYo/QyNQ== osstest@woking.xci-test.com
-ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAs6FF9nfzWIlLPeYdqNteJBoYJAcgGxQgeNi7FHYDgWNFhoYPlMPXWOuXhgNxA2/vkX9tUMVZaAh+4WTL1iRBW5B/AS/Ek2O7uM2Uq8v68D2aU9/XalLVnIxssr84pewUmKW8hZfjNnRm99RTQ2Knr2BvtwcHqXtdGYdTYCJkel+FPYQ51yXGRU7dS0D59WapkDFU1tH1Y8s+dRZcRZNRJ5f1w/KO1zx1tOrZRkO3fPlEGNZHVUYfpZLPxz0VX8tOeoaOXhKZO8vSp1pD0L/uaD6FOmugMZxbtq9wEjhZciNCq61ynRf2yt2v9DMu4EAzbW/Ws7OBvWtYj/RHcSxKbw== iwj@woking.xci-test.com
-ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA2m8+FRm8zaCy4+L2ZLsINt3OiRzDu82JE67b4Xyt3O0+IEyflPgw5zgGH69ypOn2GqYTaiBoiYNoAn9bpUksMk71q+co4gsZJ17Acm0256A3NP46ByT6z6/AKTl58vwwNKSCEAzNru53sXTYw2TcCZUN8A4vXY76OeJNJmCmgBDHCNod9fW6+EOn8ZSU1YjFUBV2UmS2ekKmsGNP5ecLAF1bZ8I13KpKUIDIY+UiG0UMwTWDfQY59SNsz6bCxv9NsxSXL29RS2XHFeIQis7t6hJuyZTT4b9YzjEAxvk8kdGzzK6314kwILibm1O1Y8LLyrYsWK1AvnJQFIhcYXF0EQ== iwj@mariner
-ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEApAkFv1FwknjOoataWvq5SRN/eUHjfQ5gfWnGJpIa4qnT+zAqYuC10BAHu3pHPV6NiedMxud0KcYlu/giQBMVMnYBdb7gWKdK4AQTgxHgvMMWHufa8oTLONLRsvyp1wQADJBzjQSjmo6HHF9faUckZHfJTfRxqLuR/3ENIyl+CRV9G6KfN9fbABejBxdfsbuTHc5ew2JsYxhDJsDFHgMjtrUoHI/d6eBTQDx8GRj8uUor8W+riFpW3whTH9dqloOyrqIke2qGVQlMNmzx5Z04vB1+n95nu9c5SGOZTUT4BQ5FybEANWQsNfJ7b3aMcYgVCVkKuRHSbW8Q4Pyn1Nh31w== ian@liberator
-END
-
 1;
index 71d64f4b3bf4eeb7b96078eb632222cc53b58085..e685512276a212a6ae086feda51b7543709dcc0d 100644 (file)
@@ -1,15 +1,8 @@
 # -*- bash -*-
 
-umask 002
+. cri-getconfig
 
-getconfig () {
-        perl -e '
-                use Osstest;
-                readglobalconfig();
-die "'$1' caps err" if "'$1'" =~ m/A-Z/;
-                print $c{"'$1'"} or die $!;
-        '
-}
+umask 002
 
 repo_tree_rev_fetch_git () {
        local treename=$1
diff --git a/cri-getconfig b/cri-getconfig
new file mode 100644 (file)
index 0000000..3847f75
--- /dev/null
@@ -0,0 +1,10 @@
+# -*- bash -*-
+
+getconfig () {
+        perl -e '
+                use Osstest;
+                readglobalconfig();
+die "'$1' caps err" if "'$1'" =~ m/A-Z/;
+                print $c{"'$1'"} or die $!;
+        '
+}
index 234c84d5c44777fc0463bc4f3254f017e13a6337..a681002a93b690c964b6aab52fd476e1316a9acc 100755 (executable)
@@ -4,7 +4,7 @@
 
 source ./tcl/osstestlib.tcl
 readconfig
-source-method JobDb
+source-method JobDB
 
 proc run-job {job} {
     global jobinfo builds flight ok need_xen_hosts anyfailed
index a30ad5a601a4e67c87f94ac15330b04a1d8352fd..627c5a5a74889c783b47de70a3b9000702caedf0 100755 (executable)
@@ -10,6 +10,15 @@ END
 
 set -e
 
+. cri-getconfig
+
+#---------- making the database with a flight and some jobs ----------
+
+jobdb=`getconfig JobDB`
+if [ "$jobdb" != Standalone ]; then
+       echo >&2 "jobdb is $jobdb!"; exit 1
+fi
+
 branch=xen-unstable
 xenbranch=xen-unstable
 
@@ -54,3 +63,10 @@ fi
 
 OSSTEST_FLIGHT=$flight \
 ./make-flight "$branch" "$xenbranch" play $buildflight >/dev/null
+
+#---------- ensuring we have a suitable rsa key ----------
+
+keypair=`getconfig TestHostKeypairPath`
+if ! test -f "$keypair"; then
+       ssh-keygen -t rsa -b 1024 -N '' -f "$keypair"
+fi
diff --git a/tcl/JobDB-Executive.tcl b/tcl/JobDB-Executive.tcl
new file mode 100644 (file)
index 0000000..e9204bf
--- /dev/null
@@ -0,0 +1,247 @@
+# -*- Tcl -*-
+
+package require Pgtcl 1.5
+
+namespace eval jobdb {
+
+proc logputs {f m} {
+    global argv
+    set time [clock format [clock seconds] -gmt true \
+                  -format "%Y-%m-%d %H:%M:%S Z"]
+    puts $f "$time \[$argv] $m"
+}
+
+proc prepare {job} {
+    global jobinfo
+    db-open
+    set found 0
+    pg_execute -array jobinfo dbh "
+        SELECT job, status, recipe FROM jobs
+                       WHERE   flight = [pg_quote $flight]
+                       AND     job = [pg_quote $job]
+    " {
+       switch -exact -- $jobinfo(status) {
+           queued - preparing - retriable - play { incr found }
+           default {
+               error "job $flight.$job status $jobinfo(status)"
+           }
+       }
+    }
+    if {!$found} {
+       error "job $flight.$job not found"
+    }
+
+    setstatus preparing
+    db-close
+}
+
+proc job-set-status-unlocked {flight job st} {
+    db-open
+    pg_execute dbh "
+            UPDATE jobs SET status='$st'
+                WHERE flight=$flight AND job='$job'
+                  AND status<>'aborted' AND status<>'broken'
+    "
+    db-close
+}
+
+proc job-set-status {flight job st} {
+    transaction flights {
+        job-set-status-unlocked $flight $job $st
+    }
+}
+
+proc set-flight {} {
+    global flight argv env
+
+    if {[string equal [lindex $argv 0] --start-delay]} {
+        after [lindex $argv 1]
+        set argv [lrange $argv 2 end]
+    }
+
+    set flight [lindex $argv 0]
+    set argv [lrange $argv 1 end]
+    set env(OSSTEST_FLIGHT) $flight
+}
+
+
+proc db-open {} {
+    global g
+    variable dbusers 0
+
+    if {$dbusers > 0} { incr dbusers; return }
+
+    # PgDbName_* are odbc-style strings as accepted by Perl's DBD::Pg
+    # but Tcl pg_connect unaccountably uses a different format which
+    # is whitespace-separated.
+    regsub -all {;} $c(ExecutiveDbname_osstestdb) { } conninfo
+    pg_connect -conninfo $conninfo -connhandle dbh
+    incr dbusers
+}
+proc db-close {} {
+    variable dbusers
+    incr dbusers -1
+    if {$dbusers > 0} return
+    if {$dbusers} { error "$dbusers ?!" }
+    pg_disconnect dbh
+}
+
+proc db-update-1 {stmt} {
+    # must be in transaction
+    set nrows [pg_execute dbh $stmt]
+    if {$nrows != 1} { error "$nrows != 1 in < $stmt >" }
+}
+
+proc lock-tables {tables} {
+    # must be inside transaction
+    foreach tab $tables {
+        pg_execute dbh "
+               LOCK TABLE $tab IN ACCESS EXCLUSIVE MODE
+        "
+    }
+}
+
+proc spawn-step-begin {flight job ts stepnovar} {
+    upvar 1 $stepnovar stepno
+
+    db-open
+
+    pg_execute dbh BEGIN
+    pg_execute dbh "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE"
+    if {[catch {
+        lock-tables flights
+       pg_execute -array stepinfo dbh "
+            SELECT max(stepno) AS maxstep FROM steps
+                WHERE flight=[pg_quote $flight] AND job=[pg_quote $job]
+        "
+        set stepno $stepinfo(maxstep)
+       if {[string length $stepno]} {
+           incr stepno
+       } else {
+           set stepno 1
+       }
+       pg_execute dbh "
+            INSERT INTO steps
+                VALUES ([pg_quote $flight], [pg_quote $job], $stepno,
+                        [pg_quote $ts], 'running',
+                        'TBD')
+        "
+       pg_execute dbh COMMIT
+    } emsg]} {
+       global errorInfo errorCode
+       set ei $errorInfo
+       set ec $errorCode
+       catch { pg_execute dbh ROLLBACK }
+        db-close
+       error $emsg $ei $ec
+    }
+}
+
+proc spawn-step-commit {flight job stepno testid} {
+    transaction flights {
+        db-update-1 "
+            UPDATE steps
+                  SET testid=[pg_quote $testid],
+                      started=[clock seconds]
+                WHERE flight=[pg_quote $flight]
+                  AND job=[pg_quote $job]
+                  AND stepno=$stepno
+        "
+    }
+
+    db-close
+}
+
+proc step-set-status {flight job stepno st} {
+    transaction flights {
+        db-update-1 "
+            UPDATE steps
+               SET status='$st',
+                   finished=[clock seconds]
+             WHERE flight=$flight AND job='$job' AND stepno=$stepno
+        "
+        set pause 0
+        pg_execute -array stopinfo dbh "
+            SELECT val FROM runvars
+             WHERE flight=$flight AND job='$job'
+               AND name='pause_on_$st'
+        " {
+            pg_execute -array stepinfo dbh "
+                SELECT * FROM steps
+                 WHERE flight=$flight AND job='$job' AND stepno=$stepno
+            " {
+                foreach col {step testid} {
+                    if {![info exists stepinfo($col)]} continue
+                    foreach pat [split $stopinfo(val) ,] {
+                        if {[string match $pat $stepinfo($col)]} {
+                            set pause 1
+                        }
+                    }
+                }
+            }
+        }
+    }
+    if {$pause} {
+        logputs stdout "PAUSING as requested"
+        catch { exec sleep 86400 }
+    }
+}
+
+proc transaction {tables script} {
+    db-open
+    while 1 {
+        set ol {}
+        pg_execute dbh BEGIN
+        pg_execute dbh "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE"
+        lock-tables $tables
+       set rc [catch { uplevel 1 $script } result]
+       if {!$rc} {
+           if {[catch {
+               pg_execute dbh COMMIT
+           } emsg]} {
+               puts "commit failed: $emsg; retrying ..."
+               pg_execute dbh ROLLBACK
+               after 500
+               continue
+           }
+       } else {
+           pg_execute dbh ROLLBACK
+       }
+        db-close
+       return -code $rc $result
+    }
+}
+
+proc become-task {comment} {
+    global env c
+    if {[info exists env(OSSTEST_TASK)]} return
+
+    set ownerqueue [socket $c(ControlDaemonHost) $c(OwnerDaemonPort)]
+    fconfigure $ownerqueue -buffering line -translation lf
+    must-gets $ownerqueue {^OK ms-ownerdaemon\M}
+    puts $ownerqueue create-task
+    must-gets $ownerqueue {^OK created-task (\d+) (\w+ [\[\]:.0-9a-f]+)$} \
+        taskid refinfo
+    fcntl $ownerqueue CLOEXEC 0
+    set env(OSSTEST_TASK) "$taskid $refinfo"
+
+    set hostname [info hostname]
+    regsub {\..*} $hostname {} hostname
+    set username "[id user]@$hostname"
+
+    transaction resources {
+        set nrows [pg_execute dbh "
+            UPDATE tasks
+               SET username = [pg_quote $username],
+                   comment = [pg_quote $comment]
+             WHERE taskid = $taskid
+               AND type = [pg_quote [lindex $refinfo 0]]
+               AND refkey = [pg_quote [lindex $refinfo 1]]
+        "]
+    }
+    if {$nrows != 1} {
+        error "$nrows $taskid $refinfo ?"
+    }
+}
+
+}; # namespace eval jobdb
diff --git a/tcl/JobDB-Standalone.tcl b/tcl/JobDB-Standalone.tcl
new file mode 100644 (file)
index 0000000..f060c64
--- /dev/null
@@ -0,0 +1,62 @@
+# -*- Tcl -*-
+
+package require sqlite3
+
+namespace eval jobdb {
+
+proc logputs {f m} { logf $f $m }
+
+proc prepare {job} {
+    global flight jobinfo
+    ensure-db-open
+    osstestdb eval {
+       SELECT job, status, recipe FROM jobs
+           WHERE flight = $flight
+           AND    job = $job
+    } jobinfo {
+       return
+    }
+    error "job $flight.$job not found"
+}
+
+proc job-set-status {flight job st} {
+    ensure-db-open
+    osstestdb eval {
+       UPDATE jobs
+          SET status = $st
+        WHERE flight = $flight
+          AND job = $job
+    }
+}
+
+proc ensure-db-open {} {
+    global c
+    if {![catch { osstestdb version }]} { return }
+    sqlite3 osstestdb $c(JobDBStandaloneFilename)
+}
+
+proc set-flight {} {
+    global flight env
+    if {![info exists env(OSSTEST_FLIGHT)]} {
+       set env(OSSTEST_FLIGHT) standalone
+    }
+    set flight $env(OSSTEST_FLIGHT)
+}
+
+proc spawn-step-begin {flight job ts stepnovar} {
+    variable stepcounter 0
+    upvar 1 $stepnovar stepno
+    set stepno [incr stepcounter]
+}
+
+proc spawn-step-commit {flight job stepno testid} {
+    logputs stdout "$flight.$job $stepno TESTID $testid..."
+}
+
+proc step-set-status {flight job stepno st} {
+    logputs stdout "$flight.$job $stepno STATUS $st"
+}
+
+proc become-task {argv} { }
+
+}; # namespace eval jobdb
diff --git a/tcl/JobDb-Executive.tcl b/tcl/JobDb-Executive.tcl
deleted file mode 100644 (file)
index e9204bf..0000000
+++ /dev/null
@@ -1,247 +0,0 @@
-# -*- Tcl -*-
-
-package require Pgtcl 1.5
-
-namespace eval jobdb {
-
-proc logputs {f m} {
-    global argv
-    set time [clock format [clock seconds] -gmt true \
-                  -format "%Y-%m-%d %H:%M:%S Z"]
-    puts $f "$time \[$argv] $m"
-}
-
-proc prepare {job} {
-    global jobinfo
-    db-open
-    set found 0
-    pg_execute -array jobinfo dbh "
-        SELECT job, status, recipe FROM jobs
-                       WHERE   flight = [pg_quote $flight]
-                       AND     job = [pg_quote $job]
-    " {
-       switch -exact -- $jobinfo(status) {
-           queued - preparing - retriable - play { incr found }
-           default {
-               error "job $flight.$job status $jobinfo(status)"
-           }
-       }
-    }
-    if {!$found} {
-       error "job $flight.$job not found"
-    }
-
-    setstatus preparing
-    db-close
-}
-
-proc job-set-status-unlocked {flight job st} {
-    db-open
-    pg_execute dbh "
-            UPDATE jobs SET status='$st'
-                WHERE flight=$flight AND job='$job'
-                  AND status<>'aborted' AND status<>'broken'
-    "
-    db-close
-}
-
-proc job-set-status {flight job st} {
-    transaction flights {
-        job-set-status-unlocked $flight $job $st
-    }
-}
-
-proc set-flight {} {
-    global flight argv env
-
-    if {[string equal [lindex $argv 0] --start-delay]} {
-        after [lindex $argv 1]
-        set argv [lrange $argv 2 end]
-    }
-
-    set flight [lindex $argv 0]
-    set argv [lrange $argv 1 end]
-    set env(OSSTEST_FLIGHT) $flight
-}
-
-
-proc db-open {} {
-    global g
-    variable dbusers 0
-
-    if {$dbusers > 0} { incr dbusers; return }
-
-    # PgDbName_* are odbc-style strings as accepted by Perl's DBD::Pg
-    # but Tcl pg_connect unaccountably uses a different format which
-    # is whitespace-separated.
-    regsub -all {;} $c(ExecutiveDbname_osstestdb) { } conninfo
-    pg_connect -conninfo $conninfo -connhandle dbh
-    incr dbusers
-}
-proc db-close {} {
-    variable dbusers
-    incr dbusers -1
-    if {$dbusers > 0} return
-    if {$dbusers} { error "$dbusers ?!" }
-    pg_disconnect dbh
-}
-
-proc db-update-1 {stmt} {
-    # must be in transaction
-    set nrows [pg_execute dbh $stmt]
-    if {$nrows != 1} { error "$nrows != 1 in < $stmt >" }
-}
-
-proc lock-tables {tables} {
-    # must be inside transaction
-    foreach tab $tables {
-        pg_execute dbh "
-               LOCK TABLE $tab IN ACCESS EXCLUSIVE MODE
-        "
-    }
-}
-
-proc spawn-step-begin {flight job ts stepnovar} {
-    upvar 1 $stepnovar stepno
-
-    db-open
-
-    pg_execute dbh BEGIN
-    pg_execute dbh "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE"
-    if {[catch {
-        lock-tables flights
-       pg_execute -array stepinfo dbh "
-            SELECT max(stepno) AS maxstep FROM steps
-                WHERE flight=[pg_quote $flight] AND job=[pg_quote $job]
-        "
-        set stepno $stepinfo(maxstep)
-       if {[string length $stepno]} {
-           incr stepno
-       } else {
-           set stepno 1
-       }
-       pg_execute dbh "
-            INSERT INTO steps
-                VALUES ([pg_quote $flight], [pg_quote $job], $stepno,
-                        [pg_quote $ts], 'running',
-                        'TBD')
-        "
-       pg_execute dbh COMMIT
-    } emsg]} {
-       global errorInfo errorCode
-       set ei $errorInfo
-       set ec $errorCode
-       catch { pg_execute dbh ROLLBACK }
-        db-close
-       error $emsg $ei $ec
-    }
-}
-
-proc spawn-step-commit {flight job stepno testid} {
-    transaction flights {
-        db-update-1 "
-            UPDATE steps
-                  SET testid=[pg_quote $testid],
-                      started=[clock seconds]
-                WHERE flight=[pg_quote $flight]
-                  AND job=[pg_quote $job]
-                  AND stepno=$stepno
-        "
-    }
-
-    db-close
-}
-
-proc step-set-status {flight job stepno st} {
-    transaction flights {
-        db-update-1 "
-            UPDATE steps
-               SET status='$st',
-                   finished=[clock seconds]
-             WHERE flight=$flight AND job='$job' AND stepno=$stepno
-        "
-        set pause 0
-        pg_execute -array stopinfo dbh "
-            SELECT val FROM runvars
-             WHERE flight=$flight AND job='$job'
-               AND name='pause_on_$st'
-        " {
-            pg_execute -array stepinfo dbh "
-                SELECT * FROM steps
-                 WHERE flight=$flight AND job='$job' AND stepno=$stepno
-            " {
-                foreach col {step testid} {
-                    if {![info exists stepinfo($col)]} continue
-                    foreach pat [split $stopinfo(val) ,] {
-                        if {[string match $pat $stepinfo($col)]} {
-                            set pause 1
-                        }
-                    }
-                }
-            }
-        }
-    }
-    if {$pause} {
-        logputs stdout "PAUSING as requested"
-        catch { exec sleep 86400 }
-    }
-}
-
-proc transaction {tables script} {
-    db-open
-    while 1 {
-        set ol {}
-        pg_execute dbh BEGIN
-        pg_execute dbh "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE"
-        lock-tables $tables
-       set rc [catch { uplevel 1 $script } result]
-       if {!$rc} {
-           if {[catch {
-               pg_execute dbh COMMIT
-           } emsg]} {
-               puts "commit failed: $emsg; retrying ..."
-               pg_execute dbh ROLLBACK
-               after 500
-               continue
-           }
-       } else {
-           pg_execute dbh ROLLBACK
-       }
-        db-close
-       return -code $rc $result
-    }
-}
-
-proc become-task {comment} {
-    global env c
-    if {[info exists env(OSSTEST_TASK)]} return
-
-    set ownerqueue [socket $c(ControlDaemonHost) $c(OwnerDaemonPort)]
-    fconfigure $ownerqueue -buffering line -translation lf
-    must-gets $ownerqueue {^OK ms-ownerdaemon\M}
-    puts $ownerqueue create-task
-    must-gets $ownerqueue {^OK created-task (\d+) (\w+ [\[\]:.0-9a-f]+)$} \
-        taskid refinfo
-    fcntl $ownerqueue CLOEXEC 0
-    set env(OSSTEST_TASK) "$taskid $refinfo"
-
-    set hostname [info hostname]
-    regsub {\..*} $hostname {} hostname
-    set username "[id user]@$hostname"
-
-    transaction resources {
-        set nrows [pg_execute dbh "
-            UPDATE tasks
-               SET username = [pg_quote $username],
-                   comment = [pg_quote $comment]
-             WHERE taskid = $taskid
-               AND type = [pg_quote [lindex $refinfo 0]]
-               AND refkey = [pg_quote [lindex $refinfo 1]]
-        "]
-    }
-    if {$nrows != 1} {
-        error "$nrows $taskid $refinfo ?"
-    }
-}
-
-}; # namespace eval jobdb
diff --git a/tcl/JobDb-Standalone.tcl b/tcl/JobDb-Standalone.tcl
deleted file mode 100644 (file)
index 3429c6a..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-# -*- Tcl -*-
-
-package require sqlite3
-
-namespace eval jobdb {
-
-proc logputs {f m} { logf $f $m }
-
-proc prepare {job} {
-    global flight jobinfo
-    ensure-db-open
-    osstestdb eval {
-       SELECT job, status, recipe FROM jobs
-           WHERE flight = $flight
-           AND    job = $job
-    } jobinfo {
-       return
-    }
-    error "job $flight.$job not found"
-}
-
-proc job-set-status {flight job st} {
-    ensure-db-open
-    osstestdb eval {
-       UPDATE jobs
-          SET status = $st
-        WHERE flight = $flight
-          AND job = $job
-    }
-}
-
-proc ensure-db-open {} {
-    global c
-    if {![catch { osstestdb version }]} { return }
-    sqlite3 osstestdb $c(JobDbStandaloneFilename)
-}
-
-proc set-flight {} {
-    global flight env
-    if {![info exists env(OSSTEST_FLIGHT)]} {
-       set env(OSSTEST_FLIGHT) standalone
-    }
-    set flight $env(OSSTEST_FLIGHT)
-}
-
-proc spawn-step-begin {flight job ts stepnovar} {
-    variable stepcounter 0
-    upvar 1 $stepnovar stepno
-    set stepno [incr stepcounter]
-}
-
-proc spawn-step-commit {flight job stepno testid} {
-    logputs stdout "$flight.$job $stepno TESTID $testid..."
-}
-
-proc step-set-status {flight job stepno st} {
-    logputs stdout "$flight.$job $stepno STATUS $st"
-}
-
-proc become-task {argv} { }
-
-}; # namespace eval jobdb
index 679589ef32338ce4f66343a90986df6fef63d1c2..37b602660e893fe5eb97fde24cba6b8bf62c2a5d 100755 (executable)
@@ -6,6 +6,6 @@ use Osstest::TestSupport;
 
 tsreadconfig();
 
-my $ts = "./ts-hosts-allocate-$c{JobDb}";
+my $ts = "./ts-hosts-allocate-$c{JobDB}";
 exec $ts, @ARGV;
 die "$ts $!";