Commit 1c32d808 authored by Leigh Stoller's avatar Leigh Stoller

New scripts to add wires and interfaces, no more direct insertion into

the DB please.
parent 64e8008f
......@@ -58,7 +58,7 @@ SBIN_SCRIPTS = vlandiff vlansync withadminprivs export_tables cvsupd.pl \
runsonxen pxelinux_makeconf attend atten \
addrfdevice addrfpath reserve announce createimagealias \
predict test-reserve prunelogfiles notify-reservations \
deprecate_image pushrootkey
deprecate_image pushrootkey addinterface addwire
WEB_SBIN_SCRIPTS= webnewnode webdeletenode webspewconlog webarchive_list \
webwanodecheckin webspewimage webdumpdescriptor webemulabfeature \
......
#!/usr/bin/perl -w
#
# Copyright (c) 2003-2017 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/>.
#
# }}}
#
use strict;
use English;
use Getopt::Std;
use Data::Dumper;
#
# Add an interface to the DB. Typically, this is used to add the switch
# side of a wire, but it can be used to add the node side too.a
#
sub usage()
{
print STDERR "Usage: addinterface [-b speed | -t ifacetype] [-m mac] ".
"[-r role] portinfo node_id [iface_id]\n";
print STDERR "Usage: addinterface -r <node_id> <iface_id>\n";
print STDERR "Options:\n";
print STDERR " -v - Turn on debugging\n";
print STDERR " -n - Impotent mode\n";
print STDERR " -r - Delete interface\n";
print STDERR " -f - (with -r) force deletion, even if iface used\n";
print STDERR " -e role - Optional interface role, default to 'other'\n";
print STDERR " -m mac - Optional MAC address. 0123456789AB format.\n";
print STDERR " -b speed - Interface speed; 100Mb,1Gb,10Gb,40Gb,100Gb\n";
print STDERR " -t type - Interface type instead of generic based on speed\n";
print STDERR " portinfo - card,port (for now, might change later)\n";
print STDERR " iface_id - eth0, eth1, 1/69, 1/6/9. If you do not specify,\n";
print STDERR " one will be constructed for you (ethXX).\n";
exit(-1);
}
my $optlist = "b:t:nvfm:re:";
my $verbose = 0;
my $impotent = 0;
my $remove = 0;
my $force = 0;
my $speed;
my $type;
my $mac = "000000000000";
my $role;
my ($card,$port);
# Protos
sub fatal($);
sub RemoveInterface($$);
#
# Configure variables
#
my $TB = "@prefix@";
#
# Testbed Support libraries
#
use lib "@prefix@/lib";
use emdb;
use EmulabConstants;
use emutil;
use User;
use Node;
use NodeType;
use Interface;
#
# Turn off line buffering on output
#
$| = 1;
#
# Untaint the path
#
$ENV{'PATH'} = "/bin:/sbin:/usr/bin:";
#
# Parse command arguments.
#
my %options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{'h'})) {
usage();
}
if (defined($options{'v'})) {
$verbose = 1;
}
if (defined($options{'n'})) {
$impotent = 1;
}
if (defined($options{'r'})) {
$remove = 1;
usage()
if (@ARGV != 2);
}
if (defined($options{'f'})) {
$force = 1;
}
if (defined($options{'e'})) {
$role = $options{'e'};
if ($role !~ /^(expt|ctrl|other|mngmnt)$/) {
fatal("Role must be one of: expt|ctrl|other|mngmnt");
}
}
else {
$role = TBDB_IFACEROLE_EXPERIMENT();
}
if (defined($options{'m'})) {
$mac = $options{'m'};
if ($mac !~ /^\w\w\w\w\w\w\w\w\w\w\w\w\w/) {
fatal("Invalid mac address format");
}
}
if (defined($options{'t'})) {
$type = Interface::Type->Lookup($options{'t'});
if (!defined($type)) {
fatal("No such interface type");
}
}
if (defined($options{'b'})) {
$speed = $options{'b'};
$type = Interface::Type->GenericType($speed);
if (!defined($type)) {
fatal("No generic interface type for speed: $speed");
}
}
#
# Verify user, must be admin.
#
my $this_user = User->ThisUser();
if (! defined($this_user)) {
fatal("You ($UID) do not exist!");
}
if (!$this_user->IsAdmin()) {
fatal("You are not a testbed administrator!");
}
if ($remove) {
exit(RemoveInterface($ARGV[0], $ARGV[1]));
}
usage()
if (@ARGV < 2 || !defined($type));
my $portinfo = $ARGV[0];
my $node_id = $ARGV[1];
my $iface_id = $ARGV[2] if (@ARGV == 3);
# Sanity check node/portinfo.
my $node = Node->Lookup($node_id);
if (!defined($node)) {
fatal("No such node $node_id");
}
if ($portinfo =~ /^(\d+),(\d+)$/) {
$card = $1;
$port = $2;
}
else {
fatal("Invalid portinfo; must be in card,port format");
}
my $interface = Interface->Lookup($node_id, $card, $port);
if (defined($interface)) {
fatal("Interface already exists for $card,$port");
}
if (defined($iface_id)) {
$interface = Interface->LookupByIface($node_id, $iface_id);
if (defined($interface)) {
fatal("Interface already exists for $iface_id");
}
}
else {
if ($node->role() eq "testnode") {
if ($node->isswitch()) {
$iface_id = sprintf("eth%02d%02d", $card, $port);
}
else {
$iface_id = "eth${card}";
}
}
else {
$iface_id = "${card}/${port}";
}
print "Will use iface: $iface_id\n";
$interface = Interface->LookupByIface($node_id, $iface_id);
if (defined($interface)) {
fatal("Interface already exists for generated $iface_id");
}
}
#
# Create the interface.
#
my $ifaceargs = {
"node_id" => $node_id,
"card" => $card,
"port" => $port,
"iface" => $iface_id,
"role" => $role,
"type" => $type->type(),
"max_speed" => $type->max_speed() / 1000,
"mac" => $mac,
};
if ($verbose || $impotent) {
if ($verbose) {
print "Creating interface with arguments:\n";
}
else {
print "Would create interface with arguments:\n";
}
print Dumper($ifaceargs);
}
if (!$impotent) {
Interface->Create($node, $ifaceargs)
or fatal("Could not create interface entry");
}
exit(0);
sub fatal($)
{
my ($mesg) = $_[0];
die("*** $0:\n".
" $mesg\n");
}
#
# Remove an interface.
#
sub RemoveInterface($$)
{
my ($node_id, $iface_id) = @_;
my $interface = Interface->LookupByIface($node_id, $iface_id);
if (!defined($interface)) {
fatal("No such interface to delete");
}
#
# See if in use.
#
my $query_result =
DBQueryFatal("select lma1.lanid from lan_member_attributes as lma1, " .
"lan_member_attributes as lma2 where " .
"lma1.lanid = lma2.lanid and lma1.memberid=lma2.memberid " .
"and lma1.attrkey='node_id' and " .
"lma1.attrvalue='$node_id' and " .
"lma2.attrkey='iface' and " .
"lma2.attrvalue='$iface_id'");
if ($query_result->numrows > 0) {
if ($force) {
print "$node_id:$iface_id appears to be in use; " .
"continuing anyway...\n";
}
else {
print "warning: $node_id:$iface_id appears to be in use; " .
"entering impotent mode (use -f to force removal)\n";
$impotent = 1;
}
}
if (!$impotent) {
# Flag indicates it is okay to delete real interface. Safety measure.
$interface->Delete(1) == 0
or fatal("Could not delete $interface");
}
return 0;
}
#!/usr/bin/perl -w
#
# Copyright (c) 2003-2017 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/>.
#
# }}}
#
use strict;
use English;
use Getopt::Std;
use Data::Dumper;
#
# Add a wire to the DB.
#
sub usage()
{
print STDERR "Usage: addwire [-t type] [-c id [-l len]] ".
"node1:iface1 node2:iface2\n";
print STDERR "Usage: addwire -r node1:iface1 node2:iface2\n";
print STDERR "Options:\n";
print STDERR " -v - Turn on debugging\n";
print STDERR " -n - Impotent mode\n";
print STDERR " -r - Delete wire\n";
print STDERR " -f - (with -r) force deletion, even if iface exists\n";
print STDERR " -c cable - Cable ID\n";
print STDERR " -l len - Cable length\n";
print STDERR " -t type - Wire type (defaults to Unused)\n";
exit(-1);
}
my $optlist = "t:nvfrc:l:";
my $verbose = 0;
my $impotent = 0;
my $remove = 0;
my $force = 0;
my $type = "other";
my $cable;
my $cablelen;
my ($node_id1,$iface_id1,$node_id2,$iface_id2);
# Protos
sub fatal($);
sub RemoveWire($);
#
# Configure variables
#
my $TB = "@prefix@";
#
# Testbed Support libraries
#
use lib "@prefix@/lib";
use emdb;
use EmulabConstants;
use emutil;
use User;
use Node;
use NodeType;
use Interface;
use Lan;
#
# Turn off line buffering on output
#
$| = 1;
#
# Untaint the path
#
$ENV{'PATH'} = "/bin:/sbin:/usr/bin:";
#
# Parse command arguments.
#
my %options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{'h'})) {
usage();
}
if (defined($options{'v'})) {
$verbose = 1;
}
if (defined($options{'n'})) {
$impotent = 1;
}
if (defined($options{'r'})) {
$remove = 1;
usage()
if (@ARGV != 2);
}
if (defined($options{'f'})) {
$force = 1;
}
if (defined($options{'t'})) {
$type = $options{'t'};
if ($type !~ /^(Trunk|Node|Control|Power|Serial|Unused|Management)$/) {
fatal("Type must be one of: ".
"Trunk|Node|Control|Power|Serial|Unused|Management");
}
}
if (defined($options{'c'})) {
$cable = $options{'c'};
}
if (defined($options{'l'})) {
$cablelen = $options{'l'};
}
#
# Verify user, must be admin.
#
my $this_user = User->ThisUser();
if (! defined($this_user)) {
fatal("You ($UID) do not exist!");
}
if (!$this_user->IsAdmin()) {
fatal("You are not a testbed administrator!");
}
usage()
if (@ARGV != 2);
if ($ARGV[0] =~ /^([-\w]+):(.+)$/) {
$node_id1 = $1;
$iface_id1 = $2;
}
else {
fatal("Invalid argument for interface: " . $ARGV[0]);
}
if ($ARGV[1] =~ /^([-\w]+):(.+)$/) {
$node_id2 = $1;
$iface_id2 = $2;
}
else {
fatal("Invalid argument for interface: " . $ARGV[1]);
}
if ($remove) {
my $wire = Interface::Wire->LookupAnyByIfaces($node_id1, $iface_id1,
$node_id2, $iface_id2);
if (!defined($wire)) {
fatal("No such wire");
}
exit(RemoveWire($wire));
}
#
# Cannot add wires unless interfaces exist for both side.
#
my $interface1 = Interface->LookupByIface($node_id1, $iface_id1);
if (!defined($interface1)) {
fatal("No interface for $node_id1:$iface_id1");
}
my $interface2 = Interface->LookupByIface($node_id2, $iface_id2);
if (!defined($interface2)) {
fatal("No interface for $node_id2:$iface_id2");
}
#
# Not allowed to have any existing wires using either interface.
#
my $wire = Interface::Wire->LookupAnyByIface($node_id1, $iface_id1);
if (defined($wire)) {
fatal("Wire using interface one already exists: $wire\n");
}
$wire = Interface::Wire->LookupAnyByIface($node_id2, $iface_id2);
if (defined($wire)) {
fatal("Wire using interface two already exists: $wire\n");
}
# Another check using card/port info, just to be sure.
$wire = Interface::Wire->LookupAny($node_id1,
$interface1->card(),
$interface1->port());
if (defined($wire)) {
fatal("Wire using interface two already exists: $wire\n");
}
$wire = Interface::Wire->LookupAny($node_id1,
$interface2->card(),
$interface2->port());
if (defined($wire)) {
fatal("Wire using interface two already exists: $wire\n");
}
#
# Create the wire.
#
my $wireargs = {
};
$wireargs->{"cable"} = $cable if (defined($cable));
$wireargs->{"length"} = $cablelen if (defined($cablelen));
if ($impotent || $verbose) {
if ($verbose) {
print "Creating interface with arguments:\n";
}
else {
print "Would create interface with arguments:\n";
}
print Dumper($wireargs);
}
if (!$impotent) {
Interface::Wire->Create($interface1, $interface2, $type, $wireargs)
or fatal("Could not create wire entry");
}
exit(0);
sub fatal($)
{
my ($mesg) = $_[0];
die("*** $0:\n".
" $mesg\n");
}
#
# Remove a wire.
#
sub RemoveWire($)
{
my ($wire) = @_;
my $interface = Interface->LookupByIface($wire->node_id1(), $wire->iface1());
if (defined($interface)) {
if (Lan->FindLansByMember($interface->node_id(), $interface->iface())) {
if ($force) {
print "$interface appears to be in use; continuing anyway...\n";
}
else {
print "warning: $interface appears to be in use; " .
"entering impotent mode (use -f to force removal)\n";
$impotent = 1;
}
}
}
$interface = Interface->LookupByIface($wire->node_id2(), $wire->iface2());
if (defined($interface)) {
if (Lan->FindLansByMember($interface->node_id(), $interface->iface())) {
if ($force) {
print "$interface appears to be in use; continuing anyway...\n";
}
else {
print "warning: $interface appears to be in use; " .
"entering impotent mode (use -f to force removal)\n";
$impotent = 1;
}
}
}
if ($impotent) {
print "Would delete $wire\n";
}
else {
$wire->Delete(1) == 0
or fatal("Could not delete $wire");
}
return 0;
}
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