You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
zabbix/ui/host_discovery.php

841 lines
31 KiB

<?php
/*
** Zabbix
** Copyright (C) 2001-2023 Zabbix SIA
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
require_once dirname(__FILE__).'/include/config.inc.php';
require_once dirname(__FILE__).'/include/hosts.inc.php';
require_once dirname(__FILE__).'/include/items.inc.php';
require_once dirname(__FILE__).'/include/forms.inc.php';
$page['title'] = _('Configuration of discovery rules');
$page['file'] = 'host_discovery.php';
$page['scripts'] = ['multilineinput.js', 'items.js'];
require_once dirname(__FILE__).'/include/page_header.php';
$paramsFieldName = getParamFieldNameByType(getRequest('type', 0));
// supported eval types
$evalTypes = [
CONDITION_EVAL_TYPE_AND_OR,
CONDITION_EVAL_TYPE_AND,
CONDITION_EVAL_TYPE_OR,
CONDITION_EVAL_TYPE_EXPRESSION
];
// VAR TYPE OPTIONAL FLAGS VALIDATION EXCEPTION
$fields = [
'hostid' => [T_ZBX_INT, O_OPT, P_SYS, DB_ID, 'isset({form}) && !isset({itemid})'],
'itemid' => [T_ZBX_INT, O_NO, P_SYS, DB_ID, '(isset({form}) && ({form} == "update"))'],
'interfaceid' => [T_ZBX_INT, O_OPT, P_SYS, DB_ID, null, _('Interface')],
'name' => [T_ZBX_STR, O_OPT, null, NOT_EMPTY, 'isset({add}) || isset({update})', _('Name')],
'description' => [T_ZBX_STR, O_OPT, null, null, 'isset({add}) || isset({update})'],
'key' => [T_ZBX_STR, O_OPT, null, NOT_EMPTY, 'isset({add}) || isset({update})', _('Key')],
'master_itemid' => [T_ZBX_STR, O_OPT, null, null,
'(isset({add}) || isset({update})) && isset({type})'.
' && {type} == '.ITEM_TYPE_DEPENDENT,
_('Master item')
],
'delay' => [T_ZBX_TU, O_OPT, P_ALLOW_USER_MACRO, null,
'(isset({add}) || isset({update})) && isset({type})'.
' && {type} != '.ITEM_TYPE_TRAPPER.' && {type} != '.ITEM_TYPE_SNMPTRAP.
' && {type} != '.ITEM_TYPE_DEPENDENT.
' && !({type} == '.ITEM_TYPE_ZABBIX_ACTIVE.
' && isset({key}) && strncmp({key}, "mqtt.get", 8) === 0)',
_('Update interval')
],
'delay_flex' => [T_ZBX_STR, O_OPT, P_ONLY_TD_ARRAY, null, null],
'status' => [T_ZBX_INT, O_OPT, null, IN(ITEM_STATUS_ACTIVE), null],
'type' => [T_ZBX_INT, O_OPT, null,
IN([-1, ITEM_TYPE_ZABBIX, ITEM_TYPE_TRAPPER, ITEM_TYPE_SIMPLE, ITEM_TYPE_INTERNAL,
ITEM_TYPE_ZABBIX_ACTIVE, ITEM_TYPE_EXTERNAL, ITEM_TYPE_DB_MONITOR,
ITEM_TYPE_IPMI, ITEM_TYPE_SSH, ITEM_TYPE_TELNET, ITEM_TYPE_JMX,
ITEM_TYPE_DEPENDENT, ITEM_TYPE_HTTPAGENT, ITEM_TYPE_SNMP, ITEM_TYPE_SCRIPT
]),
'isset({add}) || isset({update})'
],
'authtype' => [T_ZBX_INT, O_OPT, null, IN(ITEM_AUTHTYPE_PASSWORD.','.ITEM_AUTHTYPE_PUBLICKEY),
'(isset({add}) || isset({update})) && isset({type}) && {type} == '.ITEM_TYPE_SSH],
'username' => [T_ZBX_STR, O_OPT, null, NOT_EMPTY,
'(isset({add}) || isset({update})) && isset({type})'.
' && '.IN(ITEM_TYPE_SSH.','.ITEM_TYPE_TELNET, 'type'),
_('User name')
],
'password' => [T_ZBX_STR, O_OPT, null, null,
'(isset({add}) || isset({update})) && isset({type})'.
' && '.IN(ITEM_TYPE_SSH.','.ITEM_TYPE_TELNET, 'type')
],
'publickey' => [T_ZBX_STR, O_OPT, null, null,
'(isset({add}) || isset({update})) && isset({type}) && {type} == '.ITEM_TYPE_SSH.
' && {authtype} == '.ITEM_AUTHTYPE_PUBLICKEY
],
'privatekey' => [T_ZBX_STR, O_OPT, null, null,
'(isset({add}) || isset({update})) && isset({type}) && {type} == '.ITEM_TYPE_SSH.
' && {authtype} == '.ITEM_AUTHTYPE_PUBLICKEY
],
$paramsFieldName => [T_ZBX_STR, O_OPT, null, NOT_EMPTY, '(isset({add}) || isset({update}))'.
' && isset({type}) && '.IN(ITEM_TYPE_SSH.','.ITEM_TYPE_DB_MONITOR.','.
ITEM_TYPE_TELNET.','.ITEM_TYPE_CALCULATED.','.ITEM_TYPE_SCRIPT, 'type'
),
getParamFieldLabelByType(getRequest('type', 0))
],
'snmp_oid' => [T_ZBX_STR, O_OPT, null, NOT_EMPTY,
'(isset({add}) || isset({update})) && isset({type})'.
' && {type} == '.ITEM_TYPE_SNMP,
_('SNMP OID')
],
'ipmi_sensor' => [T_ZBX_STR, O_OPT, P_NO_TRIM, null,
'(isset({add}) || isset({update})) && isset({type}) && {type} == '.ITEM_TYPE_IPMI,
_('IPMI sensor')
],
'trapper_hosts' => [T_ZBX_STR, O_OPT, null, null,
'(isset({add}) || isset({update})) && isset({type}) && {type} == 2'
],
'lifetime' => [T_ZBX_STR, O_OPT, null, null, 'isset({add}) || isset({update})'],
'evaltype' => [T_ZBX_INT, O_OPT, null, IN($evalTypes), 'isset({add}) || isset({update})'],
'formula' => [T_ZBX_STR, O_OPT, null, null, 'isset({add}) || isset({update})'],
'conditions' => [T_ZBX_STR, O_OPT, P_SYS|P_ONLY_TD_ARRAY, null, null],
'lld_macro_paths' => [T_ZBX_STR, O_OPT, P_SYS|P_ONLY_TD_ARRAY, null, null],
'jmx_endpoint' => [T_ZBX_STR, O_OPT, null, NOT_EMPTY,
'(isset({add}) || isset({update})) && isset({type}) && {type} == '.ITEM_TYPE_JMX
],
'timeout' => [T_ZBX_TU, O_OPT, P_ALLOW_USER_MACRO, null,
'(isset({add}) || isset({update})) && isset({type})'.
' && '.IN(ITEM_TYPE_HTTPAGENT.','.ITEM_TYPE_SCRIPT, 'type'),
_('Timeout')
],
'url' => [T_ZBX_STR, O_OPT, null, NOT_EMPTY,
'(isset({add}) || isset({update})) && isset({type})'.
' && {type} == '.ITEM_TYPE_HTTPAGENT,
_('URL')
],
'query_fields' => [T_ZBX_STR, O_OPT, P_ONLY_TD_ARRAY, null, null],
'parameters' => [T_ZBX_STR, O_OPT, P_ONLY_TD_ARRAY, null, null],
'posts' => [T_ZBX_STR, O_OPT, null, null, null],
'status_codes' => [T_ZBX_STR, O_OPT, null, null, null],
'follow_redirects' => [T_ZBX_INT, O_OPT, null,
IN([HTTPTEST_STEP_FOLLOW_REDIRECTS_OFF, HTTPTEST_STEP_FOLLOW_REDIRECTS_ON]),
null
],
'post_type' => [T_ZBX_INT, O_OPT, null,
IN([ZBX_POSTTYPE_RAW, ZBX_POSTTYPE_JSON, ZBX_POSTTYPE_XML]),
null
],
'http_proxy' => [T_ZBX_STR, O_OPT, null, null, null],
'headers' => [T_ZBX_STR, O_OPT, P_ONLY_TD_ARRAY, null, null],
'retrieve_mode' => [T_ZBX_INT, O_OPT, null,
IN([HTTPTEST_STEP_RETRIEVE_MODE_CONTENT, HTTPTEST_STEP_RETRIEVE_MODE_HEADERS,
HTTPTEST_STEP_RETRIEVE_MODE_BOTH
]),
null
],
'request_method' => [T_ZBX_INT, O_OPT, null,
IN([HTTPCHECK_REQUEST_GET, HTTPCHECK_REQUEST_POST, HTTPCHECK_REQUEST_PUT,
HTTPCHECK_REQUEST_HEAD
]),
null
],
'allow_traps' => [T_ZBX_INT, O_OPT, null, IN([HTTPCHECK_ALLOW_TRAPS_OFF, HTTPCHECK_ALLOW_TRAPS_ON]),
null
],
'ssl_cert_file' => [T_ZBX_STR, O_OPT, null, null, null],
'ssl_key_file' => [T_ZBX_STR, O_OPT, null, null, null],
'ssl_key_password' => [T_ZBX_STR, O_OPT, null, null, null],
'verify_peer' => [T_ZBX_INT, O_OPT, null,
IN([ZBX_HTTP_VERIFY_PEER_OFF, ZBX_HTTP_VERIFY_PEER_ON]),
null
],
'verify_host' => [T_ZBX_INT, O_OPT, null,
IN([ZBX_HTTP_VERIFY_HOST_OFF, ZBX_HTTP_VERIFY_HOST_ON]),
null
],
'http_authtype' => [T_ZBX_INT, O_OPT, null,
IN([ZBX_HTTP_AUTH_NONE, ZBX_HTTP_AUTH_BASIC, ZBX_HTTP_AUTH_NTLM,
ZBX_HTTP_AUTH_KERBEROS, ZBX_HTTP_AUTH_DIGEST
]),
null
],
'http_username' => [T_ZBX_STR, O_OPT, null, null,
'(isset({add}) || isset({update})) && isset({http_authtype})'.
' && ({http_authtype} == '.ZBX_HTTP_AUTH_BASIC.
' || {http_authtype} == '.ZBX_HTTP_AUTH_NTLM.
' || {http_authtype} == '.ZBX_HTTP_AUTH_KERBEROS.
' || {http_authtype} == '.ZBX_HTTP_AUTH_DIGEST.
')',
_('Username')
],
'http_password' => [T_ZBX_STR, O_OPT, null, null,
'(isset({add}) || isset({update})) && isset({http_authtype})'.
' && ({http_authtype} == '.ZBX_HTTP_AUTH_BASIC.
' || {http_authtype} == '.ZBX_HTTP_AUTH_NTLM.
' || {http_authtype} == '.ZBX_HTTP_AUTH_KERBEROS.
' || {http_authtype} == '.ZBX_HTTP_AUTH_DIGEST.
')',
_('Password')
],
'preprocessing' => [null, O_OPT, P_NO_TRIM|P_ONLY_TD_ARRAY, null, null],
'overrides' => [null, O_OPT, P_NO_TRIM|P_ONLY_TD_ARRAY, null, null],
'context' => [T_ZBX_STR, O_MAND, P_SYS, IN('"host", "template"'), null],
// actions
'action' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT,
IN('"discoveryrule.massdelete","discoveryrule.massdisable",'.
'"discoveryrule.massenable"'
),
null
],
'g_hostdruleid' => [T_ZBX_INT, O_OPT, P_ONLY_ARRAY, DB_ID, null],
'add' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null],
'update' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null],
'clone' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null],
'delete' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null],
'cancel' => [T_ZBX_STR, O_OPT, P_SYS, null, null],
'form' => [T_ZBX_STR, O_OPT, P_SYS, null, null],
'form_refresh' => [T_ZBX_INT, O_OPT, P_SYS, null, null],
// filter
'filter_set' => [T_ZBX_STR, O_OPT, null, null, null],
'filter_rst' => [T_ZBX_STR, O_OPT, null, null, null],
'filter_groupids' => [T_ZBX_INT, O_OPT, P_ONLY_ARRAY, DB_ID, null],
'filter_hostids' => [T_ZBX_INT, O_OPT, P_ONLY_ARRAY, DB_ID, null],
'filter_name' => [T_ZBX_STR, O_OPT, null, null, null],
'filter_key' => [T_ZBX_STR, O_OPT, null, null, null],
'filter_type' => [T_ZBX_INT, O_OPT, null,
IN([-1, ITEM_TYPE_ZABBIX, ITEM_TYPE_TRAPPER, ITEM_TYPE_SIMPLE, ITEM_TYPE_INTERNAL,
ITEM_TYPE_ZABBIX_ACTIVE, ITEM_TYPE_EXTERNAL, ITEM_TYPE_DB_MONITOR,
ITEM_TYPE_IPMI, ITEM_TYPE_SSH, ITEM_TYPE_TELNET, ITEM_TYPE_JMX,
ITEM_TYPE_DEPENDENT, ITEM_TYPE_HTTPAGENT, ITEM_TYPE_SNMP, ITEM_TYPE_SCRIPT
]),
null
],
'filter_delay' => [T_ZBX_STR, O_OPT, P_UNSET_EMPTY, null, null, _('Update interval')],
'filter_lifetime' => [T_ZBX_STR, O_OPT, null, null, null],
'filter_snmp_oid' => [T_ZBX_STR, O_OPT, null, null, null],
'filter_state' => [T_ZBX_INT, O_OPT, null, IN([-1, ITEM_STATE_NORMAL, ITEM_STATE_NOTSUPPORTED]),
null
],
'filter_status' => [T_ZBX_INT, O_OPT, null, IN([-1, ITEM_STATUS_ACTIVE, ITEM_STATUS_DISABLED]),
null
],
'backurl' => [T_ZBX_STR, O_OPT, null, null, null],
// sort and sortorder
'sort' => [T_ZBX_STR, O_OPT, P_SYS, IN('"delay","key_","name","status","type"'), null],
'sortorder' => [T_ZBX_STR, O_OPT, P_SYS, IN('"'.ZBX_SORT_DOWN.'","'.ZBX_SORT_UP.'"'), null]
];
check_fields($fields);
$_REQUEST['params'] = getRequest($paramsFieldName, '');
unset($_REQUEST[$paramsFieldName]);
/*
* Permissions
*/
$itemid = getRequest('itemid');
if ($itemid) {
$items = API::DiscoveryRule()->get([
'output' => ['itemid'],
'selectHosts' => ['hostid', 'status', 'name'],
'itemids' => $itemid,
'editable' => true
]);
if (!$items) {
access_deny();
}
$hosts = $items[0]['hosts'];
}
else {
$hostid = getRequest('hostid');
if ($hostid) {
$hosts = API::Host()->get([
'output' => ['hostid', 'status', 'name'],
'hostids' => $hostid,
'templated_hosts' => true,
'editable' => true
]);
if (!$hosts) {
access_deny();
}
}
}
// Validate backurl.
if (hasRequest('backurl') && !CHtmlUrlValidator::validateSameSite(getRequest('backurl'))) {
access_deny();
}
$prefix = (getRequest('context') === 'host') ? 'web.hosts.' : 'web.templates.';
/**
* Filter.
*/
$sort_field = getRequest('sort', CProfile::get($prefix.$page['file'].'.sort', 'name'));
$sort_order = getRequest('sortorder', CProfile::get($prefix.$page['file'].'.sortorder', ZBX_SORT_UP));
CProfile::update($prefix.$page['file'].'.sort', $sort_field, PROFILE_TYPE_STR);
CProfile::update($prefix.$page['file'].'.sortorder', $sort_order, PROFILE_TYPE_STR);
if (hasRequest('filter_set')) {
CProfile::updateArray($prefix.'host_discovery.filter.groupids', getRequest('filter_groupids', []), PROFILE_TYPE_ID);
CProfile::updateArray($prefix.'host_discovery.filter.hostids', getRequest('filter_hostids', []), PROFILE_TYPE_ID);
CProfile::update($prefix.'host_discovery.filter.name', getRequest('filter_name', ''), PROFILE_TYPE_STR);
CProfile::update($prefix.'host_discovery.filter.key', getRequest('filter_key', ''), PROFILE_TYPE_STR);
CProfile::update($prefix.'host_discovery.filter.type', getRequest('filter_type', -1), PROFILE_TYPE_INT);
CProfile::update($prefix.'host_discovery.filter.delay', getRequest('filter_delay', ''), PROFILE_TYPE_STR);
CProfile::update($prefix.'host_discovery.filter.lifetime', getRequest('filter_lifetime', ''), PROFILE_TYPE_STR);
CProfile::update($prefix.'host_discovery.filter.snmp_oid', getRequest('filter_snmp_oid', ''), PROFILE_TYPE_STR);
CProfile::update($prefix.'host_discovery.filter.state', getRequest('filter_state', -1), PROFILE_TYPE_INT);
CProfile::update($prefix.'host_discovery.filter.status', getRequest('filter_status', -1), PROFILE_TYPE_INT);
}
elseif (hasRequest('filter_rst')) {
CProfile::deleteIdx($prefix.'host_discovery.filter.groupids');
if (count(CProfile::getArray($prefix.'host_discovery.filter.hostids', [])) != 1) {
CProfile::deleteIdx($prefix.'host_discovery.filter.hostids');
}
CProfile::delete($prefix.'host_discovery.filter.name');
CProfile::delete($prefix.'host_discovery.filter.key');
CProfile::delete($prefix.'host_discovery.filter.type');
CProfile::delete($prefix.'host_discovery.filter.delay');
CProfile::delete($prefix.'host_discovery.filter.lifetime');
CProfile::delete($prefix.'host_discovery.filter.snmp_oid');
CProfile::delete($prefix.'host_discovery.filter.state');
CProfile::delete($prefix.'host_discovery.filter.status');
}
$filter = [
'groups' => [],
'hosts' => [],
'name' => CProfile::get($prefix.'host_discovery.filter.name', ''),
'key' => CProfile::get($prefix.'host_discovery.filter.key', ''),
'type' => CProfile::get($prefix.'host_discovery.filter.type', -1),
'delay' => CProfile::get($prefix.'host_discovery.filter.delay', ''),
'lifetime' => CProfile::get($prefix.'host_discovery.filter.lifetime', ''),
'snmp_oid' => CProfile::get($prefix.'host_discovery.filter.snmp_oid', ''),
'state' => CProfile::get($prefix.'host_discovery.filter.state', -1),
'status' => CProfile::get($prefix.'host_discovery.filter.status', -1)
];
$filter_groupids = CProfile::getArray($prefix.'host_discovery.filter.groupids', []);
$filter_hostids = CProfile::getArray($prefix.'host_discovery.filter.hostids', []);
// Get host groups.
$filter_groupids = getSubGroups($filter_groupids, $filter['groups'], ['editable' => true], getRequest('context'));
// Get hosts.
if (getRequest('context') === 'host') {
$filter['hosts'] = $filter_hostids
? CArrayHelper::renameObjectsKeys(API::Host()->get([
'output' => ['hostid', 'name'],
'hostids' => $filter_hostids,
'editable' => true,
'preservekeys' => true
]), ['hostid' => 'id'])
: [];
}
else {
$filter['hosts'] = $filter_hostids
? CArrayHelper::renameObjectsKeys(API::Template()->get([
'output' => ['templateid', 'name'],
'templateids' => $filter_hostids,
'editable' => true,
'preservekeys' => true
]), ['templateid' => 'id'])
: [];
}
$filter_hostids = array_keys($filter['hosts']);
sort($filter_hostids);
$checkbox_hash = crc32(implode('', $filter_hostids));
/*
* Actions
*/
if (hasRequest('delete') && hasRequest('itemid')) {
$result = API::DiscoveryRule()->delete([getRequest('itemid')]);
if ($result) {
uncheckTableRows($checkbox_hash);
}
show_messages($result, _('Discovery rule deleted'), _('Cannot delete discovery rule'));
unset($_REQUEST['itemid'], $_REQUEST['form']);
}
elseif (hasRequest('add') || hasRequest('update')) {
try {
$type = (int) getRequest('type', DB::getDefault('items', 'type'));
$key = getRequest('key', DB::getDefault('items', 'key_'));
if (isItemExampleKey($type, $key)) {
throw new Exception();
}
$overrides = getRequest('overrides', []);
$db_item = null;
if (hasRequest('update')) {
$options = $overrides ? ['selectOverrides' => ['step']] : [];
$db_item = API::DiscoveryRule()->get([
'output' => ['itemid', 'templateid'],
'itemids' => $itemid
] + $options)[0];
}
$delay_flex = getRequest('delay_flex', []);
if (!isValidCustomIntervals($delay_flex, true)) {
throw new Exception();
}
$request_method = getRequest('request_method', DB::getDefault('items', 'request_method'));
$retrieve_mode_default = $request_method == HTTPCHECK_REQUEST_HEAD
? HTTPTEST_STEP_RETRIEVE_MODE_HEADERS
: DB::getDefault('items', 'retrieve_mode');
$input = [
'name' => getRequest('name', DB::getDefault('items', 'name')),
'type' => $type,
'key_' => $key,
'lifetime' => getRequest('lifetime', DB::getDefault('items', 'lifetime')),
'description' => getRequest('description', DB::getDefault('items', 'description')),
'status' => getRequest('status', ITEM_STATUS_DISABLED),
'preprocessing' => normalizeItemPreprocessingSteps(getRequest('preprocessing', [])),
'lld_macro_paths' => prepareLldMacroPaths(getRequest('lld_macro_paths', [])),
'filter' => prepareLldFilter([
'evaltype' => getRequest('evaltype', DB::getDefault('items', 'evaltype')),
'formula' => getRequest('formula', DB::getDefault('items', 'formula')),
'conditions' => getRequest('conditions', [])
]),
'overrides' => prepareLldOverrides($overrides, $db_item),
// Type fields.
// The fields used for multiple item types.
'interfaceid' => getRequest('interfaceid', 0),
'authtype' => $type == ITEM_TYPE_HTTPAGENT
? getRequest('http_authtype', DB::getDefault('items', 'authtype'))
: getRequest('authtype', DB::getDefault('items', 'authtype')),
'username' => $type == ITEM_TYPE_HTTPAGENT
? getRequest('http_username', DB::getDefault('items', 'username'))
: getRequest('username', DB::getDefault('items', 'username')),
'password' => $type == ITEM_TYPE_HTTPAGENT
? getRequest('http_password', DB::getDefault('items', 'password'))
: getRequest('password', DB::getDefault('items', 'password')),
'params' => getRequest('params', DB::getDefault('items', 'params')),
'timeout' => getRequest('timeout', DB::getDefault('items', 'timeout')),
'delay' => getDelayWithCustomIntervals(getRequest('delay', DB::getDefault('items', 'delay')), $delay_flex),
'trapper_hosts' => getRequest('trapper_hosts', DB::getDefault('items', 'trapper_hosts')),
// Dependent item type specific fields.
'master_itemid' => getRequest('master_itemid', 0),
// HTTP Agent item type specific fields.
'url' => getRequest('url', DB::getDefault('items', 'url')),
'query_fields' => prepareItemQueryFields(getRequest('query_fields', [])),
'request_method' => $request_method,
'post_type' => getRequest('post_type', DB::getDefault('items', 'post_type')),
'posts' => getRequest('posts', DB::getDefault('items', 'posts')),
'headers' => prepareItemHeaders(getRequest('headers', [])),
'status_codes' => getRequest('status_codes', DB::getDefault('items', 'status_codes')),
'follow_redirects' => getRequest('follow_redirects', HTTPTEST_STEP_FOLLOW_REDIRECTS_OFF),
'retrieve_mode' => getRequest('retrieve_mode', $retrieve_mode_default),
'output_format' => getRequest('output_format', DB::getDefault('items', 'output_format')),
'http_proxy' => getRequest('http_proxy', DB::getDefault('items', 'http_proxy')),
'verify_peer' => getRequest('verify_peer', DB::getDefault('items', 'verify_peer')),
'verify_host' => getRequest('verify_host', DB::getDefault('items', 'verify_host')),
'ssl_cert_file' => getRequest('ssl_cert_file', DB::getDefault('items', 'ssl_cert_file')),
'ssl_key_file' => getRequest('ssl_key_file', DB::getDefault('items', 'ssl_key_file')),
'ssl_key_password' => getRequest('ssl_key_password', DB::getDefault('items', 'ssl_key_password')),
'allow_traps' => getRequest('allow_traps', DB::getDefault('items', 'allow_traps')),
// IPMI item type specific fields.
'ipmi_sensor' => getRequest('ipmi_sensor', DB::getDefault('items', 'ipmi_sensor')),
// JMX item type specific fields.
'jmx_endpoint' => getRequest('jmx_endpoint', DB::getDefault('items', 'jmx_endpoint')),
// Script item type specific fields.
'parameters' => prepareItemParameters(getRequest('parameters', [])),
// SNMP item type specific fields.
'snmp_oid' => getRequest('snmp_oid', DB::getDefault('items', 'snmp_oid')),
// SSH item type specific fields.
'publickey' => getRequest('publickey', DB::getDefault('items', 'publickey')),
'privatekey' => getRequest('privatekey', DB::getDefault('items', 'privatekey'))
];
$result = true;
if (hasRequest('add')) {
$item = ['hostid' => $hostid];
$item += getSanitizedItemFields($input + [
'templateid' => 0,
'flags' => ZBX_FLAG_DISCOVERY_RULE,
'hosts' => $hosts
]);
$response = API::DiscoveryRule()->create($item);
if ($response === false) {
throw new Exception();
}
}
if (hasRequest('update')) {
$item = getSanitizedItemFields($input + $db_item + [
'flags' => ZBX_FLAG_DISCOVERY_RULE,
'hosts' => $hosts
]);
$response = API::DiscoveryRule()->update(['itemid' => $itemid] + $item);
if ($response === false) {
throw new Exception();
}
}
}
catch (Exception $e) {
$result = false;
}
if (hasRequest('add')) {
if ($result) {
CMessageHelper::setSuccessTitle(_('Discovery rule created'));
}
else {
CMessageHelper::setErrorTitle(_('Cannot add discovery rule'));
}
}
else {
if ($result) {
CMessageHelper::setSuccessTitle(_('Discovery rule updated'));
}
else {
CMessageHelper::setErrorTitle(_('Cannot update discovery rule'));
}
}
if ($result) {
unset($_REQUEST['itemid'], $_REQUEST['form']);
uncheckTableRows($checkbox_hash);
if (hasRequest('backurl')) {
$response = new CControllerResponseRedirect(getRequest('backurl'));
$response->redirect();
}
}
}
elseif (hasRequest('action') && str_in_array(getRequest('action'), ['discoveryrule.massenable', 'discoveryrule.massdisable']) && hasRequest('g_hostdruleid')) {
$itemids = getRequest('g_hostdruleid');
$status = (getRequest('action') === 'discoveryrule.massenable') ? ITEM_STATUS_ACTIVE : ITEM_STATUS_DISABLED;
$lld_rules = [];
foreach ($itemids as $itemid) {
$lld_rules[] = ['itemid' => $itemid, 'status' => $status];
}
$result = (bool) API::DiscoveryRule()->update($lld_rules);
if ($result) {
$filter_hostids ? uncheckTableRows($checkbox_hash) : uncheckTableRows();
}
$updated = count($itemids);
$messageSuccess = ($status == ITEM_STATUS_ACTIVE)
? _n('Discovery rule enabled', 'Discovery rules enabled', $updated)
: _n('Discovery rule disabled', 'Discovery rules disabled', $updated);
$messageFailed = ($status == ITEM_STATUS_ACTIVE)
? _n('Cannot enable discovery rule', 'Cannot enable discovery rules', $updated)
: _n('Cannot disable discovery rule', 'Cannot disable discovery rules', $updated);
show_messages($result, $messageSuccess, $messageFailed);
}
elseif (hasRequest('action') && getRequest('action') === 'discoveryrule.massdelete' && hasRequest('g_hostdruleid')) {
$result = API::DiscoveryRule()->delete(getRequest('g_hostdruleid'));
if ($result) {
$filter_hostids ? uncheckTableRows($checkbox_hash) : uncheckTableRows();
}
$host_drules_count = count(getRequest('g_hostdruleid'));
$messageSuccess = _n('Discovery rule deleted', 'Discovery rules deleted', $host_drules_count);
$messageFailed = _n('Cannot delete discovery rule', 'Cannot delete discovery rules', $host_drules_count);
show_messages($result, $messageSuccess, $messageFailed);
}
if (hasRequest('action') && hasRequest('g_hostdruleid') && !$result) {
$hostdrules = API::DiscoveryRule()->get([
'output' => [],
'itemids' => getRequest('g_hostdruleid'),
'editable' => true
]);
uncheckTableRows($checkbox_hash, zbx_objectValues($hostdrules, 'itemid'));
}
/*
* Display
*/
if (hasRequest('form')) {
$master_itemid = getRequest('master_itemid', 0);
if (hasRequest('itemid') && !hasRequest('clone')) {
$items = API::DiscoveryRule()->get([
'output' => API_OUTPUT_EXTEND,
'selectHosts' => ['hostid', 'name', 'status', 'flags'],
'selectFilter' => ['formula', 'evaltype', 'conditions'],
'selectLLDMacroPaths' => ['lld_macro', 'path'],
'selectPreprocessing' => ['type', 'params', 'error_handler', 'error_handler_params'],
'selectOverrides' => ['name', 'step', 'stop', 'filter', 'operations'],
'itemids' => $itemid
]);
$item = $items[0];
$host = $item['hosts'][0];
unset($item['hosts']);
if (!hasRequest('form_refresh')) {
$master_itemid = $item['master_itemid'];
}
}
else {
$item = [];
$host = $hosts[0];
}
if (getRequest('type', $item ? $item['type'] : null) == ITEM_TYPE_DEPENDENT && $master_itemid != 0) {
$db_master_items = API::Item()->get([
'output' => ['itemid', 'name'],
'itemids' => $master_itemid,
'webitems' => true
]);
if ($db_master_items) {
$item['master_item'] = $db_master_items[0];
}
}
$data = getItemFormData($item, ['form' => getRequest('form'), 'is_discovery_rule' => true]);
$data['lifetime'] = getRequest('lifetime', DB::getDefault('items', 'lifetime'));
$data['evaltype'] = getRequest('evaltype', CONDITION_EVAL_TYPE_AND_OR);
$data['formula'] = getRequest('formula');
$data['conditions'] = sortLldRuleFilterConditions(getRequest('conditions', []), $data['evaltype']);
$data['lld_macro_paths'] = getRequest('lld_macro_paths', []);
$data['overrides'] = getRequest('overrides', []);
$data['host'] = $hosts[0];
$data['preprocessing_test_type'] = CControllerPopupItemTestEdit::ZBX_TEST_TYPE_LLD;
$data['preprocessing_types'] = CDiscoveryRule::SUPPORTED_PREPROCESSING_TYPES;
$data['display_interfaces'] = in_array($hosts[0]['status'], [HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED]);
$data['backurl'] = getRequest('backurl');
if (!hasRequest('form_refresh')) {
$i = 0;
foreach ($data['preprocessing'] as &$step) {
if ($step['type'] == ZBX_PREPROC_SCRIPT) {
$step['params'] = [$step['params'], ''];
}
else {
$step['params'] = explode("\n", $step['params']);
}
$step['sortorder'] = $i++;
}
unset($step);
}
CArrayHelper::sort($data['preprocessing'], ['sortorder']);
// update form
if (hasRequest('itemid') && !getRequest('form_refresh')) {
$data['lifetime'] = $item['lifetime'];
$data['evaltype'] = $item['filter']['evaltype'];
$data['formula'] = $item['filter']['formula'];
$data['conditions'] = sortLldRuleFilterConditions($item['filter']['conditions'], $item['filter']['evaltype']);
$data['lld_macro_paths'] = $item['lld_macro_paths'];
$data['overrides'] = $item['overrides'];
// Sort overrides to be listed in step order.
CArrayHelper::sort($data['overrides'], ['step']);
}
// clone form
elseif (hasRequest('clone')) {
unset($data['itemid']);
$data['form'] = 'clone';
}
if (!$data['conditions']) {
$data['conditions'] = [[
'macro' => '',
'operator' => CONDITION_OPERATOR_REGEXP,
'value' => '',
'formulaid' => num2letter(0)
]];
}
if ($data['type'] != ITEM_TYPE_JMX) {
$data['jmx_endpoint'] = ZBX_DEFAULT_JMX_ENDPOINT;
}
$data['counter'] = null;
if (hasRequest('conditions')) {
$conditions = getRequest('conditions');
krsort($conditions);
$data['counter'] = key($conditions) + 1;
}
echo (new CView('configuration.host.discovery.edit', $data))->getOutput();
}
else {
$data = [
'filter' => $filter,
'hostid' => (count($filter_hostids) == 1) ? reset($filter_hostids) : 0,
'sort' => $sort_field,
'sortorder' => $sort_order,
'profileIdx' => $prefix.'host_discovery.filter',
'active_tab' => CProfile::get($prefix.'host_discovery.filter.active', 1),
'checkbox_hash' => $checkbox_hash,
'context' => getRequest('context')
];
// Select LLD rules.
$options = [
'output' => API_OUTPUT_EXTEND,
'selectHosts' => ['hostid', 'name', 'status', 'flags'],
'selectItems' => API_OUTPUT_COUNT,
'selectGraphs' => API_OUTPUT_COUNT,
'selectTriggers' => API_OUTPUT_COUNT,
'selectHostPrototypes' => API_OUTPUT_COUNT,
'editable' => true,
'templated' => ($data['context'] === 'template'),
'filter' => [],
'search' => [],
'sortfield' => $sort_field,
'limit' => CSettingsHelper::get(CSettingsHelper::SEARCH_LIMIT) + 1
];
if ($filter_groupids) {
$options['groupids'] = $filter_groupids;
}
if ($filter_hostids) {
$options['hostids'] = $filter_hostids;
}
if ($filter['name'] !== '') {
$options['search']['name'] = $filter['name'];
}
if ($filter['key'] !== '') {
$options['search']['key_'] = $filter['key'];
}
if ($filter['type'] != -1) {
$options['filter']['type'] = $filter['type'];
}
/*
* Trapper and SNMP trap items contain zeros in "delay" field and, if no specific type is set, look in item types
* other than trapper and SNMP trap that allow zeros. For example, when a flexible interval is used. Since trapper
* and SNMP trap items contain zeros, but those zeros should not be displayed, they cannot be filtered by entering
* either zero or any other number in filter field.
*/
if ($filter['delay'] !== '') {
if ($filter['type'] == -1 && $filter['delay'] == 0) {
$options['filter']['type'] = [ITEM_TYPE_ZABBIX, ITEM_TYPE_SIMPLE, ITEM_TYPE_INTERNAL,
ITEM_TYPE_ZABBIX_ACTIVE, ITEM_TYPE_EXTERNAL, ITEM_TYPE_DB_MONITOR, ITEM_TYPE_IPMI,
ITEM_TYPE_SSH, ITEM_TYPE_TELNET, ITEM_TYPE_JMX
];
$options['filter']['delay'] = $filter['delay'];
}
elseif ($filter['type'] == ITEM_TYPE_TRAPPER || $filter['type'] == ITEM_TYPE_DEPENDENT
|| ($filter['type'] == ITEM_TYPE_ZABBIX_ACTIVE && strncmp($filter['key'], 'mqtt.get', 8) === 0)) {
$options['filter']['delay'] = -1;
}
else {
$options['filter']['delay'] = $filter['delay'];
}
}
if ($filter['lifetime'] !== '') {
$options['filter']['lifetime'] = $filter['lifetime'];
}
if ($filter['snmp_oid'] !== '') {
$options['filter']['snmp_oid'] = $filter['snmp_oid'];
}
if ($filter['status'] != -1) {
$options['filter']['status'] = $filter['status'];
}
if ($filter['state'] != -1) {
$options['filter']['status'] = ITEM_STATUS_ACTIVE;
$options['filter']['state'] = $filter['state'];
}
$data['discoveries'] = API::DiscoveryRule()->get($options);
switch ($sort_field) {
case 'delay':
orderItemsByDelay($data['discoveries'], $sort_order, ['usermacros' => true]);
break;
case 'status':
orderItemsByStatus($data['discoveries'], $sort_order);
break;
default:
order_result($data['discoveries'], $sort_field, $sort_order);
}
$data['discoveries'] = expandItemNamesWithMasterItems($data['discoveries'], 'items');
// pager
if (hasRequest('page')) {
$page_num = getRequest('page');
}
elseif (isRequestMethod('get') && !hasRequest('cancel')) {
$page_num = 1;
}
else {
$page_num = CPagerHelper::loadPage($page['file']);
}
CPagerHelper::savePage($page['file'], $page_num);
$data['paging'] = CPagerHelper::paginate($page_num, $data['discoveries'], $sort_order,
(new CUrl('host_discovery.php'))->setArgument('context', $data['context'])
);
$data['parent_templates'] = getItemParentTemplates($data['discoveries'], ZBX_FLAG_DISCOVERY_RULE);
$data['allowed_ui_conf_templates'] = CWebUser::checkAccess(CRoleHelper::UI_CONFIGURATION_TEMPLATES);
// render view
echo (new CView('configuration.host.discovery.list', $data))->getOutput();
}
require_once dirname(__FILE__).'/include/page_footer.php';