From 5cbc31644b6f7fdb11a2f0e60d0a969ba2d6edcf Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 27 Nov 2012 12:48:03 -0800 Subject: [PATCH] Add a "close" action to Drydock resources Summary: This does nothing fancy, just closes the resource and releases/breaks leases. They'll get cleaned up in some to-be-written GC process. Test Plan: Closed resources from web UI and CLI. Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T2015 Differential Revision: https://secure.phabricator.com/D3998 --- scripts/drydock/drydock_control.php | 1 + src/__phutil_library_map__.php | 4 ++ .../PhabricatorApplicationDrydock.php | 1 + .../DrydockResourceCloseController.php | 53 +++++++++++++++++++ .../DrydockResourceViewController.php | 12 +++++ .../DrydockManagementCloseWorkflow.php | 42 +++++++++++++++ .../drydock/storage/DrydockResource.php | 30 +++++++++++ 7 files changed, 143 insertions(+) create mode 100644 src/applications/drydock/controller/DrydockResourceCloseController.php create mode 100644 src/applications/drydock/management/DrydockManagementCloseWorkflow.php diff --git a/scripts/drydock/drydock_control.php b/scripts/drydock/drydock_control.php index 816c820312..9df73e4723 100755 --- a/scripts/drydock/drydock_control.php +++ b/scripts/drydock/drydock_control.php @@ -17,6 +17,7 @@ $args->parseStandardArguments(); $workflows = array( new DrydockManagementWaitForLeaseWorkflow(), new DrydockManagementLeaseWorkflow(), + new DrydockManagementCloseWorkflow(), new PhutilHelpArgumentWorkflow(), ); diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 7df2c01013..d5b523ca92 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -433,10 +433,12 @@ phutil_register_library_map(array( 'DrydockLog' => 'applications/drydock/storage/DrydockLog.php', 'DrydockLogController' => 'applications/drydock/controller/DrydockLogController.php', 'DrydockLogQuery' => 'applications/drydock/query/DrydockLogQuery.php', + 'DrydockManagementCloseWorkflow' => 'applications/drydock/management/DrydockManagementCloseWorkflow.php', 'DrydockManagementLeaseWorkflow' => 'applications/drydock/management/DrydockManagementLeaseWorkflow.php', 'DrydockManagementWaitForLeaseWorkflow' => 'applications/drydock/management/DrydockManagementWaitForLeaseWorkflow.php', 'DrydockManagementWorkflow' => 'applications/drydock/management/DrydockManagementWorkflow.php', 'DrydockResource' => 'applications/drydock/storage/DrydockResource.php', + 'DrydockResourceCloseController' => 'applications/drydock/controller/DrydockResourceCloseController.php', 'DrydockResourceListController' => 'applications/drydock/controller/DrydockResourceListController.php', 'DrydockResourceStatus' => 'applications/drydock/constants/DrydockResourceStatus.php', 'DrydockResourceViewController' => 'applications/drydock/controller/DrydockResourceViewController.php', @@ -1688,10 +1690,12 @@ phutil_register_library_map(array( 'DrydockLog' => 'DrydockDAO', 'DrydockLogController' => 'DrydockController', 'DrydockLogQuery' => 'PhabricatorOffsetPagedQuery', + 'DrydockManagementCloseWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementLeaseWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementWaitForLeaseWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementWorkflow' => 'PhutilArgumentWorkflow', 'DrydockResource' => 'DrydockDAO', + 'DrydockResourceCloseController' => 'DrydockController', 'DrydockResourceListController' => 'DrydockController', 'DrydockResourceStatus' => 'DrydockConstants', 'DrydockResourceViewController' => 'DrydockController', diff --git a/src/applications/drydock/application/PhabricatorApplicationDrydock.php b/src/applications/drydock/application/PhabricatorApplicationDrydock.php index 3a3198cfd4..2320a2810a 100644 --- a/src/applications/drydock/application/PhabricatorApplicationDrydock.php +++ b/src/applications/drydock/application/PhabricatorApplicationDrydock.php @@ -33,6 +33,7 @@ final class PhabricatorApplicationDrydock extends PhabricatorApplication { 'resource/' => array( '' => 'DrydockResourceListController', '(?P[1-9]\d*)/' => 'DrydockResourceViewController', + '(?P[1-9]\d*)/close/' => 'DrydockResourceCloseController', ), 'lease/' => array( '' => 'DrydockLeaseListController', diff --git a/src/applications/drydock/controller/DrydockResourceCloseController.php b/src/applications/drydock/controller/DrydockResourceCloseController.php new file mode 100644 index 0000000000..94ac736b78 --- /dev/null +++ b/src/applications/drydock/controller/DrydockResourceCloseController.php @@ -0,0 +1,53 @@ +id = $data['id']; + } + + public function processRequest() { + $request = $this->getRequest(); + $user = $request->getUser(); + + $resource = id(new DrydockResource())->load($this->id); + if (!$resource) { + return new Aphront404Response(); + } + + $resource_uri = '/resource/'.$resource->getID().'/'; + $resource_uri = $this->getApplicationURI($resource_uri); + + if ($resource->getStatus() != DrydockResourceStatus::STATUS_OPEN) { + $dialog = id(new AphrontDialogView()) + ->setUser($user) + ->setTitle(pht('Resource Not Open')) + ->appendChild( + '

'.pht('You can only close "open" resources.').'

') + ->addCancelButton($resource_uri); + + return id(new AphrontDialogResponse())->setDialog($dialog); + } + + if (!$request->isDialogFormPost()) { + $dialog = id(new AphrontDialogView()) + ->setUser($user) + ->setTitle(pht('Really close resource?')) + ->appendChild( + '

'.pht( + 'Closing a resource releases all leases and destroys the '. + 'resource. It can not be undone. Continue?').'

') + ->addSubmitButton(pht('Close Resource')) + ->addCancelButton($resource_uri); + + return id(new AphrontDialogResponse())->setDialog($dialog); + } + + $resource->closeResource(); + + return id(new AphrontReloadResponse())->setURI($resource_uri); + } + +} diff --git a/src/applications/drydock/controller/DrydockResourceViewController.php b/src/applications/drydock/controller/DrydockResourceViewController.php index 3a1bbf0552..1004df042b 100644 --- a/src/applications/drydock/controller/DrydockResourceViewController.php +++ b/src/applications/drydock/controller/DrydockResourceViewController.php @@ -63,6 +63,18 @@ final class DrydockResourceViewController extends DrydockController { ->setUser($this->getRequest()->getUser()) ->setObject($resource); + $can_close = ($resource->getStatus() == DrydockResourceStatus::STATUS_OPEN); + $uri = '/resource/'.$resource->getID().'/close/'; + $uri = $this->getApplicationURI($uri); + + $view->addAction( + id(new PhabricatorActionView()) + ->setHref($uri) + ->setName(pht('Close Resource')) + ->setIcon('delete') + ->setWorkflow(true) + ->setDisabled(!$can_close)); + return $view; } diff --git a/src/applications/drydock/management/DrydockManagementCloseWorkflow.php b/src/applications/drydock/management/DrydockManagementCloseWorkflow.php new file mode 100644 index 0000000000..3d30f7f802 --- /dev/null +++ b/src/applications/drydock/management/DrydockManagementCloseWorkflow.php @@ -0,0 +1,42 @@ +setName('close') + ->setSynopsis('Close a resource.') + ->setArguments( + array( + array( + 'name' => 'ids', + 'wildcard' => true, + ), + )); + } + + public function execute(PhutilArgumentParser $args) { + $console = PhutilConsole::getConsole(); + + $ids = $args->getArg('ids'); + if (!$ids) { + throw new PhutilArgumentUsageException( + "Specify one or more resource IDs to close."); + } + + foreach ($ids as $id) { + $resource = id(new DrydockResource())->load($id); + if (!$resource) { + $console->writeErr("Resource %d does not exist!\n", $id); + } else if ($resource->getStatus() != DrydockResourceStatus::STATUS_OPEN) { + $console->writeErr("Resource %d is not 'open'!\n", $id); + } else { + $resource->closeResource(); + $console->writeErr("Closed resource %d.\n", $id); + } + } + + } + +} diff --git a/src/applications/drydock/storage/DrydockResource.php b/src/applications/drydock/storage/DrydockResource.php index 5ca4b40125..c4fa978532 100644 --- a/src/applications/drydock/storage/DrydockResource.php +++ b/src/applications/drydock/storage/DrydockResource.php @@ -54,4 +54,34 @@ final class DrydockResource extends DrydockDAO { return $this->blueprint; } + public function closeResource() { + $this->openTransaction(); + $leases = id(new DrydockLease())->loadAllWhere( + 'resourceID = %d AND status IN (%Ld)', + $this->getID(), + array( + DrydockLeaseStatus::STATUS_PENDING, + DrydockLeaseStatus::STATUS_ACTIVE, + )); + + foreach ($leases as $lease) { + switch ($lease->getStatus()) { + case DrydockLeaseStatus::STATUS_PENDING: + $message = pht('Breaking pending lease (resource closing).'); + $lease->setStatus(DrydockLeaseStatus::STATUS_BROKEN); + break; + case DrydockLeaseStatus::STATUS_ACTIVE: + $message = pht('Releasing active lease (resource closing).'); + $lease->setStatus(DrydockLeaseStatus::STATUS_RELEASED); + break; + } + DrydockBlueprint::writeLog($this, $lease, $message); + $lease->save(); + } + + $this->setStatus(DrydockResourceStatus::STATUS_CLOSED); + $this->save(); + $this->saveTransaction(); + } + }