Commit 9047e21a authored by Gary Wong's avatar Gary Wong

Add a "ctrladdr" utility to show (un)allocated addresses on the control net.

Right now, the only addresses it knows are allocated are anything assigned
in the interfaces table with a "ctrl" role, and anything in the dynamic
pool in the virt_node_public_addr table.  (And the reserved network and
broadcast addresses.)

This needs to be extended to anything else we know about!

By default, the output is supposed to be easy to parse and simply
displays the first available address.  More than one available address
can be requested with the "-n" option (e.g. "-n 10" will show the
first ten unallocated addresses).  "-n 0" will show every free
address on the subnet.

The "-a" option (meant more for human consumption) also describes
allocated addresses.  For instance, "ctrladdr -a -n 0" will show
every address on the control net, and what it's used for (if
anything).  "-r" will compress ranges of consecutive free addresses
onto a single line.

To test whether a particular address is in use, invoke it as (e.g.)
"ctrladdr -t 155.98.36.1".  This will give an exit code of 0 if the
address is available, and 1 if used.  Any other options are ignored
if "-t" is specified.
parent 8ac22379
......@@ -1119,7 +1119,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
utils/spewconlog utils/xlogin \
utils/opsdb_control utils/opsdb_control.proxy \
utils/remove_old_www utils/epmodeset \
utils/mkblob utils/rmblob \
utils/mkblob utils/rmblob utils/ctrladdr \
www/GNUmakefile www/defs.php3 www/dbdefs.php3 www/xmlrpc.php3 \
www/xmlrpcpipe.php3 \
www/swish.conf www/websearch \
......
......@@ -30,7 +30,7 @@ SBIN_SCRIPTS = vlandiff vlansync withadminprivs export_tables cvsupd.pl \
prereserve grantimage getimages localize_mfs \
management_iface sharevlan check-shared-bw \
addspecialdevice addspecialiface imagehash clone_image \
addvpubaddr imageinfo
addvpubaddr imageinfo ctrladdr
WEB_SBIN_SCRIPTS= webnewnode webdeletenode webspewconlog webarchive_list \
webwanodecheckin webspewimage
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2012 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
use Getopt::Std;
use strict;
use Socket;
#
# Configure variables
#
my $TB = "@prefix@";
my $control_network = "@CONTROL_NETWORK@";
my $control_netmask = "@CONTROL_NETMASK@";
#
# Turn off line buffering on output
#
$| = 1;
#
# Untaint the path
#
$ENV{'PATH'} = "$TB/bin:$TB/sbin:/bin:/usr/bin:/sbin:/usr/sbin";
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Testbed Support libraries
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;
#
# Handle command-line options.
#
sub usage() {
print STDERR "Usage: $0 [-t aaa.bbb.ccc.ddd] [-n num] [-a] [-r]\n" .
" -t aaa.bbb.ccc.ddd : exit 0 if address available, 1 if used\n" .
" -n num : show num addresses (0 = unlimited, defaults to 1)\n" .
" -a : show allocated addresses too (defaults to free only)\n" .
" -r : compress ranges of consecutive free addresses\n";
exit( 1 );
}
my $test = undef;
my $num = 1;
my $all = undef;
my $range = undef;
my %options = ();
if( !getopts( "t:n:ar", \%options ) ) {
usage();
}
if( $options{ 't' } ) {
$test = $options{ 't' };
}
if( exists( $options{ 'n' } ) ) {
$num = $options{ 'n' };
}
if( $options{ 'a' } ) {
$all = 1;
}
if( $options{ 'r' } ) {
$range = 1;
}
usage() unless @ARGV == 0;
my %used = ();
sub show($) {
my ($addr) = @_;
if( $used{ $addr } ) {
print $addr . " is assigned to " . $used{ $addr } . "\n";
} else {
print $addr . "\n";
}
}
my $range_start = undef;
sub range_done($) {
my ($i) = @_;
if( $range_start ) {
if( $range_start == $i - 1 ) {
print inet_ntoa( pack( "N", $range_start ) ) . "\n";
} else {
print inet_ntoa( pack( "N", $range_start ) ) . "-" .
inet_ntoa( pack( "N", $i - 1 ) ) . " (" .
( $i - 1 - $range_start ) . " addresses)\n";
}
$range_start = undef;
}
}
my $result = DBQueryWarn( "SELECT IP, node_id FROM interfaces WHERE " .
"role='ctrl';" );
if( !$result ) {
print STDERR "Could not retrieve addresses from interfaces table\n";
exit( 1 );
}
while( my( $IP, $node_id ) = $result->fetchrow_array() ) {
$used{ $IP } = $node_id;
}
$result = DBQueryWarn( "SELECT IP FROM virt_node_public_addr;" );
if( !$result ) {
print STDERR "Could not retrieve addresses from " .
"virt_node_public_addr table\n";
exit( 1 );
}
while( my( $IP ) = $result->fetchrow_array() ) {
$used{ $IP } = "dynamic virtual nodes";
}
# XXX Find any other addresses which are allocated, and add them to %used
my $net = unpack( "N", inet_aton( $control_network ) );
my $mask = unpack( "N", inet_aton( $control_netmask ) );
$used{ inet_ntoa( pack( "N", $net ) ) } = "the network";
$used{ inet_ntoa( pack( "N", $net | ~$mask ) ) } = "broadcast";
if( $test ) {
my $t = unpack( "N", inet_aton( $test ) );
if( ( $t & $mask ) != $net ) {
print STDERR "warning: address $test is not on control network\n";
}
show( $test );
exit( exists( $used{ $test } ) ? 1 : 0 );
} else {
my $free = 0;
my $i;
for( $i = $net; ( ( $i & $mask ) == $net ) &&
( !$num || $free < $num ); $i++ ) {
my $addr = inet_ntoa( pack( "N", $i ) );
if( $range ) {
if( $used{ $addr } ) {
range_done( $i );
} elsif( !defined( $range_start ) ) {
$range_start = $i;
}
show( $addr ) if( $all && $used{ $addr } );
} else {
show( $addr ) if( $all || !$used{ $addr } );
}
$free++ if( !$used{ $addr } );
}
range_done( $i );
}
exit( 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