Commit 7a76cc98 authored by Gary Wong's avatar Gary Wong

Add public IP address pool allocation and deallocation.

parent 544be71c
......@@ -5389,6 +5389,127 @@ sub ReserveSharedBandwidth($;$$)
return -1;
}
#
# Allocate per-experiment public address pools.
#
# Returns 0 on success, -1 on failure.
#
# This is atomic: on success, all addresses are allocated; on failure,
# everything is left unchanged.
#
# Current allocations are retained where appropriate, so this is suitable
# for use by swapmod.
#
sub AllocatePublicAddrPools($)
{
my ($self) = @_;
my $pid = $self->pid();
my $eid = $self->eid();
my %old_addrs;
my %pools= ();
my $db_result;
DBQueryFatal( "LOCK TABLES virt_node_public_addr WRITE, " .
"virt_address_allocation READ" );
$db_result = DBQueryWarn( "SELECT IP,pool_id FROM virt_node_public_addr " .
"WHERE pid='$pid' AND eid='$eid'" );
while( my ($addr,$pool) = $db_result->fetchrow_array() ) {
$old_addrs{$addr} = $pool;
}
$db_result = DBQueryWarn( "SELECT pool_id, count FROM virt_address_allocation " .
"WHERE pid='$pid' AND eid='$eid'" );
while( my($pool,$count) = $db_result->fetchrow_array() ) {
$pools{$pool} = $count;
}
# First, release any addresses we have and no longer need (we do
# this eagerly, so we will never generate false failures on
# allocation).
while( my ($pool,$count) = each %pools ) {
$db_result = DBQueryWarn( "SELECT COUNT(*) FROM virt_node_public_addr " .
"WHERE eid='$eid' AND pid='$pid' AND " .
"pool_id='$pool'" );
my ($n) = $db_result->fetchrow_array();
if( $n > $count ) {
my $spare;
$spare = $n - $count;
DBQueryWarn( "UPDATE virt_node_public_addr SET eid=NULL, " .
"pid=NULL, pool_id=NULL WHERE eid='$eid' " .
"AND pid='$pid' AND pool_id='$pool_id' " .
"LIMIT $spare" );
}
}
# Next, allocate any addresses we don't have and want. If this
# fails, we know the entire request is impossible to satisfy, because
# we started with the table as close to empty as we could possibly
# get.
my $failed;
while( my ($pool,$count) = each %pools ) {
$db_result = DBQueryWarn( "SELECT COUNT(*) FROM virt_node_public_addr " .
"WHERE eid='$eid' AND pid='$pid' AND " .
"pool_id='$pool'" );
my ($n) = $db_result->fetchrow_array();
if( $n < $count ) {
my $extra;
$extra = $count - $n;
DBQueryWarn( "UPDATE virt_node_public_addr SET eid='$eid', " .
"pid='$pid', pool_id='$pool' WHERE " .
"node_id IS NULL AND eid IS NULL " .
"LIMIT $extra" );
$db_result = DBQueryWarn( "SELECT COUNT(*) FROM virt_node_public_addr " .
"WHERE eid='$eid' AND pid='$pid' AND " .
"pool_id='$pool'" );
($n) = $db_result->fetchrow_array();
if( $n != $count ) {
# Couldn't do it. Roll back.
DBQueryWarn( "UPDATE virt_node_public_addr SET " .
"eid=NULL, pid=NULL, pool_id=NULL WHERE " .
"eid='$eid' AND pid='$pid'" );
while( my ($addr,$pool) = each %old_addrs ) {
DBQueryWarn( "UPDATE virt_node_public_addr SET " .
"eid='$eid', pid='$pid', pool_id='$pool' " .
"WHERE IP='$addr'" );
}
DBQueryFatal( "UNLOCK TABLES" );
return -1;
}
}
}
DBQueryFatal( "UNLOCK TABLES" );
return 0;
}
#
# Release per-experiment public address pools.
#
sub ReleasePublicAddrPools($)
{
my ($self) = @_;
my $pid = $self->pid();
my $eid = $self->eid();
DBQueryWarn( "UPDATE virt_node_public_addr SET pool_id=NULL, " .
"pid=NULL, eid=NULL WHERE pid='$pid' AND " .
"eid='$eid'" );
return 0;
}
#
# Get/Set ElabInElab attributes.
#
......
......@@ -2414,7 +2414,7 @@ sub CreateVnodes($$$)
#
$query_result =
DBQueryWarn( "SELECT IP, mask FROM virt_node_public_addr ".
"WHERE node_id IS NULL" );
"WHERE node_id IS NULL AND eid IS NULL" );
if (!$query_result || !$query_result->numrows ) {
print STDERR "*** CreateVnodes: no free public address\n";
......
......@@ -2242,6 +2242,13 @@ sub GetTicketAuxAux($$$$$$$$$$)
goto bad;
}
# Allocate any public address pools.
if( $slice_experiment->AllocatePublicAddrPools() < 0 ) {
$response = GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not allocate public address pools");
goto bad;
}
#
# This creates the descriptors but does not download the images.
# Must be done before the mapper runs.
......
......@@ -563,6 +563,11 @@ sub doSwapout($) {
}
}
if( $type >= CLEANUP ) {
print "Releasing public address pools...\n";
$experiment->ReleasePublicAddrPools();
}
#
# Grab our per-experiment switch stack name.
#
......@@ -1040,6 +1045,16 @@ sub doSwapin($) {
Enable($experiment);
}
# Allocate public IP addresses now. We do it early, because it's
# very fast and might fail (it would be silly to go through all
# the effort of mapping nodes only to later abort because we
# didn't have enough public addresses).
print "Allocating public addresses...\n";
if( $experiment->AllocatePublicAddrPools() < 0 ) {
tberror( "Failed to allocate public address pools!" );
return 1;
}
print "Mapping to physical reality ...\n";
TBDebugTimeStamp("mapper wrapper started");
......
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