icingaweb2-module-director/application/forms/HostServiceBlacklistForm.php
Ravi Srinivasa 6198cd8d9b
Alternative custom property support with dictionary handling
Introduce a first-class DirectorProperty concept that extends the existing
data-fields model with rich, structured variable types. Custom variables can
now be defined globally under a new "Custom Variables" section and assigned
to Icinga objects (hosts, services, commands, etc.).

Supported types: string, number, boolean, fixed-array, dynamic-array,
datalist-strict, datalist-non-strict, fixed-dictionary, and
dynamic-dictionary (one level of nesting allowed).

Key changes:
  - DirectorProperty object with CRUD, inheritance, and apply-for rule support
  - New form elements: Dictionary, DictionaryItem, NestedDictionary,
    NestedDictionaryItem, ArrayElement, IplBoolean
  - CustomvarController for managing global property definitions
  - VariablesController for per-object variable assignment
  - BasketSnapshotCustomVariableResolver for basket import/export of properties
  - REST API: IcingaObjectHandler extended to expose and accept structured vars
  - IcingaConfigHelper: renders dictionaries/arrays to valid Icinga 2 DSL
  - CustomVarRenderer updated for icingadb hook display
  - DB migration upgrade_192.sql: new director_property and related tables
  - CLI: MigrateCommand for migrating legacy vars to properties;
    HostsCommand for bulk host custom variable management
2026-05-15 13:41:00 +02:00

140 lines
4.3 KiB
PHP

<?php
namespace Icinga\Module\Director\Forms;
use Icinga\Exception\IcingaException;
use Icinga\Module\Director\Data\Db\DbConnection;
use Icinga\Module\Director\Objects\IcingaHost;
use Icinga\Module\Director\Objects\IcingaService;
use Icinga\Module\Director\Objects\IcingaServiceSet;
use Icinga\Web\Notification;
use Icinga\Web\Session;
use ipl\Html\Attributes;
use ipl\I18n\Translation;
use ipl\Web\Common\CsrfCounterMeasure;
use ipl\Web\Compat\CompatForm;
use Zend_Db_Adapter_Exception;
class HostServiceBlacklistForm extends CompatForm
{
use CsrfCounterMeasure;
use Translation;
/** @var bool Whether the service has been blacklisted or not */
private $blackListed = false;
protected $defaultAttributes = ['class' => 'icinga-controls'];
/** @var IcingaServiceSet Service set to which the service belongs */
private $set;
public function __construct(
protected DbConnection $db,
protected IcingaHost $host,
protected IcingaService $service
) {
$this->addAttributes(Attributes::create(['class' => ['host-service-deactivate-form']]));
if (! $this->hasBeenBlacklisted()) {
$this->addAttributes(Attributes::create(['class' => ['active']]));
} else {
$this->addAttributes(Attributes::create(['class' => ['deactivated']]));
}
}
protected function assemble(): void
{
$this->addElement($this->createCsrfCounterMeasure(Session::getSession()->getId()));
$blacklisted = $this->hasBeenBlacklisted();
$this->addElement('submit', 'submit', [
'label' => $blacklisted
? $this->translate('Reactivate Service')
: $this->translate('Deactivate Service'),
'class' => $blacklisted ? '' : 'btn-remove'
]);
}
protected function onSuccess(): void
{
if ($this->hasBeenBlacklisted()) {
if ($this->removeFromBlacklist()) {
Notification::success(sprintf(
$this->translate("Service '%s' on host '%s' has been reactivated"),
$this->service->getObjectName(),
$this->host->getObjectName()
));
}
} else {
if ($this->blacklist()) {
Notification::success(sprintf(
$this->translate("Service '%s' on host '%s' has been deactivated"),
$this->service->getObjectName(),
$this->host->getObjectName()
));
}
}
}
/**
* Whether the service has been blacklisted or not
*
* @return bool
*/
public function hasBeenBlacklisted(): bool
{
if ($this->service === null) {
return false;
}
if ($this->blackListed === false) {
// Safety check, branches
$hostId = $this->host->get('id');
$serviceId = $this->service->get('id');
if (! $hostId || ! $serviceId) {
return false;
}
$db = $this->db->getDbAdapter();
$this->blackListed = 1 === (int) $db->fetchOne(
$db->select()->from('icinga_host_service_blacklist', 'COUNT(*)')
->where('host_id = ?', $hostId)
->where('service_id = ?', $serviceId)
);
}
return $this->blackListed;
}
/**
* Remove the service from blacklist for the host
*
* @return int
*/
protected function removeFromBlacklist(): int
{
$db = $this->db->getDbAdapter();
$where = implode(' AND ', [
$db->quoteInto('host_id = ?', $this->host->get('id')),
$db->quoteInto('service_id = ?', $this->service->get('id')),
]);
return $db->delete('icinga_host_service_blacklist', $where);
}
/**
* Blacklist the service for the host
*
* @return int
*
* @throws Zend_Db_Adapter_Exception | IcingaException
*/
protected function blacklist(): int
{
$db = $this->db->getDbAdapter();
$this->host->unsetOverriddenServiceVars($this->service->getObjectName())->store();
return $db->insert('icinga_host_service_blacklist', [
'host_id' => $this->host->get('id'),
'service_id' => $this->service->get('id')
]);
}
}