source: fedkit/splitter.pl @ 3529a90

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

permissions don_t work when different users instantiate in the same experiment (can_t overwrite config files). Fixed

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