$hostGraphPrototypes = API::GraphPrototype()->get(array('hostids' => $_REQUEST['hostid'], 'discoveryids' => $hostDiscoveryRuleids, 'inherited' => false, 'selectHosts' => array('hostid'), 'output' => array('graphid', 'name'))); if (!empty($hostGraphPrototypes)) { $prototypeList = array(); foreach ($hostGraphPrototypes as $graphPrototype) { if (count($graphPrototype['hosts']) == 1) { $prototypeList[$graphPrototype['graphid']] = $graphPrototype['name']; } } order_result($prototypeList); $listBox = new CListBox('graphPrototypes', null, 8); $listBox->setAttribute('disabled', 'disabled'); $listBox->addItems($prototypeList); $hostList->addRow(_('Graph prototypes'), $listBox); } // host prototypes $hostPrototypes = API::HostPrototype()->get(array('discoveryids' => $hostDiscoveryRuleids, 'inherited' => false, 'output' => array('hostid', 'name'))); if ($hostPrototypes) { $prototypeList = array(); foreach ($hostPrototypes as $hostPrototype) { $prototypeList[$hostPrototype['hostid']] = $hostPrototype['name']; } order_result($prototypeList); $listBox = new CListBox('hostPrototypes', null, 8); $listBox->setAttribute('disabled', 'disabled'); $listBox->addItems($prototypeList); $hostList->addRow(_('Host prototypes'), $listBox); } } $divTabs->addTab('hostTab', _('Host'), $hostList); // templates $tmplList = new CFormList('tmpllist');
/** * Import discovery rules. * * @throws Exception */ protected function processDiscoveryRules() { $allDiscoveryRules = $this->getFormattedDiscoveryRules(); if (empty($allDiscoveryRules)) { return; } // unset rules that are related to hosts we did not process foreach ($allDiscoveryRules as $host => $discoveryRules) { if (!$this->referencer->isProcessedHost($host)) { unset($allDiscoveryRules[$host]); } } $itemsToCreate = array(); $itemsToUpdate = array(); foreach ($allDiscoveryRules as $host => $discoveryRules) { $hostid = $this->referencer->resolveHostOrTemplate($host); foreach ($discoveryRules as $item) { $item['hostid'] = $hostid; if (isset($item['interface_ref'])) { $item['interfaceid'] = $this->referencer->interfacesCache[$hostid][$item['interface_ref']]; } unset($item['item_prototypes']); unset($item['trigger_prototypes']); unset($item['graph_prototypes']); unset($item['host_prototypes']); $itemId = $this->referencer->resolveItem($hostid, $item['key_']); if ($itemId) { $item['itemid'] = $itemId; $itemsToUpdate[] = $item; } else { $itemsToCreate[] = $item; } } } // create/update discovery rules and add processed rules to array $processedRules $processedRules = array(); if ($this->options['discoveryRules']['createMissing'] && $itemsToCreate) { $newItemsIds = API::DiscoveryRule()->create($itemsToCreate); foreach ($newItemsIds['itemids'] as $inum => $itemid) { $item = $itemsToCreate[$inum]; $this->referencer->addItemRef($item['hostid'], $item['key_'], $itemid); } foreach ($itemsToCreate as $item) { $processedRules[$item['hostid']][$item['key_']] = 1; } } if ($this->options['discoveryRules']['updateExisting'] && $itemsToUpdate) { API::DiscoveryRule()->update($itemsToUpdate); foreach ($itemsToUpdate as $item) { $processedRules[$item['hostid']][$item['key_']] = 1; } } // refresh discovery rules because templated ones can be inherited to host and used for prototypes $this->referencer->refreshItems(); // process prototypes $prototypesToUpdate = array(); $prototypesToCreate = array(); $hostPrototypesToUpdate = array(); $hostPrototypesToCreate = array(); foreach ($allDiscoveryRules as $host => $discoveryRules) { $hostid = $this->referencer->resolveHostOrTemplate($host); foreach ($discoveryRules as $item) { // if rule was not processed we should not create/update any of its prototypes if (!isset($processedRules[$hostid][$item['key_']])) { continue; } $item['hostid'] = $hostid; $itemId = $this->referencer->resolveItem($hostid, $item['key_']); // prototypes foreach ($item['item_prototypes'] as $prototype) { $prototype['hostid'] = $hostid; $applicationsIds = array(); foreach ($prototype['applications'] as $application) { $applicationsIds[] = $this->referencer->resolveApplication($hostid, $application['name']); } $prototype['applications'] = $applicationsIds; if (isset($prototype['interface_ref'])) { $prototype['interfaceid'] = $this->referencer->interfacesCache[$hostid][$prototype['interface_ref']]; } if ($prototype['valuemap']) { $valueMapId = $this->referencer->resolveValueMap($prototype['valuemap']['name']); if (!$valueMapId) { throw new Exception(_s('Cannot find value map "%1$s" used for item prototype "%2$s" of discovery rule "%3$s" on "%4$s".', $prototype['valuemap']['name'], $prototype['name'], $item['name'], $host)); } $prototype['valuemapid'] = $valueMapId; } $prototypeId = $this->referencer->resolveItem($hostid, $prototype['key_']); $prototype['rule'] = array('hostid' => $hostid, 'key' => $item['key_']); if ($prototypeId) { $prototype['itemid'] = $prototypeId; $prototypesToUpdate[] = $prototype; } else { $prototypesToCreate[] = $prototype; } } // host prototype foreach ($item['host_prototypes'] as $hostPrototype) { // resolve group prototypes $groupLinks = array(); foreach ($hostPrototype['group_links'] as $groupLink) { $groupId = $this->referencer->resolveGroup($groupLink['group']['name']); if (!$groupId) { throw new Exception(_s('Cannot find host group "%1$s" for host prototype "%2$s" of discovery rule "%3$s" on "%4$s".', $groupLink['group']['name'], $hostPrototype['name'], $item['name'], $host)); } $groupLinks[] = array('groupid' => $groupId); } $hostPrototype['groupLinks'] = $groupLinks; $hostPrototype['groupPrototypes'] = $hostPrototype['group_prototypes']; unset($hostPrototype['group_links'], $hostPrototype['group_prototypes']); // resolve templates $templates = array(); foreach ($hostPrototype['templates'] as $template) { $templateId = $this->referencer->resolveTemplate($template['name']); if (!$templateId) { throw new Exception(_s('Cannot find template "%1$s" for host prototype "%2$s" of discovery rule "%3$s" on "%4$s".', $template['name'], $hostPrototype['name'], $item['name'], $host)); } $templates[] = array('templateid' => $templateId); } $hostPrototype['templates'] = $templates; $hostPrototypeId = $this->referencer->resolveHostPrototype($hostid, $itemId, $hostPrototype['host']); if ($hostPrototypeId) { $hostPrototype['hostid'] = $hostPrototypeId; $hostPrototypesToUpdate[] = $hostPrototype; } else { $hostPrototype['ruleid'] = $itemId; $hostPrototypesToCreate[] = $hostPrototype; } } if (isset($item['interface_ref'])) { $item['interfaceid'] = $this->referencer->interfacesCache[$hostid][$item['interface_ref']]; } unset($item['item_prototypes']); unset($item['trigger_prototypes']); unset($item['graph_prototypes']); unset($item['host_prototypes']); $itemsId = $this->referencer->resolveItem($hostid, $item['key_']); if ($itemsId) { $item['itemid'] = $itemsId; $itemsToUpdate[] = $item; } else { $itemsToCreate[] = $item; } } } if ($prototypesToCreate) { foreach ($prototypesToCreate as &$prototype) { $prototype['ruleid'] = $this->referencer->resolveItem($prototype['rule']['hostid'], $prototype['rule']['key']); } unset($prototype); $newPrototypeIds = API::ItemPrototype()->create($prototypesToCreate); foreach ($newPrototypeIds['itemids'] as $inum => $itemid) { $item = $prototypesToCreate[$inum]; $this->referencer->addItemRef($item['hostid'], $item['key_'], $itemid); } } if ($prototypesToUpdate) { foreach ($prototypesToCreate as &$prototype) { $prototype['ruleid'] = $this->referencer->resolveItem($prototype['rule']['hostid'], $prototype['rule']['key']); } unset($prototype); API::ItemPrototype()->update($prototypesToUpdate); } if ($hostPrototypesToCreate) { API::HostPrototype()->create($hostPrototypesToCreate); } if ($hostPrototypesToUpdate) { API::HostPrototype()->update($hostPrototypesToUpdate); } // refresh prototypes because templated ones can be inherited to host and used in triggers prototypes or graph prototypes $this->referencer->refreshItems(); // first we need to create item prototypes and only then graph prototypes $triggersToCreate = array(); $triggersToUpdate = array(); $graphsToCreate = array(); $graphsToUpdate = array(); foreach ($allDiscoveryRules as $host => $discoveryRules) { $hostid = $this->referencer->resolveHostOrTemplate($host); foreach ($discoveryRules as $item) { // if rule was not processed we should not create/update any of its prototypes if (!isset($processedRules[$hostid][$item['key_']])) { continue; } // trigger prototypes foreach ($item['trigger_prototypes'] as $trigger) { $triggerId = $this->referencer->resolveTrigger($trigger['description'], $trigger['expression']); if ($triggerId) { $trigger['triggerid'] = $triggerId; $triggersToUpdate[] = $trigger; } else { $triggersToCreate[] = $trigger; } } // graph prototypes foreach ($item['graph_prototypes'] as $graph) { $graphHostIds = array(); if ($graph['ymin_item_1']) { $hostId = $this->referencer->resolveHostOrTemplate($graph['ymin_item_1']['host']); $itemId = $hostId ? $this->referencer->resolveItem($hostId, $graph['ymin_item_1']['key']) : false; if (!$itemId) { throw new Exception(_s('Cannot find item "%1$s" on "%2$s" used as the Y axis MIN value for graph prototype "%3$s" of discovery rule "%4$s" on "%5$s".', $graph['ymin_item_1']['key'], $graph['ymin_item_1']['host'], $graph['name'], $item['name'], $host)); } $graph['ymin_itemid'] = $itemId; } if ($graph['ymax_item_1']) { $hostId = $this->referencer->resolveHostOrTemplate($graph['ymax_item_1']['host']); $itemId = $hostId ? $this->referencer->resolveItem($hostId, $graph['ymax_item_1']['key']) : false; if (!$itemId) { throw new Exception(_s('Cannot find item "%1$s" on "%2$s" used as the Y axis MAX value for graph prototype "%3$s" of discovery rule "%4$s" on "%5$s".', $graph['ymax_item_1']['key'], $graph['ymax_item_1']['host'], $graph['name'], $item['name'], $host)); } $graph['ymax_itemid'] = $itemId; } foreach ($graph['gitems'] as &$gitem) { if (!($gitemHostId = $this->referencer->resolveHostOrTemplate($gitem['item']['host']))) { throw new Exception(_s('Cannot find host or template "%1$s" used in graph "%2$s".', $gitem['item']['host'], $graph['name'])); } $gitem['itemid'] = $this->referencer->resolveItem($gitemHostId, $gitem['item']['key']); $graphHostIds[$gitemHostId] = $gitemHostId; } unset($gitem); // TODO: do this for all graphs at once $sql = 'SELECT g.graphid' . ' FROM graphs g,graphs_items gi,items i' . ' WHERE g.graphid=gi.graphid' . ' AND gi.itemid=i.itemid' . ' AND g.name=' . zbx_dbstr($graph['name']) . ' AND ' . dbConditionInt('i.hostid', $graphHostIds); $graphExists = DBfetch(DBselect($sql)); if ($graphExists) { $dbGraph = API::GraphPrototype()->get(array('graphids' => $graphExists['graphid'], 'output' => array('graphid'), 'editable' => true)); if (empty($dbGraph)) { throw new Exception(_s('No permission for graph "%1$s".', $graph['name'])); } $graph['graphid'] = $graphExists['graphid']; $graphsToUpdate[] = $graph; } else { $graphsToCreate[] = $graph; } } } } if ($triggersToCreate) { API::TriggerPrototype()->create($triggersToCreate); } if ($triggersToUpdate) { API::TriggerPrototype()->update($triggersToUpdate); } if ($graphsToCreate) { API::GraphPrototype()->create($graphsToCreate); } if ($graphsToUpdate) { API::GraphPrototype()->update($graphsToUpdate); } }
/** * Get discovery rules related objects from database. * * @param array $items * * @return array */ protected function prepareDiscoveryRules(array $items) { foreach ($items as &$item) { $item['itemPrototypes'] = array(); $item['graphPrototypes'] = array(); $item['triggerPrototypes'] = array(); $item['hostPrototypes'] = array(); } unset($item); // gather item prototypes $prototypes = API::ItemPrototype()->get(array('discoveryids' => zbx_objectValues($items, 'itemid'), 'output' => $this->dataFields['discoveryrule'], 'selectApplications' => API_OUTPUT_EXTEND, 'selectDiscoveryRule' => array('itemid'), 'inherited' => false, 'preservekeys' => true)); // gather value maps $valueMapIds = zbx_objectValues($prototypes, 'valuemapid'); $DbValueMaps = DBselect('SELECT vm.valuemapid, vm.name FROM valuemaps vm WHERE ' . dbConditionInt('vm.valuemapid', $valueMapIds)); $valueMaps = array(); while ($valueMap = DBfetch($DbValueMaps)) { $valueMaps[$valueMap['valuemapid']] = $valueMap['name']; } foreach ($prototypes as $prototype) { $prototype['valuemap'] = array(); if ($prototype['valuemapid']) { $prototype['valuemap']['name'] = $valueMaps[$prototype['valuemapid']]; } $items[$prototype['discoveryRule']['itemid']]['itemPrototypes'][] = $prototype; } // gather graph prototypes $graphs = API::GraphPrototype()->get(array('discoveryids' => zbx_objectValues($items, 'itemid'), 'selectDiscoveryRule' => API_OUTPUT_EXTEND, 'selectGraphItems' => API_OUTPUT_EXTEND, 'output' => API_OUTPUT_EXTEND, 'inherited' => false, 'preservekeys' => true)); $graphs = $this->prepareGraphs($graphs); foreach ($graphs as $graph) { $items[$graph['discoveryRule']['itemid']]['graphPrototypes'][] = $graph; } // gather trigger prototypes $triggers = API::TriggerPrototype()->get(array('discoveryids' => zbx_objectValues($items, 'itemid'), 'output' => API_OUTPUT_EXTEND, 'selectDiscoveryRule' => API_OUTPUT_EXTEND, 'selectItems' => array('flags', 'type'), 'inherited' => false, 'preservekeys' => true, 'expandData' => true)); foreach ($triggers as $trigger) { foreach ($trigger['items'] as $item) { if ($item['flags'] == ZBX_FLAG_DISCOVERY_CREATED || $item['type'] == ITEM_TYPE_HTTPTEST) { continue 2; } } $trigger['expression'] = explode_exp($trigger['expression']); $items[$trigger['discoveryRule']['itemid']]['triggerPrototypes'][] = $trigger; } // gather host prototypes $hostPrototypes = API::HostPrototype()->get(array('discoveryids' => zbx_objectValues($items, 'itemid'), 'output' => API_OUTPUT_EXTEND, 'selectGroupLinks' => API_OUTPUT_EXTEND, 'selectGroupPrototypes' => API_OUTPUT_EXTEND, 'selectDiscoveryRule' => API_OUTPUT_EXTEND, 'selectTemplates' => API_OUTPUT_EXTEND, 'inherited' => false, 'preservekeys' => true)); // replace group prototype group IDs with references $groupIds = array(); foreach ($hostPrototypes as $hostPrototype) { foreach ($hostPrototype['groupLinks'] as $groupLink) { $groupIds[$groupLink['groupid']] = $groupLink['groupid']; } } $groups = $this->getGroupsReferences($groupIds); // export the groups used in group prototypes $this->data['groups'] += $groups; foreach ($hostPrototypes as $hostPrototype) { foreach ($hostPrototype['groupLinks'] as &$groupLink) { $groupLink['groupid'] = $groups[$groupLink['groupid']]; } unset($groupLink); $items[$hostPrototype['discoveryRule']['itemid']]['hostPrototypes'][] = $hostPrototype; } return $items; }
/** * Deletes discovery rules and prototypes from DB that are missing in XML. * * @return null */ protected function deleteMissingDiscoveryRules() { if (!$this->options['discoveryRules']['deleteMissing']) { return; } $processedHostIds = $this->importedObjectContainer->getHostIds(); $processedTemplateIds = $this->importedObjectContainer->getTemplateIds(); $processedHostIds = array_merge($processedHostIds, $processedTemplateIds); // no hosts or templates have been processed if (!$processedHostIds) { return; } $discoveryRuleIdsXML = array(); $allDiscoveryRules = $this->getFormattedDiscoveryRules(); if ($allDiscoveryRules) { foreach ($allDiscoveryRules as $host => $discoveryRules) { $hostId = $this->referencer->resolveHostOrTemplate($host); foreach ($discoveryRules as $discoveryRule) { $discoveryRuleId = $this->referencer->resolveItem($hostId, $discoveryRule['key_']); if ($discoveryRuleId) { $discoveryRuleIdsXML[$discoveryRuleId] = $discoveryRuleId; } } } } $dbDiscoveryRuleIds = API::DiscoveryRule()->get(array('output' => array('itemid'), 'hostids' => $processedHostIds, 'preservekeys' => true, 'nopermissions' => true, 'inherited' => false)); $discoveryRulesToDelete = array_diff_key($dbDiscoveryRuleIds, $discoveryRuleIdsXML); if ($discoveryRulesToDelete) { API::DiscoveryRule()->delete(array_keys($discoveryRulesToDelete)); } // refresh discovery rules because templated ones can be inherited to host and used for prototypes $this->referencer->refreshItems(); $hostPrototypeIdsXML = array(); $triggerPrototypeIdsXML = array(); $itemPrototypeIdsXML = array(); $graphPrototypeIdsXML = array(); foreach ($allDiscoveryRules as $host => $discoveryRules) { $hostId = $this->referencer->resolveHostOrTemplate($host); foreach ($discoveryRules as $discoveryRule) { $discoveryRuleId = $this->referencer->resolveItem($hostId, $discoveryRule['key_']); if ($discoveryRuleId) { // gather host prototype IDs to delete foreach ($discoveryRule['host_prototypes'] as $hostPrototype) { $hostPrototypeId = $this->referencer->resolveHostPrototype($hostId, $discoveryRuleId, $hostPrototype['host']); if ($hostPrototypeId) { $hostPrototypeIdsXML[$hostPrototypeId] = $hostPrototypeId; } } // gather trigger prototype IDs to delete foreach ($discoveryRule['trigger_prototypes'] as $triggerPrototype) { $triggerPrototypeId = $this->referencer->resolveTrigger($triggerPrototype['description'], $triggerPrototype['expression']); if ($triggerPrototypeId) { $triggerPrototypeIdsXML[$triggerPrototypeId] = $triggerPrototypeId; } } // gather graph prototype IDs to delete foreach ($discoveryRule['graph_prototypes'] as $graphPrototype) { $graphPrototypeId = $this->referencer->resolveGraph($hostId, $graphPrototype['name']); if ($graphPrototypeId) { $graphPrototypeIdsXML[$graphPrototypeId] = $graphPrototypeId; } } // gather item prototype IDs to delete foreach ($discoveryRule['item_prototypes'] as $itemPrototype) { $itemPrototypeId = $this->referencer->resolveItem($hostId, $itemPrototype['key_']); if ($itemPrototypeId) { $itemPrototypeIdsXML[$itemPrototypeId] = $itemPrototypeId; } } } } } // delete missing host prototypes $dbHostPrototypeIds = API::HostPrototype()->get(array('output' => array('hostid'), 'discoveryids' => $discoveryRuleIdsXML, 'preservekeys' => true, 'nopermissions' => true, 'inherited' => false)); $hostPrototypesToDelete = array_diff_key($dbHostPrototypeIds, $hostPrototypeIdsXML); if ($hostPrototypesToDelete) { API::HostPrototype()->delete(array_keys($hostPrototypesToDelete)); } // delete missing trigger prototypes $dbTriggerPrototypeIds = API::TriggerPrototype()->get(array('output' => array('triggerid'), 'hostids' => $processedHostIds, 'preservekeys' => true, 'nopermissions' => true, 'inherited' => false)); $triggerPrototypesToDelete = array_diff_key($dbTriggerPrototypeIds, $triggerPrototypeIdsXML); // unlike triggers that belong to multiple hosts, trigger prototypes do not, so we just delete them if ($triggerPrototypesToDelete) { API::TriggerPrototype()->delete(array_keys($triggerPrototypesToDelete)); } // delete missing graph prototypes $dbGraphPrototypeIds = API::GraphPrototype()->get(array('output' => array('graphid'), 'hostids' => $processedHostIds, 'preservekeys' => true, 'nopermissions' => true, 'inherited' => false)); $graphPrototypesToDelete = array_diff_key($dbGraphPrototypeIds, $graphPrototypeIdsXML); // unlike graphs that belong to multiple hosts, graph prototypes do not, so we just delete them if ($graphPrototypesToDelete) { API::GraphPrototype()->delete(array_keys($graphPrototypesToDelete)); } // delete missing item prototypes $dbItemPrototypeIds = API::ItemPrototype()->get(array('output' => array('itemid'), 'hostids' => $processedHostIds, 'preservekeys' => true, 'nopermissions' => true, 'inherited' => false)); $itemPrototypesToDelete = array_diff_key($dbItemPrototypeIds, $itemPrototypeIdsXML); if ($itemPrototypesToDelete) { API::ItemPrototype()->delete(array_keys($itemPrototypesToDelete)); } }
protected function link(array $templateids, array $targetids) { if (!$this->isWritable($targetids)) { self::exception(ZBX_API_ERROR_PERMISSIONS, _('No permissions to referred object or it does not exist!')); } $links = parent::link($templateids, $targetids); foreach ($targetids as $targetid) { $linked_templates = API::Template()->get(['output' => [], 'hostids' => [$targetid], 'nopermissions' => true]); $result = DBselect('SELECT i.key_,count(*)' . ' FROM items i' . ' WHERE ' . dbConditionInt('i.hostid', array_merge($templateids, array_keys($linked_templates))) . ' GROUP BY i.key_' . ' HAVING count(*)>1', 1); if ($row = DBfetch($result)) { $target_templates = API::HostPrototype()->get(['output' => ['name'], 'hostids' => [$targetid], 'nopermissions' => true]); self::exception(ZBX_API_ERROR_PARAMETERS, _s('Item "%1$s" already exists on "%2$s", inherited from another template.', $row['key_'], $target_templates[0]['name'])); } } return $links; }
protected function link(array $templateIds, array $targetIds) { $hostsLinkageInserts = parent::link($templateIds, $targetIds); foreach ($hostsLinkageInserts as $hostTplIds) { Manager::Application()->link($hostTplIds['templateid'], $hostTplIds['hostid']); API::DiscoveryRule()->syncTemplates(array('hostids' => $hostTplIds['hostid'], 'templateids' => $hostTplIds['templateid'])); API::Itemprototype()->syncTemplates(array('hostids' => $hostTplIds['hostid'], 'templateids' => $hostTplIds['templateid'])); API::HostPrototype()->syncTemplates(array('hostids' => $hostTplIds['hostid'], 'templateids' => $hostTplIds['templateid'])); API::Item()->syncTemplates(array('hostids' => $hostTplIds['hostid'], 'templateids' => $hostTplIds['templateid'])); Manager::HttpTest()->link($hostTplIds['templateid'], $hostTplIds['hostid']); } // we do linkage in two separate loops because for triggers you need all items already created on host foreach ($hostsLinkageInserts as $hostTplIds) { API::Trigger()->syncTemplates(array('hostids' => $hostTplIds['hostid'], 'templateids' => $hostTplIds['templateid'])); API::TriggerPrototype()->syncTemplates(array('hostids' => $hostTplIds['hostid'], 'templateids' => $hostTplIds['templateid'])); API::GraphPrototype()->syncTemplates(array('hostids' => $hostTplIds['hostid'], 'templateids' => $hostTplIds['templateid'])); API::Graph()->syncTemplates(array('hostids' => $hostTplIds['hostid'], 'templateids' => $hostTplIds['templateid'])); } foreach ($hostsLinkageInserts as $hostTplIds) { API::Trigger()->syncTemplateDependencies(array('templateids' => $hostTplIds['templateid'], 'hostids' => $hostTplIds['hostid'])); } return $hostsLinkageInserts; }
protected function addRelatedObjects(array $options, array $result) { $result = parent::addRelatedObjects($options, $result); $itemIds = array_keys($result); // adding items if (!is_null($options['selectItems'])) { if ($options['selectItems'] != API_OUTPUT_COUNT) { $relationMap = $this->createRelationMap($result, 'parent_itemid', 'itemid', 'item_discovery'); $items = API::ItemPrototype()->get(array('output' => $options['selectItems'], 'nodeids' => $options['nodeids'], 'itemids' => $relationMap->getRelatedIds(), 'nopermissions' => true, 'preservekeys' => true)); $result = $relationMap->mapMany($result, $items, 'items', $options['limitSelects']); } else { $items = API::ItemPrototype()->get(array('nodeids' => $options['nodeids'], 'discoveryids' => $itemIds, 'nopermissions' => true, 'countOutput' => true, 'groupCount' => true)); $items = zbx_toHash($items, 'parent_itemid'); foreach ($result as $itemid => $item) { $result[$itemid]['items'] = isset($items[$itemid]) ? $items[$itemid]['rowscount'] : 0; } } } // adding triggers if (!is_null($options['selectTriggers'])) { if ($options['selectTriggers'] != API_OUTPUT_COUNT) { $relationMap = new CRelationMap(); $res = DBselect('SELECT id.parent_itemid,f.triggerid' . ' FROM item_discovery id,items i,functions f' . ' WHERE ' . dbConditionInt('id.parent_itemid', $itemIds) . ' AND id.itemid=i.itemid' . ' AND i.itemid=f.itemid'); while ($relation = DBfetch($res)) { $relationMap->addRelation($relation['parent_itemid'], $relation['triggerid']); } $triggers = API::TriggerPrototype()->get(array('output' => $options['selectTriggers'], 'nodeids' => $options['nodeids'], 'triggerids' => $relationMap->getRelatedIds(), 'preservekeys' => true)); $result = $relationMap->mapMany($result, $triggers, 'triggers', $options['limitSelects']); } else { $triggers = API::TriggerPrototype()->get(array('nodeids' => $options['nodeids'], 'discoveryids' => $itemIds, 'countOutput' => true, 'groupCount' => true)); $triggers = zbx_toHash($triggers, 'parent_itemid'); foreach ($result as $itemid => $item) { $result[$itemid]['triggers'] = isset($triggers[$itemid]) ? $triggers[$itemid]['rowscount'] : 0; } } } // adding graphs if (!is_null($options['selectGraphs'])) { if ($options['selectGraphs'] != API_OUTPUT_COUNT) { $relationMap = new CRelationMap(); $res = DBselect('SELECT id.parent_itemid,gi.graphid' . ' FROM item_discovery id,items i,graphs_items gi' . ' WHERE ' . dbConditionInt('id.parent_itemid', $itemIds) . ' AND id.itemid=i.itemid' . ' AND i.itemid=gi.itemid'); while ($relation = DBfetch($res)) { $relationMap->addRelation($relation['parent_itemid'], $relation['graphid']); } $graphs = API::GraphPrototype()->get(array('output' => $options['selectGraphs'], 'nodeids' => $options['nodeids'], 'graphids' => $relationMap->getRelatedIds(), 'preservekeys' => true)); $result = $relationMap->mapMany($result, $graphs, 'graphs', $options['limitSelects']); } else { $graphs = API::GraphPrototype()->get(array('nodeids' => $options['nodeids'], 'discoveryids' => $itemIds, 'countOutput' => true, 'groupCount' => true)); $graphs = zbx_toHash($graphs, 'parent_itemid'); foreach ($result as $itemid => $item) { $result[$itemid]['graphs'] = isset($graphs[$itemid]) ? $graphs[$itemid]['rowscount'] : 0; } } } // adding hosts if ($options['selectHostPrototypes'] !== null) { if ($options['selectHostPrototypes'] != API_OUTPUT_COUNT) { $relationMap = $this->createRelationMap($result, 'parent_itemid', 'hostid', 'host_discovery'); $hostPrototypes = API::HostPrototype()->get(array('output' => $options['selectHostPrototypes'], 'nodeids' => $options['nodeids'], 'hostids' => $relationMap->getRelatedIds(), 'nopermissions' => true, 'preservekeys' => true)); $result = $relationMap->mapMany($result, $hostPrototypes, 'hostPrototypes', $options['limitSelects']); } else { $hostPrototypes = API::HostPrototype()->get(array('nodeids' => $options['nodeids'], 'discoveryids' => $itemIds, 'nopermissions' => true, 'countOutput' => true, 'groupCount' => true)); $hostPrototypes = zbx_toHash($hostPrototypes, 'parent_itemid'); foreach ($result as $itemid => $item) { $result[$itemid]['hostPrototypes'] = isset($hostPrototypes[$itemid]) ? $hostPrototypes[$itemid]['rowscount'] : 0; } } } return $result; }
/** * Prepares and returns an array of child host prototypes, inherited from host prototypes $hostPrototypes * on the given hosts. * * Each host prototype must have the "ruleid" parameter set. * * @param array $hostPrototypes * @param array $hostIds * * @return array an array of unsaved child host prototypes */ protected function prepareInheritedObjects(array $hostPrototypes, array $hostIds = null) { // fetch the related discovery rules with their hosts $discoveryRules = API::DiscoveryRule()->get(array('output' => array('itemid', 'hostid'), 'selectHosts' => array('hostid'), 'itemids' => zbx_objectValues($hostPrototypes, 'ruleid'), 'templated' => true, 'nopermissions' => true, 'preservekeys' => true)); // fetch all child hosts to inherit to // do not inherit host prototypes on discovered hosts $chdHosts = API::Host()->get(array('output' => array('hostid', 'host', 'status'), 'selectParentTemplates' => array('templateid'), 'templateids' => zbx_objectValues($discoveryRules, 'hostid'), 'hostids' => $hostIds, 'nopermissions' => true, 'templated_hosts' => true, 'filter' => array('flags' => ZBX_FLAG_DISCOVERY_NORMAL))); if (empty($chdHosts)) { return array(); } // fetch the child discovery rules $childDiscoveryRules = API::DiscoveryRule()->get(array('output' => array('itemid', 'templateid', 'hostid'), 'preservekeys' => true, 'filter' => array('templateid' => array_keys($discoveryRules)))); // fetch child host prototypes and group them by discovery rule $childHostPrototypes = API::HostPrototype()->get(array('output' => array('hostid', 'host', 'templateid'), 'selectGroupLinks' => API_OUTPUT_EXTEND, 'selectGroupPrototypes' => API_OUTPUT_EXTEND, 'selectDiscoveryRule' => array('itemid'), 'discoveryids' => zbx_objectValues($childDiscoveryRules, 'itemid'))); foreach ($childDiscoveryRules as &$childDiscoveryRule) { $childDiscoveryRule['hostPrototypes'] = array(); } unset($childDiscoveryRule); foreach ($childHostPrototypes as $childHostPrototype) { $discoveryRuleId = $childHostPrototype['discoveryRule']['itemid']; unset($childHostPrototype['discoveryRule']); $childDiscoveryRules[$discoveryRuleId]['hostPrototypes'][] = $childHostPrototype; } // match each discovery that the parent host prototypes belong to to the child discovery rule for each host $discoveryRuleChildren = array(); foreach ($childDiscoveryRules as $childRule) { $discoveryRuleChildren[$childRule['templateid']][$childRule['hostid']] = $childRule['itemid']; } $newHostPrototypes = array(); foreach ($chdHosts as $host) { $hostId = $host['hostid']; // skip items not from parent templates of current host $templateIds = zbx_toHash($host['parentTemplates'], 'templateid'); $parentHostPrototypes = array(); foreach ($hostPrototypes as $inum => $parentHostPrototype) { $parentTemplateId = $discoveryRules[$parentHostPrototype['ruleid']]['hostid']; if (isset($templateIds[$parentTemplateId])) { $parentHostPrototypes[$inum] = $parentHostPrototype; } } foreach ($parentHostPrototypes as $parentHostPrototype) { $childDiscoveryRuleId = $discoveryRuleChildren[$parentHostPrototype['ruleid']][$hostId]; $exHostPrototype = null; // check if the child discovery rule already has host prototypes $exHostPrototypes = $childDiscoveryRules[$childDiscoveryRuleId]['hostPrototypes']; if ($exHostPrototypes) { $exHostPrototypesHosts = zbx_toHash($exHostPrototypes, 'host'); $exHostPrototypesTemplateIds = zbx_toHash($exHostPrototypes, 'templateid'); // look for an already created inherited host prototype // if one exists - update it if (isset($exHostPrototypesTemplateIds[$parentHostPrototype['hostid']])) { $exHostPrototype = $exHostPrototypesTemplateIds[$parentHostPrototype['hostid']]; // check if there's a host prototype on the target host with the same host name but from a different template // or no template if (isset($exHostPrototypesHosts[$parentHostPrototype['host']]) && !idcmp($exHostPrototypesHosts[$parentHostPrototype['host']]['templateid'], $parentHostPrototype['hostid'])) { $discoveryRule = DBfetch(DBselect('SELECT i.name FROM items i WHERE i.itemid=' . zbx_dbstr($exHostPrototype['discoveryRule']['itemid']))); self::exception(ZBX_API_ERROR_PARAMETERS, _s('Host prototype "%1$s" already exists on "%2$s".', $parentHostPrototype['host'], $discoveryRule['name'])); } } // look for a host prototype with the same host name // if one exists - convert it to an inherited host prototype if (isset($exHostPrototypesHosts[$parentHostPrototype['host']])) { $exHostPrototype = $exHostPrototypesHosts[$parentHostPrototype['host']]; // check that this host prototype is not inherited from a different template if ($exHostPrototype['templateid'] > 0 && !idcmp($exHostPrototype['templateid'], $parentHostPrototype['hostid'])) { $discoveryRule = DBfetch(DBselect('SELECT i.name FROM items i WHERE i.itemid=' . zbx_dbstr($exHostPrototype['discoveryRule']['itemid']))); self::exception(ZBX_API_ERROR_PARAMETERS, _s('Host prototype "%1$s" already exists on "%2$s", inherited from another template.', $parentHostPrototype['host'], $discoveryRule['name'])); } } } // copy host prototype $newHostPrototype = $parentHostPrototype; $newHostPrototype['ruleid'] = $discoveryRuleChildren[$parentHostPrototype['ruleid']][$hostId]; $newHostPrototype['templateid'] = $parentHostPrototype['hostid']; // update an existing inherited host prototype if ($exHostPrototype) { // look for existing group prototypes to update $exGroupPrototypesByTemplateId = zbx_toHash($exHostPrototype['groupPrototypes'], 'templateid'); $exGroupPrototypesByName = zbx_toHash($exHostPrototype['groupPrototypes'], 'name'); $exGroupPrototypesByGroupId = zbx_toHash($exHostPrototype['groupLinks'], 'groupid'); // look for a group prototype that can be updated foreach ($newHostPrototype['groupPrototypes'] as &$groupPrototype) { // updated an inherited item prototype by templateid if (isset($exGroupPrototypesByTemplateId[$groupPrototype['group_prototypeid']])) { $groupPrototype['group_prototypeid'] = $exGroupPrototypesByTemplateId[$groupPrototype['group_prototypeid']]['group_prototypeid']; } elseif (isset($groupPrototype['name']) && !zbx_empty($groupPrototype['name']) && isset($exGroupPrototypesByName[$groupPrototype['name']])) { $groupPrototype['templateid'] = $groupPrototype['group_prototypeid']; $groupPrototype['group_prototypeid'] = $exGroupPrototypesByName[$groupPrototype['name']]['group_prototypeid']; } elseif (isset($groupPrototype['groupid']) && $groupPrototype['groupid'] && isset($exGroupPrototypesByGroupId[$groupPrototype['groupid']])) { $groupPrototype['templateid'] = $groupPrototype['group_prototypeid']; $groupPrototype['group_prototypeid'] = $exGroupPrototypesByGroupId[$groupPrototype['groupid']]['group_prototypeid']; } else { $groupPrototype['templateid'] = $groupPrototype['group_prototypeid']; unset($groupPrototype['group_prototypeid']); } unset($groupPrototype['hostid']); } unset($groupPrototype); $newHostPrototype['hostid'] = $exHostPrototype['hostid']; } else { foreach ($newHostPrototype['groupPrototypes'] as &$groupPrototype) { $groupPrototype['templateid'] = $groupPrototype['group_prototypeid']; unset($groupPrototype['group_prototypeid'], $groupPrototype['hostid']); } unset($groupPrototype); unset($newHostPrototype['hostid']); } $newHostPrototypes[] = $newHostPrototype; } } return $newHostPrototypes; }
} } // order linked templates CArrayHelper::sort($data['host_prototype']['templates'], array('name')); // render view $itemView = new CView('configuration.host.prototype.edit', $data); $itemView->render(); $itemView->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); $data = array('form' => getRequest('form'), 'parent_discoveryid' => getRequest('parent_discoveryid'), 'discovery_rule' => $discoveryRule, 'sort' => $sortField, 'sortorder' => $sortOrder); // get items $data['hostPrototypes'] = API::HostPrototype()->get(array('discoveryids' => $data['parent_discoveryid'], 'output' => API_OUTPUT_EXTEND, 'selectTemplates' => array('templateid', 'name'), 'editable' => true, 'sortfield' => $sortField, 'limit' => $config['search_limit'] + 1)); order_result($data['hostPrototypes'], $sortField, $sortOrder); $data['paging'] = getPagingLine($data['hostPrototypes'], $sortOrder); // fetch templates linked to the prototypes $templateIds = array(); foreach ($data['hostPrototypes'] as $hostPrototype) { $templateIds = array_merge($templateIds, zbx_objectValues($hostPrototype['templates'], 'templateid')); } $templateIds = array_unique($templateIds); $linkedTemplates = API::Template()->get(array('output' => array('templateid', 'name'), 'templateids' => $templateIds, 'selectParentTemplates' => array('hostid', 'name'))); $data['linkedTemplates'] = zbx_toHash($linkedTemplates, 'templateid'); // fetch source templates and LLD rules $hostPrototypeSourceIds = getHostPrototypeSourceParentIds(zbx_objectValues($data['hostPrototypes'], 'hostid')); if ($hostPrototypeSourceIds) { $hostPrototypeSourceTemplates = DBfetchArrayAssoc(DBSelect('SELECT h.hostid,h2.name,h2.hostid AS parent_hostid' . ' FROM hosts h,host_discovery hd,items i,hosts h2' . ' WHERE h.hostid=hd.hostid' . ' AND hd.parent_itemid=i.itemid' . ' AND i.hostid=h2.hostid' . ' AND ' . dbConditionInt('h.hostid', $hostPrototypeSourceIds)), 'hostid'); foreach ($data['hostPrototypes'] as &$hostPrototype) {
$hostGraphPrototypes = API::GraphPrototype()->get(['output' => ['graphid', 'name'], 'selectHosts' => ['hostid'], 'hostids' => [$data['clone_hostid']], 'discoveryids' => $hostDiscoveryRuleIds, 'inherited' => false]); if ($hostGraphPrototypes) { $prototypeList = []; foreach ($hostGraphPrototypes as $graphPrototype) { if (count($graphPrototype['hosts']) == 1) { $prototypeList[$graphPrototype['graphid']] = $graphPrototype['name']; } } order_result($prototypeList); $listBox = new CListBox('graphPrototypes', null, 8); $listBox->setAttribute('disabled', 'disabled'); $listBox->addItems($prototypeList); $hostList->addRow(_('Graph prototypes'), $listBox); } // host prototypes $hostPrototypes = API::HostPrototype()->get(['output' => ['hostid', 'name'], 'discoveryids' => $hostDiscoveryRuleIds, 'inherited' => false]); if ($hostPrototypes) { $prototypeList = []; foreach ($hostPrototypes as $hostPrototype) { $prototypeList[$hostPrototype['hostid']] = $hostPrototype['name']; } order_result($prototypeList); $listBox = new CListBox('hostPrototypes', null, 8); $listBox->setAttribute('disabled', 'disabled'); $listBox->addItems($prototypeList); $hostList->addRow(_('Host prototypes'), $listBox); } // web scenarios $httpTests = API::HttpTest()->get(['output' => ['httptestid', 'name'], 'hostids' => [$data['clone_hostid']], 'inherited' => false]); if ($httpTests) { $httpTestList = [];
protected function link(array $templateIds, array $targetIds) { if (!API::Host()->isWritable($targetIds)) { self::exception(ZBX_API_ERROR_PERMISSIONS, _('No permissions to referred object or it does not exist!')); } $hostsLinkageInserts = parent::link($templateIds, $targetIds); foreach ($hostsLinkageInserts as $hostTplIds) { Manager::Application()->link($hostTplIds['templateid'], $hostTplIds['hostid']); API::DiscoveryRule()->syncTemplates(array('hostids' => $hostTplIds['hostid'], 'templateids' => $hostTplIds['templateid'])); API::Itemprototype()->syncTemplates(array('hostids' => $hostTplIds['hostid'], 'templateids' => $hostTplIds['templateid'])); API::HostPrototype()->syncTemplates(array('hostids' => $hostTplIds['hostid'], 'templateids' => $hostTplIds['templateid'])); API::Item()->syncTemplates(array('hostids' => $hostTplIds['hostid'], 'templateids' => $hostTplIds['templateid'])); Manager::HttpTest()->link($hostTplIds['templateid'], $hostTplIds['hostid']); } // we do linkage in two separate loops because for triggers you need all items already created on host foreach ($hostsLinkageInserts as $hostTplIds) { API::Trigger()->syncTemplates(array('hostids' => $hostTplIds['hostid'], 'templateids' => $hostTplIds['templateid'])); API::TriggerPrototype()->syncTemplates(array('hostids' => $hostTplIds['hostid'], 'templateids' => $hostTplIds['templateid'])); API::GraphPrototype()->syncTemplates(array('hostids' => $hostTplIds['hostid'], 'templateids' => $hostTplIds['templateid'])); API::Graph()->syncTemplates(array('hostids' => $hostTplIds['hostid'], 'templateids' => $hostTplIds['templateid'])); } foreach ($hostsLinkageInserts as $hostTplIds) { API::Trigger()->syncTemplateDependencies(array('templateids' => $hostTplIds['templateid'], 'hostids' => $hostTplIds['hostid'])); } return $hostsLinkageInserts; }
/** * Get discovery rules related objects from database. * * @param array $items * * @return array */ protected function prepareDiscoveryRules(array $items) { foreach ($items as &$item) { $item['itemPrototypes'] = []; $item['graphPrototypes'] = []; $item['triggerPrototypes'] = []; $item['hostPrototypes'] = []; // unset unnecessary condition fields foreach ($item['filter']['conditions'] as &$condition) { unset($condition['item_conditionid'], $condition['itemid']); } unset($condition); } unset($item); // gather item prototypes $prototypes = API::ItemPrototype()->get(['output' => $this->dataFields['item_prototype'], 'selectApplications' => ['name'], 'selectApplicationPrototypes' => ['name'], 'selectDiscoveryRule' => ['itemid'], 'discoveryids' => zbx_objectValues($items, 'itemid'), 'inherited' => false, 'preservekeys' => true]); $valuemapids = []; foreach ($prototypes as $prototype) { $valuemapids[$prototype['valuemapid']] = true; } // Value map IDs that are zeroes, should be skipped. unset($valuemapids[0]); if ($this->data['valueMaps']) { /* * If there is an option "valueMaps", some value maps may already been selected. Copy the result and remove * value map IDs that should not be selected again. */ foreach ($this->data['valueMaps'] as $valuemapid => $valuemap) { if (array_key_exists($valuemapid, $valuemapids)) { unset($valuemapids[$valuemapid]); } } } if ($valuemapids) { $this->data['valueMaps'] += API::ValueMap()->get(['output' => ['valuemapid', 'name'], 'selectMappings' => ['value', 'newvalue'], 'valuemapids' => array_keys($valuemapids), 'preservekeys' => true]); } foreach ($prototypes as $prototype) { $prototype['valuemap'] = []; if ($prototype['valuemapid'] != 0) { $prototype['valuemap']['name'] = $this->data['valueMaps'][$prototype['valuemapid']]['name']; } $items[$prototype['discoveryRule']['itemid']]['itemPrototypes'][] = $prototype; } // gather graph prototypes $graphs = API::GraphPrototype()->get(['discoveryids' => zbx_objectValues($items, 'itemid'), 'selectDiscoveryRule' => API_OUTPUT_EXTEND, 'selectGraphItems' => API_OUTPUT_EXTEND, 'output' => API_OUTPUT_EXTEND, 'inherited' => false, 'preservekeys' => true]); $graphs = $this->prepareGraphs($graphs); foreach ($graphs as $graph) { $items[$graph['discoveryRule']['itemid']]['graphPrototypes'][] = $graph; } // gather trigger prototypes $triggers = API::TriggerPrototype()->get(['discoveryids' => zbx_objectValues($items, 'itemid'), 'output' => ['expression', 'description', 'url', 'status', 'priority', 'comments', 'type'], 'selectDiscoveryRule' => API_OUTPUT_EXTEND, 'selectDependencies' => ['description', 'expression'], 'selectItems' => ['itemid', 'flags', 'type'], 'inherited' => false, 'preservekeys' => true]); $triggers = $this->prepareTriggers($triggers); foreach ($triggers as $trigger) { $items[$trigger['discoveryRule']['itemid']]['triggerPrototypes'][] = $trigger; } // gather host prototypes $hostPrototypes = API::HostPrototype()->get(['discoveryids' => zbx_objectValues($items, 'itemid'), 'output' => API_OUTPUT_EXTEND, 'selectGroupLinks' => API_OUTPUT_EXTEND, 'selectGroupPrototypes' => API_OUTPUT_EXTEND, 'selectDiscoveryRule' => API_OUTPUT_EXTEND, 'selectTemplates' => API_OUTPUT_EXTEND, 'inherited' => false, 'preservekeys' => true]); // replace group prototype group IDs with references $groupIds = []; foreach ($hostPrototypes as $hostPrototype) { foreach ($hostPrototype['groupLinks'] as $groupLink) { $groupIds[$groupLink['groupid']] = true; } } $groups = $this->getGroupsReferences(array_keys($groupIds)); // export the groups used in group prototypes $this->data['groups'] += $groups; foreach ($hostPrototypes as $hostPrototype) { foreach ($hostPrototype['groupLinks'] as &$groupLink) { $groupLink['groupid'] = $groups[$groupLink['groupid']]; } unset($groupLink); $items[$hostPrototype['discoveryRule']['itemid']]['hostPrototypes'][] = $hostPrototype; } return $items; }
protected function addRelatedObjects(array $options, array $result) { $result = parent::addRelatedObjects($options, $result); $itemIds = array_keys($result); // adding items if (!is_null($options['selectItems'])) { if ($options['selectItems'] != API_OUTPUT_COUNT) { $relationMap = $this->createRelationMap($result, 'parent_itemid', 'itemid', 'item_discovery'); $items = API::ItemPrototype()->get(array('output' => $options['selectItems'], 'itemids' => $relationMap->getRelatedIds(), 'nopermissions' => true, 'preservekeys' => true)); $result = $relationMap->mapMany($result, $items, 'items', $options['limitSelects']); } else { $items = API::ItemPrototype()->get(array('discoveryids' => $itemIds, 'nopermissions' => true, 'countOutput' => true, 'groupCount' => true)); $items = zbx_toHash($items, 'parent_itemid'); foreach ($result as $itemid => $item) { $result[$itemid]['items'] = isset($items[$itemid]) ? $items[$itemid]['rowscount'] : 0; } } } // adding triggers if (!is_null($options['selectTriggers'])) { if ($options['selectTriggers'] != API_OUTPUT_COUNT) { $relationMap = new CRelationMap(); $res = DBselect('SELECT id.parent_itemid,f.triggerid' . ' FROM item_discovery id,items i,functions f' . ' WHERE ' . dbConditionInt('id.parent_itemid', $itemIds) . ' AND id.itemid=i.itemid' . ' AND i.itemid=f.itemid'); while ($relation = DBfetch($res)) { $relationMap->addRelation($relation['parent_itemid'], $relation['triggerid']); } $triggers = API::TriggerPrototype()->get(array('output' => $options['selectTriggers'], 'triggerids' => $relationMap->getRelatedIds(), 'preservekeys' => true)); $result = $relationMap->mapMany($result, $triggers, 'triggers', $options['limitSelects']); } else { $triggers = API::TriggerPrototype()->get(array('discoveryids' => $itemIds, 'countOutput' => true, 'groupCount' => true)); $triggers = zbx_toHash($triggers, 'parent_itemid'); foreach ($result as $itemid => $item) { $result[$itemid]['triggers'] = isset($triggers[$itemid]) ? $triggers[$itemid]['rowscount'] : 0; } } } // adding graphs if (!is_null($options['selectGraphs'])) { if ($options['selectGraphs'] != API_OUTPUT_COUNT) { $relationMap = new CRelationMap(); $res = DBselect('SELECT id.parent_itemid,gi.graphid' . ' FROM item_discovery id,items i,graphs_items gi' . ' WHERE ' . dbConditionInt('id.parent_itemid', $itemIds) . ' AND id.itemid=i.itemid' . ' AND i.itemid=gi.itemid'); while ($relation = DBfetch($res)) { $relationMap->addRelation($relation['parent_itemid'], $relation['graphid']); } $graphs = API::GraphPrototype()->get(array('output' => $options['selectGraphs'], 'graphids' => $relationMap->getRelatedIds(), 'preservekeys' => true)); $result = $relationMap->mapMany($result, $graphs, 'graphs', $options['limitSelects']); } else { $graphs = API::GraphPrototype()->get(array('discoveryids' => $itemIds, 'countOutput' => true, 'groupCount' => true)); $graphs = zbx_toHash($graphs, 'parent_itemid'); foreach ($result as $itemid => $item) { $result[$itemid]['graphs'] = isset($graphs[$itemid]) ? $graphs[$itemid]['rowscount'] : 0; } } } // adding hosts if ($options['selectHostPrototypes'] !== null) { if ($options['selectHostPrototypes'] != API_OUTPUT_COUNT) { $relationMap = $this->createRelationMap($result, 'parent_itemid', 'hostid', 'host_discovery'); $hostPrototypes = API::HostPrototype()->get(array('output' => $options['selectHostPrototypes'], 'hostids' => $relationMap->getRelatedIds(), 'nopermissions' => true, 'preservekeys' => true)); $result = $relationMap->mapMany($result, $hostPrototypes, 'hostPrototypes', $options['limitSelects']); } else { $hostPrototypes = API::HostPrototype()->get(array('discoveryids' => $itemIds, 'nopermissions' => true, 'countOutput' => true, 'groupCount' => true)); $hostPrototypes = zbx_toHash($hostPrototypes, 'parent_itemid'); foreach ($result as $itemid => $item) { $result[$itemid]['hostPrototypes'] = isset($hostPrototypes[$itemid]) ? $hostPrototypes[$itemid]['rowscount'] : 0; } } } if ($options['selectFilter'] !== null) { $formulaRequested = $this->outputIsRequested('formula', $options['selectFilter']); $evalFormulaRequested = $this->outputIsRequested('eval_formula', $options['selectFilter']); $conditionsRequested = $this->outputIsRequested('conditions', $options['selectFilter']); $filters = array(); foreach ($result as $rule) { $filters[$rule['itemid']] = array('evaltype' => $rule['evaltype'], 'formula' => isset($rule['formula']) ? $rule['formula'] : ''); } // adding conditions if ($formulaRequested || $evalFormulaRequested || $conditionsRequested) { $conditions = API::getApiService()->select('item_condition', array('output' => array('item_conditionid', 'macro', 'value', 'itemid', 'operator'), 'filter' => array('itemid' => $itemIds), 'preservekeys' => true, 'sortfield' => 'item_conditionid')); $relationMap = $this->createRelationMap($conditions, 'itemid', 'item_conditionid'); $filters = $relationMap->mapMany($filters, $conditions, 'conditions'); foreach ($filters as &$filter) { // in case of a custom expression - use the given formula if ($filter['evaltype'] == CONDITION_EVAL_TYPE_EXPRESSION) { $formula = $filter['formula']; } else { // sort the conditions by macro before generating the formula $conditions = zbx_toHash($filter['conditions'], 'item_conditionid'); $conditions = order_macros($conditions, 'macro'); $formulaConditions = array(); foreach ($conditions as $condition) { $formulaConditions[$condition['item_conditionid']] = $condition['macro']; } $formula = CConditionHelper::getFormula($formulaConditions, $filter['evaltype']); } // generate formulaids from the effective formula $formulaIds = CConditionHelper::getFormulaIds($formula); foreach ($filter['conditions'] as &$condition) { $condition['formulaid'] = $formulaIds[$condition['item_conditionid']]; } unset($condition); // generated a letter based formula only for rules with custom expressions if ($formulaRequested && $filter['evaltype'] == CONDITION_EVAL_TYPE_EXPRESSION) { $filter['formula'] = CConditionHelper::replaceNumericIds($formula, $formulaIds); } if ($evalFormulaRequested) { $filter['eval_formula'] = CConditionHelper::replaceNumericIds($formula, $formulaIds); } } unset($filter); } // add filters to the result foreach ($result as &$rule) { $rule['filter'] = $filters[$rule['itemid']]; } unset($rule); } return $result; }