Commit 186c6fcf authored by Leigh Stoller's avatar Leigh Stoller

Change to previous revision; Destroy is now Warn with an option to

Terminate and/or Freeze. So now we can send email to users about an
experiment, that comes from the system and not from us personally?
parent d1d1e1f8
......@@ -61,6 +61,8 @@ sub usage()
print("Usage: manage_instance idledata instance\n");
print("Usage: manage_instance openstackstats instance\n");
print("Usage: manage_instance getmanifests instance\n");
print("Usage: manage_instance destroy instance\n");
print("Usage: manage_instance warn instance\n");
print("Usage: manage_instance applyextensionpolicy instance\n");
exit(-1);
}
......@@ -150,6 +152,7 @@ sub StartMonitor();
sub StartMonitorInternal(;$);
sub DoImageTrackerStuff($$$$$$$);
sub DoDestroy();
sub DoWarn();
sub DenyExtensionInternal($);
sub ExtendInternal($$$$$);
sub CallMethodOnAggregates($$$@);
......@@ -231,6 +234,9 @@ elsif ($action eq "terminate") {
elsif ($action eq "destroy") {
DoDestroy()
}
elsif ($action eq "warn") {
DoWarn()
}
elsif ($action eq "schedterminate") {
DoSchedTerminate()
}
......@@ -4493,6 +4499,226 @@ sub DoDestroy()
exit($exitcode);
}
#
# Warn the user and the project leader, optionally terminate/freeze.
#
sub DoWarn()
{
my $errcode = 1;
my $exitcode = 1;
my $freeze = 0;
my $terminate = 0;
my $errmsg;
my $reason;
my $logfile;
my $brand = $instance->Brand();
my $creator = $instance->GetGeniUser();
my $slice = $instance->GetGeniSlice();
my $name = $instance->name();
my $pid = $instance->pid();
my $project = $instance->GetProject();
my $slice_uuid = $slice->uuid();
my $weburl = $instance->webURL();
my $optlist = "f:FT";
my %options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"F"})) {
$freeze = 1;
}
if (defined($options{"T"})) {
$terminate = 1;
}
if (defined($options{"f"})) {
my $filename = $options{"f"};
if (! -e $filename) {
fatal("$filename does not exist");
}
open(MSG, $filename) or
fatal("Could not open $filename");
$reason = "";
while (<MSG>) {
$reason .= $_;
}
close(MSG);
}
if (!$freeze && !$terminate && !$reason) {
fatal("Must supply a message!");
}
if (!$this_user->IsAdmin()) {
fatal("Only admins can destroy experiments");
}
if (defined($reason) &&
!TBcheck_dbslot($reason, "default", "fulltext",
TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR)) {
$errmsg = "Illegal characters in your reason";
$errcode = 1;
goto bad;
}
#
# Just a message.
#
if (!$terminate) {
# This will send email if it fails.
if ($freeze) {
my $creator_uid = $instance->creator();
system("$TBACCT -u freeze $creator_uid");
if ($?) {
fatal("Could not freeze the user. Email not sent");
}
}
$reason .= "\n\n";
if ($freeze) {
$reason .=
"Your account has been frozen until this is resolved.\n\n";
}
$reason .= $weburl . "\n";
$brand->SendEmail($creator->email(),
"Your $pid/$name experiment",
$reason,
$brand->OpsEmailAddress(),
"CC: " . $project->GetLeader()->email() . "\n" .
"BCC: " . $brand->OpsEmailAddress());
if (defined($webtask)) {
$webtask->Exited(0);
}
exit(0);
}
if ($instance->admin_lockdown()) {
$errmsg = "Must clear the admin lockdown first.";
$errcode = 1;
goto bad;
}
#
# Lock the slice in case it is doing something else, like taking
# a disk image, since
#
if ($slice->Lock()) {
$errcode = GENIRESPONSE_BUSY;
$errmsg ="Experiment is busy, cannot lock it. Try again later.";
if (defined($webtask)) {
$webtask->output($errmsg);
$webtask->Exited($errcode);
}
print STDERR "$errmsg\n";
exit(1);
}
# No free time.
$instance->Update({"extension_disabled" => 1});
# Expiration is now.
$slice->SetExpiration(time());
# Now we can clear this.
if ($instance->user_lockdown()) {
if (DoLockdownInternal("clear", "user", 0, \$errmsg)) {
$slice->UnLock();
$errcode = 1;
goto bad;
}
}
# Hurry up the terminate instead of waiting for the daemon to see it.
if (!$debug) {
$logfile = TBMakeLogname("destroy");
if (my $childpid = TBBackGround($logfile)) {
my $status = 0;
#
# Wait a couple of seconds to see if there is going to be an
# immediate error. Then return and let it continue to run. This
# allows the web server to see quick errors. Later errors will
# have to be emailed.
#
sleep(5);
my $foo = waitpid($childpid, &WNOHANG);
if ($foo) {
$status = $? >> 8;
}
exit($status);
}
}
# We pass the lock through.
system("$MANAGEINSTANCE " . (defined($webtask) ? "-t $webtask_id " : "").
" -d -- terminate $uuid -L");
#
# We wait for this to finish since if its the local cluster, we cannot
# freeze before termination is complete cause of PROTOGENI_LOCALUSER.
# If there is an error terminating (other then busy), we are kinda
# screwed.
#
if ($?) {
$slice->UnLock();
if ($debug) {
exit ($? >> 8);
}
if (defined($webtask)) {
$webtask->Refresh();
print STDERR $webtask->output() . "\n";
$exitcode = $webtask->exitcode();
}
else {
$exitcode = $? >> 8;
}
SENDMAIL($TBOPS,
"Unable to terminate instance with cause!",
"Pid: $pid\n".
"Name: $name\n".
"Slice: $slice_uuid\n".
"URL: $weburl\n".
"Reason:\n\n" . (defined($reason) ? $reason : "") . "\n",
$TBOPS, undef, $logfile);
unlink($logfile) if (defined($logfile));
exit($exitcode);
}
unlink($logfile) if (defined($logfile));
my $message = "Your experiment, $pid/$name, has been terminated!\n";
if ($freeze) {
$message .= "Your account has been frozen until this is resolved.\n";
}
if (defined($reason)) {
$message .= "Reason:\n\n" . $reason . "\n";
}
else {
$message .= "You will be contacted shortly with an explaination.\n";
}
$brand->SendEmail($creator->email(),
"Your experiment has been terminated with cause!",
$message,
$brand->OpsEmailAddress(),
"CC: " . $project->GetLeader()->email(),
"BCC: " . $brand->OpsEmailAddress());
# This will send email if it fails.
if ($freeze) {
my $creator_uid = $instance->creator();
system("$TBACCT -u freeze $creator_uid");
if ($?) {
exit($? >> 8);
}
}
exit(0);
bad:
print STDERR $errmsg . "\n";
if (defined($webtask)) {
$webtask->output($errmsg);
$webtask->Exited($errcode);
}
done:
exit($exitcode);
}
#
# Apply extension policies.
......
......@@ -264,10 +264,10 @@ $(function ()
lockdown_override});
xmlthing.done(callback);
});
// Destroy an experiment.
$('#destroy-experiment-button').click(function (event) {
// Warn/Kill an experiment.
$('#warnkill-experiment-button').click(function (event) {
event.preventDefault();
DestroyExperiment();
WarnExperiment();
});
// Handler for select/deselect all rows in the list view.
......@@ -688,7 +688,7 @@ $(function ()
}
}
else if (button == "destroy")
button = "#destroy-experiment-button";
button = "#warnkill-experiment-button";
else if (button == "extend")
button = "#extend_button";
else if (button == "refresh")
......@@ -3452,14 +3452,15 @@ $(function ()
/*
* Terminate with cause and optionally freeze user.
*/
function DestroyExperiment()
function WarnExperiment()
{
// Handler for the Snapshot confirm button.
$('#destroy-experiment-confirm')
.bind("click.destroy", function (event) {
event.preventDefault();
var reason = $('#destroy-experiment-reason').val();
var freeze = $('#freeze-user-checkbox').is(':checked');
var kill = $('#destroy-terminate-checkbox').is(':checked');
var freeze = $('#destroy-freeze-checkbox').is(':checked');
var args = {"uuid" : uuid};
if (reason != "") {
args["reason"] = reason;
......@@ -3467,15 +3468,18 @@ $(function ()
if (freeze) {
args["freeze"] = true;
}
if (kill) {
args["terminate"] = true;
}
sup.HideModal("#destroy-experiment-modal", function () {
sup.ShowWaitWait();
sup.CallServerMethod(null, "status", "Destroy", args,
sup.CallServerMethod(null, "status", "Warn", args,
function(json) {
console.info("destroy", json);
console.info("warn/kill", json);
if (json.code) {
sup.HideWaitWait(function () {
sup.SpitOops("oops",
"Could not terminate experiment: " +
"Could not warn/kill experiment: " +
json.value);
});
return;
......
......@@ -186,8 +186,8 @@ $routing = array("geni-login" =>
"Do_Lockout",
"Lockdown" =>
"Do_Lockdown",
"Destroy" =>
"Do_DestroyExperiment",
"Warn" =>
"Do_WarnExperiment",
"Quarantine" =>
"Do_Quarantine",
"SaveAdminNotes" =>
......
......@@ -1868,7 +1868,7 @@ function Do_GetHealthStatus()
SPITAJAX_RESPONSE($status);
}
function Do_DestroyExperiment()
function Do_WarnExperiment()
{
global $instance, $creator, $this_user;
global $ajax_args;
......@@ -1903,14 +1903,18 @@ function Do_DestroyExperiment()
chmod($filename, 0666);
$options = "-f $filename ";
}
# Freeze user after experiment terminated.
# Terminate experiment
if (isset($ajax_args["terminate"]) && $ajax_args["terminate"]) {
$options .= "-T ";
}
# Freeze user
if (isset($ajax_args["freeze"]) && $ajax_args["freeze"]) {
$options .= "-F";
$options .= "-F ";
}
$webtask = WebTask::CreateAnonymous();
$retval = SUEXEC($this_uid, "nobody",
"webmanage_instance -t " . $webtask->task_id() . " -- ".
" destroy $uuid $options ",
" warn $uuid $options ",
SUEXEC_ACTION_IGNORE);
$webtask->Refresh();
if (isset($filename)) {
......
......@@ -6,20 +6,22 @@
<button type='button' class='close' data-dismiss='modal'
aria-hidden='true'>&times;</button>
<span class="text-center">
<h4>Terminate experiment with cause</h4></span>
<h4>Warn User or Terminate experiment with cause</h4></span>
</div>
<div class='modal-body'>
<p>
Are you sure you want to terminate this experiment and
optionally freeze the experimentor? Please provide a
reason below.
</p>
<center>
<p>
Please provide a message and check the boxes below.
</p>
<div>
<textarea id='destroy-experiment-reason'
class='form-control' rows=5></textarea>
</div>
<input type=checkbox id='freeze-user-checkbox' value=yes>
<input type=checkbox
id='destroy-terminate-checkbox' value=yes>
Terminate Experiment
<input type=checkbox style="margin-left: 20px"
id='destroy-freeze-checkbox' value=yes>
Freeze User?
<div style="margin-top: 10px;">
<button class='btn btn-primary'
......@@ -27,7 +29,7 @@
data-dismiss="modal">Cancel</button>
<button class='btn btn-danger'
id='destroy-experiment-confirm'
type='submit' name='destroy'>Terminate</button>
type='submit' name='destroy'>Confirm</button>
</div>
</center>
</div>
......
......@@ -202,11 +202,11 @@ pre {
<button class='btn btn-xs btn-danger' disabled
style='margin-left: 10px;'
style='margin-right: 10px;'
id='destroy-experiment-button' type=button
id='warnkill-experiment-button' type=button
data-toggle='popover'
data-content='Terminate an experiment with cause
data-content='Warn user or terminate experiment with cause
and optionally freeze the user account.'>
Destroy</button>
WarnKill</button>
</div>
<% } %>
<div class='pull-right'>
......
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