Commit e42d618d authored by Robert Ricci's avatar Robert Ricci
Browse files

Merge branch 'master' of git-public.flux.utah.edu:/flux/git/emulab-devel

parents 7737d85d ff389d95
event/trafgen/tg2.0
event/linktest/iperf/iperf-2.0.2
event/linktest/rude/rude-0.70
sensors/nfstrace/nfsdump2/Makefile
sensors/nfstrace/nfsdump2/config.h
sensors/nfstrace/nfsdump2/config.log
......
......@@ -2478,5 +2478,32 @@ sub LookupWideArea($$)
return Node->Lookup($node_id);
}
#
# Return the partition that an OSID is loaded on.
#
sub IsOSLoaded($$)
{
my ($self, $osinfo) = @_;
if (!ref($osinfo)) {
my $tmp = OSinfo->Lookup($osinfo);
if (!defined($tmp)) {
print STDERR "Cannot lookup osinfo for $osinfo\n";
return -1;
}
$osinfo = $tmp;
}
my $osid = $osinfo->osid();
my $nodeid = $self->node_id();
my $query_result =
DBQueryWarn("select osid from partitions as p ".
"where p.node_id='$nodeid' and p.osid='$osid'");
return -1
if (!$query_result);
return $query_result->numrows;
}
# _Always_ make sure that this 1 is at the end of the file...
1;
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2007-2009 University of Utah and the Flux Group.
# Copyright (c) 2007-2010 University of Utah and the Flux Group.
# All rights reserved.
#
package OSinfo;
......@@ -19,6 +19,7 @@ use libdb;
use libtestbed;
use Project;
use User;
use Image;
use English;
use Data::Dumper;
use overload ('""' => 'Stringify');
......@@ -433,6 +434,17 @@ sub ValidOpMode($$)
return (exists($OPMODES{$opmode}) ? 1 : 0);
}
#
# Is the osinfo "generic"
#
sub IsGeneric($)
{
my ($self) = @_;
my $version = $self->version();
return ((defined($version) && $version ne "") ? 0 : 1);
}
#
# Boot command like. The caller supplies the default in $pref.
#
......@@ -618,5 +630,28 @@ sub RunsOnParent($$)
return 1;
}
#
# Map an osinfo and node type to the actual image.
#
sub MapToImage($$)
{
my ($self, $type) = @_;
if (ref($type)) {
$type = $type->type();
}
my $osid = $self->osid();
my $query_result =
DBQueryWarn("select imageid from osidtoimageid ".
"where type='$type' and osid='$osid'");
return undef
if (!defined($query_result) || !$query_result->numrows);
my ($imageid) = $query_result->fetchrow_array();
return Image->Lookup($imageid);
}
# _Always_ make sure that this 1 is at the end of the file...
1;
......@@ -51,6 +51,7 @@ my $VERIFYCRED = "$TB/sbin/verifygenicred";
my $NODEREBOOT = "$TB/bin/node_reboot";
my $VNODESETUP = "$TB/sbin/vnode_setup";
my $POWER = "$TB/bin/power";
my $OSLOAD = "$TB/bin/os_load";
my $SNMPIT = "$TB/bin/snmpit";
my $NAMEDSETUP = "$TB/sbin/named_setup";
my $EXPORTS_SETUP = "$TB/sbin/exports_setup";
......@@ -745,6 +746,7 @@ sub Start($$$)
my %reboots = ();
my %vnodes = ();
my %poweron = ();
my %reloads = ();
foreach my $sliver (@slivers) {
next
......@@ -770,20 +772,87 @@ sub Start($$$)
if ($node->isvirtnode()) {
$vnodes{$node->node_id} = $node;
# A virtnode on a shared physical node needs nothing else.
next
if ($node->sharing_mode());
# But if non-shared, have to make sure that the phys node
# gets loaded.
my $physnodeid = $node->phys_nodeid();
next
if (exists($poweron{$physnodeid}) ||
exists($reboots{$physnodeid}) ||
exists($reloads{$physnodeid}));
$node = Node->Lookup($physnodeid);
if (!defined($node)) {
print STDERR "Could not lookup $physnodeid\n";
return -1;
}
}
#
# Look to see if local physical node was stopped (powered off).
#
if (!$node->isremotenode() &&
$sliver->state() eq "stopped") {
$poweron{$node->node_id} = $node;
}
else {
# node_reboot is smart enough to know that if a pnode
# is rebooted it can ignore the vnodes on it, so do
# not optimize this here.
$reboots{$node->node_id} = $node;
}
next
if (!$node->imageable());
my $osinfo = OSinfo->Lookup($node->def_boot_osid());
if (!defined($osinfo)) {
print STDERR "Could not get osinfo for $node\n";
return -1;
}
print STDERR "$node wants to boot $osinfo.\n";
if ($osinfo->IsGeneric()) {
#
# Look to see if local physical node was stopped (powered off).
# Map generic OSID to the specific one.
#
if (!$node->isremotenode() &&
$sliver->state() eq "stopped") {
$poweron{$node->node_id} = $node;
my $tmp = $osinfo->ResolveNextOSID($experiment);
if (!defined($tmp)) {
print STDERR "No next mapping for $osinfo on $node!\n";
return -1;
}
print STDERR " Mapping $osinfo on $node to $tmp\n";
$osinfo = $tmp;
}
#
# Make sure this OSID is actually loaded on the machine.
#
my $isloaded = $node->IsOSLoaded($osinfo);
if ($isloaded < 0) {
print STDERR
"Error determining if $osinfo is loaded on $node\n";
return -1;
}
if (! $isloaded) {
print STDERR " Setting up a reload for $node\n";
my $image = $osinfo->MapToImage($node->type());
if (!defined($image)) {
print STDERR " No image for $osinfo on $node\n";
return -1;
}
else {
# node_reboot is smart enough to know that if a pnode
# is rebooted it can ignore the vnodes on it, so do
# not optimize this here.
$reboots{$node->node_id} = $node;
if (!exists($reloads{$image->imageid()})) {
$reloads{$image->imageid()} = [ ];
}
push(@{ $reloads{$image->imageid()} }, $node);
}
else {
#
# Make sure boot is set correctly.
#
if ($node->OSSelect($osinfo, "def_boot_osid", 0)) {
print STDERR " Could not os_select $node to $osinfo\n";
return -1;
}
}
}
......@@ -806,6 +875,21 @@ sub Start($$$)
}
%vnodes = %tmp;
#
# Setup the reloads. We do not reboot the nodes until below.
#
if (keys(%reloads)) {
foreach my $imageid (keys(%reloads)) {
my @nodes = @{ $reloads{$imageid} };
my @node_ids = map { $_->node_id() } @nodes;
# No wait, no reboot. reload runs completely in the background.
system("$OSLOAD -s -r -m $imageid @node_ids");
return -1
if ($?);
}
}
if ($version >= 2) {
if (system("$GENTOPOFILE $pid $eid")) {
print STDERR "$GENTOPOFILE failed\n";
......@@ -836,7 +920,7 @@ sub Start($$$)
}
}
}
system("$SNMPIT -t $pid $eid");
system("$SNMPIT -q -t $pid $eid");
if ($?) {
print STDERR "$SNMPIT failed\n";
return -1;
......@@ -965,7 +1049,7 @@ sub Stop($$)
%vnodes = %tmp;
if ($version >= 2) {
system("$SNMPIT -r $pid $eid");
system("$SNMPIT -q -r $pid $eid");
if ($?) {
print STDERR "$SNMPIT failed\n";
return -1;
......
......@@ -92,7 +92,14 @@ my $API_VERSION = 2;
#
sub GetVersion()
{
return GeniResponse->Create( GENIRESPONSE_SUCCESS, $API_VERSION );
my $blob = {
"api" => $API_VERSION,
"level" => 1,
"input_rspec" => ( "0.1", "2" ),
"output_rspec" => "0.1"
};
return GeniResponse->Create( GENIRESPONSE_SUCCESS, $blob );
}
#
......
......@@ -764,14 +764,6 @@ sub Provision($;$)
if ($node->ModifyReservation({"genisliver_idx" => $self->idx()})) {
return -1;
}
#
# Terrible place to do this.
#
if ($node->OSSelect("<DEFAULT>", "def_boot_osid", 0) != 0) {
print STDERR "Could not os_select $node to default\n";
return -1;
}
}
return 0;
}
......
......@@ -7,6 +7,10 @@
use strict;
use lib '@prefix@/lib';
# Do this early so that we talk to the right DB.
use vars qw($GENI_DBNAME $GENI_ISCLRHOUSE);
BEGIN { $GENI_DBNAME = "geni-ch"; $GENI_ISCLRHOUSE = 1; }
use GeniCredential;
use GeniCertificate;
use GeniAuthority;
......@@ -67,7 +71,7 @@ if($numArgs !=2) {
print "Please specify <user-urn> <ch-urn> as command line arguments\n\n";
}else{
my $val = CreateSpecialCredential @ARGV;
print STDERR $val->{"code"};
print STDERR $val->{"value"};
print $val->{"output"};
#print $val->{"output"};
#print $val->{"code"};
print $val->{"value"};
}
......@@ -17,7 +17,9 @@
import getopt
import os
import re
import socket
import sys
import xml.dom.minidom
import xmlrpclib
from M2Crypto import X509
......@@ -40,6 +42,7 @@ def Usage():
-s file, --slicecredentials=file read slice credentials from file
[default: query from SA]
Commands:
copy <source> <dest> copy local dir/file <source> to remote <dest>
exec <command> run <command> on slice nodes
install <file> extract tape archive <file> onto slice nodes
list show IP addresses of node control interfaces"""
......@@ -47,6 +50,7 @@ Commands:
execfile( "test-common.py" )
NOTREADY = "---notready---"
RSYNC = "/usr/local/bin/rsync"
SSH = "/usr/bin/ssh"
#
......@@ -55,7 +59,13 @@ SSH = "/usr/bin/ssh"
commands = []
while args:
command = args.pop( 0 )
if command == "install":
if command == "copy":
if len( args ) < 2: Fatal( sys.argv[ 0 ] +
": command \"copy\" requires two parameters" )
source = args.pop( 0 )
dest = args.pop( 0 )
commands.append( ( command, source, dest ) )
elif command == "install":
if not args: Fatal( sys.argv[ 0 ] +
": command \"install\" requires a parameter" )
file = args.pop( 0 )
......@@ -98,11 +108,11 @@ if debug: print str( response[ "value" ] )
#
# Ask each manager for its relevant nodes. We talk to the component
# managers in parallel, but ask about each of its nodes serially: this
# managers in parallel, but send each of its requests serially: this
# ought to allow a reasonable amount of concurrency without excessively
# burdening any individual server.
#
params = { "credential" : slicecred }
params = { "slice_urn" : slice[ "urn" ], "credentials" : [ slicecred ] }
( pr, pw ) = os.pipe()
for cm in response[ "value" ]:
......@@ -124,33 +134,48 @@ for cm in response[ "value" ]:
print >> p, text
rval, response = do_method( None, "SliceStatus", params, cm[ "url" ],
True )
try:
rval, response = do_method( None, "SliverStatus", params, \
cm[ "url" ], True )
except:
print >> sys.stderr, "Warning: could not obtain sliver status " + \
"from " + cm[ "url" ]
os._exit( 1 )
if not rval:
if response[ "value" ][ "status" ] == "ready":
# We have a list of node IDs: now iterate over them, and hunt
# through all the details looking for the control address for
# each one.
for node in response[ "value" ][ "details" ].keys():
params[ "type" ] = "Node"
params[ "uuid" ] = node
rval, response = do_method( None, "Resolve", params,
cm[ "url" ] )
if rval:
print >> sys.stderr, "Could not resolve node " + \
node
os._exit( 1 )
if "physctrl" in response[ "value" ]:
Say( response[ "value" ][ "physctrl" ] )
elif "interfaces" in response[ "value" ]:
for interface in response[ "value" ][ "interfaces" ]:
if interface[ "role" ] == "ctrl":
Say( interface[ "IP" ] )
break
else:
print >> sys.stderr, "No address available for " + \
node
os._exit( 1 )
# There is a sliver here for us. Look up its name...
rval, response = do_method( None, "Resolve",
{ "urn" : slice[ "urn" ],
"credentials" : [ slicecred ] },
cm[ "url" ], True )
if rval:
print >> sys.stderr, "Could not resolve slice " + \
slice[ "urn" ]
os._exit( 1 )
sliver = response[ "value" ][ "sliver_urn" ];
# Now we have the sliver name, and can resolve it to
# obtain the manifest.
rval, response = do_method( None, "Resolve",
{ "urn" : sliver,
"credentials" : [ slicecred ] },
cm[ "url" ], True )
if rval:
print >> sys.stderr, "Could not resolve sliver " + sliver
os._exit( 1 )
# Wade through the manifest, and look for all node elements,
# noting the host name of each one.
doc = xml.dom.minidom.parseString( response[ "value" ] \
[ "manifest" ] )
for node in filter( lambda x: x.nodeName == "node",
doc.documentElement.childNodes ):
if node.hasAttribute( "hostname" ):
Say( socket.gethostbyname( node.getAttribute( \
"hostname" ) ) )
else:
Say( NOTREADY )
......@@ -189,7 +214,25 @@ for cm in response[ "value" ]:
nodes.sort()
for command in commands:
if command[ 0 ] == "exec":
if command[ 0 ] == "copy":
print "Copying \"" + command[ 1 ] + "\" to \"" + command[ 2 ] + "\"..."
child = {}
for node in nodes:
pid = os.fork()
if pid:
child[ pid ] = node
else:
os.execl( RSYNC, "rsync", "-a", "-e",
SSH + " -T -o 'BatchMode yes' " +
"-o 'StrictHostKeyChecking no' " +
"-o 'EscapeChar none'",
command[ 1 ], node + ":" + command[ 2 ] )
os._exit( 1 )
for node in nodes:
( pid, status ) = os.wait()
print " (finished on node " + child[ pid ] + ")"
elif command[ 0 ] == "exec":
print "Executing command \"" + command[ 1 ] + "\"..."
for node in nodes:
if not os.fork():
......
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2009 University of Utah and the Flux Group.
# Copyright (c) 2000-2010 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
......@@ -212,7 +212,7 @@ if (defined($options{"m"})) {
usage()
if (defined($options{"i"}));
foreach my $imageid (split /,/, $options{"i"}) {
foreach my $imageid (split /,/, $options{"m"}) {
if ($imageid =~ /^([-\w\.\+]+)$/) {
$imageid = $1;
......
......@@ -295,6 +295,7 @@ foreach my $power_id (keys %outlets) {
if ($power_id eq "mail" || $power_id =~ /^whol-/
|| $power_id=~ /^rmcp-/
|| $power_id eq 'drac'
|| $power_id eq 'ilo' || $power_id eq 'ilo2') {
$type = $power_id;
$IP = "";
......@@ -359,7 +360,7 @@ foreach my $power_id (keys %outlets) {
print "Control of $nodestr failed.\n"; ++$exitval;
++$errors;
}
} elsif ($type eq 'ilo2' || $type eq 'ilo') {
} elsif ($type eq 'ilo2' || $type eq 'ilo' || $type eq 'drac') {
if (iloctrl($type,$op,@nodes)) {
print "Control of $nodestr failed.\n"; ++$exitval;
++$errors;
......
......@@ -2,12 +2,13 @@
#
# EMULAB-COPYRIGHT
# Copyright (c) 2008 University of Utah and the Flux Group.
# Copyright (c) 2008-2010 University of Utah and the Flux Group.
# All rights reserved.
#
#
# Handle iLO or iLO 2 remote power control.
# Also handle DRAC since its so similar.
# Node must have an interface such that role='other' and
# interface_type='ilo2' or 'ilo'.
#
......@@ -22,6 +23,7 @@ use Exporter;
use lib "@prefix@/lib";
use libdb;
use emutil;
use IO::Pty;
use POSIX qw(setsid);
......@@ -67,7 +69,7 @@ sub iloctrl($$@) {
" where node_id='$n' and role='other'" .
" and interface_type='$type'");
if (!defined($res) || !$res || $res->num_rows() == 0) {
warn "No $type interface for $n; cannot find iLO IP!\n";
warn "No $type interface for $n; cannot find $type IP!\n";
++$exitval;
next;
}
......@@ -83,47 +85,48 @@ sub iloctrl($$@) {
}
my ($krole,$kuid,$kkey) = $res->fetchrow();
$ilo_nodeinfo{$n} = [ $IP,$krole,$kuid,$kkey ];
$ilo_nodeinfo{$n} = [ $n,$IP,$krole,$kuid,$kkey ];
}
my %kids = ();
my $timeout = 30;
for my $n (keys(%ilo_nodeinfo)) {
my ($IP,$krole,$kuid,$kkey) = @{$ilo_nodeinfo{$n}};
if ($parallelize) {
if (my $pid = fork()) {
$kids{$pid} = 1;
}
else {
my $tret;
eval {
$tret = iloexec($n,$type,$cmd,$IP,$krole,$kuid,$kkey,
$timeout);
};
if ($@) {
print "$@";
exit -1;
}
if ($parallelize) {
my $coderef = sub {
my ($n,$IP,$krole,$kuid,$kkey) = @{ $_[0] };
my $tret;
eval {
$tret = iloexec($n,$type,$cmd,$IP,$krole,$kuid,$kkey,$timeout);
};
if ($@) {
print "$@";
return -1;
}
return 0;
};
my @results = ();
my @ilos = values(%ilo_nodeinfo);
if (ParRun(undef, \@results, $coderef, @ilos)) {
print STDERR "*** power_ilo: Internal error in ParRun()!\n";
return -1;
}
else {
if (iloexec($n,$type,$cmd,$IP,$krole,$kuid,$kkey,$timeout)) {
++$exitval;
}
#
# Check the exit codes.
#
foreach my $result (@results) {
++$exitval
if ($result != 0);
}
}
else {
for my $key (keys(%ilo_nodeinfo)) {
my ($n,$IP,$krole,$kuid,$kkey) = @{$ilo_nodeinfo{$key}};
# grab child exit vals
if ($parallelize) {
while (wait() > 0) {
if ($?) {
if (iloexec($n,$type,$cmd,$IP,$krole,$kuid,$kkey,$timeout)) {
++$exitval;
}
}
}
return $exitval;
}
......@@ -147,24 +150,28 @@ sub iloexec($$$$$$$;$) {
my $power_cmd;
if ($cmd eq 'cycle') {
$power_cmd = 'power reset';
$power_cmd = ($type eq "drac" ?
'racadm serveraction powercycle' : 'power reset');
}
elsif ($cmd eq 'reset') {
$power_cmd = 'power warm';
$power_cmd = ($type eq "drac" ?
'racadm serveraction hardreset' : 'power warm');
}
elsif ($cmd eq 'on') {
$power_cmd = 'power on';
$power_cmd = ($type eq "drac" ?
'racadm serveraction powerup' : 'power on');
}
elsif ($cmd eq 'off') {
$power_cmd = 'power off';