Commit aeb3d617 authored by Leigh Stoller's avatar Leigh Stoller

Improvements to the protogeni fcgid handler:

* Fix the logging that had been messed up for while; the logfile object
  was not defined in the children, needed a little reorg.

* Add changes needed for SecureImageDownload(), which is a little
  messier with fcgid since we have to stream the image back to apache
  which means we need to reconnect the fcgid handler.

* Add the CH module, seems to work fine.

* Wrap the calls to cluster-wrapper.pl so that we can set an ENV
  variable indicating which module is being served, and then put this
  in the proc title; its very annoying that perl (sometime?) messes the
  with the proc title without permission from me, so I don't know what
  each server is serving since the command line options are gone.

* Some tweaks to the apache config file.

Note hat this is not running live yet, still just in my devel tree.
parent 5d9c502d
......@@ -857,7 +857,9 @@ ScriptAlias /protogeni/xmlrpc @prefix@/protogeni/xmlrpc/protogeni-wrapper.pl
LoadModule fcgid_module libexec/apache22/mod_fcgid.so
FcgidBusyTimeout 1000
FcgidIOTimeout 1000
FcgidMaxProcessesPerClass 25
FcgidMaxRequestLen 524288
FcgidMaxRequestsPerProcess 100
FcgidMaxProcessesPerClass 50
<LocationMatch "/protogeni/xmlrpc/(root|cluster)/*">
FcgidWrapper @prefix@/protogeni/xmlrpc/cluster-wrapper.pl
......
......@@ -66,6 +66,8 @@ my $SLICESHUTDOWN = "$TB/sbin/protogeni/shutdownslice";
my $API_VERSION = 1;
sub InitModule($) { $main::GENI_ISCLRHOUSE = 1; }
#
# This is for Flack.
#
......
#!/usr/bin/perl -w
#
# Copyright (c) 2008-2016 University of Utah and the Flux Group.
# Copyright (c) 2008-2017 University of Utah and the Flux Group.
#
# {{{GENIPUBLIC-LICENSE
#
......@@ -42,10 +42,11 @@ sub usage()
"[-c credfile] -o outfile imageid\n";
exit(1);
}
my $optlist = "ndvc:u:o:";
my $optlist = "ndvc:u:o:D";
my $impotent = 0;
my $debug = 0;
my $verbose = 0;
my $devtree = 0;
my $credfile;
my $outfile;
my $outfp;
......@@ -110,6 +111,9 @@ if (defined($options{"n"})) {
if (defined($options{"d"})) {
$debug = 1;
}
if (defined($options{"D"})) {
$devtree = 1;
}
if (defined($options{"v"})) {
$verbose = 1;
}
......@@ -183,7 +187,7 @@ my $authority = GeniAuthority->CreateFromRegistry("cm", $signer->urn());
fatal("Could not lookup authority: " . $signer->urn())
if (!defined($authority));
my $cmurl = $authority->url();
$cmurl =~ s/protogeni/protogeni\/stoller/;
$cmurl =~ s/protogeni/protogeni\/stoller/ if ($devtree);
#
# Suck over some bits.
......
......@@ -102,6 +102,7 @@ my $noanything = 0;
# Flag for XMLERROR.
my $logging = 0;
my $logforked = 0;
my $logaborted = 0;
my $iserror = 0;
my $rpcerror = 0;
my $parent = 1;
......@@ -116,8 +117,18 @@ my $GENIURN = undef;
# Root CA of $GENIURN
my $ROOTCA = undef;
sub AppendDebug($)
{
my ($stuff) = @_;
if (open(FOO, ">> /tmp/lbs.txt")) {
print FOO $stuff . "\n";
close(FOO);
}
}
#
# We do not allow any of our code to call exit, since that would kill
# We do not want the top level process to exit, since that would kill
# the fcgid daemon and apache does not like that. Instead, we "throw"
# back to the eval by calling die() since we have a DIE handler setup
# below to make sure we get a stack backtrace.
......@@ -125,6 +136,12 @@ my $ROOTCA = undef;
BEGIN {
sub myexit(;$)
{
# Children are allowed to call exit. But not the parent.
if (!$parent) {
#AppendDebug("$$ called exit from:\n" . Carp::longmess());
CORE::exit(0);
}
#AppendDebug("$$ needs to die from:\n" . Carp::longmess());
die("called exit\n");
}
*CORE::GLOBAL::exit = \&myexit;
......@@ -223,6 +240,7 @@ sub Start($$)
$logfile = undef;
$logfilename = undef;
$logforked = 0;
$logaborted = 0;
$parent = 1;
@metadata = ();
my $response = undef;
......@@ -488,6 +506,13 @@ sub Start($$)
push(@metadata, ["Version", $VERSION]) if (defined($VERSION));
push(@metadata, ["StartTime", TBTimeStamp()]);
push(@metadata, ["Project", $PROJECT]) if (defined($PROJECT));
push(@metadata, ["Fcgid", "Yes"]);
#
# Create the Logfile now, since we might call WrapperFork(), and so
# it can viewed on the web interface as a spew.
#
$logfile = CreateLogFile($logfilename);
#
# We want to catch warnings, specifically uninitialized variables,
......@@ -498,6 +523,9 @@ sub Start($$)
if ($message =~ /uninitialized value/) {
die($message);
}
elsif ($message =~ /Statement unlikely to be reached at/) {
cluck($message);
}
else {
cluck($message);
}
......@@ -596,7 +624,7 @@ sub Start($$)
# We throw it away unless its an rpc error.
$nostorelogs = 1;
}
elsif (-s $logfilename || $iserror) {
elsif ((-s $logfilename || $iserror) && !$logaborted) {
#
# On output or error send email.
#
......@@ -612,21 +640,15 @@ sub Start($$)
$nostorelogs = 0;
}
#
# If the parent, we create the Logfile, but do not store it yet,
# that will happen later. We want to create it so it can viewed on
# the web interface as a spew.
#
if ($parent) {
if ($parent && !$logaborted) {
#
# Well, we create the logfile only if want a logfile.
# If we decided we do not need the logfile, we will kill it
# later when the last child exits.
#
if (!$nostorelogs) {
$logfile = CreateLogFile($logfilename);
my $logurn = GeniHRN::Generate("@OURDOMAIN@", "log",
$logfile->logid());
if (!$rpcerror) {
$result->{'protogeni_error_log'} = $logurn;
$result->{'protogeni_error_url'} = $logfile->URL();
}
......@@ -648,16 +670,28 @@ sub Start($$)
}
}
}
if (!$logforked) {
#
# This is the last child exiting, now we can deal with the log.
#
if (defined($logfile)) {
#
# This is the last child exiting, now we can deal with the log.
#
if (!$logforked && defined($logfile)) {
if ($nostorelogs || $logaborted) {
# Delete file below.
$logfile->Delete(0);
}
else {
$logfile->SetMetadata(\@metadata, 1);
$logfile->Store();
if ($logaborted) {
$logfile->Close();
}
else {
$logfile->Store();
}
}
}
LogAbort();
#AppendDebug("$$ $method, $parent, $logforked, $logfile");
LogAbort()
if (!$logaborted);
# Last child exited, delete the file.
if (!$logforked) {
......@@ -688,7 +722,7 @@ sub CreateLogFile($)
print STDERR "Could not lookup group $GENIGROUP";
return undef;
}
my $logfile = Logfile->Create($group);
my $logfile = Logfile->Create($group, $fname);
if (!defined($logfile)) {
print STDERR "Could not create new logfile";
return undef;
......@@ -707,7 +741,7 @@ sub CreateLogFile($)
sub WrapperFork()
{
# This tells libaudit to make sure the parent sends it email first.
AuditPrefork();
#AuditPrefork();
my $mypid = fork();
if ($mypid) {
......@@ -760,6 +794,12 @@ sub AddLogfileMetaDataFromSpeaksFor($)
AddLogfileMetaData("speaking_urn", $speaksfor->owner_urn());
AddLogfileMetaData("speaking_uuid", $speaksfor->owner_uuid());
}
# See GeniCMV2::SecureImageDownload();
sub AbortLogging()
{
LogEnd(0);
$logaborted = 1;
}
#
# Verify the client certificate, including the chain, back to the CA
......
#
# Copyright (c) 2000-2016 University of Utah and the Flux Group.
# Copyright (c) 2000-2017 University of Utah and the Flux Group.
#
# {{{GENIPUBLIC-LICENSE
#
......@@ -38,7 +38,7 @@ include $(OBJDIR)/Makeconf
SETUID_BIN_SCRIPTS =
SETUID_SBIN_SCRIPTS =
SETUID_SUEXEC_SCRIPTS = protogeni-wrapper.pl protogeni-console.pl \
cluster-wrapper.pl
cluster-wrapper.pl
#
# Force dependencies on the scripts so that they will be rerun through
......@@ -49,7 +49,7 @@ all: Genixmlrpc.pm GeniResponse.pm \
protogeni-ses.pm geni-am.pm geni-ma.pm geni-sa.pm \
protogeni-wrapper.pl protogeni-console.pl protogeni-portal.pm \
protogeni-ims.pm cluster-wrapper.pl ClusterWrapper.pm ProtoGeniDefs.pm \
protogeni-cluster.pm
protogeni-cluster.pm ch-wrapper.pl cm-wrapper.pl sa-wrapper.pl
include $(TESTBED_SRCDIR)/GNUmakerules
......@@ -63,6 +63,9 @@ install-libs: $(INSTALL_LIBDIR)/Genixmlrpc.pm \
$(INSTALL_LIBDIR)/protogeni-ses.pm \
$(INSTALL_LIBDIR)/protogeni-emulab.pm \
$(INSTALL_LIBDIR)/protogeni-cluster.pm \
$(INSTALL_DIR)/protogeni/xmlrpc/ch-wrapper.pl \
$(INSTALL_DIR)/protogeni/xmlrpc/sa-wrapper.pl \
$(INSTALL_DIR)/protogeni/xmlrpc/cm-wrapper.pl \
$(INSTALL_LIBDIR)/ClusterWrapper.pm \
$(INSTALL_LIBDIR)/ProtoGeniDefs.pm \
$(INSTALL_LIBDIR)/geni-am.pm \
......
......@@ -90,6 +90,34 @@ AddModule("root",
}},
});
package ProtoGeniDefs::ProtogeniCH;
use lib '@prefix@/lib';
use GeniCH;
ProtoGeniDefs::AddModule("ch",
{
"PEMFILE" => "@prefix@/etc/genich.pem",
"DBNAME" => "geni-ch",
"DEFVERSION" => "1",
"INITMODULE" => \&GeniCH::InitModule,
"METHODS" => {"1" => {
"GetVersion" => \&GeniCH::GetVersion,
"GetCredential" => \&GeniCH::GetCredential,
"Resolve" => \&GeniCH::Resolve,
"Register" => \&GeniCH::Register,
"Remove" => \&GeniCH::Remove,
"ListComponents" => \&GeniCH::ListComponents,
"PostCRL" => \&GeniCH::PostCRL,
"Shutdown" => \&GeniCH::Shutdown,
"List" => \&GeniCH::List,
"WhoAmI" => \&GeniCH::WhoAmI,
"PostHistoryRecord" => \&GeniCH::PostHistoryRecord,
"ReadHistoryRecords" => \&GeniCH::ReadHistoryRecords,
"ListActiveSlivers" => \&GeniCH::ListActiveSlivers,
}},
});
package ProtoGeniDefs::ProtogeniSA;
use lib '@prefix@/lib';
......@@ -161,6 +189,7 @@ $V2_METHODS = {
"DescribeDataset" => \&GeniCMV2::DescribeDataset,
"ModifyDataset" => \&GeniCMV2::ModifyDataset,
"GetDatasetCredential" => \&GeniCMV2::GetDatasetCredential,
"SecureImageDownload" => \&GeniCMV2::SecureImageDownload,
"Lockdown" => \&GeniCMV2::Lockdown,
"TriggerImageUpdate"=> \&GeniCMV2::TriggerImageUpdate,
"AddNodes" => \&GeniCMV2::AddNodes,
......
#!/usr/bin/perl -w
#
# Copyright (c) 2000-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 English;
#
# This gets invoked from apache mod_fcgid. Simply a wrapper ...
#
#
# Configure variables
#
my $PROG = "@prefix@/protogeni/xmlrpc/cluster-wrapper.pl";
$ENV{'MODULE'} = "ch";
#
# Run the real thing, and never return.
#
exec $PROG;
die("Could not exec $PROG: $!");
#!/usr/bin/perl -w
#
# Copyright (c) 2008-2016 University of Utah and the Flux Group.
# Copyright (c) 2008-2017 University of Utah and the Flux Group.
#
# {{{GENIPUBLIC-LICENSE
#
......@@ -70,6 +70,30 @@ ClusterWrapper::Initialize();
#
my $FCGI_Handle = FCGI::Request();
#
# If we abort logging and want to send stream data back to apache.
# See GeniCMV2::SecureImageDownload();
#
my $logaborted = 0;
#
# This is a whacky kludge.
#
my $GENI_ISCLRHOUSE;
#
# Set process title
#
if (exists($ENV{'MODULE'})) {
my $module = $ENV{'MODULE'};
if ($module =~ /^(\w+)$/) {
$0 = $0 . " $1";
}
}
#
# Loop until dead, what is dead will never die.
#
while ($FCGI_Handle->Accept() >= 0) {
my $request = undef;
read(STDIN, $request, $ENV{CONTENT_LENGTH});
......@@ -81,6 +105,8 @@ while ($FCGI_Handle->Accept() >= 0) {
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
$logaborted = 0;
#
# We need to "detach" cause mod_fcgid has a bad "tie" implementation,
# and so most calls to open fail. detaching is fine, we have the request,
......@@ -89,6 +115,12 @@ while ($FCGI_Handle->Accept() >= 0) {
#
$FCGI_Handle->Detach();
my $response = ClusterWrapper->Start($request);
# If we aborted (attached) earlier and sent stream data,
# nothing more to do.
next
if ($logaborted);
$FCGI_Handle->Attach();
if ($response) {
print "Content-Type: text/xml \n\n" . $response;
......@@ -112,4 +144,8 @@ sub AddLogfileMetaDataFromSlice($) {
sub AddLogfileMetaDataFromSpeaksFor($) {
return ClusterWrapper::AddLogfileMetaDataFromSpeaksFor($_[0]);
}
sub AbortLogging() {
$logaborted = 1;
$FCGI_Handle->Attach();
return ClusterWrapper::AbortLogging();
}
#!/usr/bin/perl -w
#
# Copyright (c) 2000-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 English;
#
# This gets invoked from apache mod_fcgid. Simply a wrapper ...
#
#
# Configure variables
#
my $PROG = "@prefix@/protogeni/xmlrpc/cluster-wrapper.pl";
$ENV{'MODULE'} = "cm";
#
# Run the real thing, and never return.
#
exec $PROG;
die("Could not exec $PROG: $!");
#!/usr/bin/perl -w
#
# Copyright (c) 2000-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 English;
#
# This gets invoked from apache mod_fcgid. Simply a wrapper ...
#
#
# Configure variables
#
my $PROG = "@prefix@/protogeni/xmlrpc/cluster-wrapper.pl";
$ENV{'MODULE'} = "sa";
#
# Run the real thing, and never return.
#
exec $PROG;
die("Could not exec $PROG: $!");
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