Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/drydock/management/DrydockManagementLeaseWorkflow.php b/src/applications/drydock/management/DrydockManagementLeaseWorkflow.php
index 7890b27d28..fa9f83ad1e 100644
--- a/src/applications/drydock/management/DrydockManagementLeaseWorkflow.php
+++ b/src/applications/drydock/management/DrydockManagementLeaseWorkflow.php
@@ -1,221 +1,263 @@
<?php
final class DrydockManagementLeaseWorkflow
extends DrydockManagementWorkflow {
protected function didConstruct() {
$this
->setName('lease')
->setSynopsis(pht('Lease a resource.'))
->setArguments(
array(
array(
'name' => 'type',
'param' => 'resource_type',
'help' => pht('Resource type.'),
),
array(
'name' => 'until',
'param' => 'time',
'help' => pht('Set lease expiration time.'),
),
array(
'name' => 'attributes',
'param' => 'file',
'help' => pht(
'JSON file with lease attributes. Use "-" to read attributes '.
'from stdin.'),
),
+ array(
+ 'name' => 'count',
+ 'param' => 'N',
+ 'default' => 1,
+ 'help' => pht('Lease a given number of identical resources.'),
+ ),
));
}
public function execute(PhutilArgumentParser $args) {
$viewer = $this->getViewer();
$resource_type = $args->getArg('type');
- if (!$resource_type) {
+ if (!phutil_nonempty_string($resource_type)) {
throw new PhutilArgumentUsageException(
pht(
- 'Specify a resource type with `%s`.',
- '--type'));
+ 'Specify a resource type with "--type".'));
}
$until = $args->getArg('until');
if (phutil_nonempty_string($until)) {
$until = strtotime($until);
if ($until <= 0) {
throw new PhutilArgumentUsageException(
pht(
- 'Unable to parse argument to "%s".',
- '--until'));
+ 'Unable to parse argument to "--until".'));
}
}
+ $count = $args->getArgAsInteger('count');
+ if ($count < 1) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Value provided to "--count" must be a nonzero, positive '.
+ 'number.'));
+ }
+
$attributes_file = $args->getArg('attributes');
if (phutil_nonempty_string($attributes_file)) {
if ($attributes_file == '-') {
echo tsprintf(
"%s\n",
- 'Reading JSON attributes from stdin...');
+ pht('Reading JSON attributes from stdin...'));
$data = file_get_contents('php://stdin');
} else {
$data = Filesystem::readFile($attributes_file);
}
$attributes = phutil_json_decode($data);
} else {
$attributes = array();
}
- $lease = id(new DrydockLease())
- ->setResourceType($resource_type);
+ $leases = array();
+ for ($idx = 0; $idx < $count; $idx++) {
+ $lease = id(new DrydockLease())
+ ->setResourceType($resource_type);
- $drydock_phid = id(new PhabricatorDrydockApplication())->getPHID();
- $lease->setAuthorizingPHID($drydock_phid);
+ $drydock_phid = id(new PhabricatorDrydockApplication())->getPHID();
+ $lease->setAuthorizingPHID($drydock_phid);
- if ($attributes) {
- $lease->setAttributes($attributes);
- }
+ if ($attributes) {
+ $lease->setAttributes($attributes);
+ }
- // TODO: This is not hugely scalable, although this is a debugging workflow
- // so maybe it's fine. Do we even need `bin/drydock lease` in the long run?
- $all_blueprints = id(new DrydockBlueprintQuery())
- ->setViewer($viewer)
- ->execute();
- $allowed_phids = mpull($all_blueprints, 'getPHID');
- if (!$allowed_phids) {
- throw new Exception(
- pht(
- 'No blueprints exist which can plausibly allocate resources to '.
- 'satisfy the requested lease.'));
- }
- $lease->setAllowedBlueprintPHIDs($allowed_phids);
+ // TODO: This is not hugely scalable, although this is a debugging
+ // workflow so maybe it's fine. Do we even need `bin/drydock lease` in
+ // the long run?
+ $all_blueprints = id(new DrydockBlueprintQuery())
+ ->setViewer($viewer)
+ ->execute();
+ $allowed_phids = mpull($all_blueprints, 'getPHID');
+ if (!$allowed_phids) {
+ throw new Exception(
+ pht(
+ 'No blueprints exist which can plausibly allocate resources to '.
+ 'satisfy the requested lease.'));
+ }
+ $lease->setAllowedBlueprintPHIDs($allowed_phids);
- if ($until) {
- $lease->setUntil($until);
- }
+ if ($until) {
+ $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);
+ // 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);
+
+ $leases[] = $lease;
+ }
// 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\n __%s__\n\n%s\n",
- pht('Queued lease for activation:'),
- PhabricatorEnv::getProductionURI($lease->getURI()),
- pht('Waiting for daemons to activate lease...'));
+ "%s\n\n",
+ pht('Leases queued for activation:'));
+
+ foreach ($leases as $lease) {
+ $lease->queueForActivation();
- $this->waitUntilActive($lease);
+ echo tsprintf(
+ " __%s__\n",
+ PhabricatorEnv::getProductionURI($lease->getURI()));
+ }
+
+ echo tsprintf(
+ "\n%s\n\n",
+ pht('Waiting for daemons to activate leases...'));
+
+ foreach ($leases as $lease) {
+ $this->waitUntilActive($lease);
+ }
// Now that we've survived activation and the lease is good, make it
// durable.
- $lease->setReleaseOnDestruction(false);
+ foreach ($leases as $lease) {
+ $lease->setReleaseOnDestruction(false);
+ }
+
$t_end = microtime(true);
echo tsprintf(
- "%s\n\n %s\n\n%s\n",
+ "\n%s\n\n",
pht(
- 'Activation complete. This lease is permanent until manually '.
- 'released with:'),
- pht('$ ./bin/drydock release-lease --id %d', $lease->getID()),
+ 'Activation complete. Leases are permanent until manually '.
+ 'released with:'));
+
+ foreach ($leases as $lease) {
+ echo tsprintf(
+ " %s\n",
+ pht('$ ./bin/drydock release-lease --id %d', $lease->getID()));
+ }
+
+ echo tsprintf(
+ "\n%s\n",
pht(
- 'Lease activated in %sms.',
+ 'Leases 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();
$log_cursor = 0;
$log_types = DrydockLogType::getAllLogTypes();
$is_active = false;
while (!$is_active) {
$lease->reload();
$pager = id(new AphrontCursorPagerView())
->setBeforeID($log_cursor);
// While we're waiting, show the user any logs which the daemons have
// generated to give them some clue about what's going on.
$logs = id(new DrydockLogQuery())
->setViewer($viewer)
->withLeasePHIDs(array($lease->getPHID()))
->executeWithCursorPager($pager);
if ($logs) {
$logs = mpull($logs, null, 'getID');
ksort($logs);
$log_cursor = last_key($logs);
}
foreach ($logs as $log) {
$type_key = $log->getType();
if (isset($log_types[$type_key])) {
$type_object = id(clone $log_types[$type_key])
->setLog($log)
->setViewer($viewer);
$log_data = $log->getData();
$type = $type_object->getLogTypeName();
$data = $type_object->renderLogForText($log_data);
} else {
$type = pht('Unknown ("%s")', $type_key);
$data = null;
}
echo tsprintf(
- "<%s> %B\n",
+ "(Lease #%d) <%s> %B\n",
+ $lease->getID(),
$type,
$data);
}
$status = $lease->getStatus();
switch ($status) {
case DrydockLeaseStatus::STATUS_ACTIVE:
$is_active = true;
break;
case DrydockLeaseStatus::STATUS_RELEASED:
throw new Exception(pht('Lease has already been released!'));
case DrydockLeaseStatus::STATUS_DESTROYED:
throw new Exception(pht('Lease has already been destroyed!'));
case DrydockLeaseStatus::STATUS_BROKEN:
throw new Exception(pht('Lease has been broken!'));
case DrydockLeaseStatus::STATUS_PENDING:
case DrydockLeaseStatus::STATUS_ACQUIRED:
break;
default:
throw new Exception(
pht(
'Lease has unknown status "%s".',
$status));
}
if ($is_active) {
break;
} else {
sleep(1);
}
}
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Nov 24, 7:58 PM (1 d, 19 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1069
Default Alt Text
(9 KB)

Event Timeline