1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-26 00:32:42 +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()) ->setPID(getmypid())
->setStatus(PhabricatorDaemonLog::STATUS_RUNNING) ->setStatus(PhabricatorDaemonLog::STATUS_RUNNING)
->setArgv($event->getValue('argv')) ->setArgv($event->getValue('argv'))
->setExplicitArgv($event->getValue('explicitArgv'))
->save(); ->save();
$this->daemons[$id] = $daemon; $this->daemons[$id] = $daemon;

View file

@ -7,73 +7,10 @@ final class PhabricatorDaemonManagementStatusWorkflow
$this $this
->setName('status') ->setName('status')
->setSynopsis(pht('Show status of running daemons.')) ->setSynopsis(pht('Show status of running daemons.'))
->setArguments( ->setArguments(array());
array(
array(
'name' => 'all',
'help' => pht('Show the status of daemons across all hosts.'),
),
));
} }
public function execute(PhutilArgumentParser $args) { 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(); $console = PhutilConsole::getConsole();
$daemons = $this->loadAllRunningDaemons(); $daemons = $this->loadAllRunningDaemons();
@ -109,14 +46,40 @@ final class PhabricatorDaemonManagementStatusWorkflow
)); ));
foreach ($daemons as $daemon) { foreach ($daemons as $daemon) {
$table->addRow(array( if ($daemon instanceof PhabricatorDaemonLog) {
'id' => $daemon->getID(), $table->addRow(array(
'host' => $daemon->getHost(), 'id' => $daemon->getID(),
'pid' => $daemon->getPID(), 'host' => $daemon->getHost(),
'started' => date('M j Y, g:i:s A', $daemon->getDateCreated()), 'pid' => $daemon->getPID(),
'daemon' => $daemon->getDaemon(), 'started' => date('M j Y, g:i:s A', $daemon->getDateCreated()),
'argv' => csprintf('%LR', array() /* $daemon->getArgv() */), '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(); $table->draw();

View file

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

View file

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

View file

@ -10,6 +10,14 @@ final class PhabricatorDaemonReference {
private $daemonLog; 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) { public static function newFromDictionary(array $dict) {
$ref = new PhabricatorDaemonReference(); $ref = new PhabricatorDaemonReference();
@ -18,6 +26,12 @@ final class PhabricatorDaemonReference {
$ref->pid = idx($dict, 'pid'); $ref->pid = idx($dict, 'pid');
$ref->start = idx($dict, 'start'); $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; return $ref;
} }
@ -66,15 +80,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());
} }