Commit 53813c8e authored by Kirk Webb's avatar Kirk Webb

Move storageconfig fetch/parse code to libsetup.

Create "getstorageconfig" call in libsetup, following the tradition with
other tmcc information fetching routines.  It's guts were yanked out of
rc.storage.

Outside of calling the moved code from libsetup, rc.storage was also
changed slightly to store the returned information using "Storable"
since it's now dealing with an array of hashes instead of raw lines
of output from tmcc.
parent a68c8eca
......@@ -24,6 +24,7 @@
use English;
use Getopt::Std;
use Socket qw(inet_ntoa);
use Storable;
sub usage()
{
......@@ -111,53 +112,42 @@ exit(0);
#
sub doboot()
{
my @lines = ();
my $bossip;
print STDOUT "Checking Testbed storage configuration ... \n";
# XXX testing with no tmcd support
if (0) {
my @foo = (
"CMD=ELEMENT IDX=1 VOLNAME=d-1 CLASS=SAN PROTO=iSCSI HOSTID=blockhost-d-1 UUID=$IQN_PREFIX:testbed:smallsan:d-1 UUID_TYPE=iqn VOLSIZE=1000000000 PERMS=RW",
"CMD=ELEMENT IDX=2 VOLNAME=d-2 CLASS=SAN PROTO=iSCSI HOSTID=blockhost-d-1 UUID=$IQN_PREFIX:testbed:smallsan:d-2 UUID_TYPE=iqn VOLSIZE=1000000000 PERMS=RW",
"CMD=ELEMENT IDX=3 VOLNAME=foo CLASS=local PROTO=local HOSTID=localhost UUID=9SF16YDY UUID_TYPE=serial VOLSIZE=488281250"
);
@lines = @foo;
}
if (!@lines) {
# XXX uncomment this for tmp testing with alternate tmcd
configtmcc("portnum", 7778);
# XXX uncomment this for tmp testing with alternate tmcd
configtmcc("portnum",7778);
if (tmcc(TMCCCMD_STORAGE, undef, \@lines) < 0) {
fatal("Could not get storage config from server!");
}
my @cmds;
if (getstorageconfig(\@cmds) != 0) {
fatal("Error grabbing storage config!");
}
return
if (!@lines);
my $storage = parse(@lines);
if (!$storage) {
fatal("Could not parse storage config!");
if (!@cmds) {
warn("*** No storageconfig output - nothing to do");
return;
}
#
# Process in increasing order of IDX.
# Process each command in turn. Already sorted by
# getstorageconfig().
#
my @cmds = sort {$a->{'IDX'} <=> $b->{'IDX'}} @{$storage};
foreach my $cmd (@cmds) {
if (!process($cmd, 1)) {
fatal("Could not process storage command!");
fatal("Could not process storage commands!");
}
}
#
# Save config
#
if (open(CFG, ">$OLDCONFIG")) {
print CFG join("\n", @lines), "\n";
close(CFG);
my $ret = eval { Storable::store(\@cmds, $OLDCONFIG); };
if ($@) {
fatal("$@");
}
if (!$ret) {
fatal("Error stashing away storage config!");
}
}
......@@ -184,132 +174,33 @@ sub doreconfig()
sub docleanup($)
{
my ($doteardown) = @_;
my @lines = ();
my $cmdref = [];
if (-r "$OLDCONFIG") {
@lines = `cat $OLDCONFIG`;
chomp(@lines);
$cmdref = eval { Storable::retrieve($OLDCONFIG); };
if ($@) {
fatal("$@");
}
if (!$cmdref) {
fatal("Could not retrieve stashed storage config!");
}
if ($doteardown) {
unlink($OLDCONFIG);
}
}
if (!@lines) {
if (!@$cmdref) {
return;
}
my $storage = parse(@lines);
if (!$storage) {
fatal("Could not parse current storage config!");
}
#
# Process in decreasing order of IDX.
# Process each command in turn. Already sorted.
#
my @cmds = sort {$b->{'IDX'} <=> $a->{'IDX'}} @{$storage};
foreach my $cmd (@cmds) {
foreach my $cmd (@$cmdref) {
if (!process($cmd, 0, $doteardown)) {
fatal("Could not process storage command!");
}
}
}
#
# Parse the storageinfo tmcd command output. Break each line into a hash,
# verifying the fields.
#
# Format:
#
# CMD=ELEMENT IDX=<index> HOSTID=<some-storage-host> \
# CLASS=(SAN|local) PROTO=(iSCSI|local) \
# UUID=<unique-id> UUID_TYPE=<id-type> \
# VOLNAME=<id> VOLSIZE=<size-in-MiB> PERMS=<permissions>
#
# Where:
#
# if CLASS=="SAN" && PROTO=="iSCSI" :
# IDX :=
# \d+ -- monotonically increasing number indicating order of operations
# HOSTID :=
# <bs-vm-shortname> -- short name for blockstore pseudo-VM
# UUID :=
# "iqn.2000-12.net.emulab:<pid>:<eid>:<bs-vname>" -- iSCSI qualified name
# constructed from static prefix, pid, eid, and blockstore vname (from ns file).
# UUID_TYPE :=
# "iqn" -- literal string
# VOLNAME :=
# string -- Emulab name for the element
# VOLSIZE :=
# \d+ -- size in mebibytes. Informational; could be used for sanity checking.
# PERMS :=
# (RO|RW) -- i.e., read-only or read-write.
#
# if CLASS=="local" :
# IDX :=
# \d+ -- monotonically increasing number indicating order of operations
# HOSTID :=
# "localhost" -- literal string
# UUID :=
# \w+ -- unique serial number of device
# UUID_TYPE :=
# "serial" -- literal string
# VOLNAME :=
# string -- Emulab name for the element
# VOLSIZE :=
# \d+ -- size in mebibytes. Informational; could be used for sanity checking.
# PERMS :=
# <notpresent> -- this field will not show up for local elements
#
sub parse(@)
{
my %fields = (
'CMD' => 'ELEMENT',
'IDX' => '\d+',
'CLASS' => '(SAN|local)',
'PROTO' => '(iSCSI|local)',
'HOSTID' => '[-\w\.]+',
'UUID' => '[-\w\.:]+',
'UUID_TYPE'=> '(iqn|serial)',
'VOLNAME' => '[-\w]+',
'VOLSIZE' => '\d+',
'PERMS' => '(RO|RW)'
);
my @ops = ();
#
# Note that any error is fatal since these lines are interdependent.
#
foreach my $line (@_) {
chomp($line);
#
# Break the line into a hash of key/values
#
my @kvs = split(/\s+/, $line);
my %res = ();
foreach my $kv (@kvs) {
my ($key,$val,$foo) = split(/=/, $kv);
if (defined($foo)) {
warn("*** WARNING: malformed key-val pair in storageinfo: '$kv'\n");
return undef;
}
#
# Validate the info.
#
if (!exists($fields{$key})) {
warn("*** WARNING: invalid keyword in storageinfo: '$key'\n");
return undef;
}
if ($val !~ /^$fields{$key}$/) {
warn("*** WARNING: invalid value for $key in storageinfo: '$val'\n");
return undef;
}
$res{$key} = $val;
fatal("Could not process storage commands!");
}
push(@ops, \%res);
}
return \@ops;
}
#
......
......@@ -40,7 +40,7 @@ use Exporter;
gettraceconfig genhostsfile getmotelogconfig calcroutes fakejailsetup
getlocalevserver genvnodesetup getgenvnodeconfig stashgenvnodeconfig
getlinkdelayconfig getloadinfo getbootwhat getnodeattributes
copyfilefromnfs getnodeuuid getarpinfo
copyfilefromnfs getnodeuuid getarpinfo getstorageconfig
getmanifest fetchmanifestblobs runbootscript runhooks
build_fake_macs
......@@ -3341,6 +3341,124 @@ sub getarpinfo($;$)
return $atype;
}
#
# Grab and parse the storageconfig tmcd command output. Break each
# line into a hash, verifying the fields. Return sorted (by index)
# list of storage commands hashes.
#
# Format:
#
# CMD=ELEMENT IDX=<index> HOSTID=<some-storage-host> \
# CLASS=(SAN|local) PROTO=(iSCSI|local) \
# UUID=<unique-id> UUID_TYPE=<id-type> \
# VOLNAME=<id> VOLSIZE=<size-in-MiB> PERMS=<permissions>
#
# Where:
#
# if CLASS=="SAN" && PROTO=="iSCSI" :
# IDX :=
# \d+ -- monotonically increasing number indicating order of operations
# HOSTID :=
# <bs-vm-shortname> -- short name for blockstore pseudo-VM
# UUID :=
# "iqn.2000-12.net.emulab:<pid>:<eid>:<bs-vname>" -- iSCSI qualified name
# constructed from static prefix, pid, eid, and blockstore vname (from ns file).
# UUID_TYPE :=
# "iqn" -- literal string
# VOLNAME :=
# string -- Emulab name for the element
# VOLSIZE :=
# \d+ -- size in mebibytes. Informational; could be used for sanity checking.
# PERMS :=
# (RO|RW) -- i.e., read-only or read-write.
#
# if CLASS=="local" :
# IDX :=
# \d+ -- monotonically increasing number indicating order of operations
# HOSTID :=
# "localhost" -- literal string
# UUID :=
# \w+ -- unique serial number of device
# UUID_TYPE :=
# "serial" -- literal string
# VOLNAME :=
# string -- Emulab name for the element
# VOLSIZE :=
# \d+ -- size in mebibytes. Informational; could be used for sanity checking.
# PERMS :=
# <notpresent> -- this field will not show up for local elements
#
sub getstorageconfig($;$) {
my ($rptr,$nocache) = @_;
my @tmccresults = ();
my %opthash = ();
if (defined($nocache) && $nocache) {
$opthash{'nocache'} = 1;
}
if (tmcc(TMCCCMD_STORAGE, undef, \@tmccresults, %opthash) < 0) {
warn("*** WARNING: Could not get storageconfig from server!\n");
return -1;
}
my %fields = (
'CMD' => 'ELEMENT',
'IDX' => '\d+',
'CLASS' => '(SAN|local)',
'PROTO' => '(iSCSI|local)',
'HOSTID' => '[-\w\.]+',
'UUID' => '[-\w\.:]+',
'UUID_TYPE'=> '(iqn|serial)',
'VOLNAME' => '[-\w]+',
'VOLSIZE' => '\d+',
'PERMS' => '(RO|RW)'
);
my @ops = ();
#
# Note that any error is fatal since these lines are interdependent.
#
foreach my $line (@tmccresults) {
chomp($line);
#
# Break the line into a hash of key/values
#
my @kvs = split(/\s+/, $line);
my %res = ();
foreach my $kv (@kvs) {
my ($key,$val,$foo) = split(/=/, $kv);
if (defined($foo)) {
warn("*** WARNING: malformed key-val pair in storageinfo: '$kv'\n");
return -1;
}
#
# Validate the info.
#
if (!exists($fields{$key})) {
warn("*** WARNING: invalid keyword in storageinfo: '$key'\n");
return -1;
}
if ($val !~ /^$fields{$key}$/) {
warn("*** WARNING: invalid value for $key in storageinfo: '$val'\n");
return -1;
}
$res{$key} = $val;
}
push(@ops, \%res);
}
#
# return operations in decreasing order of IDX.
#
my @sortedops = sort {$b->{'IDX'} <=> $a->{'IDX'}} @ops;
@$rptr = @sortedops;
return 0;
}
#
# Fork a process to exec a command. Return the pid to wait on.
#
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment