Commit 96530667 authored by Kirk Webb's avatar Kirk Webb

Updates to parsing for blockstore objects.

parent 8109ceb1
#!/usr/bin/perl -wT
#
# Copyright (c) 2005-2012 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
package BlockstoreType;
use strict;
use Exporter;
use vars qw(@ISA @EXPORT);
@ISA = "Exporter";
@EXPORT = qw ( );
use libdb;
use libtestbed;
use English;
use Data::Dumper;
use overload ('""' => 'Stringify');
# Cache of instances to avoid regenerating them.
my %bstypes = ();
my $debug = 0;
# Little helper and debug function.
sub mysystem($)
{
my ($command) = @_;
print STDERR "Running '$command'\n"
if ($debug);
return system($command);
}
#
# Lookup a (physical) storage object type and create a class instance to
# return.
#
sub Lookup($$)
{
my ($class, $type) = @_;
# Look in cache first
return $bstypes{$type}
if (exists($bstypes{$type}));
my $self = {};
$self->{"TYPE"} = $type;
$self->{"ATTRS"} = undef;
bless($self, $class);
# Load attributes for type from DB. No attrs means type doesn't exist.
$self->LoadAttributes();
if (!$self->{"ATTRS"}) {
return undef;
}
# Add to cache.
$bstypes{$type} = $self;
return $self;
}
#
# Force a reload of the data.
#
sub LookupSync($$)
{
my ($class, $type) = @_;
# delete from cache
delete($bstypes{$type})
if (exists($bstypes{$type}));
return Lookup($class, $type);
}
#
# Return a list of all types.
#
sub AllTypes($)
{
my ($class) = @_;
my @alltypes = ();
my $query_result =
DBQueryWarn("select distinct type from blockstore_type_attributes");
return undef
if (!$query_result || !$query_result->numrows);
while (my ($type) = $query_result->fetchrow_array()) {
my $typeinfo = Lookup($class, $type);
# Something went wrong?
return undef
if (!defined($typeinfo));
push(@alltypes, $typeinfo);
}
return @alltypes;
}
sub AllClasses($)
{
my ($class) = @_;
my @allclasses = ();
my @alltypes = $class->AllTypes();
foreach my $bst (@alltypes) {
my $cl = $bst->class();
if ($cl) {
push(@allclasses, $cl)
}
}
return @allclasses;
}
sub AllProtocols($)
{
my ($class) = @_;
my @allprotos = ();
my @alltypes = $class->AllTypes();
foreach my $bst (@alltypes) {
my $proto = $bst->protocol();
if ($proto) {
push(@allprotos, $proto)
}
}
return @allprotos;
}
#
# Load attributes if not already loaded.
#
sub LoadAttributes($)
{
my ($self) = @_;
return -1
if (!ref($self));
return 0
if (defined($self->{"ATTRS"}));
#
# Get the attribute array.
#
my $type = $self->type();
my $query_result =
DBQueryWarn("select attrkey,attrvalue,attrtype ".
" from blockstore_type_attributes ".
"where type='$type'");
$self->{"ATTRS"} = {};
while (my ($key,$val,$type) = $query_result->fetchrow_array()) {
$self->{"ATTRS"}->{$key} = { "key" => $key,
"value" => $val,
"type" => $type };
}
return 0;
}
#
# Stringify for output.
#
sub Stringify($)
{
my ($self) = @_;
my $type = $self->type();
my $class = $self->class();
return "[BlockstoreType: $type/$class]";
}
#
# Look for an attribute.
#
sub GetAttribute($$;$$)
{
my ($self, $attrkey, $pattrvalue, $pattrtype) = @_;
goto bad
if (!ref($self));
$self->LoadAttributes() == 0
or goto bad;
if (!exists($self->{"ATTRS"}->{$attrkey})) {
return undef
if (!defined($pattrvalue));
$$pattrvalue = undef;
return 0;
}
my $ref = $self->{"ATTRS"}->{$attrkey};
# Return value instead if a $pattrvalue not provided.
return $ref->{'value'}
if (!defined($pattrvalue));
$$pattrvalue = $ref->{'value'};
$$pattrtype = $ref->{'type'}
if (defined($pattrtype));
return 0;
bad:
return undef
if (!defined($pattrvalue));
$$pattrvalue = undef;
return -1;
}
#
# Grab all attributes.
#
sub GetAttributes($)
{
my ($self) = @_;
return undef
if (!ref($self));
$self->LoadAttributes() == 0
or return undef;
return $self->{"ATTRS"};
}
# Shortcuts for typical attributes.
sub type($) { return $_[0]->{'TYPE'}; }
sub class($;$) {return GetAttribute($_[0], "class", $_[1]); }
sub protocol($;$) {return GetAttribute($_[0], "protocol", $_[1]); }
#
# Set the value of an attribute
#
sub SetAttribute($$$;$)
{
my ($self, $attrkey, $attrvalue, $attrtype) = @_;
goto bad
if (!ref($self));
$self->LoadAttributes() == 0
or return -1;
$attrtype = "string"
if (!defined($attrtype));
my $safe_attrvalue = DBQuoteSpecial($attrvalue);
my $type = $self->type();
DBQueryWarn("replace into node_type_attributes set ".
" type='$type', attrkey='$attrkey', ".
" attrtype='$attrtype', attrvalue=$safe_attrvalue")
or return -1;
$self->{"ATTRS"}->{$attrkey} = $attrvalue;
return 0;
}
# _Always_ make sure that this 1 is at the end of the file...
1;
...@@ -48,7 +48,7 @@ LIB_SCRIPTS = libdb.pm Node.pm libdb.py libadminctrl.pm Experiment.pm \ ...@@ -48,7 +48,7 @@ LIB_SCRIPTS = libdb.pm Node.pm libdb.py libadminctrl.pm Experiment.pm \
Image.pm OSinfo.pm Archive.pm Logfile.pm Lan.pm emdbi.pm \ Image.pm OSinfo.pm Archive.pm Logfile.pm Lan.pm emdbi.pm \
emdb.pm emutil.pm Firewall.pm VirtExperiment.pm libGeni.pm \ emdb.pm emutil.pm Firewall.pm VirtExperiment.pm libGeni.pm \
libEmulab.pm EmulabConstants.pm TraceUse.pm EmulabFeatures.pm \ libEmulab.pm EmulabConstants.pm TraceUse.pm EmulabFeatures.pm \
Port.pm Port.pm BlockstoreType.pm
# Stuff installed on plastic. # Stuff installed on plastic.
USERSBINS = genelists.proxy dumperrorlog.proxy backup USERSBINS = genelists.proxy dumperrorlog.proxy backup
......
...@@ -39,11 +39,12 @@ Blockstore instproc init {s} { ...@@ -39,11 +39,12 @@ Blockstore instproc init {s} {
$self set node {} $self set node {}
$self set type {} $self set type {}
$self set size 0 $self set size 0
$self set sclass {}
$self set proto {}
$self set type {} $self set type {}
$self set role "unknown" $self set role "unknown"
#$self set parameters {}
# storage attributes (class, protocol, etc.)
$self instvar attributes
array set attributes {}
set ::GLOBALS::last_class $self set ::GLOBALS::last_class $self
} }
...@@ -55,38 +56,40 @@ Blockstore instproc rename {old new} { ...@@ -55,38 +56,40 @@ Blockstore instproc rename {old new} {
} }
Blockstore instproc set-class {newclass} { Blockstore instproc set-class {newclass} {
set bsclasses [list "SAN" "local"] var_import ::TBCOMPAT::soclasses
$self instvar attributes
if {[lsearch -exact $bsclasses $newclass] == -1} { if {![info exists soclasses($newclass)]} {
perror "\[set-class] Class must be one of: [join $bsclasses {, }]" perror "\[set-class] Invalid storage class: $newclass"
return return
} }
$self set sclass $newclass $self set attributes(class) $newclass
return return
} }
Blockstore instproc set-protocol {newproto} { Blockstore instproc set-protocol {newproto} {
set protocols [list "iSCSI" "FCoE" "SCSI" "SATA"] var_import ::TBCOMPAT::soprotocols
$self instvar attributes
if {[lsearch -exact $protocols $newproto] == -1} { if {![info exists soprotocols($newproto)]} {
perror "\[set-protocol] Protocol must be one of: [join $protocols {, }]" perror "\[set-protocol] Invalid storage protocol: $newproto"
return return
} }
$self set proto $newproto $self set attributes(protocol) $newproto
return return
} }
Blockstore instproc set-type {newtype} { Blockstore instproc set-type {newtype} {
var_import ::TBCOMPAT::sotypes var_import ::TBCOMPAT::sotypes
if {[lsearch $sotypes $newtype] == -1} { if {![info exists sotypes($newtype)]} {
perror "\[set-type] Invalid Storage Object type: $newtype" perror "\[set-type] Invalid storage object type: $newtype"
return return
} }
$self set type $newtype $self set type $type
return return
} }
...@@ -98,7 +101,7 @@ Blockstore instproc set-size {newsize} { ...@@ -98,7 +101,7 @@ Blockstore instproc set-size {newsize} {
# Do some boundary checks. # Do some boundary checks.
if { $convsize < $mindisksize } { if { $convsize < $mindisksize } {
perror "\[set-size] $convsize is smaller than allowed minimum (1 MiB)" perror "\[set-size] $newsize is smaller than allowed minimum (1 MiB)"
return return
} }
if { $convsize % $mindisksize } { if { $convsize % $mindisksize } {
...@@ -118,33 +121,27 @@ Blockstore instproc set-size {newsize} { ...@@ -118,33 +121,27 @@ Blockstore instproc set-size {newsize} {
Blockstore instproc updatedb {DB} { Blockstore instproc updatedb {DB} {
var_import ::GLOBALS::pid var_import ::GLOBALS::pid
var_import ::GLOBALS::eid var_import ::GLOBALS::eid
var_import ::TBCOMPAT::sotypes
$self instvar sim $self instvar sim
$self instvar node $self instvar node
$self instvar type $self instvar type
$self instvar size $self instvar size
$self instvar role $self instvar role
#$self instvar parameters $self instvar attributes
if { $role == "unknown" } { # XXX: role needs more thought...
puts stderr "*** WARNING: Disk role not set and unable to infer it." #if { $role == "unknown" } {
} # puts stderr "*** WARNING: blockstore role not set and unable to infer it."
#}
# Emit top-level storage object stuff.
set vb_fields [list "vname" "type" "role" "size"] set vb_fields [list "vname" "type" "role" "size"]
set vb_values [list $self $type $role $size] set vb_values [list $self $type $role $size]
$sim spitxml_data "virt_blockstores" $vb_fields $vb_values
#if { $parameters != "" } { # Emit attributes.
#lappend fields "parameters" foreach key [lsort [array names attributes]] {
#lappend values $parameters set val $attributes($key)
#} $sim spitxml_data "virt_blockstore_attributes" [list "vname" "attrkey" "attrvalue"] [list $self $key $val]
#if { $command != "" } { }
#lappend fields "command"
#lappend values $command
#}
# Update the DB
spitxml_data "virt_blockstores" $vb_fields $vb_values
#$sim spitxml_data "virt_agents" [list "vnode" "vname" "objecttype" ] [list $node $self $objtypes(DISK) ]
} }
...@@ -109,6 +109,7 @@ use NodeType; ...@@ -109,6 +109,7 @@ use NodeType;
use Template; use Template;
use Experiment; use Experiment;
use User; use User;
use BlockstoreType;
use constant false => 0; use constant false => 0;
use constant true => 1; use constant true => 1;
...@@ -871,6 +872,22 @@ sub GenDefsFile($) ...@@ -871,6 +872,22 @@ sub GenDefsFile($)
} }
print TCL "\n\n"; print TCL "\n\n";
print TCL "# Storage Objects\n";
my @sotypes = BlockstoreType->AllTypes();
foreach my $sot (@sotypes) {
my $type = $sot->type();
my $cl = $sot->class();
my $proto = $sot->protocol();
print TCL "set sotypes($type) 1\n"
if defined($type);
print TCL "set soclasses($cl) 1\n"
if defined($cl);
print TCL "set soprotocols($proto) 1\n"
if defined($proto);
}
print TCL "\n\n";
print TCL "}\n"; print TCL "}\n";
close(TCL); close(TCL);
} }
......
...@@ -394,6 +394,7 @@ source ${GLOBALS::libdir}/sequence.tcl ...@@ -394,6 +394,7 @@ source ${GLOBALS::libdir}/sequence.tcl
source ${GLOBALS::libdir}/console.tcl source ${GLOBALS::libdir}/console.tcl
source ${GLOBALS::libdir}/topography.tcl source ${GLOBALS::libdir}/topography.tcl
source ${GLOBALS::libdir}/disk.tcl source ${GLOBALS::libdir}/disk.tcl
source ${GLOBALS::libdir}/blockstore.tcl
source ${GLOBALS::libdir}/custom.tcl source ${GLOBALS::libdir}/custom.tcl
################################################## ##################################################
...@@ -638,7 +639,6 @@ proc convert_to_bytes {size} { ...@@ -638,7 +639,6 @@ proc convert_to_bytes {size} {
set unit B set unit B
} }
# We could do better below with a regexp match. But it is better to keep it simple.
switch -- $unit { switch -- $unit {
B {set val $sz} B {set val $sz}
KB {set val [expr int($sz * 10**3)]} KB {set val [expr int($sz * 10**3)]}
......
...@@ -96,6 +96,8 @@ namespace eval TBCOMPAT { ...@@ -96,6 +96,8 @@ namespace eval TBCOMPAT {
# Storage object tracking (types, resources, etc.) # Storage object tracking (types, resources, etc.)
variable sotypes variable sotypes
variable soclasses
variable soprotocols
# NSE hack: sim type is not in DB. Just adding it now # NSE hack: sim type is not in DB. Just adding it now
set hwtypes(sim) 1 set hwtypes(sim) 1
......
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