Commit 7445d23e authored by jeremyjaouen's avatar jeremyjaouen Committed by jeremyjaouen
Browse files

enh(API): refactor DELETE platform/topology/id (#9409)

parent ce919a3f
......@@ -240,10 +240,14 @@ services:
Centreon\Domain\RemoteServer\Interfaces\RemoteServerServiceInterface:
class: Centreon\Domain\RemoteServer\RemoteServerService
Centreon\Domain\RemoteServer\Interfaces\RemoteServerRepositoryInterface:
Centreon\Domain\RemoteServer\Interfaces\RemoteServerLocalConfigurationRepositoryInterface:
class: Centreon\Infrastructure\RemoteServer\RemoteServerRepositoryFile
calls:
- [setCentreonConfFilePath, ['%centreon_etc_path%/conf.pm']]
Centreon\Domain\RemoteServer\Interfaces\RemoteServerRepositoryInterface:
class: Centreon\Infrastructure\RemoteServer\RemoteServerRepositoryRDB
# Menu
Centreon\Domain\Menu\Interfaces\MenuRepositoryInterface:
class: Centreon\Infrastructure\Menu\MenuRepositoryRDB
......@@ -15149,6 +15149,10 @@ msgstr "Erreur lors de la recherche de ressources"
msgid "Error when searching for monitoring servers"
msgstr "Erreur lors de la recherche de serveurs de supervision"
 
#:Centreon/Domain/MonitoringServer/MonitoringServerService.php:142
msgid "Error when deleting a monitoring server"
msgstr "Erreur lors de la supression d'un serveur de supervision"
#:Centreon/Domain/MonitoringServer/MonitoringServerService.php:69
msgid "Error when searching for a resource of monitoring server"
msgstr "Erreur lors de la recherche de la ressource attachée au serveur de supervision"
......@@ -15697,8 +15701,15 @@ msgid "Unable to decipher central's credentials. Please check the credentials in
msgstr "Impossible de déchiffrer les identifiants du Central. Veuillez vérifier le formulaire 'Accès du Remote'"
 
#: api/platform/topology
msgid "Failed to get the auth token. Cannot register the platform : '%s'@'%s' on the Central"
msgstr "Echec d'obtention du token d'auth. Impossible d'enregistrer sur le Central: '%s'@'%s'"
msgid "Failed to get the auth token from Central : '%s'"
msgstr "Echec d'obtention du token d'auth. sur le Central: '%s'@'%s'"
#: api/platform/topology
msgid "The platform: '%s'@'%s' cannot be found on the Central"
msgstr "La plateforme: '%s'@'%s' ne peut pas être trouvé sur le Central"
msgid "The platform: '%s'@'%s' cannot be delete from the Central"
msgstr "La plateforme: '%s'@'%s' ne peut pas être supprimé depuis le Central"
 
#: api/platform/topology
msgid "Request to the Central's API failed"
......
......@@ -18,15 +18,14 @@
* For more information : contact@centreon.com
*
*/
declare(strict_types=1);
namespace Centreon\Domain\MonitoringServer\Interfaces;
use Centreon\Domain\Entity\EntityCreator;
use Centreon\Domain\MonitoringServer\MonitoringServer;
use Centreon\Domain\MonitoringServer\MonitoringServerException;
use Centreon\Domain\MonitoringServer\MonitoringServerResource;
use Centreon\Infrastructure\MonitoringServer\MonitoringServerRepositoryRDB;
interface MonitoringServerRepositoryInterface
{
......@@ -88,4 +87,11 @@ interface MonitoringServerRepositoryInterface
* @throws MonitoringServerException
*/
public function findServerByName(string $monitoringServerName): ?MonitoringServer;
/**
* Delete a monitoring server.
*
* @param integer $monitoringServerId
*/
public function deleteServer(int $monitoringServerId): void;
}
......@@ -25,7 +25,6 @@ namespace Centreon\Domain\MonitoringServer\Interfaces;
use Centreon\Domain\MonitoringServer\MonitoringServer;
use Centreon\Domain\MonitoringServer\MonitoringServerException;
use Centreon\Domain\MonitoringServer\MonitoringServerResource;
use Centreon\Domain\MonitoringServer\MonitoringServerService;
interface MonitoringServerServiceInterface
{
......@@ -81,4 +80,12 @@ interface MonitoringServerServiceInterface
* @throws MonitoringServerException
*/
public function findServerByName(string $monitoringServerName): ?MonitoringServer;
/**
* Delete a monitoring server.
*
* @param integer $monitoringServerId
* @throws MonitoringServerException
*/
public function deleteServer(int $monitoringServerId): void;
}
......@@ -130,4 +130,16 @@ class MonitoringServerService implements MonitoringServerServiceInterface
throw new MonitoringServerException('Error when notifying a configuration change', 0, $ex);
}
}
/**
* @inheritDoc
*/
public function deleteServer(int $monitoringServerId): void
{
try {
$this->monitoringServerRepository->deleteServer($monitoringServerId);
} catch (\Exception $ex) {
throw new MonitoringServerException('Error when deleting a monitoring server', 0, $ex);
}
}
}
......@@ -115,7 +115,7 @@ class PlatformInformationService implements PlatformInformationServiceInterface
);
}
} elseif ($platformInformationUpdate->isCentral() && !$currentPlatformInformation->isCentral()) {
$this->remoteServerService->convertRemoteToCentral();
$this->remoteServerService->convertRemoteToCentral($platformInformationUpdate);
}
$this->platformInformationRepository->updatePlatformInformation($platformInformationUpdate);
......
......@@ -44,4 +44,19 @@ interface PlatformTopologyRegisterRepositoryInterface
PlatformInformation $platformInformation,
Proxy $proxy = null
): void;
/**
* Delete the platform on its parent
*
* @param Platform $platform
* @param PlatformInformation $platformInformation
* @param Proxy $proxy
* @throws RepositoryException
* @throws PlatformConflictException
*/
public function deletePlatformToParent(
Platform $platform,
PlatformInformation $platformInformation,
Proxy $proxy = null
): void;
}
......@@ -39,6 +39,7 @@ use Centreon\Domain\PlatformTopology\Interfaces\PlatformTopologyServiceInterface
use Centreon\Domain\PlatformTopology\Interfaces\PlatformTopologyRepositoryInterface;
use Centreon\Domain\PlatformInformation\Interfaces\PlatformInformationServiceInterface;
use Centreon\Domain\PlatformTopology\Interfaces\PlatformTopologyRegisterRepositoryInterface;
use Centreon\Domain\RemoteServer\Interfaces\RemoteServerRepositoryInterface;
/**
* Service intended to register a new server to the platform topology
......@@ -82,6 +83,11 @@ class PlatformTopologyService implements PlatformTopologyServiceInterface
*/
private $brokerRepository;
/**
* @var RemoteServerRepositoryInterface
*/
private $remoteServerRepository;
/**
* Broker Retention Parameter
*/
......@@ -105,7 +111,8 @@ class PlatformTopologyService implements PlatformTopologyServiceInterface
EngineConfigurationServiceInterface $engineConfigurationService,
MonitoringServerServiceInterface $monitoringServerService,
BrokerRepositoryInterface $brokerRepository,
PlatformTopologyRegisterRepositoryInterface $platformTopologyRegisterRepository
PlatformTopologyRegisterRepositoryInterface $platformTopologyRegisterRepository,
RemoteServerRepositoryInterface $remoteServerRepository
) {
$this->platformTopologyRepository = $platformTopologyRepository;
$this->platformInformationService = $platformInformationService;
......@@ -114,6 +121,7 @@ class PlatformTopologyService implements PlatformTopologyServiceInterface
$this->monitoringServerService = $monitoringServerService;
$this->brokerRepository = $brokerRepository;
$this->platformTopologyRegisterRepository = $platformTopologyRegisterRepository;
$this->remoteServerRepository = $remoteServerRepository;
}
/**
......@@ -616,7 +624,7 @@ class PlatformTopologyService implements PlatformTopologyServiceInterface
public function deletePlatformAndReallocateChildren(int $serverId): void
{
try {
if ($this->platformTopologyRepository->findPlatform($serverId) === null) {
if (($deletedPlatform = $this->platformTopologyRepository->findPlatform($serverId)) === null) {
throw new EntityNotFoundException(_('Platform not found'));
}
/**
......@@ -638,14 +646,27 @@ class PlatformTopologyService implements PlatformTopologyServiceInterface
}
/**
* Update children parent_id
* Update children parent_id.
*/
foreach ($childPlatforms as $platform) {
$platform->setParentId($topLevelPlatform->getId());
$this->updatePlatformParameters($platform);
}
}
$this->platformTopologyRepository->deletePlatform($serverId);
/**
* Delete the monitoring server and the topology.
*/
if ($deletedPlatform->getServerId() !== null) {
if ($deletedPlatform->getType() === Platform::TYPE_REMOTE) {
$this->remoteServerRepository->deleteRemoteServerByAddress($deletedPlatform->getAddress());
$this->remoteServerRepository->deleteAdditionalRemoteServer($deletedPlatform->getServerId());
}
$this->monitoringServerService->deleteServer($deletedPlatform->getServerId());
} else {
$this->platformTopologyRepository->deletePlatform($deletedPlatform->getId());
}
} catch (EntityNotFoundException | PlatformException $ex) {
throw $ex;
} catch (\Exception $ex) {
......
<?php
/*
* Copyright 2005 - 2021 Centreon (https://www.centreon.com/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* For more information : contact@centreon.com
*
*/
declare(strict_types=1);
namespace Centreon\Domain\RemoteServer\Interfaces;
/**
* This inteface is designed to configure the local instance mode of the platform.
*/
interface RemoteServerLocalConfigurationRepositoryInterface
{
/**
* Update the platform instance mode to Central.
*/
public function updateInstanceModeCentral(): void;
/**
* Update the platform instance mode to Remote.
*/
public function updateInstanceModeRemote(): void;
}
......@@ -26,12 +26,16 @@ namespace Centreon\Domain\RemoteServer\Interfaces;
interface RemoteServerRepositoryInterface
{
/**
* Update the instance mode of centreon to Central.
* Delete a Remote Server.
*
* @param string $address
*/
public function updateInstanceModeCentral(): void;
public function deleteRemoteServerByAddress(string $address): void;
/**
* Update the instance mode of centreon to Remote.
* Delete an Additional Remote Server, for pollers linked to multiple Remote Servers.
*
* @param integer $monitoringServerId
*/
public function updateInstanceModeRemote(): void;
public function deleteAdditionalRemoteServer(int $monitoringServerId): void;
}
......@@ -35,6 +35,7 @@ interface RemoteServerServiceInterface
/**
* Convert a Remote Server into a Central
* @param PlatformInformation $platformInformation
*/
public function convertRemoteToCentral(): void;
public function convertRemoteToCentral(PlatformInformation $platformInformation): void;
}
......@@ -25,17 +25,15 @@ namespace Centreon\Domain\RemoteServer;
use Centreon\Domain\Menu\MenuException;
use Centreon\Domain\PlatformTopology\Platform;
use Centreon\Domain\Repository\RepositoryException;
use Centreon\Domain\Exception\EntityNotFoundException;
use Centreon\Domain\PlatformTopology\PlatformException;
use Centreon\Domain\RemoteServer\RemoteServerException;
use Centreon\Domain\Proxy\Interfaces\ProxyServiceInterface;
use Centreon\Domain\Menu\Interfaces\MenuRepositoryInterface;
use Centreon\Domain\PlatformInformation\PlatformInformation;
use Centreon\Domain\PlatformTopology\PlatformConflictException;
use Centreon\Domain\RemoteServer\Interfaces\RemoteServerServiceInterface;
use Centreon\Domain\RemoteServer\Interfaces\RemoteServerRepositoryInterface;
use Centreon\Domain\MonitoringServer\Interfaces\MonitoringServerRepositoryInterface;
use Centreon\Domain\RemoteServer\Interfaces\RemoteServerLocalConfigurationRepositoryInterface;
use Centreon\Domain\MonitoringServer\Interfaces\MonitoringServerServiceInterface;
use Centreon\Domain\PlatformTopology\Interfaces\PlatformTopologyRepositoryInterface;
use Centreon\Domain\PlatformTopology\Interfaces\PlatformTopologyRegisterRepositoryInterface;
......@@ -53,7 +51,7 @@ class RemoteServerService implements RemoteServerServiceInterface
private $platformTopologyRepository;
/**
* @var RemoteServerRepositoryInterface
* @var RemoteServerLocalConfigurationRepositoryInterface
*/
private $remoteServerRepository;
......@@ -67,6 +65,11 @@ class RemoteServerService implements RemoteServerServiceInterface
*/
private $proxyService;
/**
* @var MonitoringServerServiceInterface
*/
private $monitoringServerService;
/**
* @param MenuRepositoryInterface $menuRepository
* @param PlatformTopologyRepositoryInterface $platformTopologyRepository
......@@ -74,15 +77,17 @@ class RemoteServerService implements RemoteServerServiceInterface
public function __construct(
MenuRepositoryInterface $menuRepository,
PlatformTopologyRepositoryInterface $platformTopologyRepository,
RemoteServerRepositoryInterface $remoteServerRepository,
RemoteServerLocalConfigurationRepositoryInterface $remoteServerRepository,
PlatformTopologyRegisterRepositoryInterface $platformTopologyRegisterRepository,
ProxyServiceInterface $proxyService
ProxyServiceInterface $proxyService,
MonitoringServerServiceInterface $monitoringServerService
) {
$this->menuRepository = $menuRepository;
$this->platformTopologyRepository = $platformTopologyRepository;
$this->remoteServerRepository = $remoteServerRepository;
$this->platformTopologyRegisterRepository = $platformTopologyRegisterRepository;
$this->proxyService = $proxyService;
$this->monitoringServerService = $monitoringServerService;
}
/**
......@@ -168,8 +173,34 @@ class RemoteServerService implements RemoteServerServiceInterface
/**
* @inheritDoc
*/
public function convertRemoteToCentral(): void
public function convertRemoteToCentral(PlatformInformation $platformInformation): void
{
/**
* Delete the platform on its parent before anything else,
* If this step throw an exception, don't go further and avoid decorelation betweens platforms.
*/
$platform = $this->platformTopologyRepository->findTopLevelPlatform();
$this->platformTopologyRegisterRepository->deletePlatformToParent(
$platform,
$platformInformation,
$this->proxyService->getProxy()
);
/**
* Find any children platform and remove them,
* as they are now attached to the Central and no longer to this platform.
*
* @var Platform[] $childrenPlatforms
*/
$childrenPlatforms = $this->platformTopologyRepository->findChildrenPlatformsByParentId(
$platform->getId()
);
foreach ($childrenPlatforms as $childrenPlatform) {
if ($childrenPlatform->getServerId() !== null) {
$this->monitoringServerService->deleteServer($childrenPlatform->getServerId());
}
}
/**
* Set Central type into Platform_Topology
*/
......
......@@ -230,7 +230,7 @@ class MonitoringServerRepositoryRDB extends AbstractRepositoryDRB implements Mon
public function findResource(int $monitoringServerId, string $resourceName): ?MonitoringServerResource
{
$request = $this->translateDbName(
'SELECT resource.* FROM `:db`.cfg_resource resource
'SELECT resource.* FROM `:db`.cfg_resource resource
INNER JOIN `:db`.cfg_resource_instance_relations rel
ON rel.resource_id = resource.resource_id
WHERE rel.instance_id = :monitoring_server_id
......@@ -273,4 +273,14 @@ class MonitoringServerRepositoryRDB extends AbstractRepositoryDRB implements Mon
$statement->execute();
}
}
/**
* @inheritDoc
*/
public function deleteServer(int $monitoringServerId): void
{
$statement = $this->db->prepare($this->translateDbName("DELETE FROM `:db`.nagios_server WHERE id = :id"));
$statement->bindValue(':id', $monitoringServerId, \PDO::PARAM_INT);
$statement->execute();
}
}
......@@ -50,6 +50,13 @@ class PlatformTopologyRegisterRepositoryAPI implements PlatformTopologyRegisterR
*/
private $apiPlatform;
/**
* Central's API endpoints base path
*
* @var string
*/
private $baseApiEndpoint;
/**
* PlatformTopologyRegisterRepositoryAPI constructor.
* @param HttpClientInterface $httpClient
......@@ -61,72 +68,87 @@ class PlatformTopologyRegisterRepositoryAPI implements PlatformTopologyRegisterR
$this->apiPlatform = $apiPlatform;
}
/**
* Get a valid token to request the API.
*
* @param PlatformInformation $platformInformation
* @param Proxy $proxy
* @throws RepositoryException
* @return string
*/
private function getToken(
PlatformInformation $platformInformation,
Proxy $proxy = null
): string {
// Central's API endpoints base path building
$this->baseApiEndpoint = $platformInformation->getApiScheme() . '://'
. $platformInformation->getCentralServerAddress() . ':'
. $platformInformation->getApiPort() . DIRECTORY_SEPARATOR
. $platformInformation->getApiPath() . '/api/v'
. ((string) $this->apiPlatform->getVersion());
// Enable specific options
$optionPayload = [];
// Enable proxy
if (null !== $proxy && !empty((string) $proxy)) {
$optionPayload['proxy'] = (string) $proxy;
}
// On https scheme, the SSL verify_peer needs to be specified
if ('https' === $platformInformation->getApiScheme()) {
$optionPayload['verify_peer'] = $platformInformation->hasApiPeerValidation();
$optionPayload['verify_host'] = $platformInformation->hasApiPeerValidation();
}
// Set the options for next http_client calls
if (!empty($optionPayload)) {
$this->httpClient = HttpClient::create($optionPayload);
}
// Central's API login payload
$loginPayload = [
'json' => [
"security" => [
"credentials" => [
"login" => $platformInformation->getApiUsername(),
"password" => $platformInformation->getApiCredentials()
]
]
]
];
// Login on the Central to get a valid token
$loginResponse = $this->httpClient->request(
'POST',
$this->baseApiEndpoint . '/login',
$loginPayload
);
$token = $loginResponse->toArray()['security']['token'] ?? false;
if (false === $token) {
throw new RepositoryException(
sprintf(
_("Failed to get the auth token from Central : '%s''"),
$platformInformation->getCentralServerAddress()
)
);
}
return $token;
}
/**
* @inheritDoc
*/
public function registerPlatformToParent(
Platform $platform,
PlatformInformation $platformInformation,
Proxy $proxyService = null
Proxy $proxy = null
): void {
/**
* Call the API on the n-1 server to register it too
*/
try {
// Central's API endpoints base path
$baseApiEndpoint = $platformInformation->getApiScheme() . '://'
. $platformInformation->getCentralServerAddress() . ':'
. $platformInformation->getApiPort() . '/'
. $platformInformation->getApiPath() . '/api/v'
. ((string) $this->apiPlatform->getVersion()) . '/';
// Enable specific options
$optionPayload = [];
// Enable proxy
if (null !== $proxyService && !empty((string) $proxyService)) {
$optionPayload['proxy'] = (string) $proxyService;
}
// On https scheme, the SSL verify_peer needs to be specified
if ('https' === $platformInformation->getApiScheme()) {
$optionPayload['verify_peer'] = $platformInformation->hasApiPeerValidation();
$optionPayload['verify_host'] = $platformInformation->hasApiPeerValidation();
}
// Set the options for next http_client calls
if (!empty($optionPayload)) {
$this->httpClient = HttpClient::create($optionPayload);
}
// Central's API login payload
$loginPayload = [
'json' => [
"security" => [
"credentials" => [
"login" => $platformInformation->getApiUsername(),
"password" => $platformInformation->getApiCredentials()
]
]
]
];
// Login on the Central to get a valid token
$loginResponse = $this->httpClient->request(
'POST',
$baseApiEndpoint . 'login',
$loginPayload
);
$token = $loginResponse->toArray()['security']['token'] ?? false;
if (false === $token) {
throw new RepositoryException(
sprintf(
_("Failed to get the auth token. Cannot register the platform : '%s'@'%s' on the Central"),
$platform->getName(),
$platform->getAddress()
)
);
}
// Get a Token
$token = $this->getToken($platformInformation, $proxy);
// Central's API register platform payload
$registerPayload = [
......@@ -144,7 +166,7 @@ class PlatformTopologyRegisterRepositoryAPI implements PlatformTopologyRegisterR
$registerResponse = $this->httpClient->request(
'POST',
$baseApiEndpoint . 'platform/topology',
$this->baseApiEndpoint . '/platform/topology',
$registerPayload
);
......@@ -195,4 +217,118 @@ class PlatformTopologyRegisterRepositoryAPI implements PlatformTopologyRegisterR
);
}
}
/**
* @inheritDoc
*/
public function deletePlatformToParent(
Platform $platform,
PlatformInformation $platformInformation,
?Proxy $proxy = null
): void {
try {