Skip to content

Commit

Permalink
RemoteApi: allow to restart the daemon
Browse files Browse the repository at this point in the history
fixes #406
  • Loading branch information
Thomas-Gelf committed Sep 28, 2022
1 parent 746dca3 commit 321de3e
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 4 deletions.
7 changes: 6 additions & 1 deletion application/clicommands/DaemonCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Icinga\Module\Vspheredb\Clicommands;

use gipfl\SimpleDaemon\Daemon;
use Icinga\Module\Vspheredb\Daemon\RpcNamespace\RpcNamespaceProcess;
use Icinga\Module\Vspheredb\Daemon\VsphereDbDaemon;

class DaemonCommand extends Command
Expand All @@ -20,7 +21,11 @@ public function runAction()
$this->assertNoVcenterParam();
$daemon = new Daemon();
$daemon->setLogger($this->logger);
$daemon->attachTask(new VsphereDbDaemon());
$vSphereDb = new VsphereDbDaemon();
$vSphereDb->on(RpcNamespaceProcess::ON_RESTART, function () use ($daemon) {
$daemon->reload();
});
$daemon->attachTask($vSphereDb);
$daemon->run($this->loop());
$this->eventuallyStartMainLoop();
}
Expand Down
11 changes: 10 additions & 1 deletion application/controllers/DaemonController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
use gipfl\Web\Widget\Hint;
use Icinga\Date\DateFormatter;
use Icinga\Module\Vspheredb\Web\Form\LogLevelForm;
use Icinga\Module\Vspheredb\Web\Form\RestartDaemonForm;
use Icinga\Module\Vspheredb\Web\Table\ControlSocketConnectionsTable;
use Icinga\Module\Vspheredb\Format;
use Icinga\Module\Vspheredb\Web\Controller;
use Icinga\Module\Vspheredb\Web\Table\VsphereApiConnectionTable;
use Icinga\Module\Vspheredb\Web\Tabs\MainTabs;
use Icinga\Module\Vspheredb\WebUtil;
use Icinga\Web\Notification;
use ipl\Html\Html;
use ipl\Html\Table;

Expand Down Expand Up @@ -70,7 +72,14 @@ protected function prepareDaemonInfo()
WebUtil::timeAgo($daemon->ts_last_refresh / 1000)
));
} else {
return $this->prepareProcessTable(JsonString::decode($daemon->process_info));
$restartForm = new RestartDaemonForm($this->remoteClient(), $this->loop());
$restartForm->on($restartForm::ON_SUCCESS, function () {
Notification::success('Daemon has been asked to restart');
$this->redirectNow($this->url());
});
$restartForm->handleRequest($this->getServerRequest());

return [$restartForm, $this->prepareProcessTable(JsonString::decode($daemon->process_info))];
}
} else {
return Hint::error($this->translate('Daemon is either not running or not connected to the Database'));
Expand Down
1 change: 1 addition & 0 deletions doc/84-Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ place.

### UI
* FEATURE: connection health icons now show more details (#400)
* FEATURE: the daemon can now be restarted from the web UI (#406)
* FIX: links pointing to the VMware HTML5 UI have now work on v6.7 and v7.x (#209)
* FIX: issues with dark/light mode in Icinga Web have been addressed (#355)
* FIX: Monitoring Rules documentation link was missing (#360)
Expand Down
11 changes: 10 additions & 1 deletion library/Vspheredb/Daemon/RemoteApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Icinga\Module\Vspheredb\Daemon;

use Evenement\EventEmitterInterface;
use Evenement\EventEmitterTrait;
use Exception;
use gipfl\Curl\CurlAsync;
use gipfl\Log\Logger;
Expand All @@ -12,6 +14,7 @@
use gipfl\Protocol\NetString\StreamWrapper;
use gipfl\Socket\UnixSocketInspection;
use gipfl\Socket\UnixSocketPeer;
use Icinga\Module\Vspheredb\Daemon\RpcNamespace\RpcNamespaceProcess;
use Icinga\Module\Vspheredb\Daemon\RpcNamespace\RpcNamespaceCurl;
use Icinga\Module\Vspheredb\Daemon\RpcNamespace\RpcNamespaceInfluxDb;
use Icinga\Module\Vspheredb\Daemon\RpcNamespace\RpcNamespaceLogger;
Expand All @@ -21,10 +24,13 @@
use Psr\Log\LoggerInterface;
use React\EventLoop\LoopInterface;
use React\Socket\ConnectionInterface;
use React\Stream\Util;
use function posix_getegid;

class RemoteApi
class RemoteApi implements EventEmitterInterface
{
use EventEmitterTrait;

/** @var LoggerInterface */
protected $logger;

Expand Down Expand Up @@ -106,7 +112,10 @@ protected function addSocketEventHandlers(ControlSocket $socket)
return;
}

$rpcProcess = new RpcNamespaceProcess($this->loop);
Util::forwardEvents($rpcProcess, $this, [RpcNamespaceProcess::ON_RESTART]);
$handler = new NamespacedPacketHandler();
$handler->registerNamespace('process', $rpcProcess);
$handler->registerNamespace('system', new RpcNamespaceSystem());
$handler->registerNamespace('vsphere', new RpcNamespaceVsphere($this->apiConnectionHandler));
$handler->registerNamespace('influxdb', new RpcNamespaceInfluxDb($this->curl, $this->loop, $this->logger));
Expand Down
53 changes: 53 additions & 0 deletions library/Vspheredb/Daemon/RpcNamespace/RpcNamespaceProcess.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace Icinga\Module\Vspheredb\Daemon\RpcNamespace;

use Evenement\EventEmitterInterface;
use Evenement\EventEmitterTrait;
use React\EventLoop\LoopInterface;

class RpcNamespaceProcess implements EventEmitterInterface
{
use EventEmitterTrait;

const ON_RESTART = 'restart';

/** @var LoopInterface */
protected $loop;

public function __construct(LoopInterface $loop)
{
$this->loop = $loop;
}

/*
public function infoRequest()
{
return $this->prepareProcessInfo($this->daemon);
}
protected function prepareProcessInfo(Daemon $daemon)
{
$details = $this->daemon->getProcessDetails()->getPropertiesToInsert();
$details['process_info'] = \json_decode($details['process_info']);
return (object) [
'state' => $this->daemon->getProcessState()->getInfo(),
'details' => (object) $details,
];
}
*/

/**
* @return bool
*/
public function restartRequest()
{
// Grant some time to ship the response
$this->loop->addTimer(0.1, function () {
$this->emit(self::ON_RESTART);
});

return true;
}
}
8 changes: 7 additions & 1 deletion library/Vspheredb/Daemon/VsphereDbDaemon.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Icinga\Module\Vspheredb\Daemon;

use Evenement\EventEmitterInterface;
use Evenement\EventEmitterTrait;
use Exception;
use gipfl\Cli\Process;
use gipfl\Curl\CurlAsync;
Expand All @@ -17,6 +19,7 @@
use Icinga\Data\ConfigObject;
use Icinga\Module\Vspheredb\Application\MemoryLimit;
use Icinga\Module\Vspheredb\Configuration;
use Icinga\Module\Vspheredb\Daemon\RpcNamespace\RpcNamespaceProcess;
use Icinga\Module\Vspheredb\Db;
use Icinga\Module\Vspheredb\Db\DbUtil;
use Icinga\Module\Vspheredb\DbObject\VCenter;
Expand All @@ -33,11 +36,13 @@
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;
use React\EventLoop\LoopInterface;
use React\Stream\Util as StreamUtil;
use RuntimeException;
use function React\Promise\resolve;

class VsphereDbDaemon implements DaemonTask, SystemdAwareTask, LoggerAwareInterface
class VsphereDbDaemon implements DaemonTask, SystemdAwareTask, LoggerAwareInterface, EventEmitterInterface
{
use EventEmitterTrait;
use LoggerAwareTrait;

const PROCESS_NAME = 'Icinga::vSphereDB';
Expand Down Expand Up @@ -419,6 +424,7 @@ protected function prepareApi(LoopInterface $loop, LoggerInterface $logger)
$this->curl = $curl;
$this->apiConnectionHandler = $connection = new ApiConnectionHandler($curl, $logger);
$this->remoteApi = new RemoteApi($connection, $curl, $loop, $logger);
StreamUtil::forwardEvents($this->remoteApi, $this, [RpcNamespaceProcess::ON_RESTART]);
$connection->on(
ApiConnectionHandler::ON_INITIALIZED_SERVER,
function (ServerInfo $server, AboutInfo $info, UuidInterface $uuid) {
Expand Down
44 changes: 44 additions & 0 deletions library/Vspheredb/Web/Form/RestartDaemonForm.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace Icinga\Module\Vspheredb\Web\Form;

use gipfl\IcingaWeb2\Icon;
use gipfl\Translation\TranslationHelper;
use gipfl\Web\Form\Feature\NextConfirmCancel;
use gipfl\Web\InlineForm;
use Icinga\Module\Vspheredb\Daemon\RemoteClient;
use React\EventLoop\LoopInterface;
use function Clue\React\Block\await;

class RestartDaemonForm extends InlineForm
{
use TranslationHelper;

/** @var RemoteClient */
protected $client;

/** @var LoopInterface */
protected $loop;

public function __construct(RemoteClient $client, LoopInterface $loop)
{
$this->client = $client;
$this->loop = $loop;
}

protected function assemble()
{
(new NextConfirmCancel(
NextConfirmCancel::buttonNext($this->translate('Restart'), [
'title' => $this->translate('Click to restart the vSphereDB background daemon'),
]),
NextConfirmCancel::buttonConfirm($this->translate('Yes, please restart')),
NextConfirmCancel::buttonCancel($this->translate('Cancel'))
))->addToForm($this);
}

protected function onSuccess()
{
await($this->client->request('process.restart'), $this->loop);
}
}

0 comments on commit 321de3e

Please sign in to comment.