Page MenuHomePhabricator

D7593.id17232.diff
No OneTemporary

D7593.id17232.diff

Index: scripts/drydock/drydock_control.php
===================================================================
--- scripts/drydock/drydock_control.php
+++ scripts/drydock/drydock_control.php
@@ -19,6 +19,7 @@
new DrydockManagementLeaseWorkflow(),
new DrydockManagementCloseWorkflow(),
new DrydockManagementReleaseWorkflow(),
+ new DrydockManagementCreateResourceWorkflow(),
new PhutilHelpArgumentWorkflow(),
);
Index: src/__phutil_library_map__.php
===================================================================
--- src/__phutil_library_map__.php
+++ src/__phutil_library_map__.php
@@ -641,10 +641,12 @@
'DrydockLogController' => 'applications/drydock/controller/DrydockLogController.php',
'DrydockLogQuery' => 'applications/drydock/query/DrydockLogQuery.php',
'DrydockManagementCloseWorkflow' => 'applications/drydock/management/DrydockManagementCloseWorkflow.php',
+ 'DrydockManagementCreateResourceWorkflow' => 'applications/drydock/management/DrydockManagementCreateResourceWorkflow.php',
'DrydockManagementLeaseWorkflow' => 'applications/drydock/management/DrydockManagementLeaseWorkflow.php',
'DrydockManagementReleaseWorkflow' => 'applications/drydock/management/DrydockManagementReleaseWorkflow.php',
'DrydockManagementWaitForLeaseWorkflow' => 'applications/drydock/management/DrydockManagementWaitForLeaseWorkflow.php',
'DrydockManagementWorkflow' => 'applications/drydock/management/DrydockManagementWorkflow.php',
+ 'DrydockPreallocatedHostBlueprint' => 'applications/drydock/blueprint/DrydockPreallocatedHostBlueprint.php',
'DrydockResource' => 'applications/drydock/storage/DrydockResource.php',
'DrydockResourceCloseController' => 'applications/drydock/controller/DrydockResourceCloseController.php',
'DrydockResourceListController' => 'applications/drydock/controller/DrydockResourceListController.php',
@@ -2950,10 +2952,12 @@
'DrydockLogController' => 'DrydockController',
'DrydockLogQuery' => 'PhabricatorOffsetPagedQuery',
'DrydockManagementCloseWorkflow' => 'DrydockManagementWorkflow',
+ 'DrydockManagementCreateResourceWorkflow' => 'DrydockManagementWorkflow',
'DrydockManagementLeaseWorkflow' => 'DrydockManagementWorkflow',
'DrydockManagementReleaseWorkflow' => 'DrydockManagementWorkflow',
'DrydockManagementWaitForLeaseWorkflow' => 'DrydockManagementWorkflow',
'DrydockManagementWorkflow' => 'PhutilArgumentWorkflow',
+ 'DrydockPreallocatedHostBlueprint' => 'DrydockBlueprint',
'DrydockResource' => 'DrydockDAO',
'DrydockResourceCloseController' => 'DrydockController',
'DrydockResourceListController' => 'DrydockController',
Index: src/applications/drydock/blueprint/DrydockLocalHostBlueprint.php
===================================================================
--- src/applications/drydock/blueprint/DrydockLocalHostBlueprint.php
+++ src/applications/drydock/blueprint/DrydockLocalHostBlueprint.php
@@ -3,8 +3,7 @@
final class DrydockLocalHostBlueprint extends DrydockBlueprint {
public function isEnabled() {
- // TODO: Figure this out.
- return true;
+ return false;
}
public function canAllocateMoreResources(array $pool) {
@@ -34,6 +33,8 @@
$resource = $this->newResourceTemplate('Host (localhost)');
$resource->setStatus(DrydockResourceStatus::STATUS_OPEN);
$resource->setAttribute('path', $path);
+ $resource->setAttribute('remote', "false");
+ $resource->setAttribute('preallocated', "false");
$resource->save();
return $resource;
@@ -42,7 +43,7 @@
protected function canAllocateLease(
DrydockResource $resource,
DrydockLease $lease) {
- return true;
+ return false;
}
protected function shouldAllocateLease(
Index: src/applications/drydock/blueprint/DrydockPreallocatedHostBlueprint.php
===================================================================
--- /dev/null
+++ src/applications/drydock/blueprint/DrydockPreallocatedHostBlueprint.php
@@ -0,0 +1,94 @@
+<?php
+
+final class DrydockPreallocatedHostBlueprint extends DrydockBlueprint {
+
+ public function isEnabled() {
+ return true;
+ }
+
+ public function canAllocateMoreResources(array $pool) {
+ return false;
+ }
+
+ protected function executeAllocateResource(DrydockLease $lease) {
+ throw new Exception("Preallocated hosts can't be dynamically allocated.");
+ }
+
+ protected function canAllocateLease(
+ DrydockResource $resource,
+ DrydockLease $lease) {
+ return
+ $lease->getAttribute('platform') === $resource->getAttribute('platform');
+ }
+
+ protected function shouldAllocateLease(
+ DrydockResource $resource,
+ DrydockLease $lease,
+ array $other_leases) {
+ return true;
+ }
+
+ protected function executeAcquireLease(
+ DrydockResource $resource,
+ DrydockLease $lease) {
+
+ // Similar to DrydockLocalHostBlueprint, we create a folder
+ // on the remote host that the lease can use.
+
+ $lease_id = $lease->getID();
+
+ // Can't use DIRECTORY_SEPERATOR here because that is relevant to
+ // the platform we're currently running on, not the platform we are
+ // remoting to.
+ $separator = '/';
+ if ($lease->getAttribute('platform') === 'windows') {
+ $separator = '\\';
+ }
+
+ // Clean up the directory path a little.
+ $base_path = rtrim($resource->getAttribute('path'), '/');
+ $base_path = rtrim($base_path, '\\');
+ $full_path = $base_path.$separator.$lease_id;
+
+ $cmd = $lease->getInterface('command');
+
+ if ($lease->getAttribute('platform') !== 'windows') {
+ $cmd->execx('mkdir %s', $full_path);
+ } else {
+ // Windows is terrible. The mkdir command doesn't even support putting
+ // the path in quotes. IN QUOTES. ARGUHRGHUGHHGG!! Do some terribly
+ // inaccurate sanity checking since we can't safely escape the path.
+ if (preg_match('/^[A-Z]\\:\\\\[a-zA-Z0-9\\\\\\ ]/', $full_path) === 0) {
+ throw new Exception(
+ 'Unsafe path detected for Windows platform: "'.$full_path.'".');
+ }
+ $cmd->execx('mkdir %C', $full_path);
+ }
+
+ $lease->setAttribute('path', $full_path);
+ }
+
+ public function getType() {
+ return 'host';
+ }
+
+ public function getInterface(
+ DrydockResource $resource,
+ DrydockLease $lease,
+ $type) {
+
+ switch ($type) {
+ case 'command':
+ return id(new DrydockSSHCommandInterface())
+ ->setConfiguration(array(
+ 'host' => $resource->getAttribute('host'),
+ 'port' => $resource->getAttribute('port'),
+ 'user' => $resource->getAttribute('user'),
+ 'ssh-keyfile' => $resource->getAttribute('ssh-keyfile'),
+ 'platform' => $resource->getAttribute('platform')));
+ }
+
+ throw new Exception("No interface of type '{$type}'.");
+ }
+
+}
Index: src/applications/drydock/interface/command/DrydockSSHCommandInterface.php
===================================================================
--- src/applications/drydock/interface/command/DrydockSSHCommandInterface.php
+++ src/applications/drydock/interface/command/DrydockSSHCommandInterface.php
@@ -4,19 +4,41 @@
public function getExecFuture($command) {
$argv = func_get_args();
- $argv = $this->applyWorkingDirectoryToArgv($argv);
+
+ // This assumes there's a UNIX shell living at the other
+ // end of the connection, which isn't the case for Windows machines.
+ if ($this->getConfig('platform') !== 'windows') {
+ $argv = $this->applyWorkingDirectoryToArgv($argv);
+ }
$full_command = call_user_func_array('csprintf', $argv);
+ if ($this->getConfig('platform') === 'windows') {
+ // On Windows platforms we need to execute cmd.exe explicitly since
+ // most commands are not really executables.
+ $full_command = 'C:\\Windows\\system32\\cmd.exe /C '.$full_command;
+ }
+
// NOTE: The "-t -t" is for psuedo-tty allocation so we can "sudo" on some
// systems, but maybe more trouble than it's worth?
- return new ExecFuture(
- 'ssh -t -t -o StrictHostKeyChecking=no -i %s %s@%s -- %s',
- $this->getConfig('ssh-keyfile'),
- $this->getConfig('user'),
- $this->getConfig('host'),
- $full_command);
+ $keyfile = $this->getConfig('ssh-keyfile');
+ if (!empty($keyfile)) {
+ return new ExecFuture(
+ 'ssh -t -t -o StrictHostKeyChecking=no -p %s -i %s %s@%s -- %s',
+ $this->getConfig('port'),
+ $this->getConfig('ssh-keyfile'),
+ $this->getConfig('user'),
+ $this->getConfig('host'),
+ $full_command);
+ } else {
+ return new ExecFuture(
+ 'ssh -t -t -o StrictHostKeyChecking=no -p %s %s@%s -- %s',
+ $this->getConfig('port'),
+ $this->getConfig('user'),
+ $this->getConfig('host'),
+ $full_command);
+ }
}
}
Index: src/applications/drydock/management/DrydockManagementCreateResourceWorkflow.php
===================================================================
--- /dev/null
+++ src/applications/drydock/management/DrydockManagementCreateResourceWorkflow.php
@@ -0,0 +1,66 @@
+<?php
+
+final class DrydockManagementCreateResourceWorkflow
+ extends DrydockManagementWorkflow {
+
+ public function didConstruct() {
+ $this
+ ->setName('create-resource')
+ ->setSynopsis('Create a resource manually.')
+ ->setArguments(
+ array(
+ array(
+ 'name' => 'name',
+ 'param' => 'resource_name',
+ 'help' => 'Resource name.',
+ ),
+ array(
+ 'name' => 'blueprint',
+ 'param' => 'blueprint_type',
+ 'help' => 'Blueprint type.',
+ ),
+ array(
+ 'name' => 'attributes',
+ 'param' => 'name=value,...',
+ 'help' => 'Resource attributes.',
+ ),
+ ));
+ }
+
+ public function execute(PhutilArgumentParser $args) {
+ $console = PhutilConsole::getConsole();
+
+ $resource_name = $args->getArg('name');
+ if (!$resource_name) {
+ throw new PhutilArgumentUsageException(
+ "Specify a resource name with `--name`.");
+ }
+
+ $blueprint_type = $args->getArg('blueprint');
+ if (!$blueprint_type) {
+ throw new PhutilArgumentUsageException(
+ "Specify a blueprint type with `--blueprint`.");
+ }
+
+ $attributes = $args->getArg('attributes');
+ if ($attributes) {
+ $options = new PhutilSimpleOptions();
+ $options->setCaseSensitive(true);
+ $attributes = $options->parse($attributes);
+ }
+
+ $resource = new DrydockResource();
+ $resource->setBlueprintClass($blueprint_type);
+ $resource->setType(id(new $blueprint_type())->getType());
+ $resource->setName($resource_name);
+ $resource->setStatus(DrydockResourceStatus::STATUS_OPEN);
+ if ($attributes) {
+ $resource->setAttributes($attributes);
+ }
+ $resource->save();
+
+ $console->writeOut("Created Resource %s\n", $resource->getID());
+ return 0;
+ }
+
+}

File Metadata

Mime Type
text/plain
Expires
Thu, Mar 20, 10:15 PM (14 h, 2 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7712521
Default Alt Text
D7593.id17232.diff (10 KB)

Event Timeline