diff --git a/scripts/drydock/drydock_control.php b/scripts/drydock/drydock_control.php --- a/scripts/drydock/drydock_control.php +++ b/scripts/drydock/drydock_control.php @@ -2,7 +2,7 @@ setTagline(pht('manage drydock software resources')); diff --git a/scripts/init/init-script-with-signals.php b/scripts/init/init-script-with-signals.php new file mode 100644 --- /dev/null +++ b/scripts/init/init-script-with-signals.php @@ -0,0 +1,11 @@ +releaseOnDestruction(); + $lease->setReleaseOnDestruction(true); if ($lease->isActive()) { // Destroy the working copy on disk. diff --git a/src/applications/drydock/management/DrydockManagementLeaseWorkflow.php b/src/applications/drydock/management/DrydockManagementLeaseWorkflow.php --- a/src/applications/drydock/management/DrydockManagementLeaseWorkflow.php +++ b/src/applications/drydock/management/DrydockManagementLeaseWorkflow.php @@ -84,21 +84,51 @@ $lease->setUntil($until); } + // If something fatals or the user interrupts the process (for example, + // with "^C"), release the lease. We'll cancel this below, if the lease + // actually activates. + $lease->setReleaseOnDestruction(true); + + // TODO: This would probably be better handled with PhutilSignalRouter, + // but it currently doesn't route SIGINT. We're initializing it to setup + // SIGTERM handling and make eventual migration easier. + $router = PhutilSignalRouter::getRouter(); + pcntl_signal(SIGINT, array($this, 'didReceiveInterrupt')); + + $t_start = microtime(true); $lease->queueForActivation(); echo tsprintf( - "%s\n", + "%s\n\n __%s__\n\n%s\n", + pht('Queued lease for activation:'), + PhabricatorEnv::getProductionURI($lease->getURI()), pht('Waiting for daemons to activate lease...')); $this->waitUntilActive($lease); + // Now that we've survived activation and the lease is good, make it + // durable. + $lease->setReleaseOnDestruction(false); + $t_end = microtime(true); + echo tsprintf( - "%s\n", - pht('Activated lease "%s".', $lease->getID())); + "%s\n\n %s\n\n%s\n", + pht( + 'Activation complete. This lease is permanent until manually '. + 'released with:'), + pht('$ ./bin/drydock release-lease --id %d', $lease->getID()), + pht( + 'Lease activated in %sms.', + new PhutilNumber((int)(($t_end - $t_start) * 1000)))); return 0; } + public function didReceiveInterrupt($signo) { + // Doing this makes us run destructors, particularly the "release on + // destruction" trigger on the lease. + exit(128 + $signo); + } private function waitUntilActive(DrydockLease $lease) { $viewer = $this->getViewer(); diff --git a/src/applications/drydock/storage/DrydockLease.php b/src/applications/drydock/storage/DrydockLease.php --- a/src/applications/drydock/storage/DrydockLease.php +++ b/src/applications/drydock/storage/DrydockLease.php @@ -36,8 +36,8 @@ * a lease, as you don't need to explicitly handle exceptions to properly * release the lease. */ - public function releaseOnDestruction() { - $this->releaseOnDestruction = true; + public function setReleaseOnDestruction($release) { + $this->releaseOnDestruction = $release; return $this; } @@ -436,6 +436,11 @@ return $this; } + public function getURI() { + $id = $this->getID(); + return "/drydock/lease/{$id}/"; + } + /* -( PhabricatorPolicyInterface )----------------------------------------- */ diff --git a/src/applications/drydock/worker/DrydockRepositoryOperationUpdateWorker.php b/src/applications/drydock/worker/DrydockRepositoryOperationUpdateWorker.php --- a/src/applications/drydock/worker/DrydockRepositoryOperationUpdateWorker.php +++ b/src/applications/drydock/worker/DrydockRepositoryOperationUpdateWorker.php @@ -62,7 +62,7 @@ DrydockCommandInterface::INTERFACE_TYPE); // No matter what happens here, destroy the lease away once we're done. - $lease->releaseOnDestruction(true); + $lease->setReleaseOnDestruction(true); $operation->applyOperation($interface);