protected function doAction() { $sortField = $this->getInput('sort', CProfile::get('web.proxies.php.sort', 'host')); $sortOrder = $this->getInput('sortorder', CProfile::get('web.proxies.php.sortorder', ZBX_SORT_UP)); CProfile::update('web.proxies.php.sort', $sortField, PROFILE_TYPE_STR); CProfile::update('web.proxies.php.sortorder', $sortOrder, PROFILE_TYPE_STR); $config = select_config(); $data = ['uncheck' => $this->hasInput('uncheck'), 'sort' => $sortField, 'sortorder' => $sortOrder, 'config' => ['max_in_table' => $config['max_in_table']]]; $data['proxies'] = API::Proxy()->get(['output' => ['proxyid', 'host', 'status', 'lastaccess', 'tls_connect', 'tls_accept'], 'selectHosts' => ['hostid', 'name', 'status'], 'sortfield' => $sortField, 'limit' => $config['search_limit'] + 1, 'editable' => true, 'preservekeys' => true]); // sorting & paging order_result($data['proxies'], $sortField, $sortOrder); $url = (new CUrl('zabbix.php'))->setArgument('action', 'proxy.list'); $data['paging'] = getPagingLine($data['proxies'], $sortOrder, $url); foreach ($data['proxies'] as &$proxy) { order_result($proxy['hosts'], 'name'); } unset($proxy); // get proxy IDs for a *selected* page $proxyIds = array_keys($data['proxies']); if ($proxyIds) { // calculate performance $dbPerformance = DBselect('SELECT h.proxy_hostid,SUM(1.0/i.delay) AS qps' . ' FROM hosts h,items i' . ' WHERE h.hostid=i.hostid' . ' AND h.status=' . HOST_STATUS_MONITORED . ' AND i.status=' . ITEM_STATUS_ACTIVE . ' AND i.delay<>0' . ' AND i.flags<>' . ZBX_FLAG_DISCOVERY_PROTOTYPE . ' AND ' . dbConditionInt('h.proxy_hostid', $proxyIds) . ' GROUP BY h.proxy_hostid'); while ($performance = DBfetch($dbPerformance)) { $data['proxies'][$performance['proxy_hostid']]['perf'] = round($performance['qps'], 2); } // get items $items = API::Item()->get(['proxyids' => $proxyIds, 'groupCount' => true, 'countOutput' => true, 'webitems' => true, 'monitored' => true]); foreach ($items as $item) { $data['proxies'][$item['proxy_hostid']]['item_count'] = $item['rowscount']; } } $response = new CControllerResponseData($data); $response->setTitle(_('Configuration of proxies')); $this->setResponse($response); }
protected function doAction() { $proxy = []; $this->getInputs($proxy, ['host', 'status', 'description', 'tls_connect', 'tls_accept', 'tls_issuer', 'tls_subject', 'tls_psk_identity', 'tls_psk']); if ($this->getInput('status', HOST_STATUS_PROXY_ACTIVE) == HOST_STATUS_PROXY_PASSIVE) { $proxy['interface'] = []; $this->getInputs($proxy['interface'], ['dns', 'ip', 'useip', 'port']); } DBstart(); if ($this->hasInput('proxy_hostids')) { // skip discovered hosts $proxy['hosts'] = API::Host()->get(['output' => ['hostid'], 'hostids' => $this->getInput('proxy_hostids'), 'filter' => ['flags' => ZBX_FLAG_DISCOVERY_NORMAL]]); } $result = API::Proxy()->create([$proxy]); if ($result) { add_audit(AUDIT_ACTION_ADD, AUDIT_RESOURCE_PROXY, '[' . $this->getInput('host', '') . '] [' . reset($result['proxyids']) . ']'); } $result = DBend($result); if ($result) { $response = new CControllerResponseRedirect('zabbix.php?action=proxy.list&uncheck=1'); $response->setMessageOk(_('Proxy added')); } else { $response = new CControllerResponseRedirect('zabbix.php?action=proxy.edit'); $response->setFormData($this->getInputAll()); $response->setMessageError(_('Cannot add proxy')); } $this->setResponse($response); }
protected function checkPermissions() { if ($this->getUserType() != USER_TYPE_SUPER_ADMIN) { return false; } $proxies = API::Proxy()->get(['proxyids' => $this->getInput('proxyids'), 'countOutput' => true, 'editable' => true]); return $proxies == count($this->getInput('proxyids')); }
protected function doAction() { // default values $data = ['sid' => $this->getUserSID(), 'proxyid' => 0, 'host' => '', 'status' => HOST_STATUS_PROXY_ACTIVE, 'dns' => 'localhost', 'ip' => '127.0.0.1', 'useip' => '1', 'port' => '10051', 'proxy_hostids' => [], 'description' => '', 'tls_accept' => HOST_ENCRYPTION_NONE, 'tls_connect' => HOST_ENCRYPTION_NONE, 'tls_issuer' => '', 'tls_psk' => '', 'tls_psk_identity' => '', 'tls_subject' => '', 'form_refresh' => 0]; // get values from the dabatase if ($this->hasInput('proxyid')) { $data['proxyid'] = $this->getInput('proxyid'); $proxies = API::Proxy()->get(['output' => ['host', 'status', 'description', 'tls_connect', 'tls_accept', 'tls_issuer', 'tls_subject', 'tls_psk_identity', 'tls_psk'], 'selectHosts' => ['hostid'], 'selectInterface' => ['interfaceid', 'dns', 'ip', 'useip', 'port'], 'proxyids' => $data['proxyid']]); $proxy = $proxies[0]; $data['host'] = $proxy['host']; $data['status'] = $proxy['status']; $data['tls_accept'] = $proxy['tls_accept']; $data['tls_connect'] = $proxy['tls_connect']; $data['tls_issuer'] = $proxy['tls_issuer']; $data['tls_psk'] = $proxy['tls_psk']; $data['tls_psk_identity'] = $proxy['tls_psk_identity']; $data['tls_subject'] = $proxy['tls_subject']; if ($data['status'] == HOST_STATUS_PROXY_PASSIVE) { $data['interfaceid'] = $proxy['interface']['interfaceid']; $data['dns'] = $proxy['interface']['dns']; $data['ip'] = $proxy['interface']['ip']; $data['useip'] = $proxy['interface']['useip']; $data['port'] = $proxy['interface']['port']; } $data['proxy_hostids'] = zbx_objectValues($proxy['hosts'], 'hostid'); $data['description'] = $proxy['description']; } // overwrite with input variables $data['host'] = $this->getInput('host', $data['host']); $data['status'] = $this->getInput('status', $data['status']); $data['dns'] = $this->getInput('dns', $data['dns']); $data['ip'] = $this->getInput('ip', $data['ip']); $data['useip'] = $this->getInput('useip', $data['useip']); $data['port'] = $this->getInput('port', $data['port']); $data['proxy_hostids'] = $this->getInput('proxy_hostids', $data['proxy_hostids']); $data['description'] = $this->getInput('description', $data['description']); $data['tls_accept'] = $this->getInput('tls_accept', $data['tls_accept']); $data['tls_connect'] = $this->getInput('tls_connect', $data['tls_connect']); $data['tls_issuer'] = $this->getInput('tls_issuer', $data['tls_issuer']); $data['tls_psk'] = $this->getInput('tls_psk', $data['tls_psk']); $data['tls_psk_identity'] = $this->getInput('tls_psk_identity', $data['tls_psk_identity']); $data['tls_subject'] = $this->getInput('tls_subject', $data['tls_subject']); $data['form_refresh'] = $this->getInput('form_refresh', $data['form_refresh']); if ($data['status'] == HOST_STATUS_PROXY_PASSIVE && $this->hasInput('interfaceid')) { $data['interfaceid'] = $this->getInput('interfaceid'); } // fetch available hosts, skip host prototypes $data['all_hosts'] = DBfetchArray(DBselect('SELECT h.hostid,h.proxy_hostid,h.name,h.flags' . ' FROM hosts h' . ' WHERE h.status IN (' . HOST_STATUS_MONITORED . ',' . HOST_STATUS_NOT_MONITORED . ')' . ' AND h.flags<>' . ZBX_FLAG_DISCOVERY_PROTOTYPE)); order_result($data['all_hosts'], 'name'); $response = new CControllerResponseData($data); $response->setTitle(_('Configuration of proxies')); $this->setResponse($response); }
protected function doAction() { $proxyids = $this->getInput('proxyids'); $result = API::Proxy()->delete($proxyids); $deleted = count($proxyids); $response = new CControllerResponseRedirect('zabbix.php?action=proxy.list&uncheck=1'); if ($result) { $response->setMessageOk(_n('Proxy deleted', 'Proxies deleted', $deleted)); } else { $response->setMessageError(_n('Cannot delete proxy', 'Cannot delete proxies', $deleted)); } $this->setResponse($response); }
public static function parseMain($rules) { $triggersForDependencies = array(); if (!empty($rules['hosts']['updateExisting']) || !empty($rules['hosts']['createMissing']) || !empty($rules['templates']['createMissing']) || !empty($rules['templates']['updateExisting'])) { $xpath = new DOMXPath(self::$xml); $hosts = $xpath->query('hosts/host'); foreach ($hosts as $host) { $host_db = self::mapXML2arr($host, XML_TAG_HOST); if (!isset($host_db['status'])) { $host_db['status'] = HOST_STATUS_TEMPLATE; } $current_host = $host_db['status'] == HOST_STATUS_TEMPLATE ? API::Template()->exists($host_db) : API::Host()->exists($host_db); if (!$current_host && ($host_db['status'] == HOST_STATUS_TEMPLATE && empty($rules['templates']['createMissing']) || $host_db['status'] != HOST_STATUS_TEMPLATE && empty($rules['hosts']['createMissing']))) { continue; } if ($current_host && ($host_db['status'] == HOST_STATUS_TEMPLATE && empty($rules['templates']['updateExisting']) || $host_db['status'] != HOST_STATUS_TEMPLATE && empty($rules['hosts']['updateExisting']))) { continue; } // there were no host visible names in 1.8 if (!isset($host_db['name'])) { $host_db['name'] = $host_db['host']; } // host will have no interfaces - we will be creating them separately $host_db['interfaces'] = null; // it is possible, that data is imported from 1.8, where there was only one network interface per host /** * @todo when new XML format will be introduced, this check should be changed to XML version check */ $old_version_input = $host_db['status'] != HOST_STATUS_TEMPLATE; if ($old_version_input) { // rearranging host structure, so it would look more like 2.0 host $interfaces = array(); // the main interface is always "agent" type if (!is_null($host_db['ip'])) { $interfaces[] = array('main' => INTERFACE_PRIMARY, 'type' => INTERFACE_TYPE_AGENT, 'useip' => $host_db['useip'], 'ip' => $host_db['ip'], 'dns' => $host_db['dns'], 'port' => $host_db['port']); } // now we need to check if host had SNMP items. If it had, we need and SNMP interface for every different port. $items = $xpath->query('items/item', $host); $snmp_interface_ports_created = array(); foreach ($items as $item) { $item_db = self::mapXML2arr($item, XML_TAG_ITEM); if (($item_db['type'] == ITEM_TYPE_SNMPV1 || $item_db['type'] == ITEM_TYPE_SNMPV2C || $item_db['type'] == ITEM_TYPE_SNMPV3) && !isset($snmp_interface_ports_created[$item_db['snmp_port']])) { $interfaces[] = array('main' => INTERFACE_PRIMARY, 'type' => INTERFACE_TYPE_SNMP, 'useip' => $host_db['useip'], 'ip' => $host_db['ip'], 'dns' => $host_db['dns'], 'port' => $item_db['snmp_port']); $snmp_interface_ports_created[$item_db['snmp_port']] = 1; } } unset($snmp_interface_ports_created); // it was a temporary variable // we ned to add ipmi interface if at least one ipmi item exists foreach ($items as $item) { $item_db = self::mapXML2arr($item, XML_TAG_ITEM); if ($item_db['type'] == ITEM_TYPE_IPMI) { // when saving a host in 1.8, it's possible to set useipmi=1 and not to fill an IP address // we were not really sure what to do with this host, // and decided to take host IP address instead and show info message about this if ($host_db['ipmi_ip'] == '') { $ipmi_ip = $host_db['ip']; info(_s('Host "%s" has "useipmi" parameter checked, but has no "ipmi_ip" parameter! Using host IP address as an address for IPMI interface.', $host_db['host'])); } else { $ipmi_ip = $host_db['ipmi_ip']; } $interfaces[] = array('main' => INTERFACE_PRIMARY, 'type' => INTERFACE_TYPE_IPMI, 'useip' => INTERFACE_USE_DNS, 'ip' => '', 'dns' => $ipmi_ip, 'port' => $host_db['ipmi_port']); // we need only one ipmi interface break; } } } if ($current_host) { $options = array('filter' => array('host' => $host_db['host']), 'output' => API_OUTPUT_EXTEND, 'editable' => 1, 'selectInterfaces' => API_OUTPUT_EXTEND); if ($host_db['status'] == HOST_STATUS_TEMPLATE) { $current_host = API::Template()->get($options); } else { $current_host = API::Host()->get($options); } if (empty($current_host)) { throw new Exception(_s('No permission for host "%1$s".', $host_db['host'])); } else { $current_host = reset($current_host); } // checking if host already exists - then some of the interfaces may not need to be created if ($host_db['status'] != HOST_STATUS_TEMPLATE) { // for every interface we got based on XML foreach ($interfaces as $i => $interface_db) { // checking every interface of current host foreach ($current_host['interfaces'] as $interface) { // if all parameters of interface are identical if ($interface['type'] == $interface_db['type'] && $interface['ip'] == $interface_db['ip'] && $interface['dns'] == $interface_db['dns'] && $interface['port'] == $interface_db['port'] && $interface['useip'] == $interface_db['useip']) { // this interface is the same as existing one! $interfaces[$i]['interfaceid'] = $interface['interfaceid']; break; } } } } $interfaces_created_with_host = false; } else { if ($host_db['status'] != HOST_STATUS_TEMPLATE) { $host_db['interfaces'] = $interfaces; $interfaces_created_with_host = true; } } // HOST GROUPS {{{ $groups = $xpath->query('groups/group', $host); $host_db['groups'] = array(); $groups_to_parse = array(); foreach ($groups as $group) { $groups_to_parse[] = array('name' => $group->nodeValue); } if (empty($groups_to_parse)) { $groups_to_parse[] = array('name' => ZBX_DEFAULT_IMPORT_HOST_GROUP); } foreach ($groups_to_parse as $group) { $current_group = API::HostGroup()->exists($group); if ($current_group) { $options = array('filter' => $group, 'output' => API_OUTPUT_EXTEND, 'editable' => 1); $current_group = API::HostGroup()->get($options); if (empty($current_group)) { throw new Exception(_s('No permissions for group "%1$s".', $group['name'])); } $host_db['groups'][] = reset($current_group); } else { $result = API::HostGroup()->create($group); if (!$result) { throw new Exception(); } $options = array('groupids' => $result['groupids'], 'output' => API_OUTPUT_EXTEND); $new_group = API::HostGroup()->get($options); $host_db['groups'][] = reset($new_group); } } // }}} HOST GROUPS // MACROS $macros = $xpath->query('macros/macro', $host); if ($macros->length > 0) { $host_db['macros'] = array(); foreach ($macros as $macro) { $host_db['macros'][] = self::mapXML2arr($macro, XML_TAG_MACRO); } } // }}} MACROS // host inventory if ($old_version_input) { if (!isset($host_db['inventory'])) { $host_db['inventory'] = array(); } $inventoryNode = $xpath->query('host_profile/*', $host); if ($inventoryNode->length > 0) { foreach ($inventoryNode as $field) { $newInventoryName = self::mapInventoryName($field->nodeName); $host_db['inventory'][$newInventoryName] = $field->nodeValue; } } $inventoryNodeExt = $xpath->query('host_profiles_ext/*', $host); if ($inventoryNodeExt->length > 0) { foreach ($inventoryNodeExt as $field) { $newInventoryName = self::mapInventoryName($field->nodeName); if (isset($host_db['inventory'][$newInventoryName]) && $field->nodeValue !== '') { $host_db['inventory'][$newInventoryName] .= "\r\n\r\n"; $host_db['inventory'][$newInventoryName] .= $field->nodeValue; } else { $host_db['inventory'][$newInventoryName] = $field->nodeValue; } } } $host_db['inventory_mode'] = isset($host_db['inventory']) ? HOST_INVENTORY_MANUAL : HOST_INVENTORY_DISABLED; } // HOSTS if (isset($host_db['proxy_hostid'])) { $proxy_exists = API::Proxy()->get(array('proxyids' => $host_db['proxy_hostid'])); if (empty($proxy_exists)) { $host_db['proxy_hostid'] = 0; } } if ($current_host && (!empty($rules['hosts']['updateExisting']) || !empty($rules['templates']['updateExisting']))) { if ($host_db['status'] == HOST_STATUS_TEMPLATE) { $host_db['templateid'] = $current_host['templateid']; $result = API::Template()->update($host_db); $current_hostid = $current_host['templateid']; } else { $host_db['hostid'] = $current_host['hostid']; $result = API::Host()->update($host_db); $current_hostid = $current_host['hostid']; } if (!$result) { throw new Exception(); } } if (!$current_host && (!empty($rules['hosts']['createMissing']) || !empty($rules['templates']['createMissing']))) { if ($host_db['status'] == HOST_STATUS_TEMPLATE) { $result = API::Template()->create($host_db); if (!$result) { throw new Exception(); } $current_hostid = reset($result['templateids']); } else { $result = API::Host()->create($host_db); if (!$result) { throw new Exception(); } $current_hostid = reset($result['hostids']); } } $current_hostname = $host_db['host']; // TEMPLATES {{{ if (!empty($rules['templateLinkage']['createMissing'])) { $templates = $xpath->query('templates/template', $host); $templateLinkage = array(); foreach ($templates as $template) { $options = array('filter' => array('host' => $template->nodeValue), 'output' => array('templateid'), 'editable' => true); $current_template = API::Template()->get($options); if (empty($current_template)) { throw new Exception(_s('No permission for template "%1$s".', $template->nodeValue)); } $current_template = reset($current_template); $templateLinkage[] = $current_template; } if ($templateLinkage) { $result = API::Template()->massAdd(array('hosts' => array('hostid' => $current_hostid), 'templates' => $templateLinkage)); if (!$result) { throw new Exception(); } } } // }}} TEMPLATES // ITEMS {{{ if (!empty($rules['items']['updateExisting']) || !empty($rules['items']['createMissing'])) { $items = $xpath->query('items/item', $host); // if this is an export from 1.8, we need to make some adjustments to items if ($old_version_input) { if (!$interfaces_created_with_host) { // if host had another interfaces, we are not touching them: they remain as is foreach ($interfaces as $i => $interface) { // interface was not already created if (!isset($interface['interfaceid'])) { // creating interface $interface['hostid'] = $current_hostid; $ids = API::HostInterface()->create($interface); if ($ids === false) { throw new Exception(); } $interfaces[$i]['interfaceid'] = reset($ids['interfaceids']); } } } else { $options = array('hostids' => $current_hostid, 'output' => API_OUTPUT_EXTEND); $interfaces = API::HostInterface()->get($options); } // we must know interface ids to assign them to items $agent_interface_id = null; $ipmi_interface_id = null; $snmp_interfaces = array(); // hash 'port' => 'iterfaceid' foreach ($interfaces as $interface) { switch ($interface['type']) { case INTERFACE_TYPE_AGENT: $agent_interface_id = $interface['interfaceid']; break; case INTERFACE_TYPE_IPMI: $ipmi_interface_id = $interface['interfaceid']; break; case INTERFACE_TYPE_SNMP: $snmp_interfaces[$interface['port']] = $interface['interfaceid']; break; } } } foreach ($items as $item) { $item_db = self::mapXML2arr($item, XML_TAG_ITEM); $item_db['hostid'] = $current_hostid; // item needs interfaces if ($old_version_input) { // 'snmp_port' column was renamed to 'port' if ($item_db['snmp_port'] != 0) { // zabbix agent items have no ports $item_db['port'] = $item_db['snmp_port']; } unset($item_db['snmp_port']); // assigning appropriate interface depending on item type switch ($item_db['type']) { // zabbix agent interface case ITEM_TYPE_ZABBIX: case ITEM_TYPE_SIMPLE: case ITEM_TYPE_EXTERNAL: case ITEM_TYPE_SSH: case ITEM_TYPE_TELNET: $item_db['interfaceid'] = $agent_interface_id; break; // snmp interface // snmp interface case ITEM_TYPE_SNMPV1: case ITEM_TYPE_SNMPV2C: case ITEM_TYPE_SNMPV3: // for an item with different port - different interface $item_db['interfaceid'] = $snmp_interfaces[$item_db['port']]; break; case ITEM_TYPE_IPMI: $item_db['interfaceid'] = $ipmi_interface_id; break; // no interfaces required for these item types // no interfaces required for these item types case ITEM_TYPE_HTTPTEST: case ITEM_TYPE_CALCULATED: case ITEM_TYPE_AGGREGATE: case ITEM_TYPE_INTERNAL: case ITEM_TYPE_ZABBIX_ACTIVE: case ITEM_TYPE_TRAPPER: case ITEM_TYPE_DB_MONITOR: $item_db['interfaceid'] = null; break; } $item_db['key_'] = self::convertOldSimpleKey($item_db['key_']); } $options = array('filter' => array('hostid' => $item_db['hostid'], 'key_' => $item_db['key_']), 'webitems' => 1, 'output' => API_OUTPUT_EXTEND, 'editable' => 1); $current_item = API::Item()->get($options); $current_item = reset($current_item); if (!$current_item && empty($rules['items']['createMissing'])) { info(_s('Item "%1$s" skipped - user rule.', $item_db['key_'])); continue; // break if not update updateExisting } if ($current_item && empty($rules['items']['updateExisting'])) { info(_s('Item "%1$s" skipped - user rule.', $item_db['key_'])); continue; // break if not update updateExisting } // ITEM APPLICATIONS {{{ $applications = $xpath->query('applications/application', $item); $item_applications = array(); $applications_to_add = array(); $applicationsIds = array(); foreach ($applications as $application) { $application_db = array('name' => $application->nodeValue, 'hostid' => $current_hostid); $current_application = API::Application()->get(array('filter' => $application_db, 'output' => API_OUTPUT_EXTEND)); $applicationValue = reset($current_application); if ($current_application) { if (empty($item_applications)) { $item_applications = $current_application; $applicationsIds[] = $applicationValue['applicationid']; } else { if (!in_array($applicationValue['applicationid'], $applicationsIds)) { $item_applications = array_merge($item_applications, $current_application); $applicationsIds[] = $applicationValue['applicationid']; } } } else { $applications_to_add[] = $application_db; } } if (!empty($applications_to_add)) { $result = API::Application()->create($applications_to_add); if (!$result) { throw new Exception(); } $options = array('applicationids' => $result['applicationids'], 'output' => API_OUTPUT_EXTEND); $new_applications = API::Application()->get($options); $item_applications = array_merge($item_applications, $new_applications); } // }}} ITEM APPLICATIONS if ($current_item && !empty($rules['items']['updateExisting'])) { $item_db['itemid'] = $current_item['itemid']; $result = API::Item()->update($item_db); if (!$result) { throw new Exception(); } $options = array('itemids' => $result['itemids'], 'webitems' => 1, 'output' => API_OUTPUT_EXTEND); $current_item = API::Item()->get($options); } if (!$current_item && !empty($rules['items']['createMissing'])) { $result = API::Item()->create($item_db); if (!$result) { throw new Exception(); } $options = array('itemids' => $result['itemids'], 'webitems' => 1, 'output' => API_OUTPUT_EXTEND); $current_item = API::Item()->get($options); } if (!empty($item_applications)) { $r = API::Application()->massAdd(array('applications' => $item_applications, 'items' => $current_item)); if ($r === false) { throw new Exception(); } } } } // }}} ITEMS // TRIGGERS {{{ if (!empty($rules['triggers']['updateExisting']) || !empty($rules['triggers']['createMissing'])) { $triggers = $xpath->query('triggers/trigger', $host); $triggers_to_add = array(); $triggers_to_upd = array(); foreach ($triggers as $trigger) { $trigger_db = self::mapXML2arr($trigger, XML_TAG_TRIGGER); if ($old_version_input) { $expressionPart = explode(':', $trigger_db['expression']); $keyName = explode(',', $expressionPart[1], 2); if (count($keyName) == 2) { $keyValue = explode('.', $keyName[1], 2); $key = $keyName[0] . "," . $keyValue[0]; if (in_array($keyName[0], self::$oldKeys) || in_array($keyName[0], self::$oldKeysPref)) { $trigger_db['expression'] = str_replace($key, self::convertOldSimpleKey($key), $trigger_db['expression']); } } } // {HOSTNAME} is here for backward compatibility $trigger_db['expression'] = str_replace('{{HOSTNAME}:', '{' . $host_db['host'] . ':', $trigger_db['expression']); $trigger_db['expression'] = str_replace('{{HOST.HOST}:', '{' . $host_db['host'] . ':', $trigger_db['expression']); $trigger_db['hostid'] = $current_hostid; if ($current_trigger = API::Trigger()->exists($trigger_db)) { $ctriggers = API::Trigger()->get(array('filter' => array('description' => $trigger_db['description']), 'hostids' => $current_hostid, 'output' => API_OUTPUT_EXTEND, 'editable' => 1)); $current_trigger = false; foreach ($ctriggers as $ct) { $tmp_exp = explode_exp($ct['expression']); if (strcmp($trigger_db['expression'], $tmp_exp) == 0) { $current_trigger = $ct; break; } } if (!$current_trigger) { throw new Exception(_s('No permission for trigger "%s".', $trigger_db['description'])); } } unset($trigger_db['hostid']); if (!$current_trigger && empty($rules['triggers']['createMissing'])) { info(_s('Trigger "%1$s" skipped - user rule.', $trigger_db['description'])); continue; // break if not update updateExisting } if ($current_trigger && empty($rules['triggers']['updateExisting'])) { info(_s('Trigger "%1$s" skipped - user rule.', $trigger_db['description'])); continue; // break if not update updateExisting } if ($current_trigger && !empty($rules['triggers']['updateExisting'])) { $trigger_db['triggerid'] = $current_trigger['triggerid']; $triggers_to_upd[] = $trigger_db; } if (!$current_trigger && !empty($rules['triggers']['createMissing'])) { $triggers_to_add[] = $trigger_db; } } if (!empty($triggers_to_upd)) { $result = API::Trigger()->update($triggers_to_upd); if (!$result) { throw new Exception(); } $options = array('triggerids' => $result['triggerids'], 'output' => API_OUTPUT_EXTEND); $r = API::Trigger()->get($options); $triggersForDependencies = array_merge($triggersForDependencies, $r); } if (!empty($triggers_to_add)) { $result = API::Trigger()->create($triggers_to_add); if (!$result) { throw new Exception(); } $options = array('triggerids' => $result['triggerids'], 'output' => API_OUTPUT_EXTEND); $r = API::Trigger()->get($options); $triggersForDependencies = array_merge($triggersForDependencies, $r); } } // }}} TRIGGERS // GRAPHS {{{ if (!empty($rules['graphs']['updateExisting']) || !empty($rules['graphs']['createMissing'])) { $graphs = $xpath->query('graphs/graph', $host); $graphs_to_add = array(); $graphs_to_upd = array(); foreach ($graphs as $graph) { // GRAPH ITEMS {{{ $gitems = $xpath->query('graph_elements/graph_element', $graph); $graph_hostids = array(); $graph_items = array(); foreach ($gitems as $gitem) { $gitem_db = self::mapXML2arr($gitem, XML_TAG_GRAPH_ELEMENT); $data = explode(':', $gitem_db['host_key_']); $gitem_host = array_shift($data); // {HOSTNAME} is here for backward compatibility $gitem_db['host'] = $gitem_host == '{HOSTNAME}' ? $host_db['host'] : $gitem_host; $gitem_db['host'] = $gitem_host == '{HOST.HOST}' ? $host_db['host'] : $gitem_host; if ($old_version_input) { $data[0] = self::convertOldSimpleKey($data[0]); } $gitem_db['key_'] = implode(':', $data); if ($current_item = API::Item()->exists($gitem_db)) { $current_item = API::Item()->get(array('filter' => array('key_' => $gitem_db['key_']), 'webitems' => 1, 'host' => $gitem_db['host'], 'output' => API_OUTPUT_EXTEND, 'editable' => 1)); if (empty($current_item)) { throw new Exception(_s('No permission for item "%1$s".', $gitem_db['key_'])); } $current_item = reset($current_item); $graph_hostids[] = $current_item['hostid']; $gitem_db['itemid'] = $current_item['itemid']; $graph_items[] = $gitem_db; } else { throw new Exception(_s('Item "%1$s" does not exist.', $gitem_db['host_key_'])); } } // }}} GRAPH ITEMS $graph_db = self::mapXML2arr($graph, XML_TAG_GRAPH); $graph_db['hostids'] = $graph_hostids; // do we need to show the graph legend, after it is imported? // in 1.8, this setting was present only for pie and exploded graphs // for other graph types we are always showing the legend if ($graph_db['graphtype'] != GRAPH_TYPE_PIE && $graph_db['graphtype'] != GRAPH_TYPE_EXPLODED) { $graph_db['show_legend'] = 1; } $current_graph = API::Graph()->exists($graph_db); if ($current_graph) { $current_graph = API::Graph()->get(array('filter' => array('name' => $graph_db['name']), 'hostids' => $graph_db['hostids'], 'output' => API_OUTPUT_EXTEND, 'editable' => 1)); if (empty($current_graph)) { throw new Exception(_s('No permission for graph "%1$s".', $graph_db['name'])); } $current_graph = reset($current_graph); } if (!$current_graph && empty($rules['graphs']['createMissing'])) { info(_s('Graph "%1$s" skipped - user rule.', $graph_db['name'])); continue; // break if not update updateExisting } if ($current_graph && empty($rules['graphs']['updateExisting'])) { info(_s('Graph "%1$s" skipped - user rule.', $graph_db['name'])); continue; // break if not update updateExisting } if (!isset($graph_db['ymin_type'])) { throw new Exception(_s('No "ymin_type" field for graph "%s".', $graph_db['name'])); } if (!isset($graph_db['ymax_type'])) { throw new Exception(_s('No "ymax_type" field for graph "%s".', $graph_db['name'])); } if ($graph_db['ymin_type'] == GRAPH_YAXIS_TYPE_ITEM_VALUE) { $item_data = explode(':', $graph_db['ymin_item_key'], 2); if (count($item_data) < 2) { throw new Exception(_s('Incorrect y min item for graph "%1$s".', $graph_db['name'])); } if (!($item = get_item_by_key($item_data[1], $item_data[0]))) { throw new Exception(_s('Missing item "%1$s" for host "%2$s".', $graph_db['ymin_item_key'], $host_db['host'])); } $graph_db['ymin_itemid'] = $item['itemid']; } if ($graph_db['ymax_type'] == GRAPH_YAXIS_TYPE_ITEM_VALUE) { $item_data = explode(':', $graph_db['ymax_item_key'], 2); if (count($item_data) < 2) { throw new Exception(_s('Incorrect y max item for graph "%1$s".', $graph_db['name'])); } if (!($item = get_item_by_key($item_data[1], $item_data[0]))) { throw new Exception(_s('Missing item "%1$s" for host "%2$s".', $graph_db['ymax_item_key'], $host_db['host'])); } $graph_db['ymax_itemid'] = $item['itemid']; } $graph_db['gitems'] = $graph_items; if ($current_graph) { $graph_db['graphid'] = $current_graph['graphid']; $graphs_to_upd[] = $graph_db; } else { $graphs_to_add[] = $graph_db; } } if (!empty($graphs_to_add)) { $r = API::Graph()->create($graphs_to_add); if ($r === false) { throw new Exception(); } } if (!empty($graphs_to_upd)) { $r = API::Graph()->update($graphs_to_upd); if ($r === false) { throw new Exception(); } } } // SCREENS if (!empty($rules['screens']['updateExisting']) || !empty($rules['screens']['createMissing'])) { $screens_node = $xpath->query('screens', $host); if ($screens_node->length > 0) { $importScreens = self::XMLtoArray($screens_node->item(0)); foreach ($importScreens as $screen) { $current_screen = API::TemplateScreen()->get(array('filter' => array('name' => $screen['name']), 'templateids' => $current_hostid, 'output' => API_OUTPUT_EXTEND, 'editable' => 1)); $current_screen = reset($current_screen); if (!$current_screen && empty($rules['screens']['createMissing'])) { info(_s('Screen "%1$s" skipped - user rule.', $screen['name'])); continue; } if ($current_screen && empty($rules['screens']['updateExisting'])) { info(_s('Screen "%1$s" skipped - user rule.', $screen['name'])); continue; } if (isset($screen['screenitems'])) { foreach ($screen['screenitems'] as &$screenitem) { $nodeCaption = isset($screenitem['resourceid']['node']) ? $screenitem['resourceid']['node'] . ':' : ''; if (!isset($screenitem['resourceid'])) { $screenitem['resourceid'] = 0; } if (is_array($screenitem['resourceid'])) { switch ($screenitem['resourcetype']) { case SCREEN_RESOURCE_GRAPH: $db_graphs = API::Graph()->getObjects($screenitem['resourceid']); if (empty($db_graphs)) { $error = _s('Cannot find graph "%1$s" used in screen "%2$s".', $nodeCaption . $screenitem['resourceid']['host'] . ':' . $screenitem['resourceid']['name'], $screen['name']); throw new Exception($error); } $tmp = reset($db_graphs); $screenitem['resourceid'] = $tmp['graphid']; break; case SCREEN_RESOURCE_SIMPLE_GRAPH: case SCREEN_RESOURCE_PLAIN_TEXT: $db_items = API::Item()->getObjects($screenitem['resourceid']); if (empty($db_items)) { $error = _s('Cannot find item "%1$s" used in screen "%2$s".', $nodeCaption . $screenitem['resourceid']['host'] . ':' . $screenitem['resourceid']['key_'], $screen['name']); throw new Exception($error); } $tmp = reset($db_items); $screenitem['resourceid'] = $tmp['itemid']; break; default: $screenitem['resourceid'] = 0; break; } } } } $screen['templateid'] = $current_hostid; if ($current_screen) { $screen['screenid'] = $current_screen['screenid']; $result = API::TemplateScreen()->update($screen); if (!$result) { throw new Exception(_('Cannot update screen.')); } info('[' . $current_hostname . '] ' . _s('Screen "%1$s" updated.', $screen['name'])); } else { $result = API::TemplateScreen()->create($screen); if (!$result) { throw new Exception(_('Cannot create screen.')); } info('[' . $current_hostname . '] ' . _s('Screen "%1$s" added.', $screen['name'])); } } } } } // DEPENDENCIES $dependencies = $xpath->query('dependencies/dependency'); if ($dependencies->length > 0) { $triggersForDependencies = zbx_objectValues($triggersForDependencies, 'triggerid'); $triggersForDependencies = array_flip($triggersForDependencies); $newDependencies = array(); foreach ($dependencies as $dependency) { $triggerDescription = $dependency->getAttribute('description'); $currentTrigger = get_trigger_by_description($triggerDescription); if ($currentTrigger && isset($triggersForDependencies[$currentTrigger['triggerid']])) { $dependsOnList = $xpath->query('depends', $dependency); foreach ($dependsOnList as $dependsOn) { $depTrigger = get_trigger_by_description($dependsOn->nodeValue); if ($depTrigger['triggerid']) { $newDependencies[] = array('triggerid' => $currentTrigger['triggerid'], 'dependsOnTriggerid' => $depTrigger['triggerid']); } } } } if ($newDependencies) { API::Trigger()->addDependencies($newDependencies); } } } }
/** * Select proxy ids for previously added proxy names. */ protected function selectProxyes() { if (!empty($this->proxies)) { $this->proxiesRefs = array(); $dbProxy = API::Proxy()->get(array('filter' => array('host' => $this->proxies), 'output' => array('hostid', 'host'), 'preservekeys' => true, 'editable' => true)); foreach ($dbProxy as $proxy) { $this->proxiesRefs[$proxy['host']] = $proxy['proxyid']; } $this->proxies = array(); } }
/** * Check interfaces input. * * @param array $interfaces * @param string $method */ public function checkInput(array &$interfaces, $method) { $update = $method == 'update'; // permissions if ($update) { $interfaceDBfields = array('interfaceid' => null); $dbInterfaces = $this->get(array('output' => API_OUTPUT_EXTEND, 'interfaceids' => zbx_objectValues($interfaces, 'interfaceid'), 'editable' => true, 'preservekeys' => true)); } else { $interfaceDBfields = array('hostid' => null, 'ip' => null, 'dns' => null, 'useip' => null, 'port' => null, 'main' => null); } $dbHosts = API::Host()->get(array('output' => array('host'), 'hostids' => zbx_objectValues($interfaces, 'hostid'), 'editable' => true, 'preservekeys' => true)); $dbProxies = API::Proxy()->get(array('output' => array('host'), 'proxyids' => zbx_objectValues($interfaces, 'hostid'), 'editable' => true, 'preservekeys' => true)); foreach ($interfaces as &$interface) { if (!check_db_fields($interfaceDBfields, $interface)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect arguments passed to function.')); } if ($update) { if (!isset($dbInterfaces[$interface['interfaceid']])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('No permissions to referred object or it does not exist!')); } $dbInterface = $dbInterfaces[$interface['interfaceid']]; if (isset($interface['hostid']) && bccomp($dbInterface['hostid'], $interface['hostid']) != 0) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Cannot switch host for interface.')); } $interface['hostid'] = $dbInterface['hostid']; // we check all fields on "updated" interface $updInterface = $interface; $interface = zbx_array_merge($dbInterface, $interface); } else { if (!isset($dbHosts[$interface['hostid']]) && !isset($dbProxies[$interface['hostid']])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('No permissions to referred object or it does not exist!')); } if (isset($dbProxies[$interface['hostid']])) { $interface['type'] = INTERFACE_TYPE_UNKNOWN; } elseif (!isset($interface['type'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect arguments passed to method.')); } } if (zbx_empty($interface['ip']) && zbx_empty($interface['dns'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('IP and DNS cannot be empty for host interface.')); } if ($interface['useip'] == INTERFACE_USE_IP && zbx_empty($interface['ip'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Interface with DNS "%1$s" cannot have empty IP address.', $interface['dns'])); } if ($interface['useip'] == INTERFACE_USE_DNS && zbx_empty($interface['dns'])) { if ($dbHosts && !empty($dbHosts[$interface['hostid']]['host'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Interface with IP "%1$s" cannot have empty DNS name while having "Use DNS" property on "%2$s".', $interface['ip'], $dbHosts[$interface['hostid']]['host'])); } elseif ($dbProxies && !empty($dbProxies[$interface['hostid']]['host'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Interface with IP "%1$s" cannot have empty DNS name while having "Use DNS" property on "%2$s".', $interface['ip'], $dbProxies[$interface['hostid']]['host'])); } else { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Interface with IP "%1$s" cannot have empty DNS name.', $interface['ip'])); } } if (isset($interface['dns'])) { $this->checkDns($interface); } if (isset($interface['ip'])) { $this->checkIp($interface); } if (isset($interface['port']) || $method == 'create') { $this->checkPort($interface); } if ($update) { $interface = $updInterface; } } unset($interface); // check if any of the affected hosts are discovered if ($update) { $interfaces = $this->extendObjects('interface', $interfaces, array('hostid')); } $this->checkValidator(zbx_objectValues($interfaces, 'hostid'), new CHostNormalValidator(array('message' => _('Cannot update interface for discovered host "%1$s".')))); }
public static function parseMain($rules) { $triggerExpressionConverter = new C24TriggerConverter(new CFunctionMacroParser(), new CMacroParser('#')); $triggersForDependencies = array(); if ($rules['hosts']['updateExisting'] || $rules['hosts']['createMissing'] || $rules['templates']['createMissing'] || $rules['templates']['updateExisting']) { $xpath = new DOMXPath(self::$xml); $hosts = $xpath->query('hosts/host'); // stores parsed host and template IDs $processedHostIds = array(); // stores converted trigger expressions for each host $triggerExpressions = array(); // stores converted item keys for each host $itemKeys = array(); // process hosts foreach ($hosts as $host) { $host_db = self::mapXML2arr($host, XML_TAG_HOST); if (!isset($host_db['status'])) { $host_db['status'] = HOST_STATUS_TEMPLATE; } if ($host_db['status'] == HOST_STATUS_TEMPLATE) { $current_host = API::Template()->get(array('output' => array('templateid'), 'filter' => array('host' => $host_db['host']), 'nopermissions' => true, 'limit' => 1)); } else { $current_host = API::Host()->get(array('output' => array('hostid'), 'filter' => array('host' => $host_db['host']), 'nopermissions' => true, 'limit' => 1)); } if (!$current_host && ($host_db['status'] == HOST_STATUS_TEMPLATE && !$rules['templates']['createMissing'] || $host_db['status'] != HOST_STATUS_TEMPLATE && !$rules['hosts']['createMissing'])) { continue; } if ($current_host && ($host_db['status'] == HOST_STATUS_TEMPLATE && !$rules['templates']['updateExisting'] || $host_db['status'] != HOST_STATUS_TEMPLATE && !$rules['hosts']['updateExisting'])) { continue; } // there were no host visible names in 1.8 if (!isset($host_db['name'])) { $host_db['name'] = $host_db['host']; } // host will have no interfaces - we will be creating them separately $host_db['interfaces'] = null; // it is possible, that data is imported from 1.8, where there was only one network interface per host /** * @todo when new XML format will be introduced, this check should be changed to XML version check */ $oldVersionInput = $host_db['status'] != HOST_STATUS_TEMPLATE; $interfaces = array(); // rearranging host structure, so it would look more like 2.0 host if ($oldVersionInput) { // the main interface is always "agent" type if (!is_null($host_db['ip'])) { $interfaces[] = array('main' => INTERFACE_PRIMARY, 'type' => INTERFACE_TYPE_AGENT, 'useip' => $host_db['useip'], 'ip' => $host_db['ip'], 'dns' => $host_db['dns'], 'port' => $host_db['port']); } // now we need to check if host had SNMP items. If it had, we need an SNMP interface for every different port. $items = $xpath->query('items/item', $host); $snmp_interface_ports_created = array(); foreach ($items as $item) { $item_db = self::mapXML2arr($item, XML_TAG_ITEM); if (($item_db['type'] == ITEM_TYPE_SNMPV1 || $item_db['type'] == ITEM_TYPE_SNMPV2C || $item_db['type'] == ITEM_TYPE_SNMPV3) && !isset($snmp_interface_ports_created[$item_db['snmp_port']])) { $interfaces[] = array('main' => $snmp_interface_ports_created ? INTERFACE_SECONDARY : INTERFACE_PRIMARY, 'type' => INTERFACE_TYPE_SNMP, 'useip' => $host_db['useip'], 'ip' => $host_db['ip'], 'dns' => $host_db['dns'], 'port' => $item_db['snmp_port']); $snmp_interface_ports_created[$item_db['snmp_port']] = 1; } } unset($snmp_interface_ports_created); // it was a temporary variable // we need to add ipmi interface if at least one ipmi item exists foreach ($items as $item) { $item_db = self::mapXML2arr($item, XML_TAG_ITEM); if ($item_db['type'] == ITEM_TYPE_IPMI) { // when saving a host in 1.8, it's possible to set useipmi=1 and not to fill an IP address // we were not really sure what to do with this host, // and decided to take host IP address instead and show info message about this if ($host_db['ipmi_ip'] === '') { $ipmi_ip = $host_db['ip']; info(_s('Host "%s" has "useipmi" parameter checked, but has no "ipmi_ip" parameter! Using host IP address as an address for IPMI interface.', $host_db['host'])); } else { $ipmi_ip = $host_db['ipmi_ip']; } $interfaces[] = array('main' => INTERFACE_PRIMARY, 'type' => INTERFACE_TYPE_IPMI, 'useip' => INTERFACE_USE_IP, 'ip' => $ipmi_ip, 'dns' => '', 'port' => $host_db['ipmi_port']); // we need only one ipmi interface break; } } } if ($current_host) { $options = array('filter' => array('host' => $host_db['host']), 'output' => API_OUTPUT_EXTEND, 'editable' => true, 'selectInterfaces' => API_OUTPUT_EXTEND); if ($host_db['status'] == HOST_STATUS_TEMPLATE) { $current_host = API::Template()->get($options); } else { $current_host = API::Host()->get($options); } if (empty($current_host)) { throw new Exception(_s('No permission for host "%1$s".', $host_db['host'])); } else { $current_host = reset($current_host); } // checking if host already exists - then some of the interfaces may not need to be created if ($host_db['status'] != HOST_STATUS_TEMPLATE) { $currentMainInterfaces = array(); $currentInterfacesByType = array(); // group existing main interfaces by interface type into $currentMainInterfaces // and group interfaces by type into $currentInterfacesByType foreach ($current_host['interfaces'] as $currentInterface) { if ($currentInterface['main'] == INTERFACE_PRIMARY) { $currentMainInterfaces[$currentInterface['type']] = $currentInterface; } $currentInterfacesByType[$currentInterface['type']][] = $currentInterface; } // loop through all interfaces we got from XML foreach ($interfaces as &$interfaceXml) { $interfaceXmlType = $interfaceXml['type']; // if this is the primary interface of some type and we have default interface of same type // in current (target) host, re-use "interfaceid" of the matching default interface // in current host if ($interfaceXml['main'] == INTERFACE_PRIMARY && isset($currentMainInterfaces[$interfaceXmlType])) { $interfaceXml['interfaceid'] = $currentMainInterfaces[$interfaceXmlType]['interfaceid']; } else { // otherwise, loop through all current (target) host interfaces with type of current // imported interface and re-use "interfaceid" in case if all interface parameters match if (isset($currentInterfacesByType[$interfaceXmlType])) { foreach ($currentInterfacesByType[$interfaceXmlType] as $currentInterface) { if ($currentInterface['ip'] == $interfaceXml['ip'] && $currentInterface['dns'] == $interfaceXml['dns'] && $currentInterface['port'] == $interfaceXml['port'] && $currentInterface['useip'] == $interfaceXml['useip']) { $interfaceXml['interfaceid'] = $currentInterface['interfaceid']; break; } } } } } unset($interfaceXml); $host_db['interfaces'] = $interfaces; } } elseif ($host_db['status'] != HOST_STATUS_TEMPLATE) { $host_db['interfaces'] = $interfaces; } // HOST GROUPS {{{ $groups = $xpath->query('groups/group', $host); $host_db['groups'] = array(); $groups_to_parse = array(); foreach ($groups as $group) { $groups_to_parse[] = array('name' => $group->nodeValue); } if (empty($groups_to_parse)) { $groups_to_parse[] = array('name' => ZBX_DEFAULT_IMPORT_HOST_GROUP); } foreach ($groups_to_parse as $group) { $hostGroup = API::HostGroup()->get(array('output' => API_OUTPUT_EXTEND, 'filter' => $group, 'editable' => true, 'limit' => 1)); if ($hostGroup) { $host_db['groups'][] = reset($hostGroup); } else { if ($rules['groups']['createMissing']) { $result = API::HostGroup()->create($group); if ($result) { $newHostGroup = API::HostGroup()->get(array('output' => API_OUTPUT_EXTEND, 'groupids' => $result['groupids'], 'limit' => 1)); $host_db['groups'][] = reset($newHostGroup); } } else { throw new Exception(_s('No permissions for host group "%1$s".', $group['name'])); } } } // }}} HOST GROUPS // MACROS $macros = $xpath->query('macros/macro', $host); if ($macros->length > 0) { $host_db['macros'] = array(); foreach ($macros as $macro) { $host_db['macros'][] = self::mapXML2arr($macro, XML_TAG_MACRO); } } // }}} MACROS // host inventory if ($oldVersionInput) { if (!isset($host_db['inventory'])) { $host_db['inventory'] = array(); } $inventoryNode = $xpath->query('host_profile/*', $host); if ($inventoryNode->length > 0) { foreach ($inventoryNode as $field) { $newInventoryName = self::mapInventoryName($field->nodeName); $host_db['inventory'][$newInventoryName] = $field->nodeValue; } } $inventoryNodeExt = $xpath->query('host_profiles_ext/*', $host); if ($inventoryNodeExt->length > 0) { foreach ($inventoryNodeExt as $field) { $newInventoryName = self::mapInventoryName($field->nodeName); if (isset($host_db['inventory'][$newInventoryName]) && $field->nodeValue !== '') { $host_db['inventory'][$newInventoryName] .= "\r\n\r\n"; $host_db['inventory'][$newInventoryName] .= $field->nodeValue; } else { $host_db['inventory'][$newInventoryName] = $field->nodeValue; } } } $host_db['inventory_mode'] = isset($host_db['inventory']) ? HOST_INVENTORY_MANUAL : HOST_INVENTORY_DISABLED; } if (isset($host_db['proxy_hostid'])) { $proxy_exists = API::Proxy()->get(array('output' => array('proxyid'), 'proxyids' => $host_db['proxy_hostid'])); if (empty($proxy_exists)) { $host_db['proxy_hostid'] = 0; } } if ($current_host && ($rules['hosts']['updateExisting'] || $rules['templates']['updateExisting'])) { if ($host_db['status'] == HOST_STATUS_TEMPLATE) { $host_db['templateid'] = $current_host['templateid']; $result = API::Template()->update($host_db); $current_hostid = $current_host['templateid']; } else { $host_db['hostid'] = $current_host['hostid']; $result = API::Host()->update($host_db); $current_hostid = $current_host['hostid']; } } if (!$current_host && ($rules['hosts']['createMissing'] || $rules['templates']['createMissing'])) { if ($host_db['status'] == HOST_STATUS_TEMPLATE) { $result = API::Template()->create($host_db); $current_hostid = reset($result['templateids']); } else { $result = API::Host()->create($host_db); $current_hostid = reset($result['hostids']); } } // store parsed host IDs $processedHostIds[$host_db['host']] = $current_hostid; } // gather triggers and convert old expressions $triggersXML = array(); // cycle each host and gather trigger descriptions and expressions foreach ($hosts as $host) { $host_db = self::mapXML2arr($host, XML_TAG_HOST); $current_hostid = isset($processedHostIds[$host_db['host']]) ? $processedHostIds[$host_db['host']] : false; if ($current_hostid) { $triggersXML[$current_hostid] = array(); $triggerExpressions[$host_db['host']] = array(); $oldVersionInput = $host_db['status'] != HOST_STATUS_TEMPLATE; $triggers = $xpath->query('triggers/trigger', $host); foreach ($triggers as $trigger) { $trigger_db = self::mapXML2arr($trigger, XML_TAG_TRIGGER); $oldExpression = $trigger_db['expression']; if (!isset($triggerExpressions[$host_db['host']][$trigger_db['description']])) { $triggerExpressions[$host_db['host']][$trigger_db['description']] = array(); } if ($oldVersionInput) { $expressionPart = explode(':', $trigger_db['expression']); $keyName = explode(',', $expressionPart[1], 2); if (count($keyName) == 2) { $keyValue = explode('.', $keyName[1], 2); $key = $keyName[0] . "," . $keyValue[0]; if (in_array($keyName[0], self::$oldKeys) || in_array($keyName[0], self::$oldKeysPref)) { $trigger_db['expression'] = str_replace($key, self::convertOldSimpleKey($key), $trigger_db['expression']); } } } // {HOSTNAME} is here for backward compatibility $trigger_db['expression'] = str_replace('{{HOSTNAME}:', '{' . $host_db['host'] . ':', $trigger_db['expression']); $trigger_db['expression'] = str_replace('{{HOST.HOST}:', '{' . $host_db['host'] . ':', $trigger_db['expression']); $trigger_db['expression'] = $triggerExpressionConverter->convert($trigger_db['expression']); $triggersXML[$current_hostid][$trigger_db['description']][$trigger_db['expression']] = $trigger_db['expression']; $triggerExpressions[$host_db['host']][$trigger_db['description']][$oldExpression] = $trigger_db['expression']; } } } // delete missing triggers if ($rules['triggers']['deleteMissing']) { // select triggers from parsed hosts $dbTriggers = API::Trigger()->get(array('output' => array('triggerid', 'description', 'expression'), 'expandExpression' => true, 'hostids' => $processedHostIds, 'selectHosts' => array('hostid'), 'preservekeys' => true, 'nopermissions' => true, 'inherited' => false, 'filter' => array('flags' => ZBX_FLAG_DISCOVERY_NORMAL))); // find corresponding trigger ID by description and expression $triggerIdsXML = array(); foreach ($dbTriggers as $dbTrigger) { $hostId = reset($dbTrigger['hosts']); if (isset($triggersXML[$hostId['hostid']][$dbTrigger['description']][$dbTrigger['expression']])) { $triggerIdsXML[$dbTrigger['triggerid']] = $dbTrigger['triggerid']; } } $triggersToDelete = array_diff_key($dbTriggers, $triggerIdsXML); $triggerIdsToDelete = array(); // check that potentially deletable trigger belongs to same hosts that are in XML // if some triggers belong to more hosts than current XML contains, don't delete them foreach ($triggersToDelete as $triggerId => $trigger) { $triggerHostIds = array_flip(zbx_objectValues($trigger['hosts'], 'hostid')); if (!array_diff_key($triggerHostIds, array_flip($processedHostIds))) { $triggerIdsToDelete[] = $triggerId; } } if ($triggerIdsToDelete) { API::Trigger()->delete($triggerIdsToDelete); } } // delete missing graphs if ($rules['graphs']['deleteMissing']) { $graphsXML = array(); // cycle each host and gather all graph names foreach ($hosts as $host) { $host_db = self::mapXML2arr($host, XML_TAG_HOST); $current_hostid = isset($processedHostIds[$host_db['host']]) ? $processedHostIds[$host_db['host']] : false; if ($current_hostid) { $graphsXML[$current_hostid] = array(); $graphs = $xpath->query('graphs/graph', $host); foreach ($graphs as $graph) { $graph_db = self::mapXML2arr($graph, XML_TAG_GRAPH); $graphsXML[$current_hostid][$graph_db['name']] = $graph_db['name']; } } } // select graphs from already parsed hosts $dbGraphs = API::Graph()->get(array('output' => array('graphid', 'name'), 'hostids' => $processedHostIds, 'selectHosts' => array('hostid'), 'preservekeys' => true, 'nopermissions' => true, 'inherited' => false, 'filter' => array('flags' => ZBX_FLAG_DISCOVERY_NORMAL))); $graphIdsXML = array(); foreach ($dbGraphs as $dbGraph) { $hostId = reset($dbGraph['hosts']); if (isset($graphsXML[$hostId['hostid']][$dbGraph['name']])) { $graphIdsXML[$dbGraph['graphid']] = $dbGraph['graphid']; } } $graphsToDelete = array_diff_key($dbGraphs, $graphIdsXML); $graphsIdsToDelete = array(); // check that potentially deletable graph belongs to same hosts that are in XML // if some graphs belong to more hosts than current XML contains, don't delete them foreach ($graphsToDelete as $graphId => $graph) { $graphHostIds = array_flip(zbx_objectValues($graph['hosts'], 'hostid')); if (!array_diff_key($graphHostIds, array_flip($processedHostIds))) { $graphsIdsToDelete[] = $graphId; } } if ($graphsIdsToDelete) { API::Graph()->delete($graphsIdsToDelete); } } // gather items and convert old keys $itemsXML = array(); foreach ($hosts as $host) { $host_db = self::mapXML2arr($host, XML_TAG_HOST); $current_hostid = isset($processedHostIds[$host_db['host']]) ? $processedHostIds[$host_db['host']] : false; if ($current_hostid) { $itemsXML[$current_hostid] = array(); $itemKeys[$host_db['host']] = array(); $oldVersionInput = $host_db['status'] != HOST_STATUS_TEMPLATE; $items = $xpath->query('items/item', $host); foreach ($items as $item) { $item_db = self::mapXML2arr($item, XML_TAG_ITEM); if ($oldVersionInput) { $oldKey = $item_db['key_']; $item_db['key_'] = self::convertOldSimpleKey($item_db['key_']); $itemKeys[$host_db['host']][$oldKey] = $item_db['key_']; } $itemsXML[$current_hostid][$item_db['key_']] = $item_db['key_']; } } } // delete missing items if ($rules['items']['deleteMissing']) { $dbItems = API::Item()->get(array('output' => array('itemid', 'key_', 'hostid'), 'hostids' => $processedHostIds, 'preservekeys' => true, 'nopermissions' => true, 'inherited' => false, 'filter' => array('flags' => ZBX_FLAG_DISCOVERY_NORMAL))); $itemIdsXML = array(); foreach ($dbItems as $dbItem) { if (isset($itemsXML[$dbItem['hostid']][$dbItem['key_']])) { $itemIdsXML[$dbItem['itemid']] = $dbItem['itemid']; } } $itemsToDelete = array_diff_key($dbItems, $itemIdsXML); if ($itemsToDelete) { API::Item()->delete(array_keys($itemsToDelete)); } } // delete missing applications if ($rules['applications']['deleteMissing']) { $applicationsXML = array(); foreach ($hosts as $host) { $host_db = self::mapXML2arr($host, XML_TAG_HOST); $current_hostid = isset($processedHostIds[$host_db['host']]) ? $processedHostIds[$host_db['host']] : false; if ($current_hostid) { $items = $xpath->query('items/item', $host); foreach ($items as $item) { $applications = $xpath->query('applications/application', $item); foreach ($applications as $application) { $applicationsXML[$current_hostid][$application->nodeValue] = $application->nodeValue; } } } } $dbApplications = API::Application()->get(array('output' => array('applicationid', 'hostid', 'name'), 'hostids' => $processedHostIds, 'preservekeys' => true, 'nopermissions' => true, 'inherited' => false)); $applicationsIdsXML = array(); foreach ($dbApplications as $dbApplication) { if (isset($applicationsXML[$dbApplication['hostid']][$dbApplication['name']])) { $applicationsIdsXML[$dbApplication['applicationid']] = $dbApplication['applicationid']; } } $applicationsToDelete = array_diff_key($dbApplications, $applicationsIdsXML); if ($applicationsToDelete) { API::Application()->delete(array_keys($applicationsToDelete)); } } // cycle each host again and create/update other objects foreach ($hosts as $host) { $host_db = self::mapXML2arr($host, XML_TAG_HOST); if (!isset($host_db['status'])) { $host_db['status'] = HOST_STATUS_TEMPLATE; } $current_hostid = isset($processedHostIds[$host_db['host']]) ? $processedHostIds[$host_db['host']] : false; if (!$current_hostid) { continue; } $oldVersionInput = $host_db['status'] != HOST_STATUS_TEMPLATE; // TEMPLATES {{{ if (!empty($rules['templateLinkage']['createMissing'])) { $templates = $xpath->query('templates/template', $host); $templateLinkage = array(); foreach ($templates as $template) { $options = array('filter' => array('host' => $template->nodeValue), 'output' => array('templateid'), 'editable' => true); $current_template = API::Template()->get($options); if (empty($current_template)) { throw new Exception(_s('No permission for template "%1$s".', $template->nodeValue)); } $current_template = reset($current_template); $templateLinkage[] = $current_template; } if ($templateLinkage) { $result = API::Template()->massAdd(array('hosts' => array('hostid' => $current_hostid), 'templates' => $templateLinkage)); if (!$result) { throw new Exception(); } } } // }}} TEMPLATES // ITEMS {{{ if ($rules['items']['updateExisting'] || $rules['items']['createMissing'] || $rules['applications']['createMissing']) { // applications are located under items in version 1.8, // so we need to get item list in any of these cases $items = $xpath->query('items/item', $host); if ($oldVersionInput) { $interfaces = API::HostInterface()->get(array('hostids' => $current_hostid, 'output' => API_OUTPUT_EXTEND)); // we must know interface ids to assign them to items $agent_interface_id = null; $ipmi_interface_id = null; $snmp_interfaces = array(); // hash 'port' => 'interfaceid' foreach ($interfaces as $interface) { switch ($interface['type']) { case INTERFACE_TYPE_AGENT: $agent_interface_id = $interface['interfaceid']; break; case INTERFACE_TYPE_IPMI: $ipmi_interface_id = $interface['interfaceid']; break; case INTERFACE_TYPE_SNMP: $snmp_interfaces[$interface['port']] = $interface['interfaceid']; break; } } } // if this is an export from 1.8, we need to make some adjustments to items // cycle each XML item foreach ($items as $item) { if ($rules['items']['updateExisting'] || $rules['items']['createMissing']) { $item_db = self::mapXML2arr($item, XML_TAG_ITEM); $item_db['hostid'] = $current_hostid; // item needs interfaces if ($oldVersionInput) { // 'snmp_port' column was renamed to 'port' if ($item_db['snmp_port'] != 0) { // zabbix agent items have no ports $item_db['port'] = $item_db['snmp_port']; } unset($item_db['snmp_port']); // assigning appropriate interface depending on item type switch ($item_db['type']) { // zabbix agent interface case ITEM_TYPE_ZABBIX: case ITEM_TYPE_SIMPLE: case ITEM_TYPE_EXTERNAL: case ITEM_TYPE_SSH: case ITEM_TYPE_TELNET: $item_db['interfaceid'] = $agent_interface_id; break; // snmp interface // snmp interface case ITEM_TYPE_SNMPV1: case ITEM_TYPE_SNMPV2C: case ITEM_TYPE_SNMPV3: // for an item with different port - different interface $item_db['interfaceid'] = $snmp_interfaces[$item_db['port']]; break; case ITEM_TYPE_IPMI: $item_db['interfaceid'] = $ipmi_interface_id; break; // no interfaces required for these item types // no interfaces required for these item types case ITEM_TYPE_HTTPTEST: case ITEM_TYPE_CALCULATED: case ITEM_TYPE_AGGREGATE: case ITEM_TYPE_INTERNAL: case ITEM_TYPE_ZABBIX_ACTIVE: case ITEM_TYPE_TRAPPER: case ITEM_TYPE_DB_MONITOR: $item_db['interfaceid'] = null; break; } $item_db['key_'] = $itemKeys[$host_db['host']][$item_db['key_']]; } $current_item = API::Item()->get(array('filter' => array('hostid' => $item_db['hostid'], 'key_' => $item_db['key_']), 'webitems' => true, 'editable' => true, 'output' => array('itemid'))); $current_item = reset($current_item); } // create applications independently of create or update item options // in case we update items, we need to assign items to applications, // so we also gather application IDs independetly of selected application options $applications = $xpath->query('applications/application', $item); $itemApplications = array(); $applicationsToAdd = array(); $applicationsIds = array(); foreach ($applications as $application) { $application_db = array('name' => $application->nodeValue, 'hostid' => $current_hostid); $current_application = API::Application()->get(array('filter' => $application_db, 'output' => API_OUTPUT_EXTEND)); $applicationValue = reset($current_application); if ($current_application) { if (!$itemApplications) { $itemApplications = $current_application; } elseif (!in_array($applicationValue['applicationid'], $applicationsIds)) { $itemApplications = array_merge($itemApplications, $current_application); } $applicationsIds[] = $applicationValue['applicationid']; } else { $applicationsToAdd[] = $application_db; } } if ($applicationsToAdd && $rules['applications']['createMissing']) { $result = API::Application()->create($applicationsToAdd); $newApplications = API::Application()->get(array('applicationids' => $result['applicationids'], 'output' => API_OUTPUT_EXTEND)); $itemApplications = array_merge($itemApplications, $newApplications); } if ($rules['items']['updateExisting'] || $rules['items']['createMissing']) { // if item does not exist and there is no need to create it, skip item creation if (!$current_item && !$rules['items']['createMissing']) { info(_s('Item "%1$s" skipped - user rule.', $item_db['key_'])); continue; } // if item exists, but there there is no need for update, skip item update if ($current_item && !$rules['items']['updateExisting']) { info(_s('Item "%1$s" skipped - user rule.', $item_db['key_'])); continue; } if ($current_item && $rules['items']['updateExisting']) { $item_db['itemid'] = $current_item['itemid']; $result = API::Item()->update($item_db); $current_item = API::Item()->get(array('itemids' => $result['itemids'], 'webitems' => true, 'output' => array('itemid'))); } if (!$current_item && $rules['items']['createMissing']) { $result = API::Item()->create($item_db); $current_item = API::Item()->get(array('itemids' => $result['itemids'], 'webitems' => true, 'output' => array('itemid'))); } // after items are created or updated, see to if items need to assigned to applications if (isset($itemApplications) && $itemApplications) { API::Application()->massAdd(array('applications' => $itemApplications, 'items' => $current_item)); } } } } // }}} ITEMS // TRIGGERS {{{ if ($rules['triggers']['updateExisting'] || $rules['triggers']['createMissing']) { $triggers = $xpath->query('triggers/trigger', $host); $triggersToCreate = array(); $triggersToUpdate = array(); foreach ($triggers as $trigger) { $trigger_db = self::mapXML2arr($trigger, XML_TAG_TRIGGER); $trigger_db['expression'] = $triggerExpressions[$host_db['host']][$trigger_db['description']][$trigger_db['expression']]; $trigger_db['hostid'] = $current_hostid; $currentTrigger = API::Trigger()->get(array('output' => array('triggerid'), 'filter' => array('description' => $trigger_db['description']), 'hostids' => array($current_hostid), 'selectHosts' => array('hostid'), 'nopermissions' => true, 'limit' => 1)); $currentTrigger = reset($currentTrigger); if ($currentTrigger) { $dbTriggers = API::Trigger()->get(array('output' => API_OUTPUT_EXTEND, 'filter' => array('description' => $trigger_db['description']), 'hostids' => array($current_hostid), 'editable' => true)); foreach ($dbTriggers as $dbTrigger) { $expression = explode_exp($dbTrigger['expression']); if (strcmp($trigger_db['expression'], $expression) == 0) { $currentTrigger = $dbTrigger; break; } if (!$currentTrigger) { throw new Exception(_s('No permission for trigger "%1$s".', $trigger_db['description'])); } } } unset($trigger_db['hostid']); if (!$currentTrigger && !$rules['triggers']['createMissing']) { info(_s('Trigger "%1$s" skipped - user rule.', $trigger_db['description'])); continue; } if ($currentTrigger && !$rules['triggers']['updateExisting']) { info(_s('Trigger "%1$s" skipped - user rule.', $trigger_db['description'])); continue; } if (!$currentTrigger && $rules['triggers']['createMissing']) { $triggersToCreate[] = $trigger_db; } if ($currentTrigger && $rules['triggers']['updateExisting']) { $trigger_db['triggerid'] = $currentTrigger['triggerid']; $triggersToUpdate[] = $trigger_db; } } if ($triggersToUpdate) { $result = API::Trigger()->update($triggersToUpdate); $triggersUpdated = API::Trigger()->get(array('output' => API_OUTPUT_EXTEND, 'triggerids' => $result['triggerids'])); $triggersForDependencies = array_merge($triggersForDependencies, $triggersUpdated); } if ($triggersToCreate) { $result = API::Trigger()->create($triggersToCreate); $triggersCreated = API::Trigger()->get(array('output' => API_OUTPUT_EXTEND, 'triggerids' => $result['triggerids'])); $triggersForDependencies = array_merge($triggersForDependencies, $triggersCreated); } } // }}} TRIGGERS // GRAPHS {{{ if ($rules['graphs']['updateExisting'] || $rules['graphs']['createMissing']) { $graphs = $xpath->query('graphs/graph', $host); $graphs_to_add = array(); $graphs_to_upd = array(); foreach ($graphs as $graph) { // GRAPH ITEMS {{{ $gitems = $xpath->query('graph_elements/graph_element', $graph); $graph_hostids = array(); $graph_items = array(); foreach ($gitems as $gitem) { $gitem_db = self::mapXML2arr($gitem, XML_TAG_GRAPH_ELEMENT); $data = explode(':', $gitem_db['host_key_']); $gitem_host = array_shift($data); // {HOSTNAME} is here for backward compatibility $gitem_db['host'] = $gitem_host == '{HOSTNAME}' ? $host_db['host'] : $gitem_host; $gitem_db['host'] = $gitem_host == '{HOST.HOST}' ? $host_db['host'] : $gitem_host; if ($oldVersionInput) { $data[0] = self::convertOldSimpleKey($data[0]); } $gitem_db['key_'] = implode(':', $data); $itemExists = API::Item()->get(array('output' => array('itemid'), 'filter' => array('key_' => $gitem_db['key_']), 'webitems' => true, 'nopermissions' => true, 'limit' => 1)); if ($itemExists) { $current_item = API::Item()->get(array('filter' => array('key_' => $gitem_db['key_']), 'webitems' => true, 'editable' => true, 'host' => $gitem_db['host'], 'output' => array('itemid', 'hostid'))); if (empty($current_item)) { throw new Exception(_s('No permission for item "%1$s".', $gitem_db['key_'])); } $current_item = reset($current_item); $graph_hostids[] = $current_item['hostid']; $gitem_db['itemid'] = $current_item['itemid']; $graph_items[] = $gitem_db; } else { throw new Exception(_s('Item "%1$s" does not exist.', $gitem_db['host_key_'])); } } // }}} GRAPH ITEMS $graph_db = self::mapXML2arr($graph, XML_TAG_GRAPH); $graph_db['hostids'] = $graph_hostids; // do we need to show the graph legend, after it is imported? // in 1.8, this setting was present only for pie and exploded graphs // for other graph types we are always showing the legend if ($graph_db['graphtype'] != GRAPH_TYPE_PIE && $graph_db['graphtype'] != GRAPH_TYPE_EXPLODED) { $graph_db['show_legend'] = 1; } $current_graph = API::Graph()->get(array('output' => array('graphid'), 'selectHosts' => array('hostid', 'host'), 'hostids' => $graph_db['hostids'], 'filter' => array('name' => $graph_db['name']), 'nopermissions' => true, 'limit' => 1)); if ($current_graph) { $current_graph = API::Graph()->get(array('output' => API_OUTPUT_EXTEND, 'hostids' => $graph_db['hostids'], 'filter' => array('name' => $graph_db['name']), 'editable' => true)); if (empty($current_graph)) { throw new Exception(_s('No permission for graph "%1$s".', $graph_db['name'])); } $current_graph = reset($current_graph); } if (!$current_graph && empty($rules['graphs']['createMissing'])) { info(_s('Graph "%1$s" skipped - user rule.', $graph_db['name'])); continue; // break if not update updateExisting } if ($current_graph && empty($rules['graphs']['updateExisting'])) { info(_s('Graph "%1$s" skipped - user rule.', $graph_db['name'])); continue; // break if not update updateExisting } if (!isset($graph_db['ymin_type'])) { throw new Exception(_s('No "ymin_type" field for graph "%s".', $graph_db['name'])); } if (!isset($graph_db['ymax_type'])) { throw new Exception(_s('No "ymax_type" field for graph "%s".', $graph_db['name'])); } if ($graph_db['ymin_type'] == GRAPH_YAXIS_TYPE_ITEM_VALUE) { $item_data = explode(':', $graph_db['ymin_item_key'], 2); if (count($item_data) < 2) { throw new Exception(_s('Incorrect y min item for graph "%1$s".', $graph_db['name'])); } if (!($item = get_item_by_key($item_data[1], $item_data[0]))) { throw new Exception(_s('Missing item "%1$s" for host "%2$s".', $graph_db['ymin_item_key'], $host_db['host'])); } $graph_db['ymin_itemid'] = $item['itemid']; } if ($graph_db['ymax_type'] == GRAPH_YAXIS_TYPE_ITEM_VALUE) { $item_data = explode(':', $graph_db['ymax_item_key'], 2); if (count($item_data) < 2) { throw new Exception(_s('Incorrect y max item for graph "%1$s".', $graph_db['name'])); } if (!($item = get_item_by_key($item_data[1], $item_data[0]))) { throw new Exception(_s('Missing item "%1$s" for host "%2$s".', $graph_db['ymax_item_key'], $host_db['host'])); } $graph_db['ymax_itemid'] = $item['itemid']; } $graph_db['gitems'] = $graph_items; if ($current_graph) { $graph_db['graphid'] = $current_graph['graphid']; $graphs_to_upd[] = $graph_db; } else { $graphs_to_add[] = $graph_db; } } if (!empty($graphs_to_add)) { API::Graph()->create($graphs_to_add); } if (!empty($graphs_to_upd)) { API::Graph()->update($graphs_to_upd); } } } // DEPENDENCIES $dependencies = $xpath->query('dependencies/dependency'); if ($dependencies->length > 0) { $triggersForDependencies = zbx_objectValues($triggersForDependencies, 'triggerid'); $triggersForDependencies = array_flip($triggersForDependencies); $triggerDependencies = array(); foreach ($dependencies as $dependency) { $triggerDescription = $dependency->getAttribute('description'); $currentTrigger = get_trigger_by_description($triggerDescription); if ($currentTrigger && isset($triggersForDependencies[$currentTrigger['triggerid']])) { $dependsOnList = $xpath->query('depends', $dependency); foreach ($dependsOnList as $dependsOn) { $depTrigger = get_trigger_by_description($dependsOn->nodeValue); if ($depTrigger) { if (!isset($triggerDependencies[$currentTrigger['triggerid']])) { $triggerDependencies[$currentTrigger['triggerid']] = array('triggerid' => $currentTrigger['triggerid'], 'dependencies' => array()); } $triggerDependencies[$currentTrigger['triggerid']]['dependencies'][] = array('triggerid' => $depTrigger['triggerid']); } } } } if ($triggerDependencies) { API::Trigger()->update($triggerDependencies); } } } }
/** * Validate conditions. * * @static * * @param array $conditions * @param int $conditions['conditiontype'] * @param array $conditions['value'] * * @return bool */ public static function validateConditions($conditions, $update = false) { $conditions = zbx_toArray($conditions); $hostGroupIdsAll = array(); $templateIdsAll = array(); $triggerIdsAll = array(); $hostIdsAll = array(); $discoveryRuleIdsAll = array(); $proxyIdsAll = array(); $proxyidsAll = array(); // build validators $timePeriodValidator = new CTimePeriodValidator(); $discoveryCheckTypeValidator = new CSetValidator(array('values' => array_keys(discovery_check_type2str()))); $discoveryObjectStatusValidator = new CSetValidator(array('values' => array_keys(discovery_object_status2str()))); $triggerSeverityValidator = new CSetValidator(array('values' => array_keys(getSeverityCaption()))); $discoveryObjectValidator = new CSetValidator(array('values' => array_keys(discovery_object2str()))); $triggerValueValidator = new CSetValidator(array('values' => array_keys(trigger_value2str()))); $eventTypeValidator = new CSetValidator(array('values' => array_keys(eventType()))); foreach ($conditions as $condition) { // on create operator is mandatory and needs validation, but on update it must be validated only if it's set if (!$update || $update && isset($condition['operator'])) { $operatorValidator = new CSetValidator(array('values' => get_operators_by_conditiontype($condition['conditiontype']))); if (!$operatorValidator->validate($condition['operator'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition operator.')); } } if (!$update || $update && isset($condition['value'])) { // validate condition values depending on condition type switch ($condition['conditiontype']) { case CONDITION_TYPE_HOST_GROUP: if (!$condition['value']) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty action condition.')); } $hostGroupIdsAll[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_TEMPLATE: if (!$condition['value']) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty action condition.')); } $templateIdsAll[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_TRIGGER: if (!$condition['value']) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty action condition.')); } $triggerIdsAll[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_HOST: if (!$condition['value']) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty action condition.')); } $hostIdsAll[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_DRULE: if (!$condition['value']) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty action condition.')); } $discoveryRuleIdsAll[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_DCHECK: if (!$condition['value']) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty action condition.')); } $proxyIdsAll[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_PROXY: if (!$condition['value']) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty action condition.')); } $proxyidsAll[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_DOBJECT: if (zbx_empty($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty action condition.')); } elseif (!$discoveryObjectValidator->validate($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition discovery object.')); } break; case CONDITION_TYPE_TIME_PERIOD: if (!$timePeriodValidator->validate($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, $timePeriodValidator->getError()); } break; case CONDITION_TYPE_DHOST_IP: if (zbx_empty($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty action condition.')); } else { if (!validate_ip_range($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect action condition ip "%1$s".', $condition['value'])); } } break; case CONDITION_TYPE_DSERVICE_TYPE: if (zbx_empty($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty action condition.')); } elseif (!$discoveryCheckTypeValidator->validate($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition discovery check.')); } break; case CONDITION_TYPE_DSERVICE_PORT: if (zbx_empty($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty action condition.')); } elseif (!validate_port_list($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect action condition port "%1$s".', $condition['value'])); } break; case CONDITION_TYPE_DSTATUS: if (zbx_empty($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty action condition.')); } elseif (!$discoveryObjectStatusValidator->validate($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition discovery status.')); } break; case CONDITION_TYPE_MAINTENANCE: if (!zbx_empty($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Maintenance action condition value must be empty.')); } break; case CONDITION_TYPE_TRIGGER_SEVERITY: if (zbx_empty($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty action condition.')); } elseif (!$triggerSeverityValidator->validate($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition trigger severity.')); } break; case CONDITION_TYPE_TRIGGER_VALUE: if (zbx_empty($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty action condition.')); } elseif (!$triggerValueValidator->validate($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition trigger value.')); } break; case CONDITION_TYPE_EVENT_TYPE: if (zbx_empty($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty action condition.')); } elseif (!$eventTypeValidator->validate($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition event type.')); } break; case CONDITION_TYPE_TRIGGER_NAME: case CONDITION_TYPE_NODE: case CONDITION_TYPE_DUPTIME: case CONDITION_TYPE_DVALUE: case CONDITION_TYPE_APPLICATION: case CONDITION_TYPE_HOST_NAME: case CONDITION_TYPE_HOST_METADATA: if (zbx_empty($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty action condition.')); } break; default: self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition type.')); break; } } } if (!API::HostGroup()->isWritable($hostGroupIdsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition host group. Host group does not exist or you have no access to it.')); } if (!API::Host()->isWritable($hostIdsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition host. Host does not exist or you have no access to it.')); } if (!API::Template()->isWritable($templateIdsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition template. Template does not exist or you have no access to it.')); } if (!API::Trigger()->isWritable($triggerIdsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition trigger. Trigger does not exist or you have no access to it.')); } if (!API::DRule()->isWritable($discoveryRuleIdsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition discovery rule. Discovery rule does not exist or you have no access to it.')); } if (!API::DCheck()->isWritable($proxyIdsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition discovery check. Discovery check does not exist or you have no access to it.')); } if (!API::Proxy()->isWritable($proxyidsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition proxy. Proxy does not exist or you have no access to it.')); } return true; }
$data['drule']['name'] = getRequest('name', ''); $data['drule']['iprange'] = getRequest('iprange', '192.168.0.1-254'); $data['drule']['delay'] = getRequest('delay', SEC_PER_HOUR); $data['drule']['status'] = getRequest('status', DRULE_STATUS_ACTIVE); $data['drule']['dchecks'] = getRequest('dchecks', []); $data['drule']['nextcheck'] = getRequest('nextcheck', 0); $data['drule']['uniqueness_criteria'] = getRequest('uniqueness_criteria', -1); } if (!empty($data['drule']['dchecks'])) { foreach ($data['drule']['dchecks'] as $id => $dcheck) { $data['drule']['dchecks'][$id]['name'] = discovery_check2str($dcheck['type'], isset($dcheck['key_']) ? $dcheck['key_'] : '', isset($dcheck['ports']) ? $dcheck['ports'] : ''); } order_result($data['drule']['dchecks'], 'name'); } // get proxies $data['proxies'] = API::Proxy()->get(['output' => API_OUTPUT_EXTEND]); order_result($data['proxies'], 'host'); // render view $discoveryView = new CView('configuration.discovery.edit', $data); $discoveryView->render(); $discoveryView->show(); } else { $sortField = getRequest('sort', CProfile::get('web.' . $page['file'] . '.sort', 'name')); $sortOrder = getRequest('sortorder', CProfile::get('web.' . $page['file'] . '.sortorder', ZBX_SORT_UP)); CProfile::update('web.' . $page['file'] . '.sort', $sortField, PROFILE_TYPE_STR); CProfile::update('web.' . $page['file'] . '.sortorder', $sortOrder, PROFILE_TYPE_STR); $config = select_config(); $data = ['sort' => $sortField, 'sortorder' => $sortOrder]; // get drules $data['drules'] = API::DRule()->get(['output' => ['proxy_hostid', 'name', 'status', 'iprange', 'delay'], 'selectDChecks' => ['type'], 'editable' => true, 'sortfield' => $sortField, 'limit' => $config['search_limit'] + 1]); if ($data['drules']) {
/** * Create CDiv with host/template information and references to it's elements * * @param string $currentElement * @param int $hostid * @param int $lld_ruleid * * @return object */ function get_header_host_table($current_element, $hostid, $lld_ruleid = 0) { $options = ['output' => ['hostid', 'status', 'proxy_hostid', 'name', 'maintenance_status', 'flags', 'available', 'snmp_available', 'jmx_available', 'ipmi_available', 'error', 'snmp_error', 'jmx_error', 'ipmi_error'], 'selectHostDiscovery' => ['ts_delete'], 'hostids' => [$hostid], 'editable' => true]; if ($lld_ruleid == 0) { $options['selectApplications'] = API_OUTPUT_COUNT; $options['selectItems'] = API_OUTPUT_COUNT; $options['selectTriggers'] = API_OUTPUT_COUNT; $options['selectGraphs'] = API_OUTPUT_COUNT; $options['selectDiscoveries'] = API_OUTPUT_COUNT; $options['selectHttpTests'] = API_OUTPUT_COUNT; } // get hosts $db_host = API::Host()->get($options); if (!$db_host) { $options = ['output' => ['templateid', 'name', 'flags'], 'templateids' => [$hostid], 'editable' => true]; if ($lld_ruleid == 0) { $options['selectApplications'] = API_OUTPUT_COUNT; $options['selectItems'] = API_OUTPUT_COUNT; $options['selectTriggers'] = API_OUTPUT_COUNT; $options['selectGraphs'] = API_OUTPUT_COUNT; $options['selectScreens'] = API_OUTPUT_COUNT; $options['selectDiscoveries'] = API_OUTPUT_COUNT; $options['selectHttpTests'] = API_OUTPUT_COUNT; } // get templates $db_host = API::Template()->get($options); $is_template = true; } else { $is_template = false; } if (!$db_host) { return null; } $db_host = reset($db_host); // get lld-rules if ($lld_ruleid != 0) { $db_discovery_rule = API::DiscoveryRule()->get(['output' => ['name'], 'selectItems' => API_OUTPUT_COUNT, 'selectTriggers' => API_OUTPUT_COUNT, 'selectGraphs' => API_OUTPUT_COUNT, 'selectHostPrototypes' => API_OUTPUT_COUNT, 'itemids' => [$lld_ruleid], 'editable' => true]); $db_discovery_rule = reset($db_discovery_rule); } /* * list and host (template) name */ $list = (new CList())->addClass(ZBX_STYLE_OBJECT_GROUP); if ($is_template) { $template = new CSpan(new CLink($db_host['name'], 'templates.php?form=update&templateid=' . $db_host['templateid'])); if ($current_element === '') { $template->addClass(ZBX_STYLE_SELECTED); } $list->addItem([new CSpan(new CLink(_('All templates'), 'templates.php?templateid=' . $db_host['templateid'] . url_param('groupid'))), '/', $template]); $db_host['hostid'] = $db_host['templateid']; } else { $proxy_name = ''; if ($db_host['proxy_hostid'] != 0) { $db_proxies = API::Proxy()->get(['output' => ['host'], 'proxyids' => [$db_host['proxy_hostid']]]); $proxy_name = CHtml::encode($db_proxies[0]['host']) . NAME_DELIMITER; } $name = $proxy_name . CHtml::encode($db_host['name']); switch ($db_host['status']) { case HOST_STATUS_MONITORED: if ($db_host['maintenance_status'] == HOST_MAINTENANCE_STATUS_ON) { $status = (new CSpan(_('In maintenance')))->addClass(ZBX_STYLE_ORANGE); } else { $status = (new CSpan(_('Enabled')))->addClass(ZBX_STYLE_GREEN); } break; case HOST_STATUS_NOT_MONITORED: $status = (new CSpan(_('Disabled')))->addClass(ZBX_STYLE_RED); break; default: $status = _('Unknown'); break; } $host = new CSpan(new CLink($name, 'hosts.php?form=update&hostid=' . $db_host['hostid'])); if ($current_element === '') { $host->addClass(ZBX_STYLE_SELECTED); } $list->addItem([new CSpan(new CLink(_('All hosts'), 'hosts.php?hostid=' . $db_host['hostid'] . url_param('groupid'))), '/', $host]); $list->addItem($status); $list->addItem(getHostAvailabilityTable($db_host)); if ($db_host['flags'] == ZBX_FLAG_DISCOVERY_CREATED && $db_host['hostDiscovery']['ts_delete'] != 0) { $lifetime_indicator = getHostLifetimeIndicator(time(), $db_host['hostDiscovery']['ts_delete']); $list->addItem((new CDiv($lifetime_indicator))->addClass(ZBX_STYLE_STATUS_CONTAINER)); } } /* * the count of rows */ if ($lld_ruleid == 0) { // applications $applications = new CSpan([new CLink(_('Applications'), 'applications.php?hostid=' . $db_host['hostid']), CViewHelper::showNum($db_host['applications'])]); if ($current_element == 'applications') { $applications->addClass(ZBX_STYLE_SELECTED); } $list->addItem($applications); // items $items = new CSpan([new CLink(_('Items'), 'items.php?filter_set=1&hostid=' . $db_host['hostid']), CViewHelper::showNum($db_host['items'])]); if ($current_element == 'items') { $items->addClass(ZBX_STYLE_SELECTED); } $list->addItem($items); // triggers $triggers = new CSpan([new CLink(_('Triggers'), 'triggers.php?hostid=' . $db_host['hostid']), CViewHelper::showNum($db_host['triggers'])]); if ($current_element == 'triggers') { $triggers->addClass(ZBX_STYLE_SELECTED); } $list->addItem($triggers); // graphs $graphs = new CSpan([new CLink(_('Graphs'), 'graphs.php?hostid=' . $db_host['hostid']), CViewHelper::showNum($db_host['graphs'])]); if ($current_element == 'graphs') { $graphs->addClass(ZBX_STYLE_SELECTED); } $list->addItem($graphs); // screens if ($is_template) { $screens = new CSpan([new CLink(_('Screens'), 'screenconf.php?templateid=' . $db_host['hostid']), CViewHelper::showNum($db_host['screens'])]); if ($current_element == 'screens') { $screens->addClass(ZBX_STYLE_SELECTED); } $list->addItem($screens); } // discovery rules $lld_rules = new CSpan([new CLink(_('Discovery rules'), 'host_discovery.php?hostid=' . $db_host['hostid']), CViewHelper::showNum($db_host['discoveries'])]); if ($current_element == 'discoveries') { $lld_rules->addClass(ZBX_STYLE_SELECTED); } $list->addItem($lld_rules); // web scenarios $http_tests = new CSpan([new CLink(_('Web scenarios'), 'httpconf.php?hostid=' . $db_host['hostid']), CViewHelper::showNum($db_host['httpTests'])]); if ($current_element == 'web') { $http_tests->addClass(ZBX_STYLE_SELECTED); } $list->addItem($http_tests); } else { $discovery_rule = (new CSpan())->addItem(new CLink(CHtml::encode($db_discovery_rule['name']), 'host_discovery.php?form=update&itemid=' . $db_discovery_rule['itemid'])); if ($current_element == 'discoveries') { $discovery_rule->addClass(ZBX_STYLE_SELECTED); } $list->addItem([(new CSpan())->addItem(new CLink(_('Discovery list'), 'host_discovery.php?hostid=' . $db_host['hostid'] . url_param('groupid'))), '/', $discovery_rule]); // item prototypes $item_prototypes = new CSpan([new CLink(_('Item prototypes'), 'disc_prototypes.php?parent_discoveryid=' . $db_discovery_rule['itemid']), CViewHelper::showNum($db_discovery_rule['items'])]); if ($current_element == 'items') { $item_prototypes->addClass(ZBX_STYLE_SELECTED); } $list->addItem($item_prototypes); // trigger prototypes $trigger_prototypes = new CSpan([new CLink(_('Trigger prototypes'), 'trigger_prototypes.php?parent_discoveryid=' . $db_discovery_rule['itemid']), CViewHelper::showNum($db_discovery_rule['triggers'])]); if ($current_element == 'triggers') { $trigger_prototypes->addClass(ZBX_STYLE_SELECTED); } $list->addItem($trigger_prototypes); // graph prototypes $graph_prototypes = new CSpan([new CLink(_('Graph prototypes'), 'graphs.php?parent_discoveryid=' . $db_discovery_rule['itemid']), CViewHelper::showNum($db_discovery_rule['graphs'])]); if ($current_element == 'graphs') { $graph_prototypes->addClass(ZBX_STYLE_SELECTED); } $list->addItem($graph_prototypes); // host prototypes if ($db_host['flags'] == ZBX_FLAG_DISCOVERY_NORMAL) { $host_prototypes = new CSpan([new CLink(_('Host prototypes'), 'host_prototypes.php?parent_discoveryid=' . $db_discovery_rule['itemid']), CViewHelper::showNum($db_discovery_rule['hostPrototypes'])]); if ($current_element == 'hosts') { $host_prototypes->addClass(ZBX_STYLE_SELECTED); } $list->addItem($host_prototypes); } } return $list; }
$data['drule']['name'] = get_request('name', ''); $data['drule']['iprange'] = get_request('iprange', '192.168.0.1-255'); $data['drule']['delay'] = get_request('delay', SEC_PER_HOUR); $data['drule']['status'] = get_request('status', DRULE_STATUS_ACTIVE); $data['drule']['dchecks'] = get_request('dchecks', array()); $data['drule']['nextcheck'] = get_request('nextcheck', 0); $data['drule']['uniqueness_criteria'] = get_request('uniqueness_criteria', -1); } if (!empty($data['drule']['dchecks'])) { foreach ($data['drule']['dchecks'] as $id => $dcheck) { $data['drule']['dchecks'][$id]['name'] = discovery_check2str($dcheck['type'], isset($dcheck['key_']) ? $dcheck['key_'] : '', isset($dcheck['ports']) ? $dcheck['ports'] : ''); } order_result($data['drule']['dchecks'], 'name'); } // get proxies $data['proxies'] = API::Proxy()->get(array('output' => API_OUTPUT_EXTEND)); order_result($data['proxies'], 'host'); // render view $discoveryView = new CView('configuration.discovery.edit', $data); $discoveryView->render(); $discoveryView->show(); } else { $data = array(); // get drules $data['drules'] = API::DRule()->get(array('output' => API_OUTPUT_EXTEND, 'sortfield' => getPageSortField('name'), 'selectDChecks' => API_OUTPUT_EXTEND, 'editable' => true)); if (!empty($data['drules'])) { foreach ($data['drules'] as $druleid => $drule) { // checks $checks = array(); foreach ($drule['dchecks'] as $check) { $checks[$check['type']] = discovery_check_type2str($check['type']);
} $ifTab->addRow($row); $hostList->addRow(_('IPMI interfaces'), new CDiv($ifTab, 'border_dotted objectgroup interface-group'), false, null, 'interface-row interface-row-last'); } // Proxy if (!$isDiscovered) { $proxyControl = new CComboBox('proxy_hostid', $proxy_hostid); $proxyControl->addItem(0, _('(no proxy)')); $db_proxies = API::Proxy()->get(array('output' => API_OUTPUT_EXTEND)); order_result($db_proxies, 'host'); foreach ($db_proxies as $proxy) { $proxyControl->addItem($proxy['proxyid'], $proxy['host']); } } else { if ($dbHost['proxy_hostid']) { $proxy = API::Proxy()->get(array('output' => array('host', 'proxyid'), 'proxyids' => $dbHost['proxy_hostid'], 'limit' => 1)); $proxy = reset($proxy); $proxyControl = new CTextBox('proxy_host', $proxy['host'], null, true); } else { $proxyControl = new CTextBox('proxy_host', _('(no proxy)'), null, true); } } $hostList->addRow(_('Monitored by proxy'), $proxyControl); $cmbStatus = new CComboBox('status', $status); $cmbStatus->addItem(HOST_STATUS_MONITORED, _('Monitored')); $cmbStatus->addItem(HOST_STATUS_NOT_MONITORED, _('Not monitored')); $hostList->addRow(_('Status'), $cmbStatus); if ($_REQUEST['form'] == 'full_clone') { // host applications $hostApps = API::Application()->get(array('hostids' => $_REQUEST['hostid'], 'inherited' => false, 'output' => array('name'), 'preservekeys' => true)); if (!empty($hostApps)) {
/** * Check permissions to DB entities referenced by action conditions. * * @param array $conditions conditions for which permissions to referenced DB entities will be checked */ protected function validateConditionsPermissions(array $conditions) { $hostGroupIdsAll = array(); $templateIdsAll = array(); $triggerIdsAll = array(); $hostIdsAll = array(); $discoveryRuleIdsAll = array(); $discoveryCheckIdsAll = array(); $proxyIdsAll = array(); foreach ($conditions as $condition) { $conditionValue = $condition['value']; // validate condition values depending on condition type switch ($condition['conditiontype']) { case CONDITION_TYPE_HOST_GROUP: $hostGroupIdsAll[$conditionValue] = $conditionValue; break; case CONDITION_TYPE_TEMPLATE: $templateIdsAll[$conditionValue] = $conditionValue; break; case CONDITION_TYPE_TRIGGER: $triggerIdsAll[$conditionValue] = $conditionValue; break; case CONDITION_TYPE_HOST: $hostIdsAll[$conditionValue] = $conditionValue; break; case CONDITION_TYPE_DRULE: $discoveryRuleIdsAll[$conditionValue] = $conditionValue; break; case CONDITION_TYPE_DCHECK: $discoveryCheckIdsAll[$conditionValue] = $conditionValue; break; case CONDITION_TYPE_PROXY: $proxyIdsAll[$conditionValue] = $conditionValue; break; } } if (!API::HostGroup()->isWritable($hostGroupIdsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition host group. Host group does not exist or you have no access to it.')); } if (!API::Host()->isWritable($hostIdsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition host. Host does not exist or you have no access to it.')); } if (!API::Template()->isWritable($templateIdsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition template. Template does not exist or you have no access to it.')); } if (!API::Trigger()->isWritable($triggerIdsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition trigger. Trigger does not exist or you have no access to it.')); } if (!API::DRule()->isWritable($discoveryRuleIdsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition discovery rule. Discovery rule does not exist or you have no access to it.')); } if (!API::DCheck()->isWritable($discoveryCheckIdsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition discovery check. Discovery check does not exist or you have no access to it.')); } if (!API::Proxy()->isWritable($proxyIdsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition proxy. Proxy does not exist or you have no access to it.')); } }
foreach ($hosts as $host) { $templateids = array_merge($templateids, zbx_objectValues($host['parentTemplates'], 'templateid')); } $templateids = array_unique($templateids); $templates = API::Template()->get(array('templateids' => $templateids, 'selectParentTemplates' => array('hostid', 'name'))); $templates = zbx_toHash($templates, 'templateid'); foreach ($hosts as $host) { $interface = reset($host['interfaces']); $applications = array(new CLink(_('Applications'), 'applications.php?groupid=' . $_REQUEST['groupid'] . '&hostid=' . $host['hostid']), ' (' . $host['applications'] . ')'); $items = array(new CLink(_('Items'), 'items.php?filter_set=1&hostid=' . $host['hostid']), ' (' . $host['items'] . ')'); $triggers = array(new CLink(_('Triggers'), 'triggers.php?groupid=' . $_REQUEST['groupid'] . '&hostid=' . $host['hostid']), ' (' . $host['triggers'] . ')'); $graphs = array(new CLink(_('Graphs'), 'graphs.php?groupid=' . $_REQUEST['groupid'] . '&hostid=' . $host['hostid']), ' (' . $host['graphs'] . ')'); $discoveries = array(new CLink(_('Discovery'), 'host_discovery.php?&hostid=' . $host['hostid']), ' (' . $host['discoveries'] . ')'); $description = array(); if ($host['proxy_hostid']) { $proxy = API::Proxy()->get(array('proxyids' => $host['proxy_hostid'], 'output' => API_OUTPUT_EXTEND)); $proxy = reset($proxy); $description[] = $proxy['host'] . ':'; } $description[] = new CLink($host['name'], 'hosts.php?form=update&hostid=' . $host['hostid'] . url_param('groupid')); $hostIF = $interface['useip'] == INTERFACE_USE_IP ? $interface['ip'] : $interface['dns']; $hostIF .= empty($interface['port']) ? '' : ': ' . $interface['port']; $status_script = null; switch ($host['status']) { case HOST_STATUS_MONITORED: if ($host['maintenance_status'] == HOST_MAINTENANCE_STATUS_ON) { $status_caption = _('In maintenance'); $status_class = 'orange'; } else { $status_caption = _('Monitored'); $status_class = 'enabled';
$ifTab = new CTable(null, 'formElementTable'); $ifTab->setAttribute('id', 'IPMIInterfaces'); $ifTab->setAttribute('data-type', 'ipmi'); $helpTextWhenDragInterfaceIPMI = new CSpan(_('Drag here to change the type of the interface to "IPMI" type.')); $helpTextWhenDragInterfaceIPMI->addClass('dragHelpText'); $buttonCol = new CCol(new CButton('addIPMIInterface', _('Add'), null, 'link_menu'), 'interface-add-control'); $col = new CCol($helpTextWhenDragInterfaceIPMI); $col->setAttribute('colspan', 6); $buttonRow = new CRow(array($buttonCol, $col)); $buttonRow->setAttribute('id', 'IPMIIterfacesFooter'); $ifTab->addRow($buttonRow); $hostList->addRow(_('IPMI interfaces'), new CDiv($ifTab, 'border_dotted objectgroup interface-group'), false, null, 'interface-row interface-row-last'); // Proxy $cmbProxy = new CComboBox('proxy_hostid', $proxy_hostid); $cmbProxy->addItem(0, _('(no proxy)')); $db_proxies = API::Proxy()->get(array('output' => API_OUTPUT_EXTEND)); order_result($db_proxies, 'host'); foreach ($db_proxies as $proxy) { $cmbProxy->addItem($proxy['proxyid'], $proxy['host']); } $hostList->addRow(_('Monitored by proxy'), $cmbProxy); $cmbStatus = new CComboBox('status', $status); $cmbStatus->addItem(HOST_STATUS_MONITORED, _('Monitored')); $cmbStatus->addItem(HOST_STATUS_NOT_MONITORED, _('Not monitored')); $hostList->addRow(_('Status'), $cmbStatus); if ($_REQUEST['form'] == 'full_clone') { // host applications $hostApps = API::Application()->get(array('hostids' => $_REQUEST['hostid'], 'inherited' => false, 'output' => API_OUTPUT_EXTEND, 'preservekeys' => true)); if (!empty($hostApps)) { $applicationsList = array(); foreach ($hostApps as $hostAppId => $hostApp) {
/* * Display */ if (isset($_REQUEST['form'])) { $data = ['discovery_rule' => $discoveryRule, 'host_prototype' => ['hostid' => getRequest('hostid'), 'templateid' => getRequest('templateid'), 'host' => getRequest('host'), 'name' => getRequest('name'), 'status' => getRequest('status', HOST_STATUS_MONITORED), 'templates' => [], 'inventory' => ['inventory_mode' => getRequest('inventory_mode', $config['default_inventory_mode'])], 'groupPrototypes' => getRequest('group_prototypes', [])], 'groups' => [], 'show_inherited_macros' => getRequest('show_inherited_macros', 0)]; // add already linked and new templates $data['host_prototype']['templates'] = API::Template()->get(['output' => ['templateid', 'name'], 'templateids' => getRequest('templates', [])]); // add parent host $parentHost = API::Host()->get(['output' => API_OUTPUT_EXTEND, 'selectGroups' => ['groupid', 'name'], 'selectInterfaces' => API_OUTPUT_EXTEND, 'selectMacros' => ['macro', 'value'], 'hostids' => $discoveryRule['hostid'], 'templated_hosts' => true]); $parentHost = reset($parentHost); $data['parent_host'] = $parentHost; if (getRequest('group_links')) { $data['groups'] = API::HostGroup()->get(['output' => API_OUTPUT_EXTEND, 'groupids' => getRequest('group_links'), 'editable' => true, 'preservekeys' => true]); } if ($parentHost['proxy_hostid']) { $proxy = API::Proxy()->get(['output' => ['host', 'proxyid'], 'proxyids' => $parentHost['proxy_hostid'], 'limit' => 1]); $data['proxy'] = reset($proxy); } // host prototype edit form if (getRequest('hostid') && !getRequest('form_refresh')) { $data['host_prototype'] = array_merge($data['host_prototype'], $hostPrototype); if (!array_key_exists('inventory_mode', $data['host_prototype']['inventory'])) { $data['host_prototype']['inventory']['inventory_mode'] = HOST_INVENTORY_DISABLED; } $data['groups'] = API::HostGroup()->get(['output' => API_OUTPUT_EXTEND, 'groupids' => zbx_objectValues($data['host_prototype']['groupLinks'], 'groupid'), 'editable' => true, 'preservekeys' => true]); // add parent templates if ($hostPrototype['templateid']) { $data['parents'] = []; $hostPrototypeId = $hostPrototype['templateid']; while ($hostPrototypeId) { $parentHostPrototype = API::HostPrototype()->get(['output' => ['itemid', 'templateid'], 'selectParentHost' => ['hostid', 'name'], 'selectDiscoveryRule' => ['itemid'], 'hostids' => $hostPrototypeId]);
/** * Validate conditions. * * @static * @param $conditions * @return bool */ public static function validateConditions($conditions) { $conditions = zbx_toArray($conditions); $hostGroupidsAll = array(); $templateidsAll = array(); $triggeridsAll = array(); $hostidsAll = array(); $discoveryRuleidsAll = array(); $discoveryCheckidsAll = array(); $proxyidsAll = array(); $discoveryCheckTypes = discovery_check_type2str(); $discoveryObjectStatuses = discovery_object_status2str(); $timePeriodValidator = new CTimePeriodValidator(); foreach ($conditions as $condition) { switch ($condition['conditiontype']) { case CONDITION_TYPE_HOST_GROUP: $hostGroupidsAll[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_HOST_TEMPLATE: $templateidsAll[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_TRIGGER: $triggeridsAll[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_HOST: $hostidsAll[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_DRULE: $discoveryRuleidsAll[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_DCHECK: $discoveryCheckidsAll[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_PROXY: $proxyidsAll[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_TIME_PERIOD: if (!$timePeriodValidator->validate($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect action condition period "%s".', $condition['value'])); } break; case CONDITION_TYPE_DHOST_IP: if (!validate_ip_range($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect action condition ip "%s".', $condition['value'])); } break; case CONDITION_TYPE_DSERVICE_TYPE: if (!isset($discoveryCheckTypes[$condition['value']])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition discovery check.')); } break; case CONDITION_TYPE_DSERVICE_PORT: if (!validate_port_list($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect action condition port "%s".', $condition['value'])); } break; case CONDITION_TYPE_DSTATUS: if (!isset($discoveryObjectStatuses[$condition['value']])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition discovery status.')); } break; case CONDITION_TYPE_MAINTENANCE: // maintenance condition has no value... break; case CONDITION_TYPE_TRIGGER_NAME: case CONDITION_TYPE_TRIGGER_VALUE: case CONDITION_TYPE_TRIGGER_SEVERITY: case CONDITION_TYPE_NODE: case CONDITION_TYPE_DOBJECT: case CONDITION_TYPE_DUPTIME: case CONDITION_TYPE_DVALUE: case CONDITION_TYPE_APPLICATION: case CONDITION_TYPE_HOST_NAME: if (zbx_empty($condition['value'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty action condition.')); } break; default: self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition type.')); break; } } if (!API::HostGroup()->isWritable($hostGroupidsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition host group. Host group does not exist or you have no access to it.')); } if (!API::Host()->isWritable($hostidsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition host. Host does not exist or you have no access to it.')); } if (!API::Template()->isWritable($templateidsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition template. Template does not exist or you have no access to it.')); } if (!API::Trigger()->isWritable($triggeridsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition trigger. Trigger does not exist or you have no access to it.')); } if (!API::DRule()->isWritable($discoveryRuleidsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition discovery rule. Discovery rule does not exist or you have no access to it.')); } if (!API::DCheck()->isWritable($discoveryCheckidsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition discovery check. Discovery check does not exist or you have no access to it.')); } if (!API::Proxy()->isWritable($proxyidsAll)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect action condition proxy. Proxy does not exist or you have no access to it.')); } return true; }
$templateIds = array(); foreach ($hosts as $host) { $templateIds = array_merge($templateIds, zbx_objectValues($host['parentTemplates'], 'templateid')); } $templateIds = array_unique($templateIds); $templates = API::Template()->get(array('templateids' => $templateIds, 'selectParentTemplates' => array('hostid', 'name'))); $templates = zbx_toHash($templates, 'templateid'); // get proxy host IDs that that are not 0 $proxyHostIds = array(); foreach ($hosts as $host) { if ($host['proxy_hostid']) { $proxyHostIds[$host['proxy_hostid']] = $host['proxy_hostid']; } } if ($proxyHostIds) { $proxies = API::Proxy()->get(array('proxyids' => $proxyHostIds, 'output' => array('host'), 'preservekeys' => true)); } foreach ($hosts as $host) { $interface = reset($host['interfaces']); $applications = array(new CLink(_('Applications'), 'applications.php?groupid=' . $_REQUEST['groupid'] . '&hostid=' . $host['hostid']), ' (' . $host['applications'] . ')'); $items = array(new CLink(_('Items'), 'items.php?filter_set=1&hostid=' . $host['hostid']), ' (' . $host['items'] . ')'); $triggers = array(new CLink(_('Triggers'), 'triggers.php?groupid=' . $_REQUEST['groupid'] . '&hostid=' . $host['hostid']), ' (' . $host['triggers'] . ')'); $graphs = array(new CLink(_('Graphs'), 'graphs.php?groupid=' . $_REQUEST['groupid'] . '&hostid=' . $host['hostid']), ' (' . $host['graphs'] . ')'); $discoveries = array(new CLink(_('Discovery'), 'host_discovery.php?&hostid=' . $host['hostid']), ' (' . $host['discoveries'] . ')'); $httpTests = array(new CLink(_('Web'), 'httpconf.php?&hostid=' . $host['hostid']), ' (' . $host['httpTests'] . ')'); $description = array(); if (isset($proxies[$host['proxy_hostid']])) { $description[] = $proxies[$host['proxy_hostid']]['host'] . NAME_DELIMITER; } if ($host['discoveryRule']) { $description[] = new CLink($host['discoveryRule']['name'], 'host_prototypes.php?parent_discoveryid=' . $host['discoveryRule']['itemid'], 'parent-discovery');
} // interface if ($data['status'] == HOST_STATUS_PROXY_PASSIVE && empty($data['interface'])) { $data['interface'] = array('dns' => 'localhost', 'ip' => '127.0.0.1', 'useip' => 1, 'port' => '10051'); } // fetch available hosts, skip host prototypes $data['dbHosts'] = DBfetchArray(DBselect('SELECT h.hostid,h.proxy_hostid,h.name,h.flags' . ' FROM hosts h' . ' WHERE h.status IN (' . HOST_STATUS_MONITORED . ',' . HOST_STATUS_NOT_MONITORED . ')' . andDbNode('h.hostid') . ' AND h.flags<>' . ZBX_FLAG_DISCOVERY_PROTOTYPE)); order_result($data['dbHosts'], 'name'); // render view $proxyView = new CView('administration.proxy.edit', $data); $proxyView->render(); $proxyView->show(); } else { $data = array('displayNodes' => is_array(get_current_nodeid()), 'config' => select_config()); $sortfield = getPageSortField('host'); $data['proxies'] = API::Proxy()->get(array('editable' => true, 'selectHosts' => array('hostid', 'host', 'name', 'status'), 'output' => API_OUTPUT_EXTEND, 'sortfield' => $sortfield, 'limit' => $config['search_limit'] + 1)); $data['proxies'] = zbx_toHash($data['proxies'], 'proxyid'); $proxyIds = array_keys($data['proxies']); // sorting & paging order_result($data['proxies'], $sortfield, getPageSortOrder()); $data['paging'] = getPagingLine($data['proxies'], array('proxyid')); // nodes foreach ($data['proxies'] as &$proxy) { $proxy['nodename'] = $data['displayNodes'] ? get_node_name_by_elid($proxy['proxyid'], true) : ''; } unset($proxy); // calculate performance $dbPerformance = DBselect('SELECT h.proxy_hostid,SUM(1.0/i.delay) AS qps' . ' FROM items i,hosts h' . ' WHERE i.status=' . ITEM_STATUS_ACTIVE . ' AND i.hostid=h.hostid' . ' AND h.status=' . HOST_STATUS_MONITORED . ' AND i.delay<>0' . ' AND ' . dbConditionInt('h.proxy_hostid', $proxyIds) . ' GROUP BY h.proxy_hostid'); while ($performance = DBfetch($dbPerformance)) { if (isset($data['proxies'][$performance['proxy_hostid']])) { $data['proxies'][$performance['proxy_hostid']]['perf'] = round($performance['qps'], 2);
$queueData = zbx_toHash($queueData, 'itemid'); $items = API::Item()->get(['output' => ['itemid', 'hostid', 'name', 'key_'], 'selectHosts' => ['name'], 'itemids' => array_keys($queueData), 'webitems' => true, 'preservekeys' => true]); $items = CMacrosResolverHelper::resolveItemNames($items); // get hosts for queue items $hostIds = zbx_objectValues($items, 'hostid'); $hostIds = array_keys(array_flip($hostIds)); $hosts = API::Host()->get(['output' => ['hostid', 'proxy_hostid'], 'hostids' => $hostIds, 'preservekeys' => true]); // get proxies for those hosts $proxyHostIds = []; foreach ($hosts as $host) { if ($host['proxy_hostid']) { $proxyHostIds[$host['proxy_hostid']] = $host['proxy_hostid']; } } if ($proxyHostIds) { $proxies = API::Proxy()->get(['proxyids' => $proxyHostIds, 'output' => ['proxyid', 'host'], 'preservekeys' => true]); } $table->setHeader([_('Scheduled check'), _('Delayed by'), _('Host'), _('Name')]); $i = 0; foreach ($queueData as $itemData) { if (!isset($items[$itemData['itemid']])) { continue; } // display only the first 500 items $i++; if ($i > QUEUE_DETAIL_ITEM_COUNT) { break; } $item = $items[$itemData['itemid']]; $host = reset($item['hosts']); $table->addRow([zbx_date2str(DATE_TIME_FORMAT_SECONDS, $itemData['nextcheck']), zbx_date2age($itemData['nextcheck']), isset($proxies[$hosts[$item['hostid']]['proxy_hostid']]) ? $proxies[$hosts[$item['hostid']]['proxy_hostid']]['host'] . NAME_DELIMITER . $host['name'] : $host['name'], $item['name_expanded']]);
/** * Converts numerical action condition values to their corresponding string values according to action condition type. * * For action condition types such as: hosts, host groups, templates, proxies, triggers, discovery rules * and discovery checks, action condition values contain IDs. All unique IDs are first collected and then queried. * For other action condition types values are returned as they are or converted using simple string convertion * functions according to action condition type. * * @param array $actions array of actions * @param array $action['filter'] array containing arrays of action conditions and other data * @param array $action['filter']['conditions'] array of action conditions * @param array $config array containing configuration parameters for getting trigger * severity names * * @return array returns an array of actions condition string values */ function actionConditionValueToString(array $actions, array $config) { $result = []; $groupIds = []; $triggerIds = []; $hostIds = []; $templateIds = []; $proxyIds = []; $dRuleIds = []; $dCheckIds = []; foreach ($actions as $i => $action) { $result[$i] = []; foreach ($action['filter']['conditions'] as $j => $condition) { // unknown types and all of the default values for other types are 'Unknown' $result[$i][$j] = _('Unknown'); switch ($condition['conditiontype']) { case CONDITION_TYPE_HOST_GROUP: $groupIds[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_TRIGGER: $triggerIds[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_HOST: $hostIds[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_TEMPLATE: $templateIds[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_PROXY: $proxyIds[$condition['value']] = $condition['value']; break; // return values as is for following condition types // return values as is for following condition types case CONDITION_TYPE_TRIGGER_NAME: case CONDITION_TYPE_HOST_METADATA: case CONDITION_TYPE_HOST_NAME: case CONDITION_TYPE_TIME_PERIOD: case CONDITION_TYPE_DHOST_IP: case CONDITION_TYPE_DSERVICE_PORT: case CONDITION_TYPE_DUPTIME: case CONDITION_TYPE_DVALUE: case CONDITION_TYPE_APPLICATION: $result[$i][$j] = $condition['value']; break; case CONDITION_TYPE_EVENT_ACKNOWLEDGED: $result[$i][$j] = $condition['value'] ? _('Ack') : _('Not Ack'); break; case CONDITION_TYPE_MAINTENANCE: $result[$i][$j] = _('maintenance'); break; case CONDITION_TYPE_TRIGGER_VALUE: $result[$i][$j] = trigger_value2str($condition['value']); break; case CONDITION_TYPE_TRIGGER_SEVERITY: $result[$i][$j] = getSeverityName($condition['value'], $config); break; case CONDITION_TYPE_DRULE: $dRuleIds[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_DCHECK: $dCheckIds[$condition['value']] = $condition['value']; break; case CONDITION_TYPE_DOBJECT: $result[$i][$j] = discovery_object2str($condition['value']); break; case CONDITION_TYPE_DSERVICE_TYPE: $result[$i][$j] = discovery_check_type2str($condition['value']); break; case CONDITION_TYPE_DSTATUS: $result[$i][$j] = discovery_object_status2str($condition['value']); break; case CONDITION_TYPE_EVENT_TYPE: $result[$i][$j] = eventType($condition['value']); break; } } } $groups = []; $triggers = []; $hosts = []; $templates = []; $proxies = []; $dRules = []; $dChecks = []; if ($groupIds) { $groups = API::HostGroup()->get(['output' => ['name'], 'groupids' => $groupIds, 'preservekeys' => true]); } if ($triggerIds) { $triggers = API::Trigger()->get(['output' => ['description'], 'triggerids' => $triggerIds, 'expandDescription' => true, 'selectHosts' => ['name'], 'preservekeys' => true]); } if ($hostIds) { $hosts = API::Host()->get(['output' => ['name'], 'hostids' => $hostIds, 'preservekeys' => true]); } if ($templateIds) { $templates = API::Template()->get(['output' => ['name'], 'templateids' => $templateIds, 'preservekeys' => true]); } if ($proxyIds) { $proxies = API::Proxy()->get(['output' => ['host'], 'proxyids' => $proxyIds, 'preservekeys' => true]); } if ($dRuleIds) { $dRules = API::DRule()->get(['output' => ['name'], 'druleids' => $dRuleIds, 'preservekeys' => true]); } if ($dCheckIds) { $dChecks = API::DCheck()->get(['output' => ['type', 'key_', 'ports'], 'dcheckids' => $dCheckIds, 'selectDRules' => ['name'], 'preservekeys' => true]); } if ($groups || $triggers || $hosts || $templates || $proxies || $dRules || $dChecks) { foreach ($actions as $i => $action) { foreach ($action['filter']['conditions'] as $j => $condition) { $id = $condition['value']; switch ($condition['conditiontype']) { case CONDITION_TYPE_HOST_GROUP: if (isset($groups[$id])) { $result[$i][$j] = $groups[$id]['name']; } break; case CONDITION_TYPE_TRIGGER: if (isset($triggers[$id])) { $host = reset($triggers[$id]['hosts']); $result[$i][$j] = $host['name'] . NAME_DELIMITER . $triggers[$id]['description']; } break; case CONDITION_TYPE_HOST: if (isset($hosts[$id])) { $result[$i][$j] = $hosts[$id]['name']; } break; case CONDITION_TYPE_TEMPLATE: if (isset($templates[$id])) { $result[$i][$j] = $templates[$id]['name']; } break; case CONDITION_TYPE_PROXY: if (isset($proxies[$id])) { $result[$i][$j] = $proxies[$id]['host']; } break; case CONDITION_TYPE_DRULE: if (isset($dRules[$id])) { $result[$i][$j] = $dRules[$id]['name']; } break; case CONDITION_TYPE_DCHECK: if (isset($dChecks[$id])) { $drule = reset($dChecks[$id]['drules']); $type = $dChecks[$id]['type']; $key_ = $dChecks[$id]['key_']; $ports = $dChecks[$id]['ports']; $dCheck = discovery_check2str($type, $key_, $ports); $result[$i][$j] = $drule['name'] . NAME_DELIMITER . $dCheck; } break; } } } } return $result; }