Page MenuHomePhabricator

D14144.id34181.diff
No OneTemporary

D14144.id34181.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -832,6 +832,7 @@
'DrydockLease' => 'applications/drydock/storage/DrydockLease.php',
'DrydockLeaseController' => 'applications/drydock/controller/DrydockLeaseController.php',
'DrydockLeaseDatasource' => 'applications/drydock/typeahead/DrydockLeaseDatasource.php',
+ 'DrydockLeaseDestroyWorker' => 'applications/drydock/worker/DrydockLeaseDestroyWorker.php',
'DrydockLeaseListController' => 'applications/drydock/controller/DrydockLeaseListController.php',
'DrydockLeaseListView' => 'applications/drydock/view/DrydockLeaseListView.php',
'DrydockLeasePHIDType' => 'applications/drydock/phid/DrydockLeasePHIDType.php',
@@ -859,6 +860,7 @@
'DrydockResource' => 'applications/drydock/storage/DrydockResource.php',
'DrydockResourceController' => 'applications/drydock/controller/DrydockResourceController.php',
'DrydockResourceDatasource' => 'applications/drydock/typeahead/DrydockResourceDatasource.php',
+ 'DrydockResourceDestroyWorker' => 'applications/drydock/worker/DrydockResourceDestroyWorker.php',
'DrydockResourceListController' => 'applications/drydock/controller/DrydockResourceListController.php',
'DrydockResourceListView' => 'applications/drydock/view/DrydockResourceListView.php',
'DrydockResourcePHIDType' => 'applications/drydock/phid/DrydockResourcePHIDType.php',
@@ -4562,6 +4564,7 @@
),
'DrydockLeaseController' => 'DrydockController',
'DrydockLeaseDatasource' => 'PhabricatorTypeaheadDatasource',
+ 'DrydockLeaseDestroyWorker' => 'DrydockWorker',
'DrydockLeaseListController' => 'DrydockLeaseController',
'DrydockLeaseListView' => 'AphrontView',
'DrydockLeasePHIDType' => 'PhabricatorPHIDType',
@@ -4595,6 +4598,7 @@
),
'DrydockResourceController' => 'DrydockController',
'DrydockResourceDatasource' => 'PhabricatorTypeaheadDatasource',
+ 'DrydockResourceDestroyWorker' => 'DrydockWorker',
'DrydockResourceListController' => 'DrydockResourceController',
'DrydockResourceListView' => 'AphrontView',
'DrydockResourcePHIDType' => 'PhabricatorPHIDType',
diff --git a/src/applications/drydock/blueprint/DrydockAlmanacServiceHostBlueprintImplementation.php b/src/applications/drydock/blueprint/DrydockAlmanacServiceHostBlueprintImplementation.php
--- a/src/applications/drydock/blueprint/DrydockAlmanacServiceHostBlueprintImplementation.php
+++ b/src/applications/drydock/blueprint/DrydockAlmanacServiceHostBlueprintImplementation.php
@@ -87,6 +87,14 @@
$exceptions);
}
+ public function destroyResource(
+ DrydockBlueprint $blueprint,
+ DrydockResource $resource) {
+ // We don't create anything when allocating hosts, so we don't need to do
+ // any cleanup here.
+ return;
+ }
+
public function canAcquireLeaseOnResource(
DrydockBlueprint $blueprint,
DrydockResource $resource,
@@ -110,6 +118,24 @@
->acquireOnResource($resource);
}
+ public function didReleaseLease(
+ DrydockBlueprint $blueprint,
+ DrydockResource $resource,
+ DrydockLease $lease) {
+ // Almanac hosts stick around indefinitely so we don't need to recycle them
+ // if they don't have any leases.
+ return;
+ }
+
+ public function destroyLease(
+ DrydockBlueprint $blueprint,
+ DrydockResource $resource,
+ DrydockLease $lease) {
+ // We don't create anything when activating a lease, so we don't need to
+ // throw anything away.
+ return;
+ }
+
private function getLeaseSlotLock(DrydockResource $resource) {
$resource_phid = $resource->getPHID();
return "almanac.host.lease({$resource_phid})";
diff --git a/src/applications/drydock/blueprint/DrydockBlueprintImplementation.php b/src/applications/drydock/blueprint/DrydockBlueprintImplementation.php
--- a/src/applications/drydock/blueprint/DrydockBlueprintImplementation.php
+++ b/src/applications/drydock/blueprint/DrydockBlueprintImplementation.php
@@ -67,6 +67,11 @@
DrydockResource $resource,
DrydockLease $lease);
+
+ /**
+ * @return void
+ * @task lease
+ */
public function activateLease(
DrydockBlueprint $blueprint,
DrydockResource $resource,
@@ -74,37 +79,40 @@
throw new PhutilMethodNotImplementedException();
}
- final public function releaseLease(
+
+ /**
+ * React to a lease being released.
+ *
+ * This callback is primarily useful for automatically releasing resources
+ * once all leases are released.
+ *
+ * @param DrydockBlueprint Blueprint which built the resource.
+ * @param DrydockResource Resource a lease was released on.
+ * @param DrydockLease Recently released lease.
+ * @return void
+ * @task lease
+ */
+ abstract public function didReleaseLease(
DrydockBlueprint $blueprint,
DrydockResource $resource,
- DrydockLease $lease) {
-
- // TODO: This is all broken nonsense.
-
- $scope = $this->pushActiveScope(null, $lease);
-
- $released = false;
-
- $lease->openTransaction();
- $lease->beginReadLocking();
- $lease->reload();
-
- if ($lease->getStatus() == DrydockLeaseStatus::STATUS_ACTIVE) {
- $lease->release();
- $lease->setStatus(DrydockLeaseStatus::STATUS_RELEASED);
- $lease->save();
- $released = true;
- }
-
- $lease->endReadLocking();
- $lease->saveTransaction();
-
- if (!$released) {
- throw new Exception(pht('Unable to release lease: lease not active!'));
- }
+ DrydockLease $lease);
- }
+ /**
+ * Destroy any temporary data associated with a lease.
+ *
+ * If a lease creates temporary state while held, destroy it here.
+ *
+ * @param DrydockBlueprint Blueprint which built the resource.
+ * @param DrydockResource Resource the lease is acquired on.
+ * @param DrydockLease The lease being destroyed.
+ * @return void
+ * @task lease
+ */
+ abstract public function destroyLease(
+ DrydockBlueprint $blueprint,
+ DrydockResource $resource,
+ DrydockLease $lease);
/* -( Resource Allocation )------------------------------------------------ */
@@ -204,12 +212,34 @@
DrydockBlueprint $blueprint,
DrydockLease $lease);
+
+ /**
+ * @task resource
+ */
public function activateResource(
DrydockBlueprint $blueprint,
DrydockResource $resource) {
throw new PhutilMethodNotImplementedException();
}
+
+ /**
+ * Destroy any temporary data associated with a resource.
+ *
+ * If a resource creates temporary state when allocated, destroy that state
+ * here. For example, you might shut down a virtual host or destroy a working
+ * copy on disk.
+ *
+ * @param DrydockBlueprint Blueprint which built the resource.
+ * @param DrydockResource Resource being destroyed.
+ * @return void
+ * @task resource
+ */
+ abstract public function destroyResource(
+ DrydockBlueprint $blueprint,
+ DrydockResource $resource);
+
+
/* -( Resource Interfaces )------------------------------------------------ */
diff --git a/src/applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php b/src/applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php
--- a/src/applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php
+++ b/src/applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php
@@ -126,6 +126,26 @@
->activateResource();
}
+ public function destroyResource(
+ DrydockBlueprint $blueprint,
+ DrydockResource $resource) {
+
+ $lease = $this->loadHostLease($resource);
+
+ // Destroy the lease on the host.
+ $lease->releaseOnDestruction();
+
+ // Destroy the working copy on disk.
+ $command_type = DrydockCommandInterface::INTERFACE_TYPE;
+ $interface = $lease->getInterface($command_type);
+
+ $root_key = 'workingcopy.root';
+ $root = $resource->getAttribute($root_key);
+ if (strlen($root)) {
+ $interface->execx('rm -rf -- %s', $root);
+ }
+ }
+
public function activateLease(
DrydockBlueprint $blueprint,
DrydockResource $resource,
@@ -162,6 +182,26 @@
$lease->activateOnResource($resource);
}
+ public function didReleaseLease(
+ DrydockBlueprint $blueprint,
+ DrydockResource $resource,
+ DrydockLease $lease) {
+ // We leave working copies around even if there are no leases on them,
+ // since the cost to maintain them is nearly zero but rebuilding them is
+ // moderately expensive and it's likely that they'll be reused.
+ return;
+ }
+
+ public function destroyLease(
+ DrydockBlueprint $blueprint,
+ DrydockResource $resource,
+ DrydockLease $lease) {
+ // When we activate a lease we just reset the working copy state and do
+ // not create any new state, so we don't need to do anything special when
+ // destroying a lease.
+ return;
+ }
+
public function getType() {
return 'working-copy';
}
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
@@ -45,11 +45,18 @@
if ($attributes) {
$lease->setAttributes($attributes);
}
- $lease
- ->queueForActivation()
- ->waitUntilActive();
+ $lease->queueForActivation();
+
+ echo tsprintf(
+ "%s\n",
+ pht('Waiting for daemons to activate lease...'));
+
+ $lease->waitUntilActive();
+
+ echo tsprintf(
+ "%s\n",
+ pht('Activated lease "%s".', $lease->getID()));
- $console->writeOut("%s\n", pht('Acquired Lease %s', $lease->getID()));
return 0;
}
diff --git a/src/applications/drydock/storage/DrydockBlueprint.php b/src/applications/drydock/storage/DrydockBlueprint.php
--- a/src/applications/drydock/storage/DrydockBlueprint.php
+++ b/src/applications/drydock/storage/DrydockBlueprint.php
@@ -143,6 +143,18 @@
$resource);
}
+
+ /**
+ * @task resource
+ */
+ public function destroyResource(DrydockResource $resource) {
+ $this->getImplementation()->destroyResource(
+ $this,
+ $resource);
+ return $this;
+ }
+
+
/* -( Acquiring Leases )--------------------------------------------------- */
@@ -188,10 +200,27 @@
/**
* @task lease
*/
- public function releaseLease(
+ public function didReleaseLease(
DrydockResource $resource,
DrydockLease $lease) {
- $this->getImplementation()->releaseLease($this, $resource, $lease);
+ $this->getImplementation()->didReleaseLease(
+ $this,
+ $resource,
+ $lease);
+ return $this;
+ }
+
+
+ /**
+ * @task lease
+ */
+ public function destroyLease(
+ DrydockResource $resource,
+ DrydockLease $lease) {
+ $this->getImplementation()->destroyLease(
+ $this,
+ $resource,
+ $lease);
return $this;
}
diff --git a/src/applications/drydock/worker/DrydockLeaseDestroyWorker.php b/src/applications/drydock/worker/DrydockLeaseDestroyWorker.php
new file mode 100644
--- /dev/null
+++ b/src/applications/drydock/worker/DrydockLeaseDestroyWorker.php
@@ -0,0 +1,39 @@
+<?php
+
+final class DrydockLeaseDestroyWorker extends DrydockWorker {
+
+ protected function doWork() {
+ $lease_phid = $this->getTaskDataValue('leasePHID');
+ $lease = $this->loadLease($lease_phid);
+ $this->destroyLease($lease);
+ }
+
+ private function destroyLease(DrydockLease $lease) {
+ $status = $lease->getStatus();
+
+ switch ($status) {
+ case DrydockLeaseStatus::STATUS_RELEASED:
+ case DrydockLeaseStatus::STATUS_BROKEN:
+ break;
+ default:
+ throw new PhabricatorWorkerPermanentFailureException(
+ pht(
+ 'Unable to destroy lease ("%s"), lease has the wrong '.
+ 'status ("%s").',
+ $lease->getPHID(),
+ $status));
+ }
+
+ $resource = $lease->getResource();
+ $blueprint = $resource->getBlueprint();
+
+ $blueprint->destroyLease($resource, $lease);
+
+ // TODO: Rename DrydockLeaseStatus::STATUS_EXPIRED to STATUS_DESTROYED.
+
+ $lease
+ ->setStatus(DrydockLeaseStatus::STATUS_EXPIRED)
+ ->save();
+ }
+
+}
diff --git a/src/applications/drydock/worker/DrydockLeaseUpdateWorker.php b/src/applications/drydock/worker/DrydockLeaseUpdateWorker.php
--- a/src/applications/drydock/worker/DrydockLeaseUpdateWorker.php
+++ b/src/applications/drydock/worker/DrydockLeaseUpdateWorker.php
@@ -53,8 +53,19 @@
DrydockSlotLock::releaseLocks($lease->getPHID());
$lease->saveTransaction();
- // TODO: Hook for resource release behaviors.
- // TODO: Schedule lease destruction.
+ PhabricatorWorker::scheduleTask(
+ 'DrydockLeaseDestroyWorker',
+ array(
+ 'leasePHID' => $lease->getPHID(),
+ ),
+ array(
+ 'objectPHID' => $lease->getPHID(),
+ ));
+
+ $resource = $lease->getResource();
+ $blueprint = $resource->getBlueprint();
+
+ $blueprint->didReleaseLease($resource, $lease);
}
}
diff --git a/src/applications/drydock/worker/DrydockResourceDestroyWorker.php b/src/applications/drydock/worker/DrydockResourceDestroyWorker.php
new file mode 100644
--- /dev/null
+++ b/src/applications/drydock/worker/DrydockResourceDestroyWorker.php
@@ -0,0 +1,35 @@
+<?php
+
+final class DrydockResourceDestroyWorker extends DrydockWorker {
+
+ protected function doWork() {
+ $resource_phid = $this->getTaskDataValue('resourcePHID');
+ $resource = $this->loadResource($resource_phid);
+ $this->destroyResource($resource);
+ }
+
+ private function destroyResource(DrydockResource $resource) {
+ $status = $resource->getStatus();
+
+ switch ($status) {
+ case DrydockResourceStatus::STATUS_CLOSED:
+ case DrydockResourceStatus::STATUS_BROKEN:
+ break;
+ default:
+ throw new PhabricatorWorkerPermanentFailureException(
+ pht(
+ 'Unable to destroy resource ("%s"), resource has the wrong '.
+ 'status ("%s").',
+ $resource->getPHID(),
+ $status));
+ }
+
+ $blueprint = $resource->getBlueprint();
+ $blueprint->destroyResource($resource);
+
+ $resource
+ ->setStatus(DrydockResourceStatus::STATUS_DESTROYED)
+ ->save();
+ }
+
+}
diff --git a/src/applications/drydock/worker/DrydockResourceUpdateWorker.php b/src/applications/drydock/worker/DrydockResourceUpdateWorker.php
--- a/src/applications/drydock/worker/DrydockResourceUpdateWorker.php
+++ b/src/applications/drydock/worker/DrydockResourceUpdateWorker.php
@@ -86,7 +86,14 @@
$lease->scheduleUpdate();
}
- // TODO: Schedule resource destruction.
+ PhabricatorWorker::scheduleTask(
+ 'DrydockResourceDestroyWorker',
+ array(
+ 'resourcePHID' => $resource->getPHID(),
+ ),
+ array(
+ 'objectPHID' => $resource->getPHID(),
+ ));
}
}

File Metadata

Mime Type
text/plain
Expires
Sat, May 11, 2:32 AM (3 w, 3 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6284716
Default Alt Text
D14144.id34181.diff (14 KB)

Event Timeline