From 7d1f62409d2e97c81da4161e78ff367fa1b308d5 Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 23 Jan 2012 16:58:38 -0800 Subject: [PATCH] Move resource allocation to task queue Summary: Run the actual resource allocation for Drydock out-of-process via the task queue. Test Plan: Ran "drydock_control.php", saw it insert a task and wait for task completion. Ran "phd debug taskmaster" and saw it run the task. Reviewers: btrahan, jungejason Reviewed By: btrahan CC: aran, epriestley Differential Revision: https://secure.phabricator.com/D1470 --- scripts/drydock/drydock_control.php | 2 + src/__phutil_library_map__.php | 2 + .../allocator/resource/DrydockAllocator.php | 44 ++--------- .../drydock/allocator/resource/__init__.php | 6 +- .../worker/DrydockAllocatorWorker.php | 78 +++++++++++++++++++ .../drydock/allocator/worker/__init__.php | 19 +++++ .../drydock/storage/lease/DrydockLease.php | 21 +++++ 7 files changed, 130 insertions(+), 42 deletions(-) create mode 100644 src/applications/drydock/allocator/worker/DrydockAllocatorWorker.php create mode 100644 src/applications/drydock/allocator/worker/__init__.php diff --git a/scripts/drydock/drydock_control.php b/scripts/drydock/drydock_control.php index edaa84e5ee..e69e1df5f9 100755 --- a/scripts/drydock/drydock_control.php +++ b/scripts/drydock/drydock_control.php @@ -29,6 +29,8 @@ $allocator = new DrydockAllocator(); $allocator->setResourceType('host'); $lease = $allocator->allocate(); +$lease->waitUntilActive(); + $i_file = $lease->getInterface('command'); list($stdout) = $i_file->execx('ls / ; echo -- ; uptime ; echo -- ; uname -n'); diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 4461c91d0d..2a011014a0 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -312,6 +312,7 @@ phutil_register_library_map(array( 'DiffusionSymbolQuery' => 'applications/diffusion/query/symbol', 'DiffusionView' => 'applications/diffusion/view/base', 'DrydockAllocator' => 'applications/drydock/allocator/resource', + 'DrydockAllocatorWorker' => 'applications/drydock/allocator/worker', 'DrydockBlueprint' => 'applications/drydock/blueprint/base', 'DrydockCommandInterface' => 'applications/drydock/interface/command/base', 'DrydockConstants' => 'applications/drydock/constants/base', @@ -1059,6 +1060,7 @@ phutil_register_library_map(array( 'DiffusionSvnRequest' => 'DiffusionRequest', 'DiffusionSymbolController' => 'DiffusionController', 'DiffusionView' => 'AphrontView', + 'DrydockAllocatorWorker' => 'PhabricatorWorker', 'DrydockCommandInterface' => 'DrydockInterface', 'DrydockController' => 'PhabricatorController', 'DrydockDAO' => 'PhabricatorLiskDAO', diff --git a/src/applications/drydock/allocator/resource/DrydockAllocator.php b/src/applications/drydock/allocator/resource/DrydockAllocator.php index f82b8fd1cb..d80e8dd2e0 100644 --- a/src/applications/drydock/allocator/resource/DrydockAllocator.php +++ b/src/applications/drydock/allocator/resource/DrydockAllocator.php @@ -42,45 +42,15 @@ final class DrydockAllocator { } public function allocate() { - $type = $this->getResourceType(); - - $candidates = id(new DrydockResource())->loadAllWhere( - 'type = %s AND status = %s', - $type, - DrydockResourceStatus::STATUS_OPEN); - - if ($candidates) { - shuffle($candidates); - $resource = head($candidates); - } else { - $blueprints = DrydockBlueprint::getAllBlueprintsForResource($type); - - foreach ($blueprints as $key => $blueprint) { - if (!$blueprint->canAllocateResources()) { - unset($blueprints[$key]); - continue; - } - } - - if (!$blueprints) { - throw new Exception( - "There are no valid existing '{$type}' resources, and no valid ". - "blueprints to build new ones."); - } - - // TODO: Rank intelligently. - shuffle($blueprints); - - $blueprint = head($blueprints); - $resource = $blueprint->allocateResource(); - } - $lease = $this->getPendingLease(); - $lease->setResourceID($resource->getID()); - $lease->setStatus(DrydockLeaseStatus::STATUS_ACTIVE); - $lease->save(); - $lease->attachResource($resource); + $task = new PhabricatorWorkerTask(); + $task->setTaskClass('DrydockAllocatorWorker'); + $task->setData(array( + 'type' => $this->getResourceType(), + 'lease' => $lease->getID(), + )); + $task->save(); return $lease; } diff --git a/src/applications/drydock/allocator/resource/__init__.php b/src/applications/drydock/allocator/resource/__init__.php index f057679f5c..c5cb0a1d34 100644 --- a/src/applications/drydock/allocator/resource/__init__.php +++ b/src/applications/drydock/allocator/resource/__init__.php @@ -6,13 +6,9 @@ -phutil_require_module('phabricator', 'applications/drydock/blueprint/base'); phutil_require_module('phabricator', 'applications/drydock/constants/leasestatus'); -phutil_require_module('phabricator', 'applications/drydock/constants/resourcestatus'); phutil_require_module('phabricator', 'applications/drydock/storage/lease'); -phutil_require_module('phabricator', 'applications/drydock/storage/resource'); - -phutil_require_module('phutil', 'utils'); +phutil_require_module('phabricator', 'infrastructure/daemon/workers/storage/task'); phutil_require_source('DrydockAllocator.php'); diff --git a/src/applications/drydock/allocator/worker/DrydockAllocatorWorker.php b/src/applications/drydock/allocator/worker/DrydockAllocatorWorker.php new file mode 100644 index 0000000000..043b883e6b --- /dev/null +++ b/src/applications/drydock/allocator/worker/DrydockAllocatorWorker.php @@ -0,0 +1,78 @@ +getTaskData(); + + $lease = id(new DrydockLease())->loadOneWhere( + 'id = %d', + $data['lease']); + if (!$lease) { + return; + } + + $type = $data['type']; + + $candidates = id(new DrydockResource())->loadAllWhere( + 'type = %s AND status = %s', + $type, + DrydockResourceStatus::STATUS_OPEN); + + if ($candidates) { + shuffle($candidates); + $resource = head($candidates); + } else { + $blueprints = DrydockBlueprint::getAllBlueprintsForResource($type); + + foreach ($blueprints as $key => $blueprint) { + if (!$blueprint->canAllocateResources()) { + unset($blueprints[$key]); + continue; + } + } + + if (!$blueprints) { + $lease->setStatus(DrydockLeaseStatus::STATUS_BROKEN); + $lease->save(); + +/* TODO + $lease->updateLog( + "There are no resources of type '{$type}' available, and no ". + "blueprints which can allocate new ones."); +*/ + + return; + } + + // TODO: Rank intelligently. + shuffle($blueprints); + + $blueprint = head($blueprints); + $resource = $blueprint->allocateResource(); + } + + $lease->setResourceID($resource->getID()); + $lease->setStatus(DrydockLeaseStatus::STATUS_ACTIVE); + $lease->save(); + } + +} + + diff --git a/src/applications/drydock/allocator/worker/__init__.php b/src/applications/drydock/allocator/worker/__init__.php new file mode 100644 index 0000000000..09a118d3f6 --- /dev/null +++ b/src/applications/drydock/allocator/worker/__init__.php @@ -0,0 +1,19 @@ +status) { + case DrydockLeaseStatus::STATUS_ACTIVE: + break 2; + case DrydockLeaseStatus::STATUS_RELEASED: + case DrydockLeaseStatus::STATUS_EXPIRED: + case DrydockLeaseStatus::STATUS_BROKEN: + throw new Exception("Lease will never become active!"); + case DrydockLeaseStatus::STATUS_PENDING: + break; + } + sleep(2); + $this->reload(); + } + + $this->attachResource($this->loadResource()); + + return $this; + } + }