diff --git a/appinfo/routes.php b/appinfo/routes.php index 91d2eec4dd3..49651fe46a7 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -395,6 +395,15 @@ 'token' => '^[a-z0-9]{4,30}$', ], ], + [ + 'name' => 'Matterbridge#getBridgeProcessState', + 'url' => '/api/{apiVersion}/bridge/{token}/process', + 'verb' => 'GET', + 'requirements' => [ + 'apiVersion' => 'v1', + 'token' => '^[a-z0-9]{4,30}$', + ], + ], [ 'name' => 'Matterbridge#editBridgeOfRoom', 'url' => '/api/{apiVersion}/bridge/{token}', diff --git a/lib/Controller/MatterbridgeController.php b/lib/Controller/MatterbridgeController.php index 70489752c0e..cea3f4f2cdd 100644 --- a/lib/Controller/MatterbridgeController.php +++ b/lib/Controller/MatterbridgeController.php @@ -60,11 +60,27 @@ public function __construct(string $appName, * @return DataResponse */ public function getBridgeOfRoom(): DataResponse { - $this->bridgeManager->checkBridge($this->room); + $pid = $this->bridgeManager->checkBridge($this->room); + $logContent = $this->bridgeManager->getBridgeLog($this->room); $bridge = $this->bridgeManager->getBridgeOfRoom($this->room); + $bridge['running'] = ($pid !== 0); + $bridge['log'] = $logContent; return new DataResponse($bridge); } + /** + * Get bridge process information + * + * @NoAdminRequired + * @RequireLoggedInModeratorParticipant + * + * @return DataResponse + */ + public function getBridgeProcessState(): DataResponse { + $result = $this->bridgeManager->getBridgeProcessState($this->room); + return new DataResponse($result); + } + /** * Edit bridge information of one room * @@ -77,11 +93,11 @@ public function getBridgeOfRoom(): DataResponse { */ public function editBridgeOfRoom(bool $enabled, array $parts = []): DataResponse { try { - $success = $this->bridgeManager->editBridgeOfRoom($this->room, $enabled, $parts); + $state = $this->bridgeManager->editBridgeOfRoom($this->room, $enabled, $parts); } catch (ImpossibleToKillException $e) { return new DataResponse(['error' => $e->getMessage()], Http::STATUS_NOT_ACCEPTABLE); } - return new DataResponse($success); + return new DataResponse($state); } /** diff --git a/lib/MatterbridgeManager.php b/lib/MatterbridgeManager.php index bab70dbdf33..5714799eeb5 100644 --- a/lib/MatterbridgeManager.php +++ b/lib/MatterbridgeManager.php @@ -92,15 +92,45 @@ public function getBridgeOfRoom(Room $room): array { return $this->getBridgeFromDb($room); } + /** + * Get bridge process information for a specific room + * + * @param Room $room the room + * @return array process state and log + */ + public function getBridgeProcessState(Room $room): array { + $bridge = $this->getBridgeFromDb($room); + + $logContent = $this->getBridgeLog($room); + + $pid = $this->checkBridgeProcess($room, $bridge, false); + return [ + 'running' => ($pid !== 0), + 'log' => $logContent + ]; + } + + /** + * Get bridge log file content + * + * @param Room $room the room + * @return string log file content + */ + public function getBridgeLog(Room $room): string { + $outputPath = sprintf('/tmp/bridge-%s.log', $room->getToken()); + $logContent = file_get_contents($outputPath); + return $logContent !== false ? $logContent : ''; + } + /** * Edit bridge information for a room * * @param Room $room the room * @param bool $enabled desired state of the bridge * @param array $parts parts of the bridge (what it connects to) - * @return bool success + * @return array bridge state */ - public function editBridgeOfRoom(Room $room, bool $enabled, array $parts = []): bool { + public function editBridgeOfRoom(Room $room, bool $enabled, array $parts = []): array { $currentBridge = $this->getBridgeOfRoom($room); $newBridge = [ 'enabled' => $enabled, @@ -118,7 +148,11 @@ public function editBridgeOfRoom(Room $room, bool $enabled, array $parts = []): // save config $this->saveBridgeToDb($room, $newBridge); - return true; + $logContent = $this->getBridgeLog($room); + return [ + 'running' => ($pid !== 0), + 'log' => $logContent + ]; } /** @@ -153,8 +187,9 @@ public function checkAllBridges(): void { /** * For one room, check mattermost process respects desired state * @param Room $room the room + * @return int the bridge process ID */ - public function checkBridge(Room $room): void { + public function checkBridge(Room $room): int { $bridge = $this->getBridgeOfRoom($room); $pid = $this->checkBridgeProcess($room, $bridge); if ($pid !== $bridge['pid']) { @@ -162,6 +197,7 @@ public function checkBridge(Room $room): void { $bridge['pid'] = $pid; $this->saveBridgeToDb($room, $bridge); } + return $pid; } private function getDataFolder(): ISimpleFolder { @@ -437,43 +473,48 @@ private function cleanUrl(string $url): string { * * @param Room $room the room * @param array $bridge bridge information + * @param $relaunch whether to launch the process if it's down but bridge is enabled * @return int the corresponding matterbridge process ID, 0 if none */ - private function checkBridgeProcess(Room $room, array $bridge): int { + private function checkBridgeProcess(Room $room, array $bridge, bool $relaunch = true): int { $pid = 0; if (isset($bridge['pid']) && intval($bridge['pid']) !== 0) { // config : there is a PID stored - $pid = intval($bridge['pid']); - $isRunning = $this->isRunning($pid); + $isRunning = $this->isRunning($bridge['pid']); // if bridge running and enabled is false : kill it if ($isRunning) { if ($bridge['enabled']) { $this->logger->info('Process running AND bridge enabled in config : doing nothing'); + $pid = $bridge['pid']; } else { - $this->logger->info('Process running AND bridge disabled in config : KILL ' . $pid); - $killed = $this->killPid($pid); + $this->logger->info('Process running AND bridge disabled in config : KILL ' . $bridge['pid']); + $killed = $this->killPid($bridge['pid']); if ($killed) { $pid = 0; } else { - $this->logger->info('Impossible to kill ' . $pid); - throw new ImpossibleToKillException('Impossible to kill bridge process [' . $pid . ']'); + $this->logger->info('Impossible to kill ' . $bridge['pid']); + throw new ImpossibleToKillException('Impossible to kill bridge process [' . $bridge['pid'] . ']'); } } } else { // no process found if ($bridge['enabled']) { - $this->logger->info('Process not found AND bridge enabled in config : relaunching'); - $pid = $this->launchMatterbridge($room); + if ($relaunch) { + $this->logger->info('Process not found AND bridge enabled in config : relaunching'); + $pid = $this->launchMatterbridge($room); + } } else { $this->logger->info('Process not found AND bridge disabled in config : doing nothing'); } } } elseif ($bridge['enabled']) { - // config : no PID stored - // config : enabled => launch it - $pid = $this->launchMatterbridge($room); - $this->logger->info('Launch process, PID is '.$pid); + if ($relaunch) { + // config : no PID stored + // config : enabled => launch it + $pid = $this->launchMatterbridge($room); + $this->logger->info('Launch process, PID is '.$pid); + } } else { $this->logger->info('No PID defined in config AND bridge disabled in config : doing nothing'); } diff --git a/src/components/RightSidebar/Matterbridge/MatterbridgeSettings.vue b/src/components/RightSidebar/Matterbridge/MatterbridgeSettings.vue index 6c699736239..c882985d4da 100644 --- a/src/components/RightSidebar/Matterbridge/MatterbridgeSettings.vue +++ b/src/components/RightSidebar/Matterbridge/MatterbridgeSettings.vue @@ -40,7 +40,17 @@ :checked="enabled" @update:checked="onEnabled"> {{ t('spreed', 'Enabled') }} + ({{ processStateText }}) + + +