Commit f9cfddd4 authored by Leigh Stoller's avatar Leigh Stoller

Changes to node control (web page). Added a backend script to do this

stuff so that the web page did not need to do anything except display
and form processing. Add tbsetup/node_control for backend so that it
can be called from the command line too. The virt_nodes table is also
updated (for those values that have virt_nodes equivalents), and this
mostly implies that changes can be applied only to swapped in
experiments since we use the reserved table to map pcXXX to its vname
so that the virt_nodes table can be updated. It is an easy extension
to allow changes based on the pid/eid/vname, but I do not see a reason
to support this ability yet. Note usage:

    Usage: node_control name=value [name=value ...] node [node ...]
           node_control -e pid,eid name=value [name=value ...]
           node_control -l
    For multiword values, use name='word0 ... wordN'
    Use -l to get a list of operational parameters you can change.
    Use -e to change parameters of all nodes in an experiment.

    {824} stoller$ /build/testbed/install//bin/node_control -l
      next_boot_osid            - (administrators only)
      startup_command
      bios_version              - (administrators only)
      rpms                      - (multiple options allowed)
      default_boot_cmdline
      default_boot_path
      default_boot_osid
      next_pxe_boot_path        - (administrators only)
      tarfiles                  - (multiple options allowed)
      pxe_boot_path             - (administrators only)
      next_boot_cmdline         - (administrators only)
      deltas                    - (multiple options allowed)
      next_boot_path            - (administrators only)
parent 3148e9ef
......@@ -1050,6 +1050,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
tbsetup/frisbeelauncher tbsetup/node_update tbsetup/webnodeupdate \
tbsetup/savelogs tbsetup/group-update tbsetup/webgroupupdate \
tbsetup/rmgroup tbsetup/webrmgroup tbsetup/mkexpdir \
tbsetup/webnodecontrol tbsetup/node_control \
tip/GNUmakefile \
tmcd/GNUmakefile tmcd/freebsd/GNUmakefile tmcd/linux/GNUmakefile \
tmcd/netbsd/GNUmakefile \
......
......@@ -172,6 +172,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
tbsetup/frisbeelauncher tbsetup/node_update tbsetup/webnodeupdate \
tbsetup/savelogs tbsetup/group-update tbsetup/webgroupupdate \
tbsetup/rmgroup tbsetup/webrmgroup tbsetup/mkexpdir \
tbsetup/webnodecontrol tbsetup/node_control \
tip/GNUmakefile \
tmcd/GNUmakefile tmcd/freebsd/GNUmakefile tmcd/linux/GNUmakefile \
tmcd/netbsd/GNUmakefile \
......
......@@ -991,25 +991,35 @@ sub IsShelved ($;$$) {
}
#
# Map nodeid to its pid/eid.
# Map nodeid to its pid/eid/vname. vname is optional.
#
# usage: NodeToExp(char *nodeid, \$pid, \$eid)
# usage: NodeidToExp(char *nodeid, \$pid, \$eid, \$vname)
# returns 1 if the node is reserved.
# returns 0 if the node is not reserved.
#
sub NodeidToExp ($$$) {
my($nodeid, $pid, $eid) = @_;
sub NodeidToExp ($$$;$) {
my($nodeid, $pid, $eid, $vname) = @_;
my $query_result =
DBQueryFatal("select pid,eid from reserved where node_id='$nodeid'");
DBQueryWarn("select pid,eid,vname from reserved ".
"where node_id='$nodeid'");
if ($query_result->num_rows < 1) {
if (! $query_result ||
! $query_result->num_rows) {
return 0;
}
my @row = $query_result->fetchrow_array();
$$pid = $row[0];
$$eid = $row[1];
if (defined($vname)) {
if (defined($row[2])) {
$$vname = $row[2];
}
else {
$$vname = undef;
}
}
return 1;
}
......
......@@ -12,10 +12,10 @@ SUBDIRS = checkpass ns2ir
BIN_STUFF = power snmpit tbend tbswapin tbswapout tbprerun tbreport \
os_load savevlans startexp endexp batchexp swapexp \
node_reboot nscheck node_update savelogs
node_reboot nscheck node_update savelogs node_control
# Stuff that mere users get on plastic.
USERBINS = os_load node_reboot nscheck node_update savelogs
USERBINS = os_load node_reboot nscheck node_update savelogs node_control
SBIN_STUFF = resetvlans console_setup.proxy sched_reload named_setup \
batch_daemon exports_setup reload_daemon sched_reserve \
......@@ -26,7 +26,7 @@ LIBEXEC_STUFF = mkprojdir rmproj mkacct-ctrl rmacct-ctrl \
os_setup mkexpdir console_setup webnscheck webreport \
webstartexp webendexp webbatchexp \
assign_wrapper ptopgen webnodeupdate webgroupupdate \
webrmgroup webswapexp
webrmgroup webswapexp webnodecontrol
LIB_STUFF = libtbsetup.pm exitonwarn.pm libtestbed.pm snmpit_intel.pm \
snmpit_cisco.pm snmpit_lib.pm snmpit_apc.pm power_rpc27.pm \
......
......@@ -821,16 +821,16 @@ foreach $pair (@nodepairs) {
$osid = $defosids{$type};
}
DBQueryFatal("UPDATE nodes set def_boot_osid=\"$osid\"," .
" def_boot_cmd_line=\"$cmdline\"," .
" startstatus=\"none\"," .
" bootstatus=\"unknown\"," .
" def_boot_cmd_line='$cmdline'," .
" startstatus='none'," .
" bootstatus='unknown'," .
" ready=0," .
" rpms=\"$rpms\"," .
" deltas=\"$deltas\"," .
" tarballs=\"$tarfiles\"," .
" startupcmd=\"$startupcmd\"," .
" failureaction=\"$failureaction\"" .
" where node_id=\"$pnode\"");
" rpms='$rpms'," .
" deltas='$deltas'," .
" tarballs='$tarfiles'," .
" startupcmd='$startupcmd'," .
" failureaction='$failureaction'" .
" where node_id='$pnode'");
} elsif (! defined($lannodes{$p2vmap{$pnode}})) {
# Delay node
DBQueryFatal("UPDATE nodes set def_boot_osid=\"" .
......
#!/usr/bin/perl -wT
use English;
use Getopt::Std;
#
# usage: node_control [options] node [node ...]
# node_control [options] -e pid,eid
#
sub usage()
{
print("Usage: node_control name=value [name=value ...] node [node ...]\n".
" node_control -e pid,eid name=value [name=value ...]\n".
" node_control -l\n".
"For multiword values, use name='word0 ... wordN'\n".
"Use -l to get a list of operational parameters you can change.\n".
"Use -e to change parameters of all nodes in an experiment.\n");
exit(-1);
}
my $optlist = "de:l";
#
# Array of allowed names. All of these values are text, so no need to
# worry about distinguishing numeric stuff.
#
# XXX This should be in the library.
#
my %controlset =
(
#
# Symbolic name => Admin, Multi args, nodes DB field, virt_nodes DB field
#
default_boot_osid => [0, 0, "def_boot_osid", "osid"],
default_boot_path => [0, 0, "def_boot_path", undef],
default_boot_cmdline => [0, 0, "def_boot_cmd_line", "cmd_line"],
startup_command => [0, 0, "startupcmd", "startupcmd"],
tarfiles => [0, 1, "tarballs", "tarfiles"],
rpms => [0, 1, "rpms", "rpms"],
deltas => [0, 1, "deltas", "deltas"],
next_boot_osid => [1, 0, "next_boot_osid", undef],
next_boot_path => [1, 0, "next_boot_path", undef],
next_boot_cmdline => [1, 0, "next_boot_cmd_line", undef],
pxe_boot_path => [1, 0, "pxe_boot_path", undef],
next_pxe_boot_path => [1, 0, "next_pxe_boot_path", undef],
bios_version => [1, 0, "bios_version", undef],
);
#
# Configure variables
#
my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
my $TBLOGS = "@TBLOGSEMAIL@";
my $ssh = "$TB/bin/sshtb -n";
my @nodes = ();
my %controls = ();
my $eidmode = 0;
my $debug = 0;
my $errors = 0;
my $pid;
my $eid;
my $dbuid;
#
# Load the Testbed support stuff.
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;
my $IsAdmin = TBAdmin($UID);
# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
# Turn off line buffering on output
$| = 1;
#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"d"})) {
$debug = 1;
}
if (defined($options{"l"})) {
foreach my $option (keys(%controlset)) {
my ($admin, $multi, $dbkey) = @{ $controlset{$option} };
printf(" %-25s ", $option);
if ($multi || $admin) {
print "- ";
}
if ($multi) {
print "(multiple options allowed) ";
}
if ($admin) {
print "(administrators only)";
}
print "\n";
}
exit(0);
}
if (defined($options{"e"})) {
$eidmode = $options{"e"};
if ($eidmode =~ /([-\w]*),([-\w]*)/) {
$pid = $1;
$eid = $2;
}
else {
usage();
}
}
if (! @ARGV) {
usage();
}
#
# Shift off the set strings (name=value). Verify that each one is in the
# proper format.
#
while (@ARGV) {
my $string = $ARGV[0];
if (! ($string =~ /([-\w]*)=[\']?([^\']*)[\']?/)) {
last;
}
shift;
if (! defined($controlset{$1})) {
die("*** $0:\n".
" Illegal control setting: $1='$2'. Try the -l option!\n");
}
my ($admin, $multi, $dbkey) = @{ $controlset{$1} };
if ($admin && ! $IsAdmin) {
die("*** $0:\n".
" You do not have permission to set $1. Try the -l option!\n");
}
if ($multi && defined($controls{$1})) {
$controls{$1} = "$controls{$1}:$2";
}
else {
$controls{$1} = "$2";
}
}
if ($debug) {
foreach my $option (keys(%controls)) {
print "Will set $option to '$controls{$option}'\n";
}
}
#
# In eidmode, check the access permission for the experiment, and then
# get the nodes. Otherwise, check access for each node given on the
# command line.
#
if ($eidmode) {
# Permission check.
if ($UID && !TBAdmin($UID) &&
! TBExptAccessCheck($UID, $pid, $eid, TB_EXPT_MODIFY)) {
die("*** $0:\n".
" You do not have permission to control nodes in $pid/$eid!\n");
}
if (! (@nodes = ExpNodes($pid, $eid))) {
die("*** $0:\n".
" There are no nodes in $pid/$eid!\n");
}
}
else {
if (! @ARGV) {
usage();
}
# Untaint the nodes.
foreach my $node ( @ARGV ) {
if ($node =~ /^([-\@\w]+)$/) {
$node = $1;
}
else {
die("Bad node name: $node.");
}
push(@nodes, $node);
}
}
#
# Create an update clause for all of the specified values.
#
my $physnodes_updatestr;
my $virtnodes_updatestr;
foreach my $option (keys(%controls)) {
my ($admin, $multi, $physdbkey, $virtdbkey) = @{ $controlset{$option} };
my $value = $controls{$option};
if (defined($physnodes_updatestr)) {
$physnodes_updatestr = "$physnodes_updatestr, $physdbkey='$value'";
}
else {
$physnodes_updatestr = "$physdbkey='$value'";
}
if (defined($virtdbkey)) {
if (defined($virtnodes_updatestr)) {
$virtnodes_updatestr = "$virtnodes_updatestr, $virtdbkey='$value'";
}
else {
$virtnodes_updatestr = "$virtdbkey='$value'";
}
}
}
if (! defined($physnodes_updatestr) && ! defined($virtnodes_updatestr)) {
exit(0);
}
if ($debug) {
if (defined($physnodes_updatestr)) {
print "Phys update will be '$physnodes_updatestr'\n";
}
if (defined($virtnodes_updatestr)) {
print "Virt update will be '$virtnodes_updatestr'\n";
}
}
#
# Now do it for every node. Do the permission check here to reduce the
# race condition window. Should probably lock instead, but thats a pain.
#
foreach my $node (@nodes) {
my $node_pid;
my $node_eid;
my $node_vname;
#
# We need the vname for the node so that we can update the virt_nodes
# table. This implies that we cannot update the virt_nodes unless the
# experiment is swapped in (so we can map from phys node name to virt
# node name). At some point, maybe we want to provide a way to change
# the params of a swapped out experiment by having the user specify
# the vname?
#
if (! NodeidToExp($node, \$node_pid, \$node_eid, \$node_vname)) {
print("*** $0:\n".
" Node $node is not a member of a swapped in experiment!\n");
$errors++;
next;
}
if (defined($physnodes_updatestr)) {
if ($UID && !$IsAdmin &&
! TBNodeAccessCheck($UID, TB_NODEACCESS_MODIFYINFO, $node)) {
print("*** $0:\n".
" You do not have permission to modify physical ".
"parameters for $node!\n");
$errors++;
next;
}
DBQueryFatal("update nodes set $physnodes_updatestr ".
"where node_id='$node'");
}
if (defined($node_vname) && defined($virtnodes_updatestr)) {
if ($UID && !$IsAdmin &&
! TBExptAccessCheck($UID, $node_pid, $node_eid, TB_EXPT_MODIFY)) {
print("*** $0:\n".
" You do not have permission to modify virtual ".
"parameters for $node!\n");
$errors++;
next;
}
DBQueryFatal("update virt_nodes set $virtnodes_updatestr ".
"where pid='$node_pid' and eid='$node_eid' ".
" and vname='$node_vname'");
}
}
exit($errors);
#!/usr/bin/perl -w
use English;
#
# This gets invoked from the Web interface. Simply a wrapper ...
#
# usage: webnodecontrol pid eid
#
#
# Configure variables
#
my $TB = "@prefix@";
#
# Run the real thing, and never return.
#
exec "$TB/bin/node_control", @ARGV;
die("webnodecontrol: Could not exec node_control: $!");
......@@ -38,27 +38,28 @@ if (isset($def_boot_osid) && strcmp($def_boot_osid, "None") == 0) {
}
#
# Create an update string, that is slightly different if an admin; we allow
# Create a command string, that is slightly different if an admin; we allow
# admin people to set next_boot parameters. Ordinary folks cannot.
#
$query_string =
"UPDATE nodes SET ".
"def_boot_osid=\"$def_boot_osid\", ".
"def_boot_path=\"$def_boot_path\", ".
"def_boot_cmd_line=\"$def_boot_cmd_line\", ".
"startupcmd='$startupcmd', ".
"tarballs='$tarballs', ".
"rpms='$rpms' ";
$command_string =
"default_boot_osid='$def_boot_osid' ".
"default_boot_path='$def_boot_path' ".
"default_boot_cmdline='$def_boot_cmd_line' ".
"startup_command='$startupcmd' ".
"tarfiles='$tarballs' ".
"rpms='$rpms' ";
if ($isadmin) {
$query_string = "$query_string, ".
"next_boot_osid=\"$next_boot_osid\", ".
"next_boot_path=\"$next_boot_path\", ".
"next_boot_cmd_line=\"$next_boot_cmd_line\" ";
$command_string = "$command_string ".
"next_boot_osid='$next_boot_osid' ".
"next_boot_path='$next_boot_path' ".
"next_boot_cmdline='$next_boot_cmd_line' ";
}
$query_string = "$query_string WHERE node_id=\"$node_id\"";
DBQueryFatal($query_string);
#
# Pass it off to the script.
#
SUEXEC($uid, "nobody", "webnodecontrol $command_string $node_id", 1);
echo "<center>
<br>
......
......@@ -188,7 +188,7 @@ echo "<tr>
<td>Startup Command[1]:</td>
<td class=\"left\">
<input type=\"text\" name=\"startupcmd\" size=\"60\"
maxlength=\"256\" value=\"$startupcmd\"></td>
maxlength=\"256\" value='$startupcmd'></td>
</tr>\n";
......
......@@ -889,6 +889,7 @@ function SHOWNODE($node_id) {
$node_id = $row[node_id];
$type = $row[type];
$bios = $row[bios_version];
$def_boot_osid = $row[def_boot_osid];
$def_boot_path = $row[def_boot_path];
$def_boot_cmd_line = $row[def_boot_cmd_line];
......@@ -915,6 +916,8 @@ function SHOWNODE($node_id) {
$tarballs = "&nbsp";
if (!$startupcmd)
$startupcmd = "&nbsp";
if (!$bios)
$bios = "&nbsp";
echo "<table border=2 cellpadding=0 cellspacing=2
align=center>\n";
......@@ -929,6 +932,11 @@ function SHOWNODE($node_id) {
<td class=left>$type</td>
</tr>\n";
echo "<tr>
<td>Bios Version:</td>
<td class=left>$bios</td>
</tr>\n";
echo "<tr>
<td>Def Boot OSID:</td>
<td class=left>$def_boot_osid</td>
......
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