From 0ccebbe4b1ddd7b0e3e4b737e557570a3ced7dfa Mon Sep 17 00:00:00 2001 From: Joshua Spence Date: Tue, 17 Jun 2014 08:41:51 +1000 Subject: [PATCH] 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 --- ...bricatorDaemonManagementStatusWorkflow.php | 85 ++++++++++++++++--- .../PhabricatorDaemonManagementWorkflow.php | 39 ++++----- .../control/PhabricatorDaemonReference.php | 28 ++++-- 3 files changed, 113 insertions(+), 39 deletions(-) diff --git a/src/applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php b/src/applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php index dbccce3dc5..18132ab15e 100644 --- a/src/applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php +++ b/src/applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php @@ -22,12 +22,22 @@ final class PhabricatorDaemonManagementStatusWorkflow } $status = 0; - printf( - "%-5s\t%-24s\t%-50s%s\n", - 'PID', - 'Started', - 'Daemon', - 'Arguments'); + $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()) { @@ -35,18 +45,67 @@ final class PhabricatorDaemonManagementStatusWorkflow $status = 2; $name = ' '.$name; } - printf( - "%5s\t%-24s\t%-50s%s\n", - $daemon->getPID(), - $daemon->getEpochStarted() + + $table->addRow(array( + 'pid' => $daemon->getPID(), + 'started' => $daemon->getEpochStarted() ? date('M j Y, g:i:s A', $daemon->getEpochStarted()) : null, - $name, - csprintf('%LR', $daemon->getArgv())); + 'daemon' => $name, + '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(); + } } diff --git a/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php b/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php index a0e1cf575e..6a7e3bd435 100644 --- a/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php +++ b/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php @@ -3,7 +3,7 @@ abstract class PhabricatorDaemonManagementWorkflow extends PhabricatorManagementWorkflow { - protected function loadAvailableDaemonClasses() { + protected final function loadAvailableDaemonClasses() { $loader = new PhutilSymbolLoader(); return $loader ->setAncestorClass('PhutilDaemon') @@ -11,12 +11,12 @@ abstract class PhabricatorDaemonManagementWorkflow ->selectSymbolsWithoutLoading(); } - public function getPIDDirectory() { + protected final function getPIDDirectory() { $path = PhabricatorEnv::getEnvConfig('phd.pid-directory'); return $this->getControlDirectory($path); } - public function getLogDirectory() { + protected final function getLogDirectory() { $path = PhabricatorEnv::getEnvConfig('phd.log-directory'); return $this->getControlDirectory($path); } @@ -35,8 +35,9 @@ abstract class PhabricatorDaemonManagementWorkflow return $path; } - public function loadRunningDaemons() { + protected final function loadRunningDaemons() { $results = array(); + $ids = array(); $pid_dir = $this->getPIDDirectory(); $pid_files = Filesystem::listDirectory($pid_dir); @@ -45,19 +46,17 @@ abstract class PhabricatorDaemonManagementWorkflow } 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; + $results[] = PhabricatorDaemonReference::newFromDictionary( + $pid_dir.'/'.$pid_file); + $ids[] = $ref->getDaemonLog()->getID(); } - return $results; + $other = id(new PhabricatorDaemonLogQuery()) + ->setViewer(PhabricatorUser::getOmnipotentUser()) + ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE) + ->execute(); + + } private function findDaemonClass($substring) { @@ -93,8 +92,7 @@ abstract class PhabricatorDaemonManagementWorkflow return head($match); } - - protected function launchDaemon($class, array $argv, $debug) { + protected final function launchDaemon($class, array $argv, $debug) { $daemon = $this->findDaemonClass($class); $console = PhutilConsole::getConsole(); @@ -212,7 +210,7 @@ abstract class PhabricatorDaemonManagementWorkflow } } - protected function willLaunchDaemons() { + protected final function willLaunchDaemons() { $console = PhutilConsole::getConsole(); $console->writeErr(pht('Preparing to launch daemons.')."\n"); @@ -224,7 +222,7 @@ abstract class PhabricatorDaemonManagementWorkflow /* -( Commands )----------------------------------------------------------- */ - protected function executeStartCommand($keep_leases = false) { + protected final function executeStartCommand($keep_leases = false) { $console = PhutilConsole::getConsole(); $running = $this->loadRunningDaemons(); @@ -278,8 +276,7 @@ abstract class PhabricatorDaemonManagementWorkflow return 0; } - - protected function executeStopCommand(array $pids) { + protected final function executeStopCommand(array $pids) { $console = PhutilConsole::getConsole(); $daemons = $this->loadRunningDaemons(); diff --git a/src/infrastructure/daemon/control/PhabricatorDaemonReference.php b/src/infrastructure/daemon/control/PhabricatorDaemonReference.php index 679680a62e..a2a71228a7 100644 --- a/src/infrastructure/daemon/control/PhabricatorDaemonReference.php +++ b/src/infrastructure/daemon/control/PhabricatorDaemonReference.php @@ -10,6 +10,19 @@ final class PhabricatorDaemonReference { 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) { $ref = new PhabricatorDaemonReference(); @@ -18,6 +31,12 @@ final class PhabricatorDaemonReference { $ref->pid = idx($dict, 'pid'); $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; } @@ -66,15 +85,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()); }