source: fedkit/splitter.pl @ 0e23fdb

axis_examplecompt_changesinfo-opsversion-1.30version-2.00version-3.01version-3.02
Last change on this file since 0e23fdb was 0e23fdb, checked in by Ted Faber <faber@…>, 17 years ago

Cover my sin of using a shell glob. /bin/csh treats this badly and an explicit
call to /bin/sh and some gross quoting is in order.

  • Property mode set to 100644
File size: 23.2 KB
Line 
1#!/usr/bin/perl
2
3use Getopt::Std;
4use IO::File;
5use IO::Dir;
6use IO::Pipe;
7use File::Copy;
8
9@scripts = ("federate.sh", "smbmount.pl", "make_hosts", "fed-tun.pl");
10$local_script_dir = ".";
11
12# Parse the config file.  The format is a colon-separated parameter name
13# followed by the value of that parameter to the end of the line.  This parses
14# that format and puts the parameters into the referenced hash.  Parameter
15# names are mapped to lower case, parameter values are unchanged.  Returns 0 on
16# failure (e.g. file open) and 1 on success.
17sub parse_config {
18    my($file, $href) = @_;
19    my($fh) = new IO::File($file);
20       
21    unless ($fh) {
22        warn "Can't open $file: $!\n";
23        return 0;
24    }
25
26    while (<$fh>) {
27        next if /^\s*#/ || /^\s*$/;     # Skip comments & blanks
28        chomp;
29        /^([^:]+):\s*(.*)/ && do {
30            my($key) = $1; 
31
32            $key =~ tr/A-Z/a-z/;
33            $href->{$key} = $2;
34            next;
35        };
36        warn "Unparasble line in $file: $_\n";
37    }
38    $fh->close();   # It will close when it goes out of scope, but...
39    return 1;
40}
41
42
43# use scp to transfer a file, reporting true if successful and false otherwise.
44# Parameters are the local file name, the ssh host destination (either hostname
45# oe user@host), and an optional destination file name or directory.  If no
46# destination is given, the file is transferred to the given user's home
47# directory.  If only a machine is given in the ssh host destination, the
48# current user is used.
49sub scp_file {
50    my($file, $where, $dest) = @_;
51
52    # XXX system with a relative pathname is sort of gross
53    system("scp $file $where:$dest");
54    if ($?) {
55        warn "scp failed $?\n";
56        return 0;
57    }
58    else { return 1; }
59}
60
61# use ssh to execute the given command on the machine (and as the user) in
62# $where.  Parameters are the ssh destination directive ($where) and the
63# command to execute, and a prefix to be placed on a message generated if the
64# command fails.   On failure print a warning if a warning prefix was given and
65# return false.
66sub ssh_cmd {
67    my($user, $host, $cmd, $wname) = @_;
68
69    # XXX system with a relative pathname is sort of gross
70    system ("ssh $user\@$host $cmd");
71    if ($?) {
72        warn "$wname failed $?\n" if $wname;
73        return 0;
74    }
75    else { return 1; }
76}
77
78# Ship local copies of the federation scripts out to the given host.  If any of
79# the script transfers fails, return 0.  The scripts to transfer are from the
80# global @scripts and are found locally in $local_script_dir (another global).
81sub ship_scripts {
82    my($host, $user, $dest_dir) = @_;       # Where, who, where remotely
83    my($s);
84
85    &ssh_cmd($user, $host, "mkdir -p $dest_dir");
86    for $s (@scripts) {
87        &scp_file("$local_script_dir/$s", "$user\@$host", $dest_dir) || 
88            return 0;
89    }
90    return 1;
91}
92
93# Ship per-testbed configuration generated by this script to the remote /proj
94# directories on the remote testbeds
95sub ship_configs {
96    my($host, $user, $src_dir, $dest_dir) = @_;     # Where, who, where remotely
97    my($d, $f);
98
99
100    $d = IO::Dir->new($src_dir) || return 0;
101
102    # All directories under $tmpdir are 770 so we can delete them later.
103    &ssh_cmd($user, $host, "mkdir -p $dest_dir") || return 0;
104    &ssh_cmd($user, $host, "chmod 770 $dest_dir") || return 0;
105    while ( $f = $d->read()) {
106        next if $f =~ /^\./;
107        if ( -d "$src_dir/$f" ) {
108            &ship_configs($host, $user, "$src_dir/$f", "$dest_dir/$f") || 
109                return 0;
110        }
111        else {
112            &scp_file("$src_dir/$f", "$user\@$host", $dest_dir) || return 0;
113        }
114    }
115    return 1;
116}
117
118
119
120
121# Start a sub section of the experiment on a given testbed.  The testbed and
122# the user to start the experiment as are pulled from the global per-testbed
123# hash, as is the project name on the remote testbed.  Parameters are the
124# testbed and the experiment id.  Configuration files are scp-ed over to the
125# target testbed from the global $tmpdir/$tb directory.  Then the current state
126# of the experiment determined using expinfo.  From that state, the experiment
127# is either created, modified or spapped in.  If everything succeeds, true is
128# returned.
129sub start_segment {
130    my($tb, $eid) = @_;                     # testbed and experiment ID
131    my($host) = "$host{$tb}$domain{$tb}";   # Host name of remote ops (FQDN)
132    my($user) = $user{$tb};                 # user to pass to ssh
133    my($pid) = $project{$tb};               # remote project to start the
134                                            # experiment under
135    my($tclfile) = "./$eid.$tb.tcl";        # Local tcl file with the
136                                            # sub-experiment
137    my($proj_dir) = "/proj/$pid/exp/$eid/tmp";  # Where to stash federation stuff
138    my($to_hostname) = "$proj_dir/hosts";   # remote hostnames file
139    my($status) = new IO::Pipe;             # The pipe to get status
140
141    # Determine the status of the remote experiment
142    $status->reader("ssh $user\@$host /usr/testbed/bin/expinfo $pid $eid") || 
143        die "Can't ssh to $user\@$host:$!\n";
144
145    # XXX: this is simple now.  Parsing may become more complex
146    while (<$status>) {
147        /State: (\w+)/ && ($state = $1);
148        /No\s+such\s+experiment/ && ($state = "none");
149    }
150    $status->close();
151    print "$tb: $state\n";
152
153    # Copy the experiment definition data over
154    &scp_file("$tmpdir/$tb/$tclfile", "$user\@$host") || return 0;
155    # Clear out any old experiment data; if not deleted, copies over it by
156    # different users will fail.
157    # (O /bin/csh, how evil thou art.  The -c and the escaped single quotes
158    # force the /bin/sh interpretation of the trailing * (which we need to keep
159    # tmp around))  Again, this needs to be done more properly once we have a
160    # non-ssh interface here.)
161    &ssh_cmd($user, $host, "/bin/sh -c \\'/bin/rm -rf $proj_dir/*\\'") || 
162        return 0;
163    # Remote experiment is active.  Modify it.
164    if ($state eq "active") {
165        # First copy new scripts and hostinfo into the remote /proj
166        &scp_file("$tmpdir/hostnames", "$user\@$host", $to_hostname) ||
167            return 0;
168        &ship_scripts($host, $user, $proj_dir) || return 0;
169        &ship_configs($host, $user, "$tmpdir/$tb", $proj_dir) || return 0;
170        &ssh_cmd($user, $host, "/usr/testbed/bin/modexp -r -s -w $pid " . 
171            "$eid $tclfile", "modexp") || return 0;
172        return 1;
173    }
174
175    # Remote experiment is swapped out, modify it and swap it in.
176    if ($state eq "swapped") {
177        # First copy new scripts and hostinfo into the remote /proj (because
178        # the experiment exists, the directory tree should be there.
179        &scp_file("$tmpdir/hostnames", "$user\@$host", $to_hostname) ||
180            return 0;
181        &ship_scripts($host, $user, $proj_dir) || return 0;
182        &ship_configs($host, $user, "$tmpdir/$tb", $proj_dir) || return 0;
183        &ssh_cmd($user, $host, "/usr/testbed/bin/modexp -w $pid $eid $tclfile", 
184            "modexp") || return 0;
185        # Now start up
186        &ssh_cmd($user, $host, "/usr/testbed/bin/swapexp -w $pid $eid in", 
187            "swapexp") || return 0;
188        return 1;
189    }
190
191    # No remote experiment.  Create one.  We do this in 2 steps so we can put
192    # the configuration files and scripts into the new experiment directories.
193    if ($state eq "none") {
194        &ssh_cmd($user, $host, "/usr/testbed/bin/startexp -f -w -p " . 
195            "$pid -e $eid $tclfile", "startexp") || return 0;
196        # First copy new scripts and hostinfo into the remote /proj
197        &scp_file("$tmpdir/hostnames", "$user\@$host", $to_hostname) ||
198            return 0;
199        &ship_scripts($host, $user, $proj_dir) || return 0;
200        &ship_configs($host, $user, "$tmpdir/$tb", $proj_dir) || return 0;
201        # Now start up
202        &ssh_cmd($user, $host, "/usr/testbed/bin/swapexp -w $pid $eid in", 
203            "swapexp") || return 0;
204        return 1;
205    }
206
207    # Every branch for a known state returns.  If execution gets here, the
208    # state is unknown.
209    warn "unknown state: $state\n";
210    return 0;
211}
212
213# Swap out a sub-experiment - probably because another has failed.  Arguments
214# are testbed and experiment.  Most of the control flow is similar to
215# start_segment, though much simpler.
216sub stop_segment {
217    my($tb, $eid) = @_;
218    my($user) = "$user{$tb}";
219    my($host) = "$host{$tb}$domain{$tb}";
220    my($pid) = $project{$tb};
221
222    &ssh_cmd($user, $host, "/usr/testbed/bin/swapexp -w $pid $eid out", 
223        "swapexp (out)") || return 0;
224    return 1;
225}
226
227
228$pid = $gid = "dummy";              # Default project and group to pass to
229                                    # $tcl_splitter above.  These are total
230                                    # dummy arguments;  the splitter doesn't
231                                    # use them at all, but we supply them to
232                                    # keep our changes to the parser minimal.
233# Argument processing.
234getopts('c:f:nd', \%opts);
235$splitter_config = $opts{'c'} || "./splitter.conf";
236$debug = $opts{'d'};
237&parse_config("$splitter_config", \%opts) || 
238    die "Cannot read config file $splitter_conf: $!\n";
239
240
241$startem = $opts{'n'} ? 0 : 1;          # If true, start the sub-experiments
242$eid = $opts{'experiment'};             # Experiment ID
243$tcl = $opts{'f'} || shift;             # The experiment description
244$master = $opts{'master'};              # Master testbed
245$tmpdir = $opts{'tmpdir'} || $opts{'tempdir'}|| "/tmp"; # tmp files
246$tb_config = $opts{'testbeds'} || "./testbeds"; # testbed configurations
247$local_script_dir = $opts{'scriptdir'}; # Local scripts
248
249$smb_share = $opts{'smbshare'} ||       # Share to mount from the master
250    die "Must give an SMB share\n";
251$project_user = $opts{'smbuser'} ||     # User to mount project dirs as
252    die "Must give an SMB user\n";
253
254# For now specify these.  We may want to generate them later.
255$gw_pubkey = $opts{'gatewaypubkey'};
256($gw_pubkey_base = $gw_pubkey) =~ s#.*/##;
257$gw_secretkey = $opts{'gatewaysecretkey'};
258($gw_secretkey_base = $gw_secretkey) =~ s#.*/##;
259
260# tcl program to split experiments (changed during devel)
261$tcl_splitter = $opts{'tclparse'} || "/usr/testbed/lib/ns2ir/parse.tcl";
262# tclsh to call directly (changed during devel)
263$tclsh = $opts{'tclsh'} || "/usr/local/bin/otclsh";
264
265# Prefix to avoid collisions
266$tmpdir .= "/split$$";
267
268# Create a workspace
269unless (-d "$tmpdir") {
270    mkdir("$tmpdir") || die "Can't create $tmpdir: $!";
271}
272
273# Validate scripts directory
274for $s (@scripts) {
275    die "$local_script_dir/$s not in local script directory. Try -d\n"
276        unless -r "$local_script_dir/$s";
277}
278
279die "Must supply file, master and experiment" unless $master && $tcl && $eid;
280
281# Read a hash of per-testbed parameters from the local configurations.
282$conf = new IO::File($tb_config) || 
283    die "can't read testbed configutions from $tb_config: $!\n";
284while (<$conf>) {
285    next if /^#/;
286    chomp;
287    ($tb, $h, $d, $u, $p, $es, $gs, $mes, $mgs, $t, $i, $fs, $boss, $tun) = 
288        split(":", $_);
289    $host{$tb} = $h;
290    $user{$tb} = $u;
291    $domain{$tb} = $d;
292    $project{$tb} = $p;
293    $gwtype{$tb} = $t;
294    $expstart{$tb} = $es;
295    $gwstart{$tb} = $gs;
296    $mexpstart{$tb} = $mes;
297    $mgwstart{$tb} = $mgs;
298    $gwimage{$tb} = $i;
299    $fs{$tb} = $fs;
300    $boss{$tb} = $boss;
301    $tun{$tb} = $tun;
302
303    # Make sure the domain starts with a period
304    $domain{$tb} = ".$domain{$tb}" unless $domain{$tb} =~ /^\./;
305}
306$conf->close();
307
308# Open a pipe to the splitter program and start it parsing the experiments
309$pipe = new IO::Pipe;
310# NB no more -p call on parse call.
311$pipe->reader("$tclsh $tcl_splitter -s -m $master  $pid $gid $eid $tcl") || 
312    die "Cannot execute $tclsh $tcl_splitter -s -m $master $pid $gid $eid $tcl:$!\n";
313
314# Parse the splitter output.  This loop creates the sub experiments, gateway
315# configurations and hostnames file
316while (<$pipe>) {
317    # Start of a sub-experiment
318    /^#\s+Begin\s+Testbed\s+\((\w+)\)/ && do {
319        $ctb = $1;
320
321        # If we know the testbed, start collecting its sub experiment tcl
322        # description.  If not, warn the caller and ignore the configuration of
323        # this testbed.
324        if ($host{$ctb}) {
325            $allocated{$ctb}++; # Keep track of the testbeds allocated
326
327            unless (-d "$tmpdir/$ctb") {
328                mkdir("$tmpdir/$ctb") || die "Can't create $tmpdir/$ctb: $!";
329            }
330            $destfile = "$tmpdir/$ctb/$eid.$ctb.tcl";
331
332            open(FILE, ">$destfile") || die "Cannot open $destfile:$!\n";
333        }
334        else { 
335            warn "No such testbed $ctb\n";
336            $destfile = "";
337        }
338        next;
339    };
340
341    # End of that experiment
342    /^#\s+End\s+Testbed\s+\((\w+)\)/ && do {
343        # Simple syntax check and close out this experiment's tcl description
344        die "Mismatched testbed markers ($1, $ctb)\n" unless ($1 eq $ctb);
345        close(FILE);
346        $destfile = $ctb = "";
347        next;
348    };
349
350    # Beginning of a gateway set
351    /^#\s+Begin\s+gateways\s+\((\w+)\)/ && do {
352        $gateways = $1;
353        # If we've heard of this tb, create the config lines for it one at a
354        # time.
355        if ($allocated{$gateways}) {
356            # Just in case.  This directory should already have been created
357            # above.
358            unless (-d "$tmpdir/$gateways") {
359                mkdir("$tmpdir/$gateways") || 
360                    die "Can't create $tmpdir/$gateways: $!";
361            }
362        }
363        else {
364            warn "Gateways given (and ignored) for testbed not in use: " .
365                "$gateways\n";
366            $gateways = 0;
367        }
368        next;
369    };
370    # End of the gateways section.  Output the client config for this testbed
371    /^#\s+End\s+gateways\s+\((\w+)\)/ && do {
372        die "Mismatched gateway markers ($1, $gateways)\n" 
373            unless !$gateways || $gateways == $1;
374
375        die "No control gateway for $gateways?" unless $control_gateway;
376        # Client config
377        $cc = new IO::File(">$tmpdir/$gateways/client.conf");
378        die "Can't open $tmpdir/$gateways/client.conf: $!\n" unless $cc;
379        print $cc "ControlGateway: $control_gateway\n";
380        print $cc "SMBShare: $smb_share\n";
381        print $cc "ProjectUser: $project_user\n";
382        $cc->close();
383       
384        $gateways = 0;
385        next;
386    };
387    # Beginning of the hostnames list.  Collection is always in the hostnames
388    # file.
389    /^#\s+Begin\s+hostnames/ && do {
390        $destfile = "$tmpdir/hostnames";
391        open(FILE, ">$destfile") || die "Can't open $destfile:$!\n";
392        next;
393    };
394    # end of the hostnames list.
395    /^#\s+End\s+hostnames/ && do {
396        close(FILE);
397        $destfile = "";
398        next;
399    };
400
401    # Generate gateway configuration info, one file per line
402    $gateways && do {
403        chomp;
404        my($dtb, $myname, $desthost, $type) = split(" ", $_);
405        my($sdomain) = $domain{$gateways};      # domain for the source
406        my($ddomain) = $domain{$dtb};           # domain for the destination
407        my($sproject) = $project{$gateways};    # Project of the destination
408
409        $sdomain = ".$eid.$project{$gateways}$sdomain";
410        $ddomain = ".$eid.$project{$dtb}$ddomain";
411
412        # If either end of this link is in the master side of the testbed, that
413        # side is the active end. Otherwise the first testbed encountered in
414        # the file will be the active end.  The $active_end variable keeps
415        # track of those decisions
416        if ( $dtb eq $master ) { $active = "false"; }
417        elsif ($gateways eq $master ) { $active = "true"; }
418        elsif ( $active_end{"$dtb-$gateways"} ) { $active="false"; }
419        else { $active_end{"$gateways-$dtb"}++; $active = "true"; }
420
421        # This is used to create the client configuration.
422        $control_gateway = "$myname$sdomain"
423            if $type =~ /(control|both)/;
424
425        # Write out the file
426        $gwconfig= new IO::File(">$tmpdir/$gateways/$myname$sdomain.gw.conf")|| 
427            die "can't open $tmpdir/$gateways/$myname$sdomain.gw.conf: $!\n";
428
429        print $gwconfig "Active: $active\n";
430        print $gwconfig "TunnelCfg: $tun{$gateways}\n";
431        print $gwconfig "BossName: $boss{$master}$domain{$master}\n";
432        print $gwconfig "FsName: $fs{$master}$domain{$master}\n";
433        print $gwconfig "Type: $type\n";
434        print $gwconfig "Peer: $desthost$ddomain\n";
435        print $gwconfig "Pubkeys: " . 
436            "/proj/$sproject/exp/$eid/tmp/$gw_pubkey_base\n";
437        print $gwconfig "Privkeys: " .
438            "/proj/$sproject/exp/$eid/tmp/$gw_secretkey_base\n";
439        $gwconfig->close();
440
441        # This testbed has a gateway (most will) so make a copy of the keys it
442        # needs in this testbed's subdirectory.  start_segment will transfer
443        # them.
444        unless (-r "$tmpdir/$gateways/$gw_pubkey_base" ) {
445            copy($gw_pubkey, "$tmpdir/$gateways/$gw_pubkey_base") ||
446                die "Can't copy pubkeys ($gw_pubkey to " . 
447                    "$tmpdir/$gateways/$gw_pubkey_base): $!\n";
448        }
449        if ($active eq "true" ) {
450            unless (-r "$tmpdir/$gateways/$gw_secretkey_base" ) {
451                copy($gw_secretkey, "$tmpdir/$gateways/$gw_secretkey_base") ||
452                    die "Can't copy secret keys ($gw_secretkey to " . 
453                        "$tmpdir/$gateways/$gw_secretkey_base): $!\n";
454            }
455        }
456
457        #done processing gateway entry, ready for next line
458        next; 
459    };
460    (/^#\s+Begin\s+tarfiles/../^#\s+End\s+tarfiles/) && do {
461        next if /^#/;
462        chomp;
463        push(@tarfiles, $_);
464        next;
465    };
466
467    next unless $destfile;  # Unidentified testbed, ignore config
468
469    # Substitute variables
470    s/GWTYPE/$gwtype{$ctb}/g;
471    s/GWIMAGE/$gwimage{$ctb}/g;
472    if ($ctb eq $master ) {
473        s/GWSTART/$mgwstart{$ctb}/g;
474        s/EXPSTART/$mexpstart{$ctb}/g;
475    }
476    else {
477        s/GWSTART/$gwstart{$ctb}/g;
478        s/EXPSTART/$expstart{$ctb}/g;
479    }
480    # XXX: oh is this bad
481    s#GWCONF#FEDDIR\`hostname\`.gw.conf#g;
482    s#FEDDIR#/proj/$project{$ctb}/exp/$eid/tmp/#g;
483    print FILE;
484}
485$pipe->close();
486die "No nodes in master testbed ($master)\n" unless $allocated{$master};
487
488for $t (@tarfiles) {
489    die "tarfile '$t' unreadable: $!\n" unless -r $t;
490    for $tb (keys %allocated) {
491        unless (-d "$tmpdir/$tb/tarfiles") {
492            mkdir("$tmpdir/$tb/tarfiles") || 
493                die "Can't create $tmpdir/$tb/tarfiles:$!\n";
494        }
495        copy($t, "$tmpdir/$tb/tarfiles") || 
496                die "Can't copy $t to  $tmpdir/$tb/tarfiles:$!\n";
497    }
498}
499
500exit(0) unless $startem;
501
502# Start up the slave sub-experiments first
503TESTBED:
504for $tb (keys %allocated) {
505    if ($tb ne $master) {
506        if (&start_segment($tb, $eid)) { $started{$tb}++; }
507        else { last TESTBED; }
508    }
509}
510
511# Now the master
512if (&start_segment($master, $eid)) { 
513    $started{$master}++;
514}
515
516# If any testbed failed, swap the rest out.
517if ( scalar(keys %started) != scalar(keys %allocated)) {
518    for $tb (keys %started) { &stop_segment($tb, $eid); }
519    print "Error starting experiment\n";
520    exit(1);
521}
522print "Experiment started\n";
523system("rm -rf $tmpdir") unless $debug;
524exit(0);    # set the exit value
525
526=pod
527
528=head1 NAME
529
530B<splitter.pl>
531
532=head1 SYNOPSIS
533
534B<splitter.pl> [B<-nd>] [B<-c> F<config_file>] [B<-f> F<experiment_tcl>]
535    [F<experiment_tcl>]
536
537=head1 DESCRIPTION
538
539B<splitter.pl> invokes the DETER experiment parser to split an annotated
540experiment into multiple sub-experments and instantiates the sub-experiments on
541their intended testbeds.  Annotation is accomplished using the
542tb-set-node-testbed command, added to the parser.
543
544The testbed labels are meaningful based on their presence in the testbeds file.
545that file can be specified in the configuration file using the B<Testbeds>
546directive, and defaults to F<./testbeds>.  The syntax is described below.
547
548Most of the intermediate files are staged in a sub-directory of a temporary
549files directory and deleted at the end of the script.  Specifying the B<-d>
550flag on the command line avoids the deletion for debbugging.  By default the
551temporary files directory is directory is F</tmp> and can be reset in the
552configuration file using the B<Tmpdir> directive.  Intermediate files are
553stored under a subdirectory formed by adding the process ID of the splitter
554process.  For example, if the temporary files directory is F</tmp> and the
555B<splitter.pl> process ID is 2323, the temporary files will be stored in
556F</tmp/split2323/>.
557
558The expreriment is split out into one experiment description per testbed in the
559temporary directory named as F<experiment.testbed.tcl> where the experiment is
560the experiment ID given in the configuration file, and the testbed is the
561tb-set-node-testbed parameter for the nodes in the file.
562
563If the B<-n> option is absent the sub-experiments are then instantiated on
564their testbeds.  (Here B<-n> is analogous to its use in L<make(1)>).
565Per-testbed parameters are set in the testbeds file.  Sub-experiments on
566slave testbeds are instantiated in a random order, but the master testbed is
567currently instantiated last.
568
569Scripts to start federation (the federation kit) are copied into the local
570experiment's tmp file - e.g., F</proj/DETER/exp/simple-split/tmp>.  These are
571taken from the directory given by the B<ScriptDir> directive in the
572configuration file.
573
574If any sub-experiment fails to instantiate, the other sub-exeriments are
575swapped out.
576
577=head2 Configuration File
578
579The configuration file is a simple attribute-value pair set of colon-separated
580parameters and values.  A configuration file must be present, either specified
581in the B<-c> flag or the default F<./splitter.conf>.  All the parameter names
582are case insensitive, but should not include any whitespace.  Parameter values
583may include whitespace, but no newlines.
584
585Possible parameters are:
586
587=over 5
588
589=item Experiment
590
591The name of the experiment on the various testbeds
592
593=item Master
594
595The master testbed label from the testbeds file, described below.
596
597=item Testbeds
598
599The testbeds file described below, giving per-testbed parameters.  If this
600directive is absent the testbeds file defaults to F<./testbeds>
601
602=item ScriptDir
603
604Location of the default federation scripts, i.e. the federation kit.
605
606=item GatewayPubkey
607
608=item GatewaySecretKey
609
610The names of the files containing secret and public keys to use in setting up
611tunnels between testbeds.  These will eventually be automatically generated.
612
613=item TmpDir
614
615=item TempDir
616
617The directory where temporary files are created.  These are synonyms, but
618should both be specified, B<TmpDir> has priority.  If neither is specified,
619F</tmp> is used.
620
621=item SMBShare
622
623The SMB share on the master testbed that will be exported to remote clients.
624
625=item SMBUser
626
627The experiment user to mount project directories as.  This user needs to be a
628member of the exported experiment - that is one of the users in the project
629containing this experiment on the master testbed.
630
631=item Tclparse
632
633The pathname to the experiment parsing program.  Only developers should set
634this.
635
636=item Tclsh
637
638The pathname to the local oTcl shell.  Only developers should set
639this.
640
641=back
642
643=head2 Testbeds file
644
645The configuration file (F<./testbeds> unless overridden by B<-c>) is a
646colon-separated set of parameters keyed by testbed name.  The fields, in order,
647are:
648
649=over 5
650
651=item name
652
653The testbed to which this line of parameters applies.
654
655=item user
656
657The user under which to make requests to this testbed.  The user running
658B<splitter.pl> must be able to authenicate as this user under L<ssh(1)> to this
659testbed.
660
661=item host
662
663The host name of the testbed's ops node.  The user calling B<splitter.pl> must
664be able to execute commands on this host via L<ssh(1)>.
665
666=item domain
667
668The domain of nodes in this testbed (including the ops host).
669
670=item project
671
672The project under which to instantiate sub-experiments on this testbed.
673
674=item gateway type
675
676The node type for inter-testbed gateway nodes on this testbed.
677
678=item experiment start (slave)
679
680The start command to run on experimental nodes when this testbed is used as a
681slave.  In all the start commands the string FEDDIR will be replaced by the
682local experiment's federation scripts directory and the string GWCONF replaced
683by the gatway configuration file.
684
685=item gateway start (slave)
686
687The start command to run on gateway nodes when this testbed is used as a slave.
688The same string substitutions are made in this command as in experiment start.
689
690=item experiment start (master)
691
692The start command to run on experimental nodes when this testbed is used as a
693master.  The same string substitutions are made in this command as in
694experiment start.
695
696=item gateway start (master)
697
698The start command to run on gateway nodes when this testbed is used as a
699master.  The same string substitutions are made in this command as in
700experiment start.
701
702=item gateway image
703
704The disk image to be loaded on a gateway node on this testbed.
705
706=back
707
708The parsing of the testbeds is extremely simple.  Colons separate each
709field and there is n provision for escaping them at this time.
710
711=head1 ENVIRONMENT
712
713B<splitter.pl> does not directly make use of environment variables, but calls
714out to L<ssh(1)> and (indirectly) to L<sh(1)>, which may be influenced by the
715environment.
716
717=head1 SEE ALSO
718
719L<sh(1)>, L<ssh(1)>
720
721=cut
Note: See TracBrowser for help on using the repository browser.