1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-18 21:02:41 +01:00

Query daemons across all hosts with ./bin/phd status --all.

Summary: Ref T4209. Currently, `./bin/phd status` prints a table showing the daemons that are executing on the current host. It would be useful to be able to conventiently query the daemons running across all hosts. This would also (theoretically) make it possible to conditionally start daemons on a host depending upon the current state and on the daemons running on other hosts.

Test Plan:
```
> ./bin/phd status --all
ID      Host                    PID     Started                     Daemon                                            Arguments
   18          phabricator     6969   Jun 12 2014, 4:44:22 PM     PhabricatorTaskmasterDaemon
   17          phabricator     6961   Jun 12 2014, 4:44:19 PM     PhabricatorTaskmasterDaemon
   16          phabricator     6955   Jun 12 2014, 4:44:15 PM     PhabricatorTaskmasterDaemon
   15          phabricator     6950   Jun 12 2014, 4:44:14 PM     PhabricatorTaskmasterDaemon
   14          phabricator     6936   Jun 12 2014, 4:44:13 PM     PhabricatorGarbageCollectorDaemon
   13          phabricator     6931   Jun 12 2014, 4:44:12 PM     PhabricatorRepositoryPullLocalDaemon
```

Reviewers: #blessed_reviewers, epriestley

Reviewed By: #blessed_reviewers, epriestley

Subscribers: epriestley, Korvin

Maniphest Tasks: T4209

Differential Revision: https://secure.phabricator.com/D9497
This commit is contained in:
Joshua Spence 2014-06-17 08:41:51 +10:00
parent 78635a15c1
commit 0ccebbe4b1
3 changed files with 113 additions and 39 deletions

View file

@ -22,12 +22,22 @@ final class PhabricatorDaemonManagementStatusWorkflow
} }
$status = 0; $status = 0;
printf( $table = id(new PhutilConsoleTable())
"%-5s\t%-24s\t%-50s%s\n", ->addColumns(array(
'PID', 'pid' => array(
'Started', 'title' => 'PID',
'Daemon', ),
'Arguments'); 'started' => array(
'title' => 'Started',
),
'daemon' => array(
'title' => 'Daemon',
),
'argv' => array(
'title' => 'Arguments',
),
));
foreach ($daemons as $daemon) { foreach ($daemons as $daemon) {
$name = $daemon->getName(); $name = $daemon->getName();
if (!$daemon->isRunning()) { if (!$daemon->isRunning()) {
@ -35,18 +45,67 @@ final class PhabricatorDaemonManagementStatusWorkflow
$status = 2; $status = 2;
$name = '<DEAD> '.$name; $name = '<DEAD> '.$name;
} }
printf(
"%5s\t%-24s\t%-50s%s\n", $table->addRow(array(
$daemon->getPID(), 'pid' => $daemon->getPID(),
$daemon->getEpochStarted() 'started' => $daemon->getEpochStarted()
? date('M j Y, g:i:s A', $daemon->getEpochStarted()) ? date('M j Y, g:i:s A', $daemon->getEpochStarted())
: null, : null,
$name, 'daemon' => $name,
csprintf('%LR', $daemon->getArgv())); 'argv' => csprintf('%LR', $daemon->getArgv()),
));
} }
return $status; $table->draw();
} }
protected function executeGlobal() {
$console = PhutilConsole::getConsole();
$daemons = $this->loadAllRunningDaemons();
if (!$daemons) {
$console->writeErr(
"%s\n",
pht('There are no running Phabricator daemons.'));
return 1;
}
$status = 0;
$table = id(new PhutilConsoleTable())
->addColumns(array(
'id' => array(
'title' => 'ID',
),
'host' => array(
'title' => 'Host',
),
'pid' => array(
'title' => 'PID',
),
'started' => array(
'title' => 'Started',
),
'daemon' => array(
'title' => 'Daemon',
),
'argv' => array(
'title' => 'Arguments',
),
));
foreach ($daemons as $daemon) {
$table->addRow(array(
'id' => $daemon->getID(),
'host' => $daemon->getHost(),
'pid' => $daemon->getPID(),
'started' => date('M j Y, g:i:s A', $daemon->getDateCreated()),
'daemon' => $daemon->getDaemon(),
'argv' => csprintf('%LR', array() /* $daemon->getArgv() */),
));
}
$table->draw();
}
} }

View file

@ -3,7 +3,7 @@
abstract class PhabricatorDaemonManagementWorkflow abstract class PhabricatorDaemonManagementWorkflow
extends PhabricatorManagementWorkflow { extends PhabricatorManagementWorkflow {
protected function loadAvailableDaemonClasses() { protected final function loadAvailableDaemonClasses() {
$loader = new PhutilSymbolLoader(); $loader = new PhutilSymbolLoader();
return $loader return $loader
->setAncestorClass('PhutilDaemon') ->setAncestorClass('PhutilDaemon')
@ -11,12 +11,12 @@ abstract class PhabricatorDaemonManagementWorkflow
->selectSymbolsWithoutLoading(); ->selectSymbolsWithoutLoading();
} }
public function getPIDDirectory() { protected final function getPIDDirectory() {
$path = PhabricatorEnv::getEnvConfig('phd.pid-directory'); $path = PhabricatorEnv::getEnvConfig('phd.pid-directory');
return $this->getControlDirectory($path); return $this->getControlDirectory($path);
} }
public function getLogDirectory() { protected final function getLogDirectory() {
$path = PhabricatorEnv::getEnvConfig('phd.log-directory'); $path = PhabricatorEnv::getEnvConfig('phd.log-directory');
return $this->getControlDirectory($path); return $this->getControlDirectory($path);
} }
@ -35,8 +35,9 @@ abstract class PhabricatorDaemonManagementWorkflow
return $path; return $path;
} }
public function loadRunningDaemons() { protected final function loadRunningDaemons() {
$results = array(); $results = array();
$ids = array();
$pid_dir = $this->getPIDDirectory(); $pid_dir = $this->getPIDDirectory();
$pid_files = Filesystem::listDirectory($pid_dir); $pid_files = Filesystem::listDirectory($pid_dir);
@ -45,19 +46,17 @@ abstract class PhabricatorDaemonManagementWorkflow
} }
foreach ($pid_files as $pid_file) { foreach ($pid_files as $pid_file) {
$pid_data = Filesystem::readFile($pid_dir.'/'.$pid_file); $results[] = PhabricatorDaemonReference::newFromDictionary(
$dict = json_decode($pid_data, true); $pid_dir.'/'.$pid_file);
if (!is_array($dict)) { $ids[] = $ref->getDaemonLog()->getID();
// Just return a hanging reference, since control code needs to be
// robust against unusual system states.
$dict = array();
}
$ref = PhabricatorDaemonReference::newFromDictionary($dict);
$ref->setPIDFile($pid_dir.'/'.$pid_file);
$results[] = $ref;
} }
return $results; $other = id(new PhabricatorDaemonLogQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE)
->execute();
} }
private function findDaemonClass($substring) { private function findDaemonClass($substring) {
@ -93,8 +92,7 @@ abstract class PhabricatorDaemonManagementWorkflow
return head($match); return head($match);
} }
protected final function launchDaemon($class, array $argv, $debug) {
protected function launchDaemon($class, array $argv, $debug) {
$daemon = $this->findDaemonClass($class); $daemon = $this->findDaemonClass($class);
$console = PhutilConsole::getConsole(); $console = PhutilConsole::getConsole();
@ -212,7 +210,7 @@ abstract class PhabricatorDaemonManagementWorkflow
} }
} }
protected function willLaunchDaemons() { protected final function willLaunchDaemons() {
$console = PhutilConsole::getConsole(); $console = PhutilConsole::getConsole();
$console->writeErr(pht('Preparing to launch daemons.')."\n"); $console->writeErr(pht('Preparing to launch daemons.')."\n");
@ -224,7 +222,7 @@ abstract class PhabricatorDaemonManagementWorkflow
/* -( Commands )----------------------------------------------------------- */ /* -( Commands )----------------------------------------------------------- */
protected function executeStartCommand($keep_leases = false) { protected final function executeStartCommand($keep_leases = false) {
$console = PhutilConsole::getConsole(); $console = PhutilConsole::getConsole();
$running = $this->loadRunningDaemons(); $running = $this->loadRunningDaemons();
@ -278,8 +276,7 @@ abstract class PhabricatorDaemonManagementWorkflow
return 0; return 0;
} }
protected final function executeStopCommand(array $pids) {
protected function executeStopCommand(array $pids) {
$console = PhutilConsole::getConsole(); $console = PhutilConsole::getConsole();
$daemons = $this->loadRunningDaemons(); $daemons = $this->loadRunningDaemons();

View file

@ -10,6 +10,19 @@ final class PhabricatorDaemonReference {
private $daemonLog; private $daemonLog;
public static function newFromFile($path) {
$pid_data = Filesystem::readFile($path);
$dict = json_decode($pid_data, true);
if (!is_array($dict)) {
// Just return a hanging reference, since control code needs to be
// robust against unusual system states.
$dict = array();
}
$ref = self::newFromDictionary($dict);
$ref->pidFile = $path;
return $ref;
}
public static function newFromDictionary(array $dict) { public static function newFromDictionary(array $dict) {
$ref = new PhabricatorDaemonReference(); $ref = new PhabricatorDaemonReference();
@ -18,6 +31,12 @@ final class PhabricatorDaemonReference {
$ref->pid = idx($dict, 'pid'); $ref->pid = idx($dict, 'pid');
$ref->start = idx($dict, 'start'); $ref->start = idx($dict, 'start');
$this->daemonLog = id(new PhabricatorDaemonLog())->loadOneWhere(
'daemon = %s AND pid = %d AND dateCreated = %d',
$this->name,
$this->pid,
$this->start);
return $ref; return $ref;
} }
@ -66,15 +85,14 @@ final class PhabricatorDaemonReference {
return $this->start; return $this->start;
} }
public function setPIDFile($pid_file) {
$this->pidFile = $pid_file;
return $this;
}
public function getPIDFile() { public function getPIDFile() {
return $this->pidFile; return $this->pidFile;
} }
public function getDaemonLog() {
return $this->daemonLog;
}
public function isRunning() { public function isRunning() {
return self::isProcessRunning($this->getPID()); return self::isProcessRunning($this->getPID());
} }