Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15340844
D10394.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
15 KB
Referenced Files
None
Subscribers
None
D10394.diff
View Options
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
@@ -621,6 +621,8 @@
'DrydockManagementLeaseWorkflow' => 'applications/drydock/management/DrydockManagementLeaseWorkflow.php',
'DrydockManagementReleaseWorkflow' => 'applications/drydock/management/DrydockManagementReleaseWorkflow.php',
'DrydockManagementWorkflow' => 'applications/drydock/management/DrydockManagementWorkflow.php',
+ 'DrydockMinMaxBlueprintImplementation' => 'applications/drydock/blueprint/DrydockMinMaxBlueprintImplementation.php',
+ 'DrydockMinMaxExpiryBlueprintImplementation' => 'applications/drydock/blueprint/DrydockMinMaxExpiryBlueprintImplementation.php',
'DrydockMinMaxTestBlueprintImplementation' => 'applications/drydock/blueprint/DrydockMinMaxTestBlueprintImplementation.php',
'DrydockPreallocatedHostBlueprintImplementation' => 'applications/drydock/blueprint/DrydockPreallocatedHostBlueprintImplementation.php',
'DrydockQuery' => 'applications/drydock/query/DrydockQuery.php',
@@ -3384,7 +3386,9 @@
'DrydockManagementLeaseWorkflow' => 'DrydockManagementWorkflow',
'DrydockManagementReleaseWorkflow' => 'DrydockManagementWorkflow',
'DrydockManagementWorkflow' => 'PhabricatorManagementWorkflow',
- 'DrydockMinMaxTestBlueprintImplementation' => 'DrydockBlueprintImplementation',
+ 'DrydockMinMaxBlueprintImplementation' => 'DrydockBlueprintImplementation',
+ 'DrydockMinMaxExpiryBlueprintImplementation' => 'DrydockMinMaxBlueprintImplementation',
+ 'DrydockMinMaxTestBlueprintImplementation' => 'DrydockMinMaxExpiryBlueprintImplementation',
'DrydockPreallocatedHostBlueprintImplementation' => 'DrydockBlueprintImplementation',
'DrydockQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'DrydockResource' => array(
diff --git a/src/applications/drydock/blueprint/DrydockMinMaxTestBlueprintImplementation.php b/src/applications/drydock/blueprint/DrydockMinMaxBlueprintImplementation.php
copy from src/applications/drydock/blueprint/DrydockMinMaxTestBlueprintImplementation.php
copy to src/applications/drydock/blueprint/DrydockMinMaxBlueprintImplementation.php
--- a/src/applications/drydock/blueprint/DrydockMinMaxTestBlueprintImplementation.php
+++ b/src/applications/drydock/blueprint/DrydockMinMaxBlueprintImplementation.php
@@ -1,57 +1,13 @@
<?php
-final class DrydockMinMaxTestBlueprintImplementation
+abstract class DrydockMinMaxBlueprintImplementation
extends DrydockBlueprintImplementation {
- public function isEnabled() {
- return true;
- }
-
- public function isTest() {
- return true;
- }
-
- public function getBlueprintName() {
- return pht('Min / Max Count Test');
- }
-
- public function getDescription() {
- return pht('Used to test min / max counts.');
- }
-
public function canAllocateMoreResources(array $pool) {
$max_count = $this->getDetail('max-count');
return count($pool) < $max_count;
}
- protected function executeAllocateResource(
- DrydockResource $resource,
- DrydockLease $lease) {
-
- $path = '/srv/alloctest/'.$resource->getID();
-
- $resource
- ->setName($path)
- ->setStatus(DrydockResourceStatus::STATUS_PENDING)
- ->setAttributes(array(
- 'path' => $path))
- ->save();
-
- mkdir($path);
-
- sleep(10);
-
- $resource->setStatus(DrydockResourceStatus::STATUS_OPEN);
- $resource->save();
- }
-
- protected function canAllocateLease(
- DrydockResource $resource,
- DrydockLease $lease) {
-
- return true;
- }
-
protected function shouldAllocateLease(
DrydockAllocationContext $context,
DrydockResource $resource,
@@ -87,45 +43,6 @@
return $minimum_lease_resource_id === $resource->getID();
}
- protected function executeAcquireLease(
- DrydockResource $resource,
- DrydockLease $lease) {
-
- while ($resource->getStatus() == DrydockResourceStatus::STATUS_PENDING) {
- // This resource is still being set up by another allocator, wait until
- // it is set to open.
- sleep(5);
- $resource->reload();
- }
-
- $path = $resource->getAttribute('path').'/'.$lease->getID();
-
- mkdir($path);
-
- sleep(10);
-
- $lease->setAttribute('path', $path);
- }
-
- public function getType() {
- return 'storage';
- }
-
- public function getInterface(
- DrydockResource $resource,
- DrydockLease $lease,
- $type) {
-
- throw new Exception("No interface of type '{$type}'.");
- }
-
- protected function executeReleaseLease(
- DrydockResource $resource,
- DrydockLease $lease) {
-
- execx('rm -R %s', $lease->getAttribute('path'));
- }
-
protected function shouldCloseUnleasedResource(
DrydockAllocationContext $context,
DrydockResource $resource) {
@@ -134,20 +51,19 @@
$this->getDetail('min-count');
}
- protected function executeCloseResource(DrydockResource $resource) {
- execx('rm -R %s', $resource->getAttribute('path'));
- }
-
-
public function getFieldSpecifications() {
return array(
+ 'min-max-header' => array(
+ 'name' => pht('Allocation Limits'),
+ 'type' => 'header',
+ ),
'min-count' => array(
'name' => pht('Minimum Resources'),
'type' => 'int',
'required' => true,
'caption' => pht(
'The minimum number of resources to keep open in '.
- 'this pool at all times.')
+ 'this pool at all times.'),
),
'max-count' => array(
'name' => pht('Maximum Resources'),
@@ -159,7 +75,7 @@
'leases on existing resources and thus exceeding '.
'`leases-per-resource`. If this parameter is left blank, then '.
'this blueprint has no limit on the number of resources it '.
- 'can allocate.')
+ 'can allocate.'),
),
'leases-per-resource' => array(
'name' => pht('Maximum Leases Per Resource'),
@@ -174,7 +90,7 @@
'another resource providing `max-count` would not be exceeded.'.
' If `max-count` would be exceeded, Drydock will instead '.
'overallocate the lease to an existing resource and '.
- 'exceed the limit specified here.')
+ 'exceed the limit specified here.'),
),
);
}
diff --git a/src/applications/drydock/blueprint/DrydockMinMaxExpiryBlueprintImplementation.php b/src/applications/drydock/blueprint/DrydockMinMaxExpiryBlueprintImplementation.php
new file mode 100644
--- /dev/null
+++ b/src/applications/drydock/blueprint/DrydockMinMaxExpiryBlueprintImplementation.php
@@ -0,0 +1,92 @@
+<?php
+
+abstract class DrydockMinMaxExpiryBlueprintImplementation
+ extends DrydockMinMaxBlueprintImplementation {
+
+ public function canAllocateMoreResources(array $pool) {
+ $max_count = $this->getDetail('max-count');
+
+ $expiry = $this->getDetail('expiry');
+
+ // Only count resources that haven't yet expired, so we can overallocate
+ // if another expired resource is about to be closed (but is still waiting
+ // on it's current resources to be released).
+ $count = 0;
+ $now = time();
+ foreach ($pool as $resource) {
+ $lifetime = $now - $resource->getDateCreated();
+ if ($lifetime <= $expiry) {
+ $count++;
+ }
+ }
+
+ return $count < $max_count;
+ }
+
+ protected function shouldAllocateLease(
+ DrydockAllocationContext $context,
+ DrydockResource $resource,
+ DrydockLease $lease) {
+
+ // If we have no leases allocated to this resource, then we always allow
+ // the parent logic to evaluate. The reason for this is that an expired
+ // resource can only be closed when a lease is released, so if the resource
+ // is open and has no leases, then we'll never reach the code that checks
+ // the expiry to close it. So we allow this lease to occur, so that we'll
+ // hit `shouldCloseUnleasedResource` in the future and the resource will
+ // be closed.
+ if ($context->getCurrentResourceLeaseCount() === 0) {
+ return parent::shouldAllocateLease($context, $resource, $lease);
+ }
+
+ $expiry = $this->getDetail('expiry');
+
+ if ($expiry !== null) {
+ $lifetime = time() - $resource->getDateCreated();
+
+ if ($lifetime > $expiry) {
+ // Prevent allocation of leases to this resource, since it's over
+ // it's lifetime allowed.
+ return false;
+ }
+ }
+
+ return parent::shouldAllocateLease($context, $resource, $lease);
+ }
+
+ protected function shouldCloseUnleasedResource(
+ DrydockAllocationContext $context,
+ DrydockResource $resource) {
+
+ $expiry = $this->getDetail('expiry');
+
+ if ($expiry !== null) {
+ $lifetime = time() - $resource->getDateCreated();
+
+ if ($lifetime > $expiry) {
+ // Force closure of resources that have expired.
+ return true;
+ }
+ }
+
+ return parent::shouldCloseUnleasedResource($context, $resource);
+ }
+
+ public function getFieldSpecifications() {
+ return array(
+ 'expiry-header' => array(
+ 'name' => pht('Resource Expiration'),
+ 'type' => 'header',
+ ),
+ 'expiry' => array(
+ 'name' => pht('Expiry Time'),
+ 'type' => 'int',
+ 'caption' => pht(
+ 'After this time (in seconds) has elapsed since resource creation, '.
+ 'Drydock will no longer lease against the resource, and it will be '.
+ 'closed when there are no more leases (regardless of minimum '.
+ 'resource limits).'),
+ ),
+ ) + parent::getFieldSpecifications();
+ }
+}
diff --git a/src/applications/drydock/blueprint/DrydockMinMaxTestBlueprintImplementation.php b/src/applications/drydock/blueprint/DrydockMinMaxTestBlueprintImplementation.php
--- a/src/applications/drydock/blueprint/DrydockMinMaxTestBlueprintImplementation.php
+++ b/src/applications/drydock/blueprint/DrydockMinMaxTestBlueprintImplementation.php
@@ -1,7 +1,7 @@
<?php
final class DrydockMinMaxTestBlueprintImplementation
- extends DrydockBlueprintImplementation {
+ extends DrydockMinMaxExpiryBlueprintImplementation {
public function isEnabled() {
return true;
@@ -19,11 +19,6 @@
return pht('Used to test min / max counts.');
}
- public function canAllocateMoreResources(array $pool) {
- $max_count = $this->getDetail('max-count');
- return count($pool) < $max_count;
- }
-
protected function executeAllocateResource(
DrydockResource $resource,
DrydockLease $lease) {
@@ -39,7 +34,7 @@
mkdir($path);
- sleep(10);
+ sleep($this->getDetail('seconds-to-open'));
$resource->setStatus(DrydockResourceStatus::STATUS_OPEN);
$resource->save();
@@ -52,41 +47,6 @@
return true;
}
- protected function shouldAllocateLease(
- DrydockAllocationContext $context,
- DrydockResource $resource,
- DrydockLease $lease) {
-
- // If the current resource can allocate a lease, allow it.
- if ($context->getCurrentResourceLeaseCount() <
- $this->getDetail('leases-per-resource')) {
- return true;
- }
-
- // We don't have enough room under the `leases-per-instance` limit, but
- // this limit can be bypassed if we've allocated all of the resources
- // we allow.
- $open_count = $context->getBlueprintOpenResourceCount();
- if ($open_count < $this->getDetail('max-count')) {
- return false;
- }
-
- // Find the resource that has the least leases.
- $all_lease_counts_grouped = $context->getResourceLeaseCounts();
- $minimum_lease_count = $all_lease_counts_grouped[$resource->getID()];
- $minimum_lease_resource_id = $resource->getID();
- foreach ($all_lease_counts_grouped as $resource_id => $lease_count) {
- if ($minimum_lease_count > $lease_count) {
- $minimum_lease_count = $lease_count;
- $minimum_lease_resource_id = $resource_id;
- }
- }
-
- // If we are that resource, then allow it, otherwise let the other
- // less-leased resource run through this logic and allocate the lease.
- return $minimum_lease_resource_id === $resource->getID();
- }
-
protected function executeAcquireLease(
DrydockResource $resource,
DrydockLease $lease) {
@@ -102,7 +62,7 @@
mkdir($path);
- sleep(10);
+ sleep($this->getDetail('seconds-to-lease'));
$lease->setAttribute('path', $path);
}
@@ -138,44 +98,26 @@
execx('rm -R %s', $resource->getAttribute('path'));
}
-
public function getFieldSpecifications() {
return array(
- 'min-count' => array(
- 'name' => pht('Minimum Resources'),
- 'type' => 'int',
- 'required' => true,
- 'caption' => pht(
- 'The minimum number of resources to keep open in '.
- 'this pool at all times.')
+ 'test-configuration' => array(
+ 'name' => pht('Test Configuration'),
+ 'type' => 'header',
),
- 'max-count' => array(
- 'name' => pht('Maximum Resources'),
+ 'seconds-to-open' => array(
+ 'name' => pht('Seconds to Open'),
'type' => 'int',
'caption' => pht(
- 'The maximum number of resources to allow open at any time. '.
- 'If the number of resources currently open are equal to '.
- '`max-count` and another lease is requested, Drydock will place '.
- 'leases on existing resources and thus exceeding '.
- '`leases-per-resource`. If this parameter is left blank, then '.
- 'this blueprint has no limit on the number of resources it '.
- 'can allocate.')
+ 'The time to sleep during creation of a resource.'),
+ 'required' => true,
),
- 'leases-per-resource' => array(
- 'name' => pht('Maximum Leases Per Resource'),
+ 'seconds-to-lease' => array(
+ 'name' => pht('Seconds to Lease'),
'type' => 'int',
- 'required' => true,
'caption' => pht(
- 'The soft limit on the number of leases to allocate to an '.
- 'individual resource in the pool. Drydock will choose the '.
- 'resource with the lowest number of leases when selecting a '.
- 'resource to lease on. If all current resources have '.
- '`leases-per-resource` leases on them, then Drydock will allocate '.
- 'another resource providing `max-count` would not be exceeded.'.
- ' If `max-count` would be exceeded, Drydock will instead '.
- 'overallocate the lease to an existing resource and '.
- 'exceed the limit specified here.')
+ 'The time to sleep while acquiring a lease.'),
+ 'required' => true,
),
- );
+ ) + parent::getFieldSpecifications();
}
}
diff --git a/src/applications/drydock/util/DrydockAllocationContext.php b/src/applications/drydock/util/DrydockAllocationContext.php
--- a/src/applications/drydock/util/DrydockAllocationContext.php
+++ b/src/applications/drydock/util/DrydockAllocationContext.php
@@ -41,7 +41,8 @@
' ON lease.resourceID = resource.id '.
'WHERE resource.blueprintPHID = %s '.
'AND resource.status IN (%Ld) '.
- 'AND lease.status IN (%Ld) ',
+ 'AND lease.status IN (%Ld) '.
+ 'GROUP BY resource.id',
$table_resource,
$table_lease,
$blueprint->getPHID(),
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Mar 10, 5:18 PM (2 w, 2 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7460065
Default Alt Text
D10394.diff (15 KB)
Attached To
Mode
D10394: [drydock/core] Abstract min-max blueprint and implement expiry logic
Attached
Detach File
Event Timeline
Log In to Comment