Commit 78cda04e authored by Leigh B. Stoller's avatar Leigh B. Stoller
Browse files

More version 2 API changes.

parent 73a08a70
......@@ -26,6 +26,7 @@ use GeniRegistry;
use GeniUtil;
use GeniHRN;
use emutil;
use Lan;
use Data::Dumper;
use English;
use overload ('""' => 'Stringify');
......@@ -46,6 +47,11 @@ my $SIGNCRED = "$TB/sbin/signgenicred";
my $VERIFYCRED = "$TB/sbin/verifygenicred";
my $NODEREBOOT = "$TB/bin/node_reboot";
my $VNODESETUP = "$TB/sbin/vnode_setup";
my $POWER = "$TB/bin/power";
my $SNMPIT = "$TB/bin/snmpit";
my $NAMEDSETUP = "$TB/sbin/named_setup";
my $EXPORTS_SETUP = "$TB/sbin/exports_setup";
my $GENTOPOFILE = "$TB/libexec/gentopofile";
# Cache of instances to avoid regenerating them.
my %aggregates = ();
......@@ -151,8 +157,7 @@ sub Create($$$$$$)
my $idx = TBGetUniqueIndex('next_aggregate', 1);
# Create a cert pair, which gives us a new uuid.
$nickname =~ /[.](.+)$/;
my $urn = GeniHRN::Generate( "@OURDOMAIN@", "component", $1 );
my $urn = GeniHRN::Generate( "@OURDOMAIN@", "sliver", $idx );
my $certificate = GeniCertificate->Create("aggregate", $urn, $hrn, $TBOPS);
if (!defined($certificate)) {
print STDERR "GeniAggregate::Create: ".
......@@ -644,12 +649,14 @@ sub ProcessManifest($$)
# XXX Is is assumed that there is a single toplevel aggregate for the
# slice, so we can get all the nodes.
#
sub Start($)
sub Start($$$)
{
my ($self) = @_;
my ($self, $version, $restart) = @_;
return -1
if (! ref($self));
$restart = 0
if (!defined($restart));
my $experiment = Experiment->Lookup($self->slice_uuid());
if (!defined($experiment)) {
......@@ -676,8 +683,6 @@ sub Start($)
print STDERR "Could not map $sliver to a node\n";
return -1;
}
print STDERR "GeniAggregate:StartSliver $node\n";
my $reservation = $node->Reservation();
if (!defined($reservation)) {
print STDERR "$node no long belongs to $self\n";
......@@ -712,6 +717,43 @@ sub Start($)
}
%vnodes = %tmp;
if ($version >= 2) {
if (system("$GENTOPOFILE $pid $eid")) {
print STDERR "$GENTOPOFILE failed\n";
return -1;
}
if (system("$EXPORTS_SETUP")) {
print STDERR "$EXPORTS_SETUP failed\n";
return -1;
}
# The nodes will not boot locally unless there is a DNS record.
if (system("$NAMEDSETUP")) {
print STDERR "$NAMEDSETUP failed\n";
return -1;
}
if ($restart) {
my @diff = ();
my @same = ();
if (Lan->CompareVlansWithSwitches($experiment, \@diff, \@same)) {
print STDERR "CompareVlansWithSwitches failed!\n";
return -1;
}
if (@diff) {
system("$SNMPIT -f ". join(" ", map("-o $_", @diff)));
if ($?) {
print STDERR "Failed to remove obsolete VLANs.\n";
return -1;
}
}
}
system("$SNMPIT -t $pid $eid");
if ($?) {
print STDERR "$SNMPIT failed\n";
return -1;
}
}
#
# Now reboot the physical nodes, then any leftover virtual nodes.
#
......@@ -735,6 +777,124 @@ sub Start($)
return -1
if ($?);
}
#
# Worked? Set the new state. Needs more thought ...
#
foreach my $sliver (@slivers) {
$sliver->SetState("started")
if (ref($sliver) eq "GeniSliver::Node");
}
return 0;
}
#
# Stop all the slivers in the aggregate. Stop is brutal, better to
# use restart!
#
sub Stop($$)
{
my ($self, $version) = @_;
return -1
if (! ref($self));
my $experiment = Experiment->Lookup($self->slice_uuid());
if (!defined($experiment)) {
print STDERR "Could not map $self to its experiment\n";
return -1;
}
my $pid = $experiment->pid();
my $eid = $experiment->eid();
my @slivers = ();
if ($self->SliverList(\@slivers) != 0) {
print STDERR "Could not get sliver list for $self\n";
return -1;
}
my %pnodes = ();
my %vnodes = ();
foreach my $sliver (@slivers) {
next
if (ref($sliver) ne "GeniSliver::Node");
my $node = Node->Lookup($sliver->uuid());
if (!defined($node)) {
print STDERR "Could not map $sliver to a node\n";
return -1;
}
my $reservation = $node->Reservation();
if (!defined($reservation)) {
print STDERR "$node no long belongs to $self\n";
return -1;
}
if ($reservation->SameExperiment($experiment)) {
if ($node->isvirtnode()) {
$vnodes{$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.
$pnodes{$node->node_id} = $node;
}
}
else {
print STDERR "$node is reserved to another, not $self\n";
# Signal error so we can look at what happened.
return -1;
}
}
#
# Cull out vnodes that are going to get killed cause the
# physnode is getting powered down.
#
my %tmp = %vnodes;
foreach my $vnode (values(%vnodes)) {
if (!exists($pnodes{$vnode->phys_nodeid()})) {
$tmp{$vnode->node_id()} = $vnode;
}
}
%vnodes = %tmp;
if ($version >= 2) {
system("$SNMPIT -r $pid $eid");
if ($?) {
print STDERR "$SNMPIT failed\n";
return -1;
}
}
#
# Now power down the physical nodes, then any leftover virtual nodes.
#
if (keys(%pnodes)) {
my @node_ids = keys(%pnodes);
#
# Should waiting be an option?
#
system("$POWER off @node_ids");
return -1
if ($?);
}
if (keys(%vnodes)) {
my @node_ids = keys(%vnodes);
#
# Should waiting be an option?
#
system("$VNODESETUP -j -k -m $pid $eid @node_ids");
return -1
if ($?);
}
#
# Worked? Set the new state. Needs more thought ...
#
foreach my $sliver (@slivers) {
$sliver->SetState("stopped")
if (ref($sliver) eq "GeniSliver::Node");
}
return 0;
}
......@@ -815,6 +975,63 @@ sub UnProvision($;$)
return 0;
}
sub ComputeState($)
{
my ($self) = @_;
my $started = 0;
my $stopped = 0;
my $unknown = 0;
my $count = 0;
return -1
if (! ref($self));
my @slivers = ();
if ($self->SliverList(\@slivers) != 0) {
print STDERR "Could not get sliver list for $self\n";
return -1;
}
foreach my $sliver (@slivers) {
#
# Just nodes for now.
#
next
if (ref($sliver) ne "GeniSliver::Node");
my $status;
my $state = $sliver->state();
if (!defined($state)) {
print STDERR "Could not determine state for $sliver in $self\n";
return -1;
}
if ($sliver->ComputeStatus(\$status)) {
print STDERR "Could not determine status for $sliver in $self\n";
return -1;
}
if ($state eq "started") {
$started++;
}
elsif ($state eq "stopped") {
$stopped++;
}
else {
$unknown++;
}
$count++;
}
if ($stopped == $count) {
$self->SetState("stopped");
}
elsif ($started == $count) {
$self->SetState("started");
}
else {
$self->SetState("mixed");
}
return 0;
}
############################################################################
#
# Link aggregates need special handling.
......@@ -878,7 +1095,7 @@ sub UnProvision($)
#
# Nothing to do yet.
#
sub Start($)
sub Start($$)
{
my ($self) = @_;
......@@ -891,7 +1108,7 @@ sub Start($)
#
# Nothing to do yet.
#
sub Stop($)
sub Stop($$)
{
my ($self) = @_;
......@@ -1174,7 +1391,7 @@ sub UnProvision($)
#
# Nothing to do yet.
#
sub Start($)
sub Start($$)
{
my ($self) = @_;
......@@ -1187,7 +1404,7 @@ sub Start($)
#
# Nothing to do yet.
#
sub Stop($)
sub Stop($$)
{
my ($self) = @_;
......
......@@ -1724,10 +1724,12 @@ sub SliverWorkAux($$$$$$$)
}
$restorephys = 1;
system("$SNMPIT -r $pid $eid");
if ($?) {
print STDERR "Could not tear down vlans\n";
goto bad;
if (!$v2) {
system("$SNMPIT -r $pid $eid");
if ($?) {
print STDERR "Could not tear down vlans\n";
goto bad;
}
}
}
else {
......@@ -2066,19 +2068,28 @@ sub SliverWorkAux($$$$$$$)
# We want to do this stuff only once, not for each node.
#
# Must have the topofile for node boot. Might need locking on this.
if (system("$GENTOPOFILE $pid $eid")) {
print STDERR "$GENTOPOFILE failed\n";
goto bad;
}
if (system("$EXPORTS_SETUP")) {
print STDERR "$EXPORTS_SETUP failed\n";
goto bad;
}
# The nodes will not boot locally unless there is a DNS record.
if (system("$NAMEDSETUP")) {
print STDERR "$NAMEDSETUP failed\n";
goto bad;
#
if (!$v2) {
if (system("$GENTOPOFILE $pid $eid")) {
print STDERR "$GENTOPOFILE failed\n";
goto bad;
}
if (system("$EXPORTS_SETUP")) {
print STDERR "$EXPORTS_SETUP failed\n";
goto bad;
}
# The nodes will not boot locally unless there is a DNS record.
if (system("$NAMEDSETUP")) {
print STDERR "$NAMEDSETUP failed\n";
goto bad;
}
system("$SNMPIT -t $pid $eid");
if ($?) {
$message = "Could not set up vlans";
goto bad;
}
}
# Set up plab nodes all at once.
if ($needplabslice && @plabnodes && !$impotent) {
my @node_ids = map { $_->node_id() } @plabnodes;
......@@ -2090,15 +2101,6 @@ sub SliverWorkAux($$$$$$$)
}
}
#
# Run snmpit ...
#
system("$SNMPIT -t $pid $eid");
if ($?) {
$message = "Could not set up vlans";
goto bad;
}
# The Manifest.
my $manifest =
eval { XMLout($rspec, "NoAttr" => 1, RootName => "manifest") };
......@@ -2180,12 +2182,14 @@ sub SliverWorkAux($$$$$$$)
print STDERR "Could not restore backup state for $pid,$eid\n";
}
}
system("$SNMPIT -t $pid $eid");
if ($?) {
print STDERR "Could not restore vlans\n";
if (!$v2) {
system("$SNMPIT -t $pid $eid");
if ($?) {
print STDERR "Could not restore vlans\n";
}
}
}
else {
elsif (!$v2) {
system("$SNMPIT -r $pid $eid");
if ($?) {
print STDERR "Could not tear down vlans\n";
......@@ -2442,7 +2446,7 @@ sub StartSliver($)
}
}
if (!$impotent && $sliver->Start() != 0) {
if (!$impotent && $sliver->Start($API_VERSION, 0) != 0) {
$slice->UnLock();
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not start sliver/aggregate");
......@@ -3662,13 +3666,6 @@ sub CleanupDeadSlice($;$)
return -1;
}
}
# These are not serious errors.
if (system("$EXPORTS_SETUP")) {
print STDERR "$EXPORTS_SETUP failed\n";
}
if (system("$NAMEDSETUP")) {
print STDERR "$NAMEDSETUP failed\n";
}
}
#
......@@ -3747,6 +3744,16 @@ sub CleanupDeadSlice($;$)
DBQueryWarn("delete from geni_manifests ".
"where slice_uuid='$slice_uuid'");
if (defined($experiment)) {
# These are not serious errors.
if (system("$EXPORTS_SETUP")) {
print STDERR "$EXPORTS_SETUP failed\n";
}
if (system("$NAMEDSETUP")) {
print STDERR "$NAMEDSETUP failed\n";
}
}
return 0
if (!$purge);
......
......@@ -346,7 +346,7 @@ sub CreateSliver($)
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Internal Error");
}
if ($aggregate->Start() != 0) {
if ($aggregate->Start($API_VERSION, 0) != 0) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not start sliver");
}
......@@ -545,7 +545,34 @@ sub StartSliver($)
my $slice_urn = $argref->{'slice_urn'};
my $sliver_urns = $argref->{'component_urns'};
my $credentials = $argref->{'credentials'};
return SliverAction("start", $slice_urn, $sliver_urns, $credentials);
}
sub StopSliver($)
{
my ($argref) = @_;
my $slice_urn = $argref->{'slice_urn'};
my $sliver_urns = $argref->{'component_urns'};
my $credentials = $argref->{'credentials'};
return SliverAction("stop", $slice_urn, $sliver_urns, $credentials);
}
sub RestartSliver($)
{
my ($argref) = @_;
my $slice_urn = $argref->{'slice_urn'};
my $sliver_urns = $argref->{'component_urns'};
my $credentials = $argref->{'credentials'};
return SliverAction("restart", $slice_urn, $sliver_urns, $credentials);
}
sub SliverAction($$$$)
{
my ($action, $slice_urn, $sliver_urns, $credentials) = @_;
if (! (defined($credentials) &&
(defined($slice_urn) || defined($sliver_urns)))) {
return GeniResponse->MalformedArgsResponse("Missing arguments");
......@@ -576,8 +603,8 @@ sub StartSliver($)
if (defined($slice_urn)) {
if (! GeniHRN::IsValid($slice_urn)) {
return GeniResponse->MalformedArgsResponse("Bad characters ".
"in URN");
return
GeniResponse->MalformedArgsResponse("Bad characters in URN");
}
if ($slice_urn ne $slice->urn()) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN(), undef,
......@@ -586,14 +613,54 @@ sub StartSliver($)
if ($slice->Lock() != 0) {
return GeniResponse->BusyResponse();
}
if ($aggregate->Start() != 0) {
if ($aggregate->ComputeState()) {
$slice->UnLock();
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not start sliver/aggregate");
print STDERR "Could not determine current state\n";
return GeniResponse->Create(GENIRESPONSE_ERROR);
}
if ($action eq "start") {
if ($aggregate->state() ne "stopped") {
$slice->UnLock();
return GeniResponse->Create(GENIRESPONSE_REFUSED, undef,
"Sliver is not stopped (yet)");
}
if ($aggregate->Start($API_VERSION, 0) != 0) {
$slice->UnLock();
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not start sliver");
}
}
elsif ($action eq "stop") {
if ($aggregate->state() ne "started") {
$slice->UnLock();
return GeniResponse->Create(GENIRESPONSE_REFUSED, undef,
"Sliver is not started (yet)");
}
if ($aggregate->Stop($API_VERSION) != 0) {
$slice->UnLock();
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not stop sliver");
}
}
elsif ($action eq "restart") {
if ($aggregate->state() ne "started") {
$slice->UnLock();
return GeniResponse->Create(GENIRESPONSE_REFUSED, undef,
"Sliver is not started (yet)");
}
if ($aggregate->Start($API_VERSION, 1) != 0) {
$slice->UnLock();
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not restart sliver");
}
}
$slice->UnLock();
return GeniResponse->Create(GENIRESPONSE_SUCCESS);
}
else {
}
return GeniResponse->Create(GENIRESPONSE_UNSUPPORTED);
}
#
......@@ -635,54 +702,45 @@ sub SliverStatus($)
if ($slice->Lock() != 0) {
return GeniResponse->BusyResponse();
}
if ($aggregate->ComputeState()) {
print STDERR "SliverStatus: Could not compute state for $aggregate\n";
$slice->UnLock();
return GeniResponse->Create(GENIRESPONSE_ERROR);
}
#
# Grab all the slivers for this slice, and then
# look for just the nodes.
#
my $blob = {
"state" => "started",
"status" => "ready",
"details" => {},
};
my @slivers = ();
if ($aggregate->SliverList(\@slivers) != 0) {
print STDERR "SliverStatus: Could not get slivers for $aggregate\n";
$slice->UnLock();
return GeniResponse->Create(GENIRESPONSE_ERROR);
}
my $blob = {
"state" => $aggregate->state(),
"status" => "ready",
"details" => {},
};
foreach my $sliver (@slivers) {
next
if ($sliver->isa("GeniAggregate"));
next
if ($sliver->resource_type() ne "Node");
my $node_uuid = $sliver->uuid();
my $node = GeniCM::LookupNode($node_uuid);
if (!defined($node)) {
$slice->UnLock();
print STDERR "SliverStatus: Cannot find node by uuid $node_uuid\n";
return GeniResponse->Create(GENIRESPONSE_ERROR);
}
my $urn = GeniHRN::Generate($OURDOMAIN, "sliver", $node->node_id());
my $state = "started";
my $status = "unknown";
my $urn = $sliver->urn();
my $state = $sliver->state();
my $status = $sliver->status();
my $error = "";
if ($node->IsUp()) {
$status = "ready";
}
elsif ($node->eventstate() eq TBDB_NODESTATE_TBFAILED()) {
$status = "failed";
$blob->{'status'} = "failed";
my $bootlog;