#!/usr/bin/perl -w
require 5.003;
use strict;
use lib '/usr/local/polygraph/BB';
require Command;
require Blob;
require Executer;
require Tools;
use Logger;
# Client -> Server Names
# note: these are host names/ips, not necessarily poly-robot/server ips
my @Hosts = (
'10.10.1.1' => '10.10.129.1', # hard coded pairs
#&importHostNames(), # or use shell environment variables
);
my $Proxy = '10.10.1.1:3128'; # one for all
my $Master = '10.10.0.1'; # monitoring machine
my $Take = time()-940000000; # to avoid new logs overwriting old ones
my %HostPairs = @Hosts;
# executed before each run
my @HeadCmds = (
Cmd('date'),
Pairs(
'ssh $clt killall polyclt',
'ssh $srv killall polysrv',
),
All('ssh $host mkdir logs'),
All('ssh $host /usr/sbin/ntpdate -b $Master'),
Cmd('sleep 600'),
);
# executed after each run
my @TailCmds = (
Pairs(
'ssh $clt killall -INT polyclt',
'ssh $srv killall -INT polysrv',
),
Pairs(
'scp -p $clt:logs/clt.\* logs.archive/',
'scp -p $srv:logs/srv.\* logs.archive/',
),
All('ssh $host mv logs logs.local/$name'),
Cmd('exprep.pl logs.archive/clt.$exp_mask.*.log'),
Cmd('date'),
);
my @BlobCfgs = (
{
# this is a no-proxy run for Polygraph 1.x
# for Polygraph 2.x, see pmix2 workload and
# remove --proxy option
name => 'no-proxy.rr$rr.take$Take',
exp_mask => 'no-proxy.rr:*:.take$Take',
body => [ Pairs(
'ssh $clt sleep 10\;
bin/polyclt
--ports 1024:30000
--verb_lvl 4
--origin $srv:80
--rng_seed $cmd_id
--rep_cachable 80p
--pconn_use_lmt zipf:64
--nagle off
--robots 1
--req_rate $rr/sec
--dhr 55p
--pop_model unif
--tmp_loc none
--cool_phase 1min
--goal -1:1hr:0.30
--log_size 15MB
--log logs/clt.$name.$clt.log
--console logs/clt.$name.$clt.con
--notify $Master:18256
--label np$rr
',
'ssh $srv bin/polysrv
--port 80
--verb_lvl 4
--rng_seed $cmd_id
--idle_tout 135sec
--pconn_use_lmt zipf:16
--nagle off
--xact_think norm:3s,1.5s
--obj_bday const:-1year
--obj_with_lmt 100p
--obj_life_cycle const:2year
--obj_expire 100p=lmt+const:1
--goal 4.1hr
--log_size 15MB
--log logs/srv.$name.$srv.log
--console logs/srv.$name.$srv.con
--notify $Master:18256
--label np$rr
',
),
],
runs => [ Runs('rr', 500) ],
},
{
name => 'fill.cl$cl.take$Take',
exp_mask => 'fill.cl:*:.take$Take',
body => [ Pairs(
'ssh $clt bin/polyclt
--ports 1024:30000
--verb_lvl 4
--proxy $Proxy --origin $srv:80
--rng_seed $cmd_id
--unique_urls 1
--rep_cachable 100p
--pconn_use_lmt const:1000
--nagle off
--robots $cl
--launch_win 30sec
--cool_phase 1min
--goal -1:8hr:.30
--log_size 35MB
--log logs/clt.$name.$clt.log
--console logs/clt.$name.$clt.con
--notify $Master:18256
--label fl$cl
',
'ssh $srv bin/polysrv
--port 80
--verb_lvl 4
--rng_seed $cmd_id
--pconn_use_lmt const:1000
--nagle off
--obj_bday const:-1year
--obj_with_lmt 100p
--obj_life_cycle const:2year
--obj_expire 100p=lmt+const:1
--idle_tout 5min
--log_size 35MB
--log logs/srv.$name.$srv.log
--console logs/srv.$name.$srv.con
--notify $Master:18256
--label fl$cl
',
),
],
runs => [ Runs('cl', 10) ],
},
{
name => 'dcomm.rr$rr.take$Take',
exp_mask => 'dcomm.rr:*:.take$Take',
body => [ Pairs(
'ssh $clt sleep 10\;
bin/polyclt
--ports 1024:30000
--verb_lvl 4
--proxy $Proxy --origin $srv:80
--launch_win 1min
--rng_seed $cmd_id
--rep_cachable 80p
--pconn_use_lmt zipf:64
--nagle off
--robots 1
--req_rate $rr/sec
--dhr 55p
--pop_model unif
--tmp_loc none
--cool_phase 1min
--goal -1:4hr:0.30
--log_size 15MB
--log logs/clt.$name.$clt.log
--console logs/clt.$name.$clt.con
--notify $Master:18256
--label dc$rr
',
'ssh $srv bin/polysrv
--port 80
--verb_lvl 4
--rng_seed $cmd_id
--pconn_use_lmt zipf:16
--nagle off
--idle_tout 135sec
--xact_think norm:3s,1.5s
--obj_bday const:-1year
--obj_with_lmt 100p
--obj_life_cycle const:2year
--obj_expire 100p=lmt+const:1
--goal 4.1hr
--log_size 15MB
--log logs/srv.$name.$srv.log
--console logs/srv.$name.$srv.con
--notify $Master:18256
--label dc$rr
',
),
],
runs => [ Runs('rr', 100, 150) ],
},
{
# these specs assume that all PGL files
# are in pgs/ and pgs/include remote directories
# you may want to adjust @HeadCmds to sync those
# directories automatically before each run
# remove --proxy option for transparent setups
# and no-proxy tests
name => 'pmix2.take$Take',
exp_mask => 'pmix2.take:*:ip',
body => [ Pairs(
'ssh $clt sleep 10\;
bin/polyclt
--proxy $Proxy
--config pgs/polymix-2.pg
--cfg_dirs pgs/include
--verb_lvl 10
--rng_seed $cmd_id
--log logs/clt.$name.ip$clt.log
--console logs/clt.$name.ip$clt.con
--notify $Master:18256
--label pm2
',
'ssh $srv bin/polysrv
--config pgs/polymix-2.pg
--cfg_dirs pgs/include
--verb_lvl 10
--rng_seed $cmd_id
--idle_tout 5min
--log logs/srv.$name.ip$srv.log
--console logs/srv.$name.ip$srv.con
--notify $Master:18256
--label pm2
',
),
],
# this is left for backwards compatability, not used
runs => [ Runs('rr', map { sprintf('%.2f', $_/1.) }
1
) ],
},
{
# warning: this workload specs comes from the first
# bake-off tests and may need adjustments with later
# version of Polygraph
name => 'pmix1.rr$rr.take$Take',
exp_mask => 'pmix1.rr:*:.take$Take',
body => [ Pairs(
'ssh $clt polyclt
--ports 1024:30000
--verb_lvl 4
--proxy $Proxy --origin $srv:80
--launch_win 1min
--rng_seed $cmd_id
--rep_cachable 80p
--robots 1
--req_rate $rr/sec
--dhr 55p
--pop_model unif
--tmp_loc none
--cool_phase 1min
--goal -1:1hr:0.30
--log logs/clt.$name.$clt.log
--console logs/clt.$name.$clt.con
',
'ssh $srv polysrv
--port 80
--verb_lvl 4
--rng_seed $cmd_id
--idle_tout 135sec
--xact_think norm:3s,1.5s
--goal 1.1hr
--log logs/srv.$name.$srv.log
--console logs/srv.$name.$srv.con
',
),
],
runs => [ Runs('rr', 10, 100) ],
},
);
$| = 1;
my @BlobPlan = ();
my @ActiveBlobNames = @ARGV;
my $FilterNames = scalar @ActiveBlobNames;
my @PossibleBlobNames = ();
foreach my $blob_cfg (@BlobCfgs) {
my $blob = new BB::Blob($blob_cfg->{name});
die() unless $blob_cfg->{body};
die() unless $blob_cfg->{runs};
$blob->exp_mask($blob_cfg->{exp_mask});
$blob->head($blob_cfg->{head} || [@HeadCmds]);
$blob->body($blob_cfg->{body});
$blob->tail($blob_cfg->{tail} || [@TailCmds]);
foreach (@{$blob_cfg->{runs}}) {
my $b = $blob->clone($_);
push @PossibleBlobNames, $b->name();
# filter out extras
if ($FilterNames) {
next if ! grep { $b->name() =~ m/$_/; } @ActiveBlobNames;
}
push @BlobPlan, $b;
}
}
if (!@BlobPlan) {
die("No blobs!\n") unless $FilterNames;
die(sprintf("No matching blobs among: %s\n",
join(' ', @PossibleBlobNames)));
}
&Log("pid: $$");
&printRoutes(@Hosts);
&Log("starting...");
&Log("plan: ", join(' ', map { $_->name() } @BlobPlan));
&startNext(); # start the sequence
while (defined &BB::Executer::Step(60)) { ; }
&Log("terminating...");
exit 0;
sub startNext {
my $blob = shift @BlobPlan;
return &Log("no more blobs") unless $blob;
$blob->run(\&blobDone);
}
sub blobDone {
&startNext();
}
sub Cmd {
my ($tmpl, $label) = @_;
return new BB::Command($tmpl, $label || 'local');
}
sub All {
my $tmpl = shift;
my $cmd = Cmd($tmpl, '$host');
my @cfgs = Cfgs('host', @Hosts);
return BB::Tools::Breed($cmd, @cfgs);
}
sub Pairs {
my ($tmpl_clt, $tmpl_srv) = @_;
my $cmd_clt = Cmd($tmpl_clt, '$clt');
my $cmd_srv = Cmd($tmpl_srv, '$srv');
# these are actually the same
my @cfgs_clt = Cfgs2(\%HostPairs);
my @cfgs_srv = Cfgs2(\%HostPairs);
# note the order!
return
BB::Tools::Breed($cmd_srv, @cfgs_srv),
BB::Tools::Breed($cmd_clt, @cfgs_clt);
}
sub Runs {
my $var_name = shift;
return Cfgs($var_name, @_);
}
sub Cfgs {
my $var_name = shift;
my @cfgs = ();
foreach (@_) {
push @cfgs, {
$var_name => $_,
Proxy => $Proxy,
Take => $Take,
Master => $Master,
};
}
return @cfgs;
}
sub Cfgs2 {
my $hosts = shift;
my @cfgs = ();
my ($clt, $srv);
while (($clt, $srv) = each %{$hosts}) {
push @cfgs, { clt => $clt, srv => $srv,
Proxy => $Proxy,
Take => $Take,
Master => $Master,
};
}
return @cfgs;
}
# read well-known environment variables for clt/srv addresses
sub importHostNames {
my $err = sprintf("bad \$clients or \$servers env vars!\nclt: %s\nsrv: %s;\nstopped",
$ENV{'clients'} || '<none>',
$ENV{'servers'} || '<none>');
die($err) if !$ENV{'clients'} || !$ENV{'servers'};
my @clts = split(/\s+/, $ENV{'clients'});
my @srvs = split(/\s+/, $ENV{'servers'});
die($err) if !@clts || !@srvs;
die($err) if (scalar @clts) != (scalar @srvs);
die($err) if grep { !&hostAddr('[13579]$', $_) } @clts;
die($err) if grep { !&hostAddr('[02468]$', $_) } @srvs;
my @res = ();
while (@clts && @srvs) {
push @res, pop @clts, pop @srvs;
}
return @res;
}
sub printRoutes {
my @routes = @_;
my $table = '';
for (my $i = 0; $i <= $#routes; $i += 2) {
$table .= sprintf("%s => %s\n", $routes[$i], $routes[$i+1]);
}
&Log("routing table:\n", ButifyBuf($table));
}
sub hostAddr {
my $pattern = shift;
for (shift) {
return undef unless $_;
my @comps = split /\./;
return undef if !@comps;
return undef if $comps[$#comps] !~ /$pattern/;
}
return 1;
}
syntax highlighted by Code2HTML, v. 0.9.1