1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-27 07:50:57 +01:00

Unify the local and global view for ./bin/phd status.

Summary:
Ref T4209. Unifies the local (`./bin/phd status`) and global (`./bin/phd status --all`) view into a single table. This generally makes it easy to administer daemons running across multiple hosts.

Depends on D9606.

Test Plan:
```
> sudo ./bin/phd status
ID Host      PID  Started                 Daemon                               Arguments
38 localhost 2282 Jun 18 2014, 7:52:56 AM PhabricatorRepositoryPullLocalDaemon
39 localhost 2289 Jun 18 2014, 7:52:57 AM PhabricatorGarbageCollectorDaemon
40 localhost 2294 Jun 18 2014, 7:52:57 AM PhabricatorTaskmasterDaemon
41 localhost 2314 Jun 18 2014, 7:52:58 AM PhabricatorTaskmasterDaemon
42 localhost 2319 Jun 18 2014, 7:52:59 AM PhabricatorTaskmasterDaemon
43 localhost 2328 Jun 18 2014, 7:53:00 AM PhabricatorTaskmasterDaemon
44 localhost 2354 Jun 18 2014, 7:53:08 AM PhabricatorRepositoryPullLocalDaemon X --not Y
```

Reviewers: #blessed_reviewers, epriestley

Reviewed By: #blessed_reviewers, epriestley

Subscribers: epriestley, Korvin

Maniphest Tasks: T4209

Differential Revision: https://secure.phabricator.com/D9607
This commit is contained in:
Joshua Spence 2014-06-18 11:44:52 +10:00
parent b93fe30008
commit f52fbf6117
6 changed files with 78 additions and 94 deletions

View file

@ -0,0 +1,3 @@
ALTER TABLE {$NAMESPACE}_daemon.daemon_log
ADD COLUMN explicitArgv longtext CHARACTER SET utf8
COLLATE utf8_bin NOT NULL AFTER argv;

View file

@ -37,6 +37,7 @@ final class PhabricatorDaemonEventListener extends PhabricatorEventListener {
->setPID(getmypid())
->setStatus(PhabricatorDaemonLog::STATUS_RUNNING)
->setArgv($event->getValue('argv'))
->setExplicitArgv($event->getValue('explicitArgv'))
->save();
$this->daemons[$id] = $daemon;

View file

@ -7,73 +7,10 @@ final class PhabricatorDaemonManagementStatusWorkflow
$this
->setName('status')
->setSynopsis(pht('Show status of running daemons.'))
->setArguments(
array(
array(
'name' => 'all',
'help' => pht('Show the status of daemons across all hosts.'),
),
));
->setArguments(array());
}
public function execute(PhutilArgumentParser $args) {
if ($args->getArg('all')) {
return $this->executeGlobal();
} else {
return $this->executeLocal();
}
}
protected function executeLocal() {
$console = PhutilConsole::getConsole();
$daemons = $this->loadRunningDaemons();
if (!$daemons) {
$console->writeErr(
"%s\n",
pht('There are no running Phabricator daemons.'));
return 1;
}
$status = 0;
$table = id(new PhutilConsoleTable())
->addColumns(array(
'pid' => array(
'title' => 'PID',
),
'started' => array(
'title' => 'Started',
),
'daemon' => array(
'title' => 'Daemon',
),
'argv' => array(
'title' => 'Arguments',
),
));
foreach ($daemons as $daemon) {
$name = $daemon->getName();
if (!$daemon->isRunning()) {
$daemon->updateStatus(PhabricatorDaemonLog::STATUS_DEAD);
$status = 2;
$name = '<DEAD> '.$name;
}
$table->addRow(array(
'pid' => $daemon->getPID(),
'started' => $daemon->getEpochStarted()
? date('M j Y, g:i:s A', $daemon->getEpochStarted())
: null,
'daemon' => $name,
'argv' => csprintf('%LR', $daemon->getArgv()),
));
}
$table->draw();
}
protected function executeGlobal() {
$console = PhutilConsole::getConsole();
$daemons = $this->loadAllRunningDaemons();
@ -109,14 +46,40 @@ final class PhabricatorDaemonManagementStatusWorkflow
));
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() */),
));
if ($daemon instanceof PhabricatorDaemonLog) {
$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', $daemon->getExplicitArgv()),
));
} else if ($daemon instanceof PhabricatorDaemonReference) {
$name = $daemon->getName();
if (!$daemon->isRunning()) {
$daemon->updateStatus(PhabricatorDaemonLog::STATUS_DEAD);
$status = 2;
$name = '<DEAD> '.$name;
}
$daemon_log = $daemon->getDaemonLog();
$id = null;
if ($daemon_log) {
$id = $daemon_log->getID();
}
$table->addRow(array(
'id' => $id,
'host' => 'localhost',
'pid' => $daemon->getPID(),
'started' => $daemon->getEpochStarted()
? date('M j Y, g:i:s A', $daemon->getEpochStarted())
: null,
'daemon' => $name,
'argv' => csprintf('%LR', $daemon->getArgv()),
));
}
}
$table->draw();

View file

@ -36,35 +36,38 @@ abstract class PhabricatorDaemonManagementWorkflow
}
protected final function loadRunningDaemons() {
$results = array();
$daemons = array();
$pid_dir = $this->getPIDDirectory();
$pid_files = Filesystem::listDirectory($pid_dir);
if (!$pid_files) {
return $results;
}
foreach ($pid_files as $pid_file) {
$pid_data = Filesystem::readFile($pid_dir.'/'.$pid_file);
$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 = PhabricatorDaemonReference::newFromDictionary($dict);
$ref->setPIDFile($pid_dir.'/'.$pid_file);
$results[] = $ref;
$daemons[] = PhabricatorDaemonReference::newFromFile(
$pid_dir.'/'.$pid_file);
}
return $results;
return $daemons;
}
protected final function loadAllRunningDaemons() {
return id(new PhabricatorDaemonLogQuery())
$local_daemons = $this->loadRunningDaemons();
$local_ids = array();
foreach ($local_daemons as $daemon) {
$daemon_log = $daemon->getDaemonLog();
if ($daemon_log) {
$local_ids[] = $daemon_log->getID();
}
}
$remote_daemons = id(new PhabricatorDaemonLogQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withoutIDs($local_ids)
->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE)
->execute();
return array_merge($local_daemons, $remote_daemons);
}
private function findDaemonClass($substring) {
@ -280,7 +283,6 @@ abstract class PhabricatorDaemonManagementWorkflow
}
$console->writeErr(pht('Done.')."\n");
return 0;
}

View file

@ -13,12 +13,14 @@ final class PhabricatorDaemonLog extends PhabricatorDaemonDAO
protected $host;
protected $pid;
protected $argv;
protected $explicitArgv;
protected $status;
public function getConfiguration() {
return array(
self::CONFIG_SERIALIZATION => array(
'argv' => self::SERIALIZATION_JSON,
'explicitArgv' => self::SERIALIZATION_JSON,
),
) + parent::getConfiguration();
}

View file

@ -10,6 +10,14 @@ final class PhabricatorDaemonReference {
private $daemonLog;
public static function newFromFile($path) {
$pid_data = Filesystem::readFile($path);
$dict = phutil_json_decode($pid_data);
$ref = self::newFromDictionary($dict);
$ref->pidFile = $path;
return $ref;
}
public static function newFromDictionary(array $dict) {
$ref = new PhabricatorDaemonReference();
@ -18,6 +26,12 @@ final class PhabricatorDaemonReference {
$ref->pid = idx($dict, 'pid');
$ref->start = idx($dict, 'start');
$ref->daemonLog = id(new PhabricatorDaemonLog())->loadOneWhere(
'daemon = %s AND pid = %d AND dateCreated = %d',
$ref->name,
$ref->pid,
$ref->start);
return $ref;
}
@ -66,15 +80,14 @@ final class PhabricatorDaemonReference {
return $this->start;
}
public function setPIDFile($pid_file) {
$this->pidFile = $pid_file;
return $this;
}
public function getPIDFile() {
return $this->pidFile;
}
public function getDaemonLog() {
return $this->daemonLog;
}
public function isRunning() {
return self::isProcessRunning($this->getPID());
}