2015-04-24 08:26:44 -04:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace Icinga\Module\Director\Objects;
|
|
|
|
|
|
2018-10-08 00:30:31 -04:00
|
|
|
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;
|
2015-06-11 16:44:17 -04:00
|
|
|
use Icinga\Module\Director\IcingaConfig\IcingaConfigHelper as c;
|
2016-10-14 04:32:51 -04:00
|
|
|
use Icinga\Module\Director\IcingaConfig\IcingaLegacyConfigHelper as c1;
|
2017-09-02 17:29:06 -04:00
|
|
|
use Icinga\Module\Director\Objects\Extension\Arguments;
|
2018-05-04 07:11:42 -04:00
|
|
|
use Zend_Db_Select as DbSelect;
|
2015-06-11 16:01:12 -04:00
|
|
|
|
2018-10-08 00:30:31 -04:00
|
|
|
class IcingaCommand extends IcingaObject implements ObjectWithArguments, ExportInterface
|
2015-04-24 08:26:44 -04:00
|
|
|
{
|
2017-09-02 17:29:06 -04:00
|
|
|
use Arguments;
|
|
|
|
|
|
2015-04-24 08:26:44 -04:00
|
|
|
protected $table = 'icinga_command';
|
|
|
|
|
|
2015-08-28 17:44:26 -04:00
|
|
|
protected $type = 'CheckCommand';
|
|
|
|
|
|
2021-10-05 12:19:01 -04:00
|
|
|
protected $uuidColumn = 'uuid';
|
|
|
|
|
|
2018-06-01 05:33:39 -04:00
|
|
|
protected $defaultProperties = [
|
2019-03-26 07:02:13 -04:00
|
|
|
'id' => null,
|
2021-10-05 12:19:01 -04:00
|
|
|
'uuid' => null,
|
2019-03-26 07:02:13 -04:00
|
|
|
'object_name' => null,
|
|
|
|
|
'object_type' => null,
|
|
|
|
|
'disabled' => 'n',
|
|
|
|
|
'methods_execute' => null,
|
|
|
|
|
'command' => null,
|
|
|
|
|
'timeout' => null,
|
|
|
|
|
'zone_id' => null,
|
|
|
|
|
'is_string' => null,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
protected $booleans = [
|
|
|
|
|
'is_string' => 'is_string',
|
2018-06-01 05:33:39 -04:00
|
|
|
];
|
2015-06-11 16:01:12 -04:00
|
|
|
|
2015-06-24 04:13:27 -04:00
|
|
|
protected $supportsCustomVars = true;
|
|
|
|
|
|
2015-08-28 17:44:26 -04:00
|
|
|
protected $supportsFields = true;
|
|
|
|
|
|
2015-06-29 04:39:37 -04:00
|
|
|
protected $supportsImports = true;
|
|
|
|
|
|
2016-10-13 09:44:53 -04:00
|
|
|
protected $supportedInLegacy = true;
|
|
|
|
|
|
2018-06-01 05:33:39 -04:00
|
|
|
protected $intervalProperties = [
|
2016-03-09 12:12:01 -05:00
|
|
|
'timeout' => 'timeout',
|
2018-06-01 05:33:39 -04:00
|
|
|
];
|
2016-03-09 12:12:01 -05:00
|
|
|
|
2018-06-01 05:33:39 -04:00
|
|
|
protected $relations = [
|
|
|
|
|
'zone' => 'IcingaZone',
|
|
|
|
|
];
|
2016-04-01 08:08:11 -04:00
|
|
|
|
2015-12-01 21:20:55 -05:00
|
|
|
protected static $pluginDir;
|
|
|
|
|
|
2018-06-01 05:33:39 -04:00
|
|
|
protected $hiddenExecuteTemplates = [
|
2016-08-25 06:16:00 -04:00
|
|
|
'PluginCheck' => 'plugin-check-command',
|
|
|
|
|
'PluginNotification' => 'plugin-notification-command',
|
|
|
|
|
'PluginEvent' => 'plugin-event-command',
|
|
|
|
|
|
|
|
|
|
// Special, internal:
|
|
|
|
|
'IcingaCheck' => 'icinga-check-command',
|
|
|
|
|
'ClusterCheck' => 'cluster-check-command',
|
2022-03-28 03:46:24 -04:00
|
|
|
'ClusterZoneCheck' => 'cluster-zone-check-command',
|
2016-08-25 06:16:00 -04:00
|
|
|
'IdoCheck' => 'ido-check-command',
|
|
|
|
|
'RandomCheck' => 'random-check-command',
|
2018-06-01 05:33:39 -04:00
|
|
|
];
|
2016-08-25 06:16:00 -04:00
|
|
|
|
2016-02-26 05:58:37 -05:00
|
|
|
/**
|
|
|
|
|
* Render the 'medhods_execute' property as 'execute'
|
|
|
|
|
*
|
|
|
|
|
* Execute is a reserved word in SQL, column name was prefixed
|
|
|
|
|
*
|
|
|
|
|
* Avoid complaints for method names with underscore:
|
|
|
|
|
* @codingStandardsIgnoreStart
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
2015-06-11 16:01:12 -04:00
|
|
|
protected function renderMethods_execute()
|
|
|
|
|
{
|
2016-02-26 05:58:37 -05:00
|
|
|
// @codingStandardsIgnoreEnd
|
2016-08-25 06:16:00 -04:00
|
|
|
return '';
|
2015-06-11 16:01:12 -04:00
|
|
|
}
|
2015-10-16 12:13:42 -04:00
|
|
|
|
2016-05-19 11:04:28 -04:00
|
|
|
protected function renderObjectHeader()
|
|
|
|
|
{
|
2018-06-01 05:33:39 -04:00
|
|
|
if ($execute = $this->get('methods_execute')) {
|
2016-08-25 06:16:00 -04:00
|
|
|
$itlImport = sprintf(
|
|
|
|
|
' import "%s"' . "\n",
|
2018-06-01 05:33:39 -04:00
|
|
|
$this->hiddenExecuteTemplates[$execute]
|
2016-08-25 06:16:00 -04:00
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
$itlImport = '';
|
|
|
|
|
}
|
2016-06-22 17:58:09 -04:00
|
|
|
|
2016-11-14 07:25:01 -05:00
|
|
|
$execute = $this->getSingleResolvedProperty('methods_execute');
|
2016-06-22 17:58:09 -04:00
|
|
|
if ($execute === 'PluginNotification') {
|
2016-08-25 06:16:00 -04:00
|
|
|
return $this->renderObjectHeaderWithType('NotificationCommand') . $itlImport;
|
2016-06-22 17:58:09 -04:00
|
|
|
} elseif ($execute === 'PluginEvent') {
|
2016-08-25 06:16:00 -04:00
|
|
|
return $this->renderObjectHeaderWithType('EventCommand') . $itlImport;
|
2016-05-19 11:04:28 -04:00
|
|
|
} else {
|
2016-08-25 06:16:00 -04:00
|
|
|
return parent::renderObjectHeader() . $itlImport;
|
2016-05-19 11:04:28 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-01 05:33:39 -04:00
|
|
|
/**
|
|
|
|
|
* @param $type
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
2016-06-22 17:58:09 -04:00
|
|
|
protected function renderObjectHeaderWithType($type)
|
|
|
|
|
{
|
|
|
|
|
return sprintf(
|
|
|
|
|
"%s %s %s {\n",
|
|
|
|
|
$this->getObjectTypeName(),
|
|
|
|
|
$type,
|
|
|
|
|
c::renderString($this->getObjectName())
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-01 21:20:55 -05:00
|
|
|
public function mungeCommand($value)
|
|
|
|
|
{
|
|
|
|
|
if (is_array($value)) {
|
|
|
|
|
$value = implode(' ', $value);
|
|
|
|
|
} elseif (is_object($value)) {
|
|
|
|
|
// { type => Function } -> really??
|
|
|
|
|
return null;
|
2018-06-01 05:33:39 -04:00
|
|
|
// return $value;
|
2015-12-01 21:20:55 -05:00
|
|
|
}
|
|
|
|
|
|
2024-01-17 10:16:31 -05:00
|
|
|
if (isset($value, self::$pluginDir) && strpos($value, self::$pluginDir) === 0) {
|
|
|
|
|
$value = substr($value, strlen(self::$pluginDir) + 1);
|
2015-12-01 21:20:55 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $value;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-26 03:00:45 -04:00
|
|
|
public function getNextSkippableKeyName()
|
|
|
|
|
{
|
|
|
|
|
$key = $this->makeSkipKey();
|
|
|
|
|
$cnt = 1;
|
|
|
|
|
while (isset($this->arguments()->$key)) {
|
|
|
|
|
$cnt++;
|
|
|
|
|
$key = $this->makeSkipKey($cnt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $key;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function makeSkipKey($num = null)
|
|
|
|
|
{
|
|
|
|
|
if ($num === null) {
|
|
|
|
|
return '(no key)';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return sprintf('(no key.%d)', $num);
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-28 11:44:42 -04:00
|
|
|
protected function prefersGlobalZone()
|
2016-04-23 08:08:25 -04:00
|
|
|
{
|
2016-07-28 11:44:42 -04:00
|
|
|
return true;
|
2016-04-23 08:08:25 -04:00
|
|
|
}
|
|
|
|
|
|
2018-06-01 05:33:39 -04:00
|
|
|
/**
|
|
|
|
|
* @return string
|
|
|
|
|
* @throws \Zend_Db_Select_Exception
|
|
|
|
|
*/
|
2018-05-04 07:11:42 -04:00
|
|
|
public function countDirectUses()
|
|
|
|
|
{
|
|
|
|
|
$db = $this->getDb();
|
|
|
|
|
$id = (int) $this->get('id');
|
|
|
|
|
|
|
|
|
|
$qh = $db->select()->from(
|
|
|
|
|
array('h' => 'icinga_host'),
|
|
|
|
|
array('cnt' => 'COUNT(*)')
|
|
|
|
|
)->where('h.check_command_id = ?', $id)
|
|
|
|
|
->orWhere('h.event_command_id = ?', $id);
|
|
|
|
|
$qs = $db->select()->from(
|
|
|
|
|
array('s' => 'icinga_service'),
|
|
|
|
|
array('cnt' => 'COUNT(*)')
|
|
|
|
|
)->where('s.check_command_id = ?', $id)
|
|
|
|
|
->orWhere('s.event_command_id = ?', $id);
|
|
|
|
|
$qn = $db->select()->from(
|
|
|
|
|
array('n' => 'icinga_notification'),
|
|
|
|
|
array('cnt' => 'COUNT(*)')
|
|
|
|
|
)->where('n.command_id = ?', $id);
|
|
|
|
|
$query = $db->select()->union(
|
|
|
|
|
[$qh, $qs, $qn],
|
|
|
|
|
DbSelect::SQL_UNION_ALL
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return $db->fetchOne($db->select()->from(
|
|
|
|
|
['all_cnts' => $query],
|
|
|
|
|
['cnt' => 'SUM(cnt)']
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-01 05:33:39 -04:00
|
|
|
/**
|
|
|
|
|
* @return bool
|
|
|
|
|
* @throws \Zend_Db_Select_Exception
|
|
|
|
|
*/
|
2018-05-04 07:11:42 -04:00
|
|
|
public function isInUse()
|
|
|
|
|
{
|
|
|
|
|
return $this->countDirectUses() > 0;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-08 00:30:31 -04:00
|
|
|
public function getUniqueIdentifier()
|
|
|
|
|
{
|
|
|
|
|
return $this->getObjectName();
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-16 12:13:42 -04:00
|
|
|
protected function renderCommand()
|
|
|
|
|
{
|
2018-06-01 05:33:39 -04:00
|
|
|
$command = $this->get('command');
|
2015-10-16 12:39:13 -04:00
|
|
|
$prefix = '';
|
2016-04-01 08:08:27 -04:00
|
|
|
if (preg_match('~^([A-Z][A-Za-z0-9_]+\s\+\s)(.+?)$~', $command, $m)) {
|
2019-03-26 07:02:13 -04:00
|
|
|
$prefix = $m[1];
|
2015-10-16 12:39:13 -04:00
|
|
|
$command = $m[2];
|
2016-05-13 10:01:47 -04:00
|
|
|
} elseif (! $this->isAbsolutePath($command)) {
|
2015-10-16 12:39:13 -04:00
|
|
|
$prefix = 'PluginDir + ';
|
2015-10-28 17:28:43 -04:00
|
|
|
$command = '/' . $command;
|
2015-10-16 12:39:13 -04:00
|
|
|
}
|
2019-03-26 07:02:13 -04:00
|
|
|
|
|
|
|
|
$inherited = $this->getInheritedProperties();
|
|
|
|
|
|
2024-10-22 08:31:14 -04:00
|
|
|
if (
|
|
|
|
|
$this->get('is_string') === 'y' || ($this->get('is_string') === null
|
|
|
|
|
&& property_exists($inherited, 'is_string') && $inherited->is_string === 'y')
|
|
|
|
|
) {
|
2019-03-26 07:02:13 -04:00
|
|
|
return c::renderKeyValue('command', $prefix . c::renderString($command));
|
|
|
|
|
} else {
|
|
|
|
|
$parts = preg_split('/\s+/', $command, -1, PREG_SPLIT_NO_EMPTY);
|
|
|
|
|
array_unshift($parts, c::alreadyRendered($prefix . c::renderString(array_shift($parts))));
|
|
|
|
|
|
|
|
|
|
return c::renderKeyValue('command', c::renderArray($parts));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @codingStandardsIgnoreStart
|
|
|
|
|
*/
|
|
|
|
|
protected function renderIs_string()
|
|
|
|
|
{
|
|
|
|
|
// @codingStandardsIgnoreEnd
|
|
|
|
|
return '';
|
2015-10-16 12:13:42 -04:00
|
|
|
}
|
2015-12-01 20:53:27 -05:00
|
|
|
|
2016-05-13 10:01:47 -04:00
|
|
|
protected function isAbsolutePath($path)
|
|
|
|
|
{
|
|
|
|
|
return $path[0] === '/'
|
|
|
|
|
|| $path[0] === '\\'
|
2018-06-01 05:33:39 -04:00
|
|
|
|| preg_match('/^[A-Za-z]:\\\/', substr($path, 0, 3))
|
|
|
|
|
|| preg_match('/^%[A-Z][A-Za-z0-9\(\)-]*%/', $path);
|
2016-05-13 10:01:47 -04:00
|
|
|
}
|
|
|
|
|
|
2015-12-01 21:20:55 -05:00
|
|
|
public static function setPluginDir($pluginDir)
|
|
|
|
|
{
|
|
|
|
|
self::$pluginDir = $pluginDir;
|
|
|
|
|
}
|
2016-10-14 04:32:51 -04:00
|
|
|
|
2016-10-14 05:07:37 -04:00
|
|
|
public function getLegacyObjectType()
|
2016-10-14 04:32:51 -04:00
|
|
|
{
|
|
|
|
|
// there is only one type of command in Icinga 1.x
|
|
|
|
|
return 'command';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function renderLegacyCommand()
|
|
|
|
|
{
|
2018-06-01 05:33:39 -04:00
|
|
|
$command = $this->get('command');
|
2016-10-14 04:32:51 -04:00
|
|
|
if (preg_match('~^(\$USER\d+\$/?)(.+)$~', $command)) {
|
|
|
|
|
// should be fine, since the user decided to use a macro
|
|
|
|
|
} elseif (! $this->isAbsolutePath($command)) {
|
2024-10-22 08:31:14 -04:00
|
|
|
$command = '$USER1$/' . $command;
|
2016-10-14 04:32:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return c1::renderKeyValue(
|
2024-10-22 08:31:14 -04:00
|
|
|
$this->getLegacyObjectType() . '_line',
|
2016-10-14 04:32:51 -04:00
|
|
|
c1::renderString($command)
|
|
|
|
|
);
|
|
|
|
|
}
|
2015-04-24 08:26:44 -04:00
|
|
|
}
|