/** * Updates the children of the trigger on the given hosts and propagates the inheritance to all child hosts. * If the given trigger was assigned to a different template or a host, all of the child triggers, that became * obsolete will be deleted. * * @param array $trigger the trigger with an exploded expression * @param array $hostids * * @return bool */ protected function inherit(array $trigger, array $hostIds = null) { $triggerTemplates = API::Template()->get(array('triggerids' => $trigger['triggerid'], 'output' => API_OUTPUT_EXTEND, 'nopermissions' => true)); if (empty($triggerTemplates)) { // nothing to inherit, just exit return true; } if (!isset($trigger['expression']) || !isset($trigger['description'])) { $dbTriggers = $this->get(array('triggerids' => $trigger['triggerid'], 'output' => array('expression', 'description'), 'nopermissions' => true)); $dbTrigger = reset($dbTriggers); if (!isset($trigger['description'])) { $trigger['description'] = $dbTrigger['description']; } if (!isset($trigger['expression'])) { $trigger['expression'] = explode_exp($dbTrigger['expression']); } } // fetch all of the child hosts $childHosts = API::Host()->get(array('templateids' => zbx_objectValues($triggerTemplates, 'templateid'), 'output' => array('hostid', 'host'), 'preservekeys' => true, 'hostids' => $hostIds, 'nopermissions' => true, 'templated_hosts' => true)); foreach ($childHosts as $childHost) { // update the child trigger on the child host $newTrigger = $this->inheritOnHost($trigger, $childHost, $triggerTemplates); // propagate the trigger inheritance to all child hosts $this->inherit($newTrigger); } return true; }
/** * Updates the children of the trigger on the given hosts and propagates the inheritance to all child hosts. * If the given trigger was assigned to a different template or a host, all of the child triggers, that became * obsolete will be deleted. * * @param array $trigger the trigger with an exploded expression * @param array $hostids * * @return bool */ protected function inherit(array $trigger, array $hostids = null) { $triggerTemplates = API::Template()->get(array('triggerids' => $trigger['triggerid'], 'output' => API_OUTPUT_EXTEND, 'nopermissions' => true)); // fetch the existing child triggers $templatedTriggers = $this->get(array('output' => array('triggerid', 'description'), 'filter' => array('templateid' => $trigger['triggerid']), 'selectHosts' => array('name'), 'preservekeys' => true)); // no templates found, which means, that the trigger is no longer a templated trigger if (empty($triggerTemplates)) { // delete all of the former child triggers that may exist if ($templatedTriggers) { foreach ($templatedTriggers as $trigger) { info(_s('Deleted: Trigger "%1$s" on "%2$s".', $trigger['description'], implode(', ', zbx_objectValues($trigger['hosts'], 'name')))); } $this->deleteByIds(zbx_objectValues($templatedTriggers, 'triggerid')); } // nothing to inherit, just exit return true; } if (!isset($trigger['expression']) || !isset($trigger['description'])) { $options = array('triggerids' => $trigger['triggerid'], 'output' => API_OUTPUT_EXTEND, 'preservekeys' => true, 'nopermissions' => true); $dbTrigger = $this->get($options); $dbTrigger = reset($dbTrigger); if (!isset($trigger['description'])) { $trigger['description'] = $dbTrigger['description']; } if (!isset($trigger['expression'])) { $trigger['expression'] = explode_exp($dbTrigger['expression']); } } // fetch all of the child hosts $chdHosts = API::Host()->get(array('templateids' => zbx_objectValues($triggerTemplates, 'templateid'), 'output' => array('hostid', 'host'), 'preservekeys' => true, 'hostids' => $hostids, 'nopermissions' => true, 'templated_hosts' => true)); foreach ($chdHosts as $childHost) { // update the child trigger on the child host $newTrigger = $this->inheritOnHost($trigger, $childHost, $triggerTemplates); // propagate the trigger inheritance to all child hosts $this->inherit($newTrigger); unset($templatedTriggers[$newTrigger['triggerid']]); } // if we've updated the children of the trigger on all of the host, and there are still some children left, // we must delete them if ($templatedTriggers && !$hostids) { foreach ($templatedTriggers as $trigger) { info(_s('Deleted: Trigger "%1$s" on "%2$s".', $trigger['description'], implode(', ', zbx_objectValues($trigger['hosts'], 'name')))); } $this->deleteByIds(zbx_objectValues($templatedTriggers, 'triggerid')); } return true; }
protected function addRelatedObjects(array $options, array $result) { $result = parent::addRelatedObjects($options, $result); $hostPrototypeIds = array_keys($result); // adding discovery rule if ($options['selectDiscoveryRule'] !== null && $options['selectDiscoveryRule'] != API_OUTPUT_COUNT) { $relationMap = $this->createRelationMap($result, 'hostid', 'parent_itemid', 'host_discovery'); $discoveryRules = API::DiscoveryRule()->get(['output' => $options['selectDiscoveryRule'], 'itemids' => $relationMap->getRelatedIds(), 'nopermissions' => true, 'preservekeys' => true]); $result = $relationMap->mapOne($result, $discoveryRules, 'discoveryRule'); } // adding group links if ($options['selectGroupLinks'] !== null && $options['selectGroupLinks'] != API_OUTPUT_COUNT) { $groupPrototypes = DBFetchArray(DBselect('SELECT hg.group_prototypeid,hg.hostid' . ' FROM group_prototype hg' . ' WHERE ' . dbConditionInt('hg.hostid', $hostPrototypeIds) . ' AND hg.groupid IS NOT NULL')); $relationMap = $this->createRelationMap($groupPrototypes, 'hostid', 'group_prototypeid'); $groupPrototypes = API::getApiService()->select('group_prototype', ['output' => $options['selectGroupLinks'], 'group_prototypeids' => $relationMap->getRelatedIds(), 'preservekeys' => true]); foreach ($groupPrototypes as &$groupPrototype) { unset($groupPrototype['name']); } unset($groupPrototype); $result = $relationMap->mapMany($result, $groupPrototypes, 'groupLinks'); } // adding group prototypes if ($options['selectGroupPrototypes'] !== null && $options['selectGroupPrototypes'] != API_OUTPUT_COUNT) { $groupPrototypes = DBFetchArray(DBselect('SELECT hg.group_prototypeid,hg.hostid' . ' FROM group_prototype hg' . ' WHERE ' . dbConditionInt('hg.hostid', $hostPrototypeIds) . ' AND hg.groupid IS NULL')); $relationMap = $this->createRelationMap($groupPrototypes, 'hostid', 'group_prototypeid'); $groupPrototypes = API::getApiService()->select('group_prototype', ['output' => $options['selectGroupPrototypes'], 'group_prototypeids' => $relationMap->getRelatedIds(), 'preservekeys' => true]); foreach ($groupPrototypes as &$groupPrototype) { unset($groupPrototype['groupid']); } unset($groupPrototype); $result = $relationMap->mapMany($result, $groupPrototypes, 'groupPrototypes'); } // adding host if ($options['selectParentHost'] !== null && $options['selectParentHost'] != API_OUTPUT_COUNT) { $relationMap = new CRelationMap(); $dbRules = DBselect('SELECT hd.hostid,i.hostid AS parent_hostid' . ' FROM host_discovery hd,items i' . ' WHERE ' . dbConditionInt('hd.hostid', $hostPrototypeIds) . ' AND hd.parent_itemid=i.itemid'); while ($relation = DBfetch($dbRules)) { $relationMap->addRelation($relation['hostid'], $relation['parent_hostid']); } $hosts = API::Host()->get(['output' => $options['selectParentHost'], 'hostids' => $relationMap->getRelatedIds(), 'templated_hosts' => true, 'nopermissions' => true, 'preservekeys' => true]); $result = $relationMap->mapOne($result, $hosts, 'parentHost'); } // adding templates if ($options['selectTemplates'] !== null) { if ($options['selectTemplates'] != API_OUTPUT_COUNT) { $relationMap = $this->createRelationMap($result, 'hostid', 'templateid', 'hosts_templates'); $templates = API::Template()->get(['output' => $options['selectTemplates'], 'templateids' => $relationMap->getRelatedIds(), 'preservekeys' => true]); $result = $relationMap->mapMany($result, $templates, 'templates'); } else { $templates = API::Template()->get(['hostids' => $hostPrototypeIds, 'countOutput' => true, 'groupCount' => true]); $templates = zbx_toHash($templates, 'hostid'); foreach ($result as $hostid => $host) { $result[$hostid]['templates'] = isset($templates[$hostid]) ? $templates[$hostid]['rowscount'] : 0; } } } // adding inventory if ($options['selectInventory'] !== null) { $relationMap = $this->createRelationMap($result, 'hostid', 'hostid'); // only allow to retrieve the hostid and inventory_mode fields $output = []; if ($this->outputIsRequested('hostid', $options['selectInventory'])) { $output[] = 'hostid'; } if ($this->outputIsRequested('inventory_mode', $options['selectInventory'])) { $output[] = 'inventory_mode'; } $inventory = API::getApiService()->select('host_inventory', ['output' => $output, 'filter' => ['hostid' => $hostPrototypeIds]]); $result = $relationMap->mapOne($result, zbx_toHash($inventory, 'hostid'), 'inventory'); } return $result; }
protected function inherit($graph, $hostids = null) { $graphTemplates = API::Template()->get(array('itemids' => zbx_objectValues($graph['gitems'], 'itemid'), 'output' => array('templateid'), 'nopermissions' => true)); if (empty($graphTemplates)) { return true; } $graphTemplate = reset($graphTemplates); $chdHosts = API::Host()->get(array('templateids' => $graphTemplate['templateid'], 'output' => array('hostid', 'host'), 'preservekeys' => true, 'hostids' => $hostids, 'nopermissions' => true, 'templated_hosts' => true)); $graph = $this->get(array('graphids' => $graph['graphid'], 'nopermissions' => true, 'filter' => array('flags' => null), 'selectGraphItems' => API_OUTPUT_EXTEND, 'output' => API_OUTPUT_EXTEND)); $graph = reset($graph); foreach ($chdHosts as $chdHost) { $tmpGraph = $graph; $tmpGraph['templateid'] = $graph['graphid']; $tmpGraph['gitems'] = getSameGraphItemsForHost($tmpGraph['gitems'], $chdHost['hostid']); if (!$tmpGraph['gitems']) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Graph "%1$s" cannot inherit. No required items on "%2$s".', $tmpGraph['name'], $chdHost['host'])); } if ($tmpGraph['ymax_itemid'] > 0) { $ymaxItemid = getSameGraphItemsForHost(array(array('itemid' => $tmpGraph['ymax_itemid'])), $chdHost['hostid']); if (!$ymaxItemid) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Graph "%1$s" cannot inherit. No required items on "%2$s" (Ymax value item).', $tmpGraph['name'], $chdHost['host'])); } $ymaxItemid = reset($ymaxItemid); $tmpGraph['ymax_itemid'] = $ymaxItemid['itemid']; } if ($tmpGraph['ymin_itemid'] > 0) { $yminItemid = getSameGraphItemsForHost(array(array('itemid' => $tmpGraph['ymin_itemid'])), $chdHost['hostid']); if (!$yminItemid) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Graph "%1$s" cannot inherit. No required items on "%2$s" (Ymin value item).', $tmpGraph['name'], $chdHost['host'])); } $yminItemid = reset($yminItemid); $tmpGraph['ymin_itemid'] = $yminItemid['itemid']; } // check if templated graph exists $chdGraphs = $this->get(array('filter' => array('templateid' => $tmpGraph['graphid'], 'flags' => array(ZBX_FLAG_DISCOVERY_PROTOTYPE, ZBX_FLAG_DISCOVERY_NORMAL)), 'output' => API_OUTPUT_EXTEND, 'selectGraphItems' => API_OUTPUT_EXTEND, 'preservekeys' => true, 'hostids' => $chdHost['hostid'])); if ($chdGraph = reset($chdGraphs)) { if ($tmpGraph['name'] !== $chdGraph['name']) { $graphExists = $this->get(array('output' => array('graphid'), 'hostids' => $chdHost['hostid'], 'filter' => array('name' => $tmpGraph['name'], 'flags' => null), 'nopermissions' => true, 'limit' => 1)); if ($graphExists) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Graph "%1$s" already exists on "%2$s".', $tmpGraph['name'], $chdHost['host'])); } } elseif ($chdGraph['flags'] != $tmpGraph['flags']) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Graph with same name but other type exist.')); } $tmpGraph['graphid'] = $chdGraph['graphid']; $this->updateReal($tmpGraph, $chdGraph); } else { $chdGraph = $this->get(array('filter' => array('name' => $tmpGraph['name'], 'flags' => null), 'output' => API_OUTPUT_EXTEND, 'selectGraphItems' => API_OUTPUT_EXTEND, 'preservekeys' => true, 'nopermissions' => true, 'hostids' => $chdHost['hostid'])); if ($chdGraph = reset($chdGraph)) { if ($chdGraph['templateid'] != 0) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Graph "%1$s" already exists on "%2$s" (inherited from another template).', $tmpGraph['name'], $chdHost['host'])); } elseif ($chdGraph['flags'] != $tmpGraph['flags']) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Graph with same name but other type exist.')); } $chdGraphItemItems = array(); foreach (array(API::Item(), API::ItemPrototype()) as $api) { $chdGraphItemItems += $api->get(array('output' => array('key_', 'hostid', 'itemid'), 'itemids' => zbx_objectValues($chdGraph['gitems'], 'itemid'), 'preservekeys' => true)); } if (count($chdGraph['gitems']) == count($tmpGraph['gitems'])) { foreach ($tmpGraph['gitems'] as $gitem) { foreach ($chdGraph['gitems'] as $chdGraphItem) { $chdGraphItemItem = $chdGraphItemItems[$chdGraphItem['itemid']]; if ($gitem['key_'] == $chdGraphItemItem['key_'] && bccomp($chdHost['hostid'], $chdGraphItemItem['hostid']) == 0) { continue 2; } } self::exception(ZBX_API_ERROR_PARAMETERS, _s('Graph "%1$s" already exists on "%2$s" (items are not identical).', $tmpGraph['name'], $chdHost['host'])); } $tmpGraph['graphid'] = $chdGraph['graphid']; $this->updateReal($tmpGraph, $chdGraph); } else { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Graph "%1$s" already exists on "%2$s" (items are not identical).', $tmpGraph['name'], $chdHost['host'])); } } else { $graphid = $this->createReal($tmpGraph); $tmpGraph['graphid'] = $graphid; } } $this->inherit($tmpGraph); } }
/** * Validates the input parameters for the update() method. * * @param array $hosts hosts data array * @param array $db_hosts db hosts data array * * @throws APIException if the input is invalid. */ protected function validateUpdate(array $hosts, array $db_hosts) { $host_db_fields = ['hostid' => null]; $hosts_full = []; foreach ($hosts as $host) { // Validate mandatory fields. if (!check_db_fields($host_db_fields, $host)) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Wrong fields for host "%1$s".', array_key_exists('host', $host) ? $host['host'] : '')); } // Validate host permissions. if (!array_key_exists($host['hostid'], $db_hosts)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('No permissions to referred object or it does not exist!')); } // Validate "groups" field. if (array_key_exists('groups', $host) && (!is_array($host['groups']) || !$host['groups'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('No groups for host "%1$s".', $db_hosts[$host['hostid']]['host'])); } // Permissions to host groups is validated in massUpdate(). } $inventory_fields = zbx_objectValues(getHostInventories(), 'db_field'); $status_validator = new CLimitedSetValidator(['values' => [HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED], 'messageInvalid' => _('Incorrect status for host "%1$s".')]); $update_discovered_validator = new CUpdateDiscoveredValidator(['allowed' => ['hostid', 'status', 'inventory', 'description'], 'messageAllowedField' => _('Cannot update "%2$s" for a discovered host "%1$s".')]); $host_names = []; foreach ($hosts as &$host) { $db_host = $db_hosts[$host['hostid']]; $host_name = array_key_exists('host', $host) ? $host['host'] : $db_host['host']; if (array_key_exists('status', $host)) { $status_validator->setObjectName($host_name); $this->checkValidator($host['status'], $status_validator); } if (array_key_exists('inventory', $host) && $host['inventory']) { if (array_key_exists('inventory_mode', $host) && $host['inventory_mode'] == HOST_INVENTORY_DISABLED) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot set inventory fields for disabled inventory.')); } $fields = array_keys($host['inventory']); foreach ($fields as $field) { if (!in_array($field, $inventory_fields)) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect inventory field "%s".', $field)); } } } // cannot update certain fields for discovered hosts $update_discovered_validator->setObjectName($host_name); $this->checkPartialValidator($host, $update_discovered_validator, $db_host); if (array_key_exists('interfaces', $host)) { if (!is_array($host['interfaces']) || !$host['interfaces']) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('No interfaces for host "%s".', $host['host'])); } } if (array_key_exists('host', $host)) { if (!preg_match('/^' . ZBX_PREG_HOST_FORMAT . '$/', $host['host'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect characters used for host name "%s".', $host['host'])); } if (array_key_exists('host', $host_names) && array_key_exists($host['host'], $host_names['host'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Duplicate host. Host with the same host name "%s" already exists in data.', $host['host'])); } $host_names['host'][$host['host']] = $host['hostid']; } if (array_key_exists('name', $host)) { // if visible name is empty replace it with host name if (zbx_empty(trim($host['name']))) { if (!array_key_exists('host', $host)) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Visible name cannot be empty if host name is missing.')); } $host['name'] = $host['host']; } if (array_key_exists('name', $host_names) && array_key_exists($host['name'], $host_names['name'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Duplicate host. Host with the same visible name "%s" already exists in data.', $host['name'])); } $host_names['name'][$host['name']] = $host['hostid']; } $hosts_full[] = zbx_array_merge($db_host, $host); } unset($host); if (array_key_exists('host', $host_names) || array_key_exists('name', $host_names)) { $filter = []; if (array_key_exists('host', $host_names)) { $filter['host'] = array_keys($host_names['host']); } if (array_key_exists('name', $host_names)) { $filter['name'] = array_keys($host_names['name']); } $hosts_exists = $this->get(['output' => ['hostid', 'host', 'name'], 'filter' => $filter, 'searchByAny' => true, 'nopermissions' => true, 'preservekeys' => true]); foreach ($hosts_exists as $host_exists) { if (array_key_exists('host', $host_names) && array_key_exists($host_exists['host'], $host_names['host']) && bccomp($host_exists['hostid'], $host_names['host'][$host_exists['host']]) != 0) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Host with the same name "%s" already exists.', $host_exists['host'])); } if (array_key_exists('name', $host_names) && array_key_exists($host_exists['name'], $host_names['name']) && bccomp($host_exists['hostid'], $host_names['name'][$host_exists['name']]) != 0) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Host with the same visible name "%s" already exists.', $host_exists['name'])); } } $templates_exists = API::Template()->get(['output' => ['hostid', 'host', 'name'], 'filter' => $filter, 'searchByAny' => true, 'nopermissions' => true, 'preservekeys' => true]); foreach ($templates_exists as $template_exists) { if (array_key_exists('host', $host_names) && array_key_exists($template_exists['host'], $host_names['host']) && bccomp($template_exists['templateid'], $host_names['host'][$template_exists['host']]) != 0) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Template with the same name "%s" already exists.', $template_exists['host'])); } if (array_key_exists('name', $host_names) && array_key_exists($template_exists['name'], $host_names['name']) && bccomp($template_exists['templateid'], $host_names['name'][$template_exists['name']]) != 0) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Template with the same visible name "%s" already exists.', $template_exists['name'])); } } } $this->validateEncryption($hosts_full); }
protected function addRelatedObjects(array $options, array $result) { $result = parent::addRelatedObjects($options, $result); if ($options['globalmacro'] === null) { $hostMacroIds = array_keys($result); /* * Adding objects */ // adding groups if ($options['selectGroups'] !== null && $options['selectGroups'] != API_OUTPUT_COUNT) { $res = DBselect('SELECT hm.hostmacroid,hg.groupid' . ' FROM hostmacro hm,hosts_groups hg' . ' WHERE ' . dbConditionInt('hm.hostmacroid', $hostMacroIds) . ' AND hm.hostid=hg.hostid'); $relationMap = new CRelationMap(); while ($relation = DBfetch($res)) { $relationMap->addRelation($relation['hostmacroid'], $relation['groupid']); } $groups = API::HostGroup()->get(array('output' => $options['selectGroups'], 'groupids' => $relationMap->getRelatedIds(), 'preservekeys' => true)); $result = $relationMap->mapMany($result, $groups, 'groups'); } // adding templates if ($options['selectTemplates'] !== null && $options['selectTemplates'] != API_OUTPUT_COUNT) { $relationMap = $this->createRelationMap($result, 'hostmacroid', 'hostid'); $templates = API::Template()->get(array('output' => $options['selectTemplates'], 'templateids' => $relationMap->getRelatedIds(), 'preservekeys' => true)); $result = $relationMap->mapMany($result, $templates, 'templates'); } // adding templates if ($options['selectHosts'] !== null && $options['selectHosts'] != API_OUTPUT_COUNT) { $relationMap = $this->createRelationMap($result, 'hostmacroid', 'hostid'); $templates = API::Host()->get(array('output' => $options['selectHosts'], 'hostids' => $relationMap->getRelatedIds(), 'preservekeys' => true)); $result = $relationMap->mapMany($result, $templates, 'hosts'); } } return $result; }
/** * Check if all templates trigger belongs to are linked to same hosts. * * @throws APIException * * @param $trigger * * @return bool */ protected function validateItems(array $trigger) { $expressionData = new CTriggerExpression(); $expressionData->parse($trigger['expression']); $templatesData = API::Template()->get(['output' => ['templateid'], 'selectHosts' => ['hostid'], 'selectTemplates' => ['templateid'], 'filter' => ['host' => $expressionData->getHosts()], 'nopermissions' => true, 'preservekeys' => true]); $firstTemplate = array_pop($templatesData); if ($firstTemplate) { $compareLinks = array_merge(zbx_objectValues($firstTemplate['hosts'], 'hostid'), zbx_objectValues($firstTemplate['templates'], 'templateid')); foreach ($templatesData as $data) { $linkedTo = array_merge(zbx_objectValues($data['hosts'], 'hostid'), zbx_objectValues($data['templates'], 'templateid')); if (array_diff($compareLinks, $linkedTo) || array_diff($linkedTo, $compareLinks)) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Trigger "%s" belongs to templates with different linkages.', $trigger['description'])); } } } return true; }
$hosts = API::Host()->get(array('groupids' => $pageFilter->groupid > 0 ? $pageFilter->groupid : null, 'editable' => true, 'sortfield' => $sortfield, 'sortorder' => $sortorder, 'limit' => $config['search_limit'] + 1, 'search' => array('name' => empty($_REQUEST['filter_host']) ? null : $_REQUEST['filter_host'], 'ip' => empty($_REQUEST['filter_ip']) ? null : $_REQUEST['filter_ip'], 'dns' => empty($_REQUEST['filter_dns']) ? null : $_REQUEST['filter_dns']), 'filter' => array('port' => empty($_REQUEST['filter_port']) ? null : $_REQUEST['filter_port']))); } else { $hosts = array(); } // sorting && paging order_result($hosts, $sortfield, $sortorder); $paging = getPagingLine($hosts, array('hostid')); $hosts = API::Host()->get(array('hostids' => zbx_objectValues($hosts, 'hostid'), 'output' => API_OUTPUT_EXTEND, 'selectParentTemplates' => array('hostid', 'name'), 'selectInterfaces' => API_OUTPUT_EXTEND, 'selectItems' => API_OUTPUT_COUNT, 'selectDiscoveries' => API_OUTPUT_COUNT, 'selectTriggers' => API_OUTPUT_COUNT, 'selectGraphs' => API_OUTPUT_COUNT, 'selectApplications' => API_OUTPUT_COUNT, 'selectHttpTests' => API_OUTPUT_COUNT, 'selectDiscoveryRule' => array('itemid', 'name'), 'selectHostDiscovery' => array('ts_delete'))); order_result($hosts, $sortfield, $sortorder); // selecting linked templates to templates linked to hosts $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'] . ')');
$frmGroup->addItem(array(_('Group') . SPACE, $pageFilter->getGroupsCB())); $templateWidget->addHeader(_('Templates'), $frmGroup); $templateWidget->addHeaderRowNumber(); $form = new CForm(); $form->setName('templates'); $table = new CTableInfo(_('No templates found.')); $table->setHeader(array(new CCheckBox('all_templates', null, "checkAll('" . $form->getName() . "', 'all_templates', 'templates');"), make_sorting_header(_('Templates'), 'name', $sortField, $sortOrder), _('Applications'), _('Items'), _('Triggers'), _('Graphs'), _('Screens'), _('Discovery'), _('Web'), _('Linked templates'), _('Linked to'))); // get templates $templates = array(); if ($pageFilter->groupsSelected) { $templates = API::Template()->get(array('output' => array('templateid', 'name'), 'groupids' => $pageFilter->groupid > 0 ? $pageFilter->groupid : null, 'editable' => true, 'sortfield' => $sortField, 'limit' => $config['search_limit'] + 1)); } // sorting && paging order_result($templates, $sortField, $sortOrder); $paging = getPagingLine($templates); $templates = API::Template()->get(array('templateids' => zbx_objectValues($templates, 'templateid'), 'editable' => true, 'output' => array('name', 'proxy_hostid'), 'selectHosts' => array('hostid', 'name', 'status'), 'selectTemplates' => array('hostid', 'name', 'status'), 'selectParentTemplates' => array('hostid', 'name', 'status'), 'selectItems' => API_OUTPUT_COUNT, 'selectTriggers' => API_OUTPUT_COUNT, 'selectGraphs' => API_OUTPUT_COUNT, 'selectApplications' => API_OUTPUT_COUNT, 'selectDiscoveries' => API_OUTPUT_COUNT, 'selectScreens' => API_OUTPUT_COUNT, 'selectHttpTests' => API_OUTPUT_COUNT, 'nopermissions' => true)); order_result($templates, $sortField, $sortOrder); foreach ($templates as $template) { $templatesOutput = array(); if ($template['proxy_hostid']) { $proxy = get_host_by_hostid($template['proxy_hostid']); $templatesOutput[] = $proxy['host'] . NAME_DELIMITER; } $templatesOutput[] = new CLink($template['name'], 'templates.php?form=update&templateid=' . $template['templateid'] . url_param('groupid')); $applications = array(new CLink(_('Applications'), 'applications.php?groupid=' . $_REQUEST['groupid'] . '&hostid=' . $template['templateid']), ' (' . $template['applications'] . ')'); $items = array(new CLink(_('Items'), 'items.php?filter_set=1&groupid=' . $_REQUEST['groupid'] . '&hostid=' . $template['templateid']), ' (' . $template['items'] . ')'); $triggers = array(new CLink(_('Triggers'), 'triggers.php?groupid=' . $_REQUEST['groupid'] . '&hostid=' . $template['templateid']), ' (' . $template['triggers'] . ')'); $graphs = array(new CLink(_('Graphs'), 'graphs.php?groupid=' . $_REQUEST['groupid'] . '&hostid=' . $template['templateid']), ' (' . $template['graphs'] . ')'); $screens = array(new CLink(_('Screens'), 'screenconf.php?templateid=' . $template['templateid']), ' (' . $template['screens'] . ')'); $discoveries = array(new CLink(_('Discovery'), 'host_discovery.php?&hostid=' . $template['templateid']), ' (' . $template['discoveries'] . ')'); $httpTests = array(new CLink(_('Web'), 'httpconf.php?groupid=' . $_REQUEST['groupid'] . '&hostid=' . $template['templateid']), ' (' . $template['httpTests'] . ')');
$templates = array(); $sortfield = getPageSortField('name'); $sortorder = getPageSortOrder(); if ($pageFilter->groupsSelected) { $options = array('editable' => 1, 'sortfield' => $sortfield, 'sortorder' => $sortorder, 'limit' => $config['search_limit'] + 1); if ($pageFilter->groupid > 0) { $options['groupids'] = $pageFilter->groupid; } $templates = API::Template()->get($options); } // sorting && paging order_result($templates, $sortfield, $sortorder); $paging = getPagingLine($templates); //-------- $options = array('templateids' => zbx_objectValues($templates, 'templateid'), 'editable' => 1, 'output' => array('name', 'proxy_hostid'), 'selectHosts' => array('hostid', 'name', 'status'), 'selectTemplates' => array('hostid', 'name', 'status'), 'selectParentTemplates' => array('hostid', 'name', 'status'), 'selectItems' => API_OUTPUT_COUNT, 'selectTriggers' => API_OUTPUT_COUNT, 'selectGraphs' => API_OUTPUT_COUNT, 'selectApplications' => API_OUTPUT_COUNT, 'selectDiscoveries' => API_OUTPUT_COUNT, 'selectScreens' => API_OUTPUT_COUNT, 'nopermissions' => 1); $templates = API::Template()->get($options); order_result($templates, $sortfield, $sortorder); //----- foreach ($templates as $template) { $templates_output = array(); if ($template['proxy_hostid']) { $proxy = get_host_by_hostid($template['proxy_hostid']); $templates_output[] = $proxy['host'] . ':'; } $templates_output[] = new CLink($template['name'], 'templates.php?form=update&templateid=' . $template['templateid'] . url_param('groupid')); $applications = array(new CLink(_('Applications'), 'applications.php?groupid=' . $_REQUEST['groupid'] . '&hostid=' . $template['templateid']), ' (' . $template['applications'] . ')'); $items = array(new CLink(_('Items'), 'items.php?filter_set=1&groupid=' . $_REQUEST['groupid'] . '&hostid=' . $template['templateid']), ' (' . $template['items'] . ')'); $triggers = array(new CLink(_('Triggers'), 'triggers.php?groupid=' . $_REQUEST['groupid'] . '&hostid=' . $template['templateid']), ' (' . $template['triggers'] . ')'); $graphs = array(new CLink(_('Graphs'), 'graphs.php?groupid=' . $_REQUEST['groupid'] . '&hostid=' . $template['templateid']), ' (' . $template['graphs'] . ')'); $screens = array(new CLink(_('Screens'), 'screenconf.php?templateid=' . $template['templateid']), ' (' . $template['screens'] . ')'); $discoveries = array(new CLink(_('Discovery'), 'host_discovery.php?&hostid=' . $template['hostid']), ' (' . $template['discoveries'] . ')');
$itemView = new CView('configuration.item.edit', $data); $itemView->render(); $itemView->show(); } elseif ((hasRequest('action') && getRequest('action') == 'item.massupdateform' || hasRequest('massupdate')) && hasRequest('group_itemid')) { $data = array('form' => getRequest('form'), 'action' => 'item.massupdateform', 'hostid' => getRequest('hostid'), 'itemids' => getRequest('group_itemid', array()), 'description' => getRequest('description', ''), 'delay' => getRequest('delay', ZBX_ITEM_DELAY_DEFAULT), 'delay_flex' => getRequest('delay_flex', array()), 'history' => getRequest('history', 90), 'status' => getRequest('status', 0), 'type' => getRequest('type', 0), 'interfaceid' => getRequest('interfaceid', 0), 'snmp_community' => getRequest('snmp_community', 'public'), 'port' => getRequest('port', ''), 'value_type' => getRequest('value_type', ITEM_VALUE_TYPE_UINT64), 'data_type' => getRequest('data_type', ITEM_DATA_TYPE_DECIMAL), 'trapper_hosts' => getRequest('trapper_hosts', ''), 'units' => getRequest('units', ''), 'authtype' => getRequest('authtype', ''), 'username' => getRequest('username', ''), 'password' => getRequest('password', ''), 'publickey' => getRequest('publickey', ''), 'privatekey' => getRequest('privatekey', ''), 'valuemapid' => getRequest('valuemapid', 0), 'delta' => getRequest('delta', 0), 'trends' => getRequest('trends', DAY_IN_YEAR), 'applications' => getRequest('applications', array()), 'snmpv3_contextname' => getRequest('snmpv3_contextname', ''), 'snmpv3_securityname' => getRequest('snmpv3_securityname', ''), 'snmpv3_securitylevel' => getRequest('snmpv3_securitylevel', 0), 'snmpv3_authprotocol' => getRequest('snmpv3_authprotocol', ITEM_AUTHPROTOCOL_MD5), 'snmpv3_authpassphrase' => getRequest('snmpv3_authpassphrase', ''), 'snmpv3_privprotocol' => getRequest('snmpv3_privprotocol', ITEM_PRIVPROTOCOL_DES), 'snmpv3_privpassphrase' => getRequest('snmpv3_privpassphrase', ''), 'formula' => getRequest('formula', '1'), 'logtimefmt' => getRequest('logtimefmt', ''), 'initial_item_type' => null, 'multiple_interface_types' => false, 'visible' => getRequest('visible', array())); $data['displayApplications'] = true; $data['displayInterfaces'] = true; // hosts $data['hosts'] = API::Host()->get(array('output' => array('hostid'), 'itemids' => $data['itemids'], 'selectItems' => array('itemid'), 'selectInterfaces' => API_OUTPUT_EXTEND)); $hostCount = count($data['hosts']); if ($hostCount > 1) { $data['displayApplications'] = false; $data['displayInterfaces'] = false; } else { // get template count to display applications multiselect only for single template $templates = API::Template()->get(array('output' => array('templateid'), 'itemids' => $data['itemids'])); $templateCount = count($templates); if ($templateCount != 0) { $data['displayInterfaces'] = false; if ($templateCount == 1 && !$data['hostid']) { // if selected from filter without 'hostid' $templates = reset($templates); $data['hostid'] = $templates['templateid']; } // if items belong to single template and some belong to single host, don't display application multiselect // and don't display application multiselect for multiple templates if ($hostCount == 1 && $templateCount == 1 || $templateCount > 1) { $data['displayApplications'] = false; } } if ($hostCount == 1 && $data['displayInterfaces']) {
protected function unlink($templateids, $targetids = null) { $cond = ['templateid' => $templateids]; if (!is_null($targetids)) { $cond['hostid'] = $targetids; } DB::delete('hosts_templates', $cond); if (!is_null($targetids)) { $hosts = API::Host()->get(['hostids' => $targetids, 'output' => ['hostid', 'host'], 'nopermissions' => true]); } else { $hosts = API::Host()->get(['templateids' => $templateids, 'output' => ['hostid', 'host'], 'nopermissions' => true]); } if (!empty($hosts)) { $templates = API::Template()->get(['templateids' => $templateids, 'output' => ['hostid', 'host'], 'nopermissions' => true]); $hosts = implode(', ', zbx_objectValues($hosts, 'host')); $templates = implode(', ', zbx_objectValues($templates, 'host')); info(_s('Templates "%1$s" unlinked from hosts "%2$s".', $templates, $hosts)); } }
protected function addRelatedObjects(array $options, array $result) { $result = parent::addRelatedObjects($options, $result); $hostids = array_keys($result); // adding groups if ($options['selectGroups'] !== null) { $relationMap = $this->createRelationMap($result, 'hostid', 'groupid', 'hosts_groups'); $groups = API::HostGroup()->get(array('output' => $options['selectGroups'], 'groupids' => $relationMap->getRelatedIds(), 'preservekeys' => true)); $result = $relationMap->mapMany($result, $groups, 'groups'); } // adding templates if ($options['selectParentTemplates'] !== null) { if ($options['selectParentTemplates'] != API_OUTPUT_COUNT) { $relationMap = $this->createRelationMap($result, 'hostid', 'templateid', 'hosts_templates'); $templates = API::Template()->get(array('output' => $options['selectParentTemplates'], 'templateids' => $relationMap->getRelatedIds(), 'preservekeys' => true)); if (!is_null($options['limitSelects'])) { order_result($templates, 'host'); } $result = $relationMap->mapMany($result, $templates, 'parentTemplates', $options['limitSelects']); } else { $templates = API::Template()->get(array('hostids' => $hostids, 'countOutput' => true, 'groupCount' => true)); $templates = zbx_toHash($templates, 'hostid'); foreach ($result as $hostid => $host) { $result[$hostid]['parentTemplates'] = isset($templates[$hostid]) ? $templates[$hostid]['rowscount'] : 0; } } } // adding items if ($options['selectItems'] !== null) { if ($options['selectItems'] != API_OUTPUT_COUNT) { $items = API::Item()->get(array('output' => $this->outputExtend($options['selectItems'], array('hostid', 'itemid')), 'hostids' => $hostids, 'nopermissions' => true, 'preservekeys' => true)); if (!is_null($options['limitSelects'])) { order_result($items, 'name'); } $relationMap = $this->createRelationMap($items, 'hostid', 'itemid'); $items = $this->unsetExtraFields($items, array('hostid', 'itemid'), $options['selectItems']); $result = $relationMap->mapMany($result, $items, 'items', $options['limitSelects']); } else { $items = API::Item()->get(array('hostids' => $hostids, 'nopermissions' => true, 'countOutput' => true, 'groupCount' => true)); $items = zbx_toHash($items, 'hostid'); foreach ($result as $hostid => $host) { $result[$hostid]['items'] = isset($items[$hostid]) ? $items[$hostid]['rowscount'] : 0; } } } // adding discoveries if ($options['selectDiscoveries'] !== null) { if ($options['selectDiscoveries'] != API_OUTPUT_COUNT) { $items = API::DiscoveryRule()->get(array('output' => $this->outputExtend($options['selectDiscoveries'], array('hostid', 'itemid')), 'hostids' => $hostids, 'nopermissions' => true, 'preservekeys' => true)); if (!is_null($options['limitSelects'])) { order_result($items, 'name'); } $relationMap = $this->createRelationMap($items, 'hostid', 'itemid'); $items = $this->unsetExtraFields($items, array('hostid', 'itemid'), $options['selectDiscoveries']); $result = $relationMap->mapMany($result, $items, 'discoveries', $options['limitSelects']); } else { $items = API::DiscoveryRule()->get(array('hostids' => $hostids, 'nopermissions' => true, 'countOutput' => true, 'groupCount' => true)); $items = zbx_toHash($items, 'hostid'); foreach ($result as $hostid => $host) { $result[$hostid]['discoveries'] = isset($items[$hostid]) ? $items[$hostid]['rowscount'] : 0; } } } // adding triggers if ($options['selectTriggers'] !== null) { if ($options['selectTriggers'] != API_OUTPUT_COUNT) { // discovered items $res = DBselect('SELECT i.hostid,f.triggerid' . ' FROM items i,functions f' . ' WHERE ' . dbConditionInt('i.hostid', $hostids) . ' AND i.itemid=f.itemid'); $relationMap = new CRelationMap(); while ($relation = DBfetch($res)) { $relationMap->addRelation($relation['hostid'], $relation['triggerid']); } $triggers = API::Trigger()->get(array('output' => $options['selectTriggers'], 'triggerids' => $relationMap->getRelatedIds(), 'preservekeys' => true)); if (!is_null($options['limitSelects'])) { order_result($triggers, 'description'); } $result = $relationMap->mapMany($result, $triggers, 'triggers', $options['limitSelects']); } else { $triggers = API::Trigger()->get(array('hostids' => $hostids, 'countOutput' => true, 'groupCount' => true)); $triggers = zbx_toHash($triggers, 'hostid'); foreach ($result as $hostid => $host) { $result[$hostid]['triggers'] = isset($triggers[$hostid]) ? $triggers[$hostid]['rowscount'] : 0; } } } // adding graphs if ($options['selectGraphs'] !== null) { if ($options['selectGraphs'] != API_OUTPUT_COUNT) { // discovered items $res = DBselect('SELECT i.hostid,gi.graphid' . ' FROM items i,graphs_items gi' . ' WHERE ' . dbConditionInt('i.hostid', $hostids) . ' AND i.itemid=gi.itemid'); $relationMap = new CRelationMap(); while ($relation = DBfetch($res)) { $relationMap->addRelation($relation['hostid'], $relation['graphid']); } $graphs = API::Graph()->get(array('output' => $options['selectGraphs'], 'graphids' => $relationMap->getRelatedIds(), 'preservekeys' => true)); if (!is_null($options['limitSelects'])) { order_result($graphs, 'name'); } $result = $relationMap->mapMany($result, $graphs, 'graphs', $options['limitSelects']); } else { $graphs = API::Graph()->get(array('hostids' => $hostids, 'countOutput' => true, 'groupCount' => true)); $graphs = zbx_toHash($graphs, 'hostid'); foreach ($result as $hostid => $host) { $result[$hostid]['graphs'] = isset($graphs[$hostid]) ? $graphs[$hostid]['rowscount'] : 0; } } } // adding http tests if ($options['selectHttpTests'] !== null) { if ($options['selectHttpTests'] != API_OUTPUT_COUNT) { $httpTests = API::HttpTest()->get(array('output' => $this->outputExtend($options['selectHttpTests'], array('hostid', 'httptestid')), 'hostids' => $hostids, 'nopermissions' => true, 'preservekeys' => true)); if (!is_null($options['limitSelects'])) { order_result($httpTests, 'name'); } $relationMap = $this->createRelationMap($httpTests, 'hostid', 'httptestid'); $httpTests = $this->unsetExtraFields($httpTests, array('hostid', 'httptestid'), $options['selectHttpTests']); $result = $relationMap->mapMany($result, $httpTests, 'httpTests', $options['limitSelects']); } else { $httpTests = API::HttpTest()->get(array('hostids' => $hostids, 'nopermissions' => true, 'countOutput' => true, 'groupCount' => true)); $httpTests = zbx_toHash($httpTests, 'hostid'); foreach ($result as $hostId => $host) { $result[$hostId]['httpTests'] = isset($httpTests[$hostId]) ? $httpTests[$hostId]['rowscount'] : 0; } } } // adding applications if ($options['selectApplications'] !== null) { if ($options['selectApplications'] != API_OUTPUT_COUNT) { $applications = API::Application()->get(array('output' => $this->outputExtend($options['selectApplications'], array('hostid', 'applicationid')), 'hostids' => $hostids, 'nopermissions' => true, 'preservekeys' => true)); if (!is_null($options['limitSelects'])) { order_result($applications, 'name'); } $relationMap = $this->createRelationMap($applications, 'hostid', 'applicationid'); $applications = $this->unsetExtraFields($applications, array('hostid', 'applicationid'), $options['selectApplications']); $result = $relationMap->mapMany($result, $applications, 'applications', $options['limitSelects']); } else { $applications = API::Application()->get(array('output' => $options['selectApplications'], 'hostids' => $hostids, 'nopermissions' => true, 'countOutput' => true, 'groupCount' => true)); $applications = zbx_toHash($applications, 'hostid'); foreach ($result as $hostid => $host) { $result[$hostid]['applications'] = isset($applications[$hostid]) ? $applications[$hostid]['rowscount'] : 0; } } } // adding macros if ($options['selectMacros'] !== null && $options['selectMacros'] != API_OUTPUT_COUNT) { $macros = API::UserMacro()->get(array('output' => $this->outputExtend($options['selectMacros'], array('hostid', 'hostmacroid')), 'hostids' => $hostids, 'preservekeys' => true)); $relationMap = $this->createRelationMap($macros, 'hostid', 'hostmacroid'); $macros = $this->unsetExtraFields($macros, array('hostid', 'hostmacroid'), $options['selectMacros']); $result = $relationMap->mapMany($result, $macros, 'macros', $options['limitSelects']); } return $result; }
if (isset($_REQUEST['hostgroupid']) && !empty($_REQUEST['hostgroupid'])) { $triggerOptions['groupids'] = $_REQUEST['hostgroupid']; } // filter template group $groupsComboBox = new CComboBox('filter_groupid', $_REQUEST['filter_groupid'], 'javascript: submit();'); $groupsComboBox->addItem(0, _('all')); $groups = API::HostGroup()->get(array('output' => array('groupid', 'name'), 'templated_hosts' => true, 'with_triggers' => true)); order_result($groups, 'name'); foreach ($groups as $group) { $groupsComboBox->addItem($group['groupid'], $group['name']); } $filterForm->addRow(_('Template group'), $groupsComboBox); // filter template $templateComboBox = new CComboBox('filter_hostid', $_REQUEST['filter_hostid'], 'javascript: submit();'); $templateComboBox->addItem(0, _('all')); $templates = API::Template()->get(array('output' => array('templateid', 'name'), 'groupids' => empty($_REQUEST['filter_groupid']) ? null : $_REQUEST['filter_groupid'], 'with_triggers' => true)); order_result($templates, 'name'); $templateIds = array(); foreach ($templates as $template) { $templateIds[$template['templateid']] = $template['templateid']; $templateComboBox->addItem($template['templateid'], $template['name']); } $filterForm->addRow(_('Template'), $templateComboBox); // filter trigger $triggerComboBox = new CComboBox('tpl_triggerid', getRequest('tpl_triggerid', 0), 'javascript: submit()'); $triggerComboBox->addItem(0, _('all')); $sqlCondition = empty($_REQUEST['filter_hostid']) ? ' AND ' . dbConditionInt('h.hostid', $templateIds) : ' AND h.hostid=' . zbx_dbstr($_REQUEST['filter_hostid']); $sql = 'SELECT DISTINCT t.triggerid,t.description,h.name' . ' FROM triggers t,hosts h,items i,functions f' . ' WHERE f.itemid=i.itemid' . ' AND h.hostid=i.hostid' . ' AND t.status=' . TRIGGER_STATUS_ENABLED . ' AND t.triggerid=f.triggerid' . ' AND h.status=' . HOST_STATUS_TEMPLATE . ' AND i.status=' . ITEM_STATUS_ACTIVE . $sqlCondition . ' ORDER BY t.description'; $triggers = DBfetchArrayAssoc(DBselect($sql), 'triggerid'); foreach ($triggers as $trigger) { $templateName = empty($_REQUEST['filter_hostid']) ? $trigger['name'] . NAME_DELIMITER : '';
CProfile::update('web.items.' . $name, implode(';', $_REQUEST[$name]), PROFILE_TYPE_STR); } else { $_REQUEST[$name] = array(); $subfiltersVal = CProfile::get('web.items.' . $name); if (!zbx_empty($subfiltersVal)) { $_REQUEST[$name] = explode(';', $subfiltersVal); $_REQUEST[$name] = array_combine($_REQUEST[$name], $_REQUEST[$name]); } } } } if (!isset($_REQUEST['form']) && isset($_REQUEST['filter_hostid']) && !empty($_REQUEST['filter_hostid'])) { if (!isset($host)) { $host = API::Host()->getObjects(array('hostid' => $_REQUEST['filter_hostid'])); if (empty($host)) { $host = API::Template()->getObjects(array('hostid' => $_REQUEST['filter_hostid'])); } $host = reset($host); } if ($host) { $_REQUEST['hostid'] = isset($host['hostid']) ? $host['hostid'] : $host['templateid']; } } /* * Actions */ $result = false; if (isset($_REQUEST['add_delay_flex']) && isset($_REQUEST['new_delay_flex'])) { $timePeriodValidator = new CTimePeriodValidator(array('allowMultiple' => false)); $_REQUEST['delay_flex'] = get_request('delay_flex', array()); if ($timePeriodValidator->validate($_REQUEST['new_delay_flex']['period'])) {
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); } } } }
/** * Generates array with HTML items representing operation with description * * @param int $type short or long description, use const. SHORT_DESCRIPTION and LONG_DESCRIPTION * @param array $data * @param int $data['operationtype'] type of operation: OPERATION_TYPE_MESSAGE, OPERATION_TYPE_COMMAND, ... * @param int $data['opmessage']['mediatypeid'] type id of message media * @param bool $data['opmessage']['default_msg'] should default message be used * @param bool $data['opmessage']['operationid'] if true $data['operationid'] will be used to retrieve default messages from DB * @param string $data['opmessage']['subject'] subject of message * @param string $data['opmessage']['message'] message it self * @param array $data['opmessage_usr'] list of user ids if OPERATION_TYPE_MESSAGE * @param array $data['opmessage_grp'] list of group ids if OPERATION_TYPE_MESSAGE * @param array $data['opcommand_grp'] list of group ids if OPERATION_TYPE_COMMAND * @param array $data['opcommand_hst'] list of host ids if OPERATION_TYPE_COMMAND * @param array $data['opgroup'] list of group ids if OPERATION_TYPE_GROUP_ADD or OPERATION_TYPE_GROUP_REMOVE * @param array $data['optemplate'] list of template ids if OPERATION_TYPE_TEMPLATE_ADD or OPERATION_TYPE_TEMPLATE_REMOVE * @param int $data['operationid'] id of operation * @param int $data['opcommand']['type'] type of command: ZBX_SCRIPT_TYPE_IPMI, ZBX_SCRIPT_TYPE_SSH, ... * @param string $data['opcommand']['command'] actual command * @param int $data['opcommand']['scriptid'] script id used if $data['opcommand']['type'] is ZBX_SCRIPT_TYPE_GLOBAL_SCRIPT * * @return array */ function get_operation_descr($type, $data) { $result = array(); if ($type == SHORT_DESCRIPTION) { switch ($data['operationtype']) { case OPERATION_TYPE_MESSAGE: $mediaTypes = API::Mediatype()->get(array('mediatypeids' => $data['opmessage']['mediatypeid'], 'output' => array('description'))); if (empty($mediaTypes)) { $mediatype = _('all media'); } else { $mediatype = reset($mediaTypes); $mediatype = $mediatype['description']; } if (!empty($data['opmessage_usr'])) { $users = API::User()->get(array('userids' => zbx_objectValues($data['opmessage_usr'], 'userid'), 'output' => array('userid', 'alias', 'name', 'surname'))); order_result($users, 'alias'); foreach ($users as $user) { $fullnames[] = getUserFullname($user); } $result[] = bold(_('Send message to users') . NAME_DELIMITER); $result[] = array(implode(', ', $fullnames), SPACE, _('via'), SPACE, $mediatype); $result[] = BR(); } if (!empty($data['opmessage_grp'])) { $usrgrps = API::UserGroup()->get(array('usrgrpids' => zbx_objectValues($data['opmessage_grp'], 'usrgrpid'), 'output' => API_OUTPUT_EXTEND)); order_result($usrgrps, 'name'); $result[] = bold(_('Send message to user groups') . NAME_DELIMITER); $result[] = array(implode(', ', zbx_objectValues($usrgrps, 'name')), SPACE, _('via'), SPACE, $mediatype); $result[] = BR(); } break; case OPERATION_TYPE_COMMAND: if (!isset($data['opcommand_grp'])) { $data['opcommand_grp'] = array(); } if (!isset($data['opcommand_hst'])) { $data['opcommand_hst'] = array(); } $hosts = API::Host()->get(array('hostids' => zbx_objectValues($data['opcommand_hst'], 'hostid'), 'output' => array('hostid', 'name'))); foreach ($data['opcommand_hst'] as $cmd) { if ($cmd['hostid'] != 0) { continue; } $result[] = array(bold(_('Run remote commands on current host')), BR()); break; } if (!empty($hosts)) { order_result($hosts, 'name'); $result[] = bold(_('Run remote commands on hosts') . NAME_DELIMITER); $result[] = array(implode(', ', zbx_objectValues($hosts, 'name')), BR()); } $groups = API::HostGroup()->get(array('groupids' => zbx_objectValues($data['opcommand_grp'], 'groupid'), 'output' => array('groupid', 'name'))); if (!empty($groups)) { order_result($groups, 'name'); $result[] = bold(_('Run remote commands on host groups') . NAME_DELIMITER); $result[] = array(implode(', ', zbx_objectValues($groups, 'name')), BR()); } break; case OPERATION_TYPE_HOST_ADD: $result[] = array(bold(_('Add host')), BR()); break; case OPERATION_TYPE_HOST_REMOVE: $result[] = array(bold(_('Remove host')), BR()); break; case OPERATION_TYPE_HOST_ENABLE: $result[] = array(bold(_('Enable host')), BR()); break; case OPERATION_TYPE_HOST_DISABLE: $result[] = array(bold(_('Disable host')), BR()); break; case OPERATION_TYPE_GROUP_ADD: case OPERATION_TYPE_GROUP_REMOVE: if (!isset($data['opgroup'])) { $data['opgroup'] = array(); } $groups = API::HostGroup()->get(array('groupids' => zbx_objectValues($data['opgroup'], 'groupid'), 'output' => array('groupid', 'name'))); if (!empty($groups)) { order_result($groups, 'name'); if (OPERATION_TYPE_GROUP_ADD == $data['operationtype']) { $result[] = bold(_('Add to host groups') . NAME_DELIMITER); } else { $result[] = bold(_('Remove from host groups') . NAME_DELIMITER); } $result[] = array(implode(', ', zbx_objectValues($groups, 'name')), BR()); } break; case OPERATION_TYPE_TEMPLATE_ADD: case OPERATION_TYPE_TEMPLATE_REMOVE: if (!isset($data['optemplate'])) { $data['optemplate'] = array(); } $templates = API::Template()->get(array('templateids' => zbx_objectValues($data['optemplate'], 'templateid'), 'output' => array('hostid', 'name'))); if (!empty($templates)) { order_result($templates, 'name'); if (OPERATION_TYPE_TEMPLATE_ADD == $data['operationtype']) { $result[] = bold(_('Link to templates') . NAME_DELIMITER); } else { $result[] = bold(_('Unlink from templates') . NAME_DELIMITER); } $result[] = array(implode(', ', zbx_objectValues($templates, 'name')), BR()); } break; default: } } else { switch ($data['operationtype']) { case OPERATION_TYPE_MESSAGE: if (isset($data['opmessage']['default_msg']) && !empty($data['opmessage']['default_msg'])) { if (isset($_REQUEST['def_shortdata']) && isset($_REQUEST['def_longdata'])) { $result[] = array(bold(_('Subject') . NAME_DELIMITER), BR(), zbx_nl2br($_REQUEST['def_shortdata'])); $result[] = array(bold(_('Message') . NAME_DELIMITER), BR(), zbx_nl2br($_REQUEST['def_longdata'])); } elseif (isset($data['opmessage']['operationid'])) { $sql = 'SELECT a.def_shortdata,a.def_longdata ' . ' FROM actions a,operations o ' . ' WHERE a.actionid=o.actionid ' . ' AND o.operationid=' . zbx_dbstr($data['operationid']); if ($rows = DBfetch(DBselect($sql, 1))) { $result[] = array(bold(_('Subject') . NAME_DELIMITER), BR(), zbx_nl2br($rows['def_shortdata'])); $result[] = array(bold(_('Message') . NAME_DELIMITER), BR(), zbx_nl2br($rows['def_longdata'])); } } } else { $result[] = array(bold(_('Subject') . NAME_DELIMITER), BR(), zbx_nl2br($data['opmessage']['subject'])); $result[] = array(bold(_('Message') . NAME_DELIMITER), BR(), zbx_nl2br($data['opmessage']['message'])); } break; case OPERATION_TYPE_COMMAND: switch ($data['opcommand']['type']) { case ZBX_SCRIPT_TYPE_IPMI: $result[] = array(bold(_('Run IPMI command') . NAME_DELIMITER), BR(), italic(zbx_nl2br($data['opcommand']['command']))); break; case ZBX_SCRIPT_TYPE_SSH: $result[] = array(bold(_('Run SSH commands') . NAME_DELIMITER), BR(), italic(zbx_nl2br($data['opcommand']['command']))); break; case ZBX_SCRIPT_TYPE_TELNET: $result[] = array(bold(_('Run TELNET commands') . NAME_DELIMITER), BR(), italic(zbx_nl2br($data['opcommand']['command']))); break; case ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT: if ($data['opcommand']['execute_on'] == ZBX_SCRIPT_EXECUTE_ON_AGENT) { $result[] = array(bold(_('Run custom commands on Zabbix agent') . NAME_DELIMITER), BR(), italic(zbx_nl2br($data['opcommand']['command']))); } else { $result[] = array(bold(_('Run custom commands on Zabbix server') . NAME_DELIMITER), BR(), italic(zbx_nl2br($data['opcommand']['command']))); } break; case ZBX_SCRIPT_TYPE_GLOBAL_SCRIPT: $userScripts = API::Script()->get(array('scriptids' => $data['opcommand']['scriptid'], 'output' => API_OUTPUT_EXTEND)); $userScript = reset($userScripts); $result[] = array(bold(_('Run global script') . NAME_DELIMITER), italic($userScript['name'])); break; default: $result[] = array(bold(_('Run commands') . NAME_DELIMITER), BR(), italic(zbx_nl2br($data['opcommand']['command']))); } break; default: } } return $result; }
/** * Validate input for copy method. * * @param array $data */ protected function validateCopy(array $data) { $screenIds = $data['screenIds']; $templateIds = $data['templateIds']; $screens = $this->get(array('screenids' => $screenIds, 'output' => array('screenid', 'name', 'templateid'), 'editable' => true, 'preservekeys' => true)); foreach ($screenIds as $screenId) { if (!isset($screens[$screenId])) { self::exception(ZBX_API_ERROR_PERMISSIONS, _('No permissions to referred object or it does not exist!')); } } // check permissions on templates if (!API::Template()->isWritable($templateIds)) { self::exception(ZBX_API_ERROR_PERMISSIONS, _('No permissions to referred object or it does not exist!')); } // check if screen with same name exists $existingScreens = $this->get(array('filter' => array('name' => zbx_objectValues($screens, 'name'), 'templateid' => $templateIds), 'output' => array('screenid', 'name', 'templateid'), 'preservekeys' => true)); foreach ($existingScreens as $existingScreen) { $template = DBfetch(DBselect('SELECT h.name FROM hosts h WHERE h.hostid=' . $existingScreen['templateid'])); self::exception(ZBX_API_ERROR_PARAMETERS, _s('Screen "%1$s" already exists on template "%2$2".', $existingScreen['name'], $template['name'])); } }
$_REQUEST['filter_snmp_oid'] = CProfile::get('web.items.filter_snmp_oid'); $_REQUEST['filter_port'] = CProfile::get('web.items.filter_port'); $_REQUEST['filter_value_type'] = CProfile::get('web.items.filter_value_type', -1); $_REQUEST['filter_data_type'] = CProfile::get('web.items.filter_data_type', -1); $_REQUEST['filter_delay'] = CProfile::get('web.items.filter_delay'); $_REQUEST['filter_history'] = CProfile::get('web.items.filter_history'); $_REQUEST['filter_trends'] = CProfile::get('web.items.filter_trends'); $_REQUEST['filter_status'] = CProfile::get('web.items.filter_status'); $_REQUEST['filter_templated_items'] = CProfile::get('web.items.filter_templated_items', -1); $_REQUEST['filter_with_triggers'] = CProfile::get('web.items.filter_with_triggers', -1); $_REQUEST['filter_ipmi_sensor'] = CProfile::get('web.items.filter_ipmi_sensor'); } if (isset($_REQUEST['filter_hostname']) && !zbx_empty($_REQUEST['filter_hostname'])) { $hostid = API::Host()->getObjects(array('name' => $_REQUEST['filter_hostname'])); if (empty($hostid)) { $hostid = API::Template()->getObjects(array('name' => $_REQUEST['filter_hostname'])); } $hostid = reset($hostid); $hostid = $hostid ? $hostid['hostid'] : 0; } // subfilters foreach (array('subfilter_apps', 'subfilter_types', 'subfilter_value_types', 'subfilter_status', 'subfilter_templated_items', 'subfilter_with_triggers', 'subfilter_hosts', 'subfilter_interval', 'subfilter_history', 'subfilter_trends') as $name) { $_REQUEST[$name] = isset($_REQUEST['filter_set']) ? array() : get_request($name, array()); } /* * Actions */ $result = false; if (isset($_REQUEST['add_delay_flex']) && isset($_REQUEST['new_delay_flex'])) { $timePeriodValidator = new CTimePeriodValidator(array('allow_multiple' => false)); $_REQUEST['delay_flex'] = get_request('delay_flex', array());
/** * Get templates for export from database. * * @param array $templateIds */ protected function gatherTemplates(array $templateIds) { $templates = API::Template()->get(array('templateids' => $templateIds, 'output' => array('host', 'name'), 'selectMacros' => API_OUTPUT_EXTEND, 'selectGroups' => API_OUTPUT_EXTEND, 'selectParentTemplates' => API_OUTPUT_EXTEND, 'preservekeys' => true)); // merge host groups with all groups $templateGroups = array(); foreach ($templates as &$template) { $templateGroups += zbx_toHash($template['groups'], 'groupid'); $template['screens'] = array(); $template['applications'] = array(); $template['discoveryRules'] = array(); $template['items'] = array(); } unset($template); $this->data['groups'] += $templateGroups; // applications $applications = API::Application()->get(array('hostids' => $templateIds, 'output' => API_OUTPUT_EXTEND, 'inherited' => false, 'preservekeys' => true)); foreach ($applications as $application) { if (!isset($templates[$application['hostid']]['applications'])) { $templates[$application['hostid']]['applications'] = array(); } $templates[$application['hostid']]['applications'][] = $application; } // screens $screens = API::TemplateScreen()->get(array('templateids' => $templateIds, 'selectScreenItems' => API_OUTPUT_EXTEND, 'noInheritance' => true, 'output' => API_OUTPUT_EXTEND, 'preservekeys' => true)); $this->prepareScreenExport($screens); foreach ($screens as $screen) { if (!isset($templates[$screen['templateid']]['screens'])) { $templates[$screen['templateid']]['screens'] = array(); } $templates[$screen['templateid']]['screens'][] = $screen; } $this->data['templates'] = $templates; $this->gatherTemplateItems($templateIds); $this->gatherTemplateDiscoveryRules($templateIds); }
/** * Import hosts. * * @param array $hosts * * @throws Exception */ public function import(array $hosts) { $hostsToCreate = array(); $hostsToUpdate = array(); foreach ($hosts as $host) { // preserve host related templates to massAdd them later if ($this->options['templateLinkage']['createMissing'] && !empty($host['templates'])) { foreach ($host['templates'] as $template) { $templateId = $this->referencer->resolveTemplate($template['name']); if (!$templateId) { throw new Exception(_s('Template "%1$s" for host "%2$s" does not exist.', $template['name'], $host['host'])); } $templateLinkage[$host['host']][] = array('templateid' => $templateId); } } unset($host['templates']); $host = $this->resolveHostReferences($host); if (isset($host['hostid'])) { $hostsToUpdate[] = $host; } else { $hostsToCreate[] = $host; } } $hostsToUpdate = $this->addInterfaceIds($hostsToUpdate); // create/update hosts if ($this->options['hosts']['createMissing'] && $hostsToCreate) { $newHostIds = API::Host()->create($hostsToCreate); foreach ($newHostIds['hostids'] as $hnum => $hostId) { $hostHost = $hostsToCreate[$hnum]['host']; $this->processedHostIds[$hostHost] = $hostId; $this->referencer->addHostRef($hostHost, $hostId); if (!empty($templateLinkage[$hostHost])) { API::Template()->massAdd(array('hosts' => array('hostid' => $hostId), 'templates' => $templateLinkage[$hostHost])); } } } if ($this->options['hosts']['updateExisting'] && $hostsToUpdate) { API::Host()->update($hostsToUpdate); foreach ($hostsToUpdate as $host) { $this->processedHostIds[$host['host']] = $host['hostid']; if (!empty($templateLinkage[$host['host']])) { API::Template()->massAdd(array('hosts' => $host, 'templates' => $templateLinkage[$host['host']])); } } } // create interfaces cache interface_ref->interfaceid $dbInterfaces = API::HostInterface()->get(array('hostids' => $this->processedHostIds, 'output' => API_OUTPUT_EXTEND)); foreach ($hosts as $host) { if (isset($this->processedHostIds[$host['host']])) { foreach ($host['interfaces'] as $interface) { $hostId = $this->processedHostIds[$host['host']]; if (!isset($this->referencer->interfacesCache[$hostId])) { $this->referencer->interfacesCache[$hostId] = array(); } foreach ($dbInterfaces as $dbInterface) { if ($hostId == $dbInterface['hostid'] && $dbInterface['ip'] == $interface['ip'] && $dbInterface['dns'] == $interface['dns'] && $dbInterface['useip'] == $interface['useip'] && $dbInterface['port'] == $interface['port'] && $dbInterface['type'] == $interface['type'] && $dbInterface['main'] == $interface['main'] && $dbInterface['bulk'] == $interface['bulk']) { $refName = $interface['interface_ref']; $this->referencer->interfacesCache[$hostId][$refName] = $dbInterface['interfaceid']; } } } } } }
/** * Check if trigger prototype has a correct trigger expression and has at least one item prototype and belongs to * one discovery rule, does not belong to a host and a template simultaneously and has permissions to all hosts and * templates in the expression. * * @param array $triggerPrototype * @param string $triggerPrototype['description'] * @param string $triggerPrototype['expression'] * * @throws APIException * * @return void */ protected function checkExpression(array $triggerPrototype) { $triggerExpression = new CTriggerExpression(); if (!$triggerExpression->parse($triggerPrototype['expression'])) { self::exception(ZBX_API_ERROR_PARAMETERS, $triggerExpression->error); } $lld_rules = []; if ($triggerExpression->expressions) { $expressions = []; $hosts = []; $has_host = false; $has_template = false; foreach ($triggerExpression->expressions as $expression) { if (!array_key_exists($expression['host'], $expressions)) { $expressions[$expression['host']] = ['hostid' => null, 'items' => []]; } $expressions[$expression['host']]['items'][$expression['item']] = true; $hosts[$expression['host']] = true; } $db_hosts = API::Host()->get(['output' => ['hostid', 'host'], 'filter' => ['host' => array_keys($hosts)]]); foreach ($db_hosts as $db_host) { $expressions[$db_host['host']]['hostid'] = $db_host['hostid']; $has_host = true; unset($hosts[$db_host['host']]); } if ($hosts) { $db_templates = API::Template()->get(['output' => ['templateid', 'host'], 'filter' => ['host' => array_keys($hosts)]]); foreach ($db_templates as $db_template) { $expressions[$db_template['host']]['hostid'] = $db_template['templateid']; $has_template = true; } } if ($has_host && $has_template) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect trigger prototype expression.' . ' Trigger prototype expression elements should not belong to a template and a host simultaneously.')); } foreach ($expressions as $host => $expression) { if ($expression['hostid'] === null) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect trigger prototype expression.' . ' Host "%1$s" does not exist or you have no access to this host.', $host)); } $db_item_prototypes = API::ItemPrototype()->get(['output' => [], 'selectDiscoveryRule' => ['itemid'], 'hostids' => [$expression['hostid']], 'filter' => ['key_' => array_keys($expression['items'])], 'nopermissions' => true]); foreach ($db_item_prototypes as $db_item_prototype) { $lld_rules[$db_item_prototype['discoveryRule']['itemid']] = true; } } if (count($lld_rules) > 1) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Trigger prototype "%1$s" contains item prototypes from multiple discovery rules.', $triggerPrototype['description'])); } } if (!$lld_rules) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Trigger prototype "%1$s" must contain at least one item prototype.', $triggerPrototype['description'])); } }
/** * Get Itemprototype data */ public function get($options = array()) { $result = array(); $userType = self::$userData['type']; $userid = self::$userData['userid']; // allowed columns for sorting $sortColumns = array('itemid', 'name', 'key_', 'delay', 'history', 'trends', 'type', 'status'); // allowed output options for [ select_* ] params $subselectsAllowedOutputs = array(API_OUTPUT_REFER, API_OUTPUT_EXTEND, API_OUTPUT_CUSTOM); $sqlParts = array('select' => array('items' => 'i.itemid'), 'from' => array('items' => 'items i'), 'where' => array('i.flags=' . ZBX_FLAG_DISCOVERY_CHILD), 'group' => array(), 'order' => array(), 'limit' => null); $defOptions = array('nodeids' => null, 'groupids' => null, 'templateids' => null, 'hostids' => null, 'itemids' => null, 'discoveryids' => null, 'graphids' => null, 'triggerids' => null, 'inherited' => null, 'templated' => null, 'monitored' => null, 'editable' => null, 'nopermissions' => null, 'filter' => null, 'search' => null, 'searchByAny' => null, 'startSearch' => null, 'excludeSearch' => null, 'searchWildcardsEnabled' => null, 'output' => API_OUTPUT_REFER, 'selectHosts' => null, 'selectApplications' => null, 'selectTriggers' => null, 'selectGraphs' => null, 'countOutput' => null, 'groupCount' => null, 'preservekeys' => null, 'sortfield' => '', 'sortorder' => '', 'limit' => null, 'limitSelects' => null); $options = zbx_array_merge($defOptions, $options); if (is_array($options['output'])) { unset($sqlParts['select']['items']); $dbTable = DB::getSchema('items'); $sqlParts['select']['itemid'] = 'i.itemid'; foreach ($options['output'] as $field) { if (isset($dbTable['fields'][$field])) { $sqlParts['select'][$field] = 'i.' . $field; } } $options['output'] = API_OUTPUT_CUSTOM; } // editable + PERMISSION CHECK if ($userType != USER_TYPE_SUPER_ADMIN && !$options['nopermissions']) { $permission = $options['editable'] ? PERM_READ_WRITE : PERM_READ_ONLY; $userGroups = getUserGroupsByUserId($userid); $sqlParts['where'][] = 'EXISTS (' . 'SELECT NULL' . ' FROM hosts_groups hgg' . ' JOIN rights r' . ' ON r.id=hgg.groupid' . ' AND ' . dbConditionInt('r.groupid', $userGroups) . ' WHERE i.hostid=hgg.hostid' . ' GROUP BY hgg.hostid' . ' HAVING MIN(r.permission)>=' . $permission . ')'; } // nodeids $nodeids = !is_null($options['nodeids']) ? $options['nodeids'] : get_current_nodeid(); // templateids if (!is_null($options['templateids'])) { zbx_value2array($options['templateids']); if (!is_null($options['hostids'])) { zbx_value2array($options['hostids']); $options['hostids'] = array_merge($options['hostids'], $options['templateids']); } else { $options['hostids'] = $options['templateids']; } } // hostids if (!is_null($options['hostids'])) { zbx_value2array($options['hostids']); if ($options['output'] != API_OUTPUT_EXTEND) { $sqlParts['select']['hostid'] = 'i.hostid'; } $sqlParts['where']['hostid'] = dbConditionInt('i.hostid', $options['hostids']); if (!is_null($options['groupCount'])) { $sqlParts['group']['i'] = 'i.hostid'; } } // itemids if (!is_null($options['itemids'])) { zbx_value2array($options['itemids']); $sqlParts['where']['itemid'] = dbConditionInt('i.itemid', $options['itemids']); } // discoveryids if (!is_null($options['discoveryids'])) { zbx_value2array($options['discoveryids']); if ($options['output'] != API_OUTPUT_SHORTEN) { $sqlParts['select']['discoveryid'] = 'id.parent_itemid'; } $sqlParts['from']['item_discovery'] = 'item_discovery id'; $sqlParts['where'][] = dbConditionInt('id.parent_itemid', $options['discoveryids']); $sqlParts['where']['idi'] = 'i.itemid=id.itemid'; if (!is_null($options['groupCount'])) { $sqlParts['group']['id'] = 'id.parent_itemid'; } } // triggerids if (!is_null($options['triggerids'])) { zbx_value2array($options['triggerids']); if ($options['output'] != API_OUTPUT_SHORTEN) { $sqlParts['select']['triggerid'] = 'f.triggerid'; } $sqlParts['from']['functions'] = 'functions f'; $sqlParts['where'][] = dbConditionInt('f.triggerid', $options['triggerids']); $sqlParts['where']['if'] = 'i.itemid=f.itemid'; } // graphids if (!is_null($options['graphids'])) { zbx_value2array($options['graphids']); if ($options['output'] != API_OUTPUT_SHORTEN) { $sqlParts['select']['graphid'] = 'gi.graphid'; } $sqlParts['from']['graphs_items'] = 'graphs_items gi'; $sqlParts['where'][] = dbConditionInt('gi.graphid', $options['graphids']); $sqlParts['where']['igi'] = 'i.itemid=gi.itemid'; } // inherited if (!is_null($options['inherited'])) { if ($options['inherited']) { $sqlParts['where'][] = 'i.templateid IS NOT NULL'; } else { $sqlParts['where'][] = 'i.templateid IS NULL'; } } // templated if (!is_null($options['templated'])) { $sqlParts['from']['hosts'] = 'hosts h'; $sqlParts['where']['hi'] = 'h.hostid=i.hostid'; if ($options['templated']) { $sqlParts['where'][] = 'h.status=' . HOST_STATUS_TEMPLATE; } else { $sqlParts['where'][] = 'h.status<>' . HOST_STATUS_TEMPLATE; } } // monitored if (!is_null($options['monitored'])) { $sqlParts['from']['hosts'] = 'hosts h'; $sqlParts['where']['hi'] = 'h.hostid=i.hostid'; if ($options['monitored']) { $sqlParts['where'][] = 'h.status=' . HOST_STATUS_MONITORED; $sqlParts['where'][] = 'i.status=' . ITEM_STATUS_ACTIVE; } else { $sqlParts['where'][] = '(h.status<>' . HOST_STATUS_MONITORED . ' OR i.status<>' . ITEM_STATUS_ACTIVE . ')'; } } // search if (is_array($options['search'])) { zbx_db_search('items i', $options, $sqlParts); } // --- FILTER --- if (is_array($options['filter'])) { $this->dbFilter('items i', $options, $sqlParts); if (isset($options['filter']['host'])) { zbx_value2array($options['filter']['host']); $sqlParts['from']['hosts'] = 'hosts h'; $sqlParts['where']['hi'] = 'h.hostid=i.hostid'; $sqlParts['where']['h'] = dbConditionString('h.host', $options['filter']['host']); } } // output if ($options['output'] == API_OUTPUT_EXTEND) { $sqlParts['select']['items'] = 'i.*'; } // countOutput if (!is_null($options['countOutput'])) { $options['sortfield'] = ''; $sqlParts['select'] = array('count(DISTINCT i.itemid) as rowscount'); //groupCount if (!is_null($options['groupCount'])) { foreach ($sqlParts['group'] as $key => $fields) { $sqlParts['select'][$key] = $fields; } } } // sorting zbx_db_sorting($sqlParts, $options, $sortColumns, 'i'); // limit if (zbx_ctype_digit($options['limit']) && $options['limit']) { $sqlParts['limit'] = $options['limit']; } //---------- $itemids = array(); $sqlParts['select'] = array_unique($sqlParts['select']); $sqlParts['from'] = array_unique($sqlParts['from']); $sqlParts['where'] = array_unique($sqlParts['where']); $sqlParts['group'] = array_unique($sqlParts['group']); $sqlParts['order'] = array_unique($sqlParts['order']); $sqlSelect = ''; $sqlFrom = ''; $sqlWhere = ''; $sqlGroup = ''; $sqlOrder = ''; if (!empty($sqlParts['select'])) { $sqlSelect .= implode(',', $sqlParts['select']); } if (!empty($sqlParts['from'])) { $sqlFrom .= implode(',', $sqlParts['from']); } if (!empty($sqlParts['where'])) { $sqlWhere .= ' AND ' . implode(' AND ', $sqlParts['where']); } if (!empty($sqlParts['group'])) { $sqlWhere .= ' GROUP BY ' . implode(',', $sqlParts['group']); } if (!empty($sqlParts['order'])) { $sqlOrder .= ' ORDER BY ' . implode(',', $sqlParts['order']); } $sqlLimit = $sqlParts['limit']; $sql = 'SELECT ' . zbx_db_distinct($sqlParts) . ' ' . $sqlSelect . ' FROM ' . $sqlFrom . ' WHERE ' . DBin_node('i.itemid', $nodeids) . $sqlWhere . $sqlGroup . $sqlOrder; //SDI($sql); $res = DBselect($sql, $sqlLimit); while ($item = DBfetch($res)) { if (!is_null($options['countOutput'])) { if (!is_null($options['groupCount'])) { $result[] = $item; } else { $result = $item['rowscount']; } } else { $itemids[$item['itemid']] = $item['itemid']; if ($options['output'] == API_OUTPUT_SHORTEN) { $result[$item['itemid']] = array('itemid' => $item['itemid']); } else { if (!isset($result[$item['itemid']])) { $result[$item['itemid']] = array(); } if (!is_null($options['selectHosts']) && !isset($result[$item['itemid']]['hosts'])) { $result[$item['itemid']]['hosts'] = array(); } if (!is_null($options['selectApplications']) && !isset($result[$item['itemid']]['applications'])) { $result[$item['itemid']]['applications'] = array(); } if (!is_null($options['selectTriggers']) && !isset($result[$item['itemid']]['triggers'])) { $result[$item['itemid']]['triggers'] = array(); } if (!is_null($options['selectGraphs']) && !isset($result[$item['itemid']]['graphs'])) { $result[$item['itemid']]['graphs'] = array(); } // hostids if (isset($item['hostid']) && is_null($options['selectHosts'])) { if (!isset($result[$item['itemid']]['hosts'])) { $result[$item['itemid']]['hosts'] = array(); } $result[$item['itemid']]['hosts'][] = array('hostid' => $item['hostid']); } // triggerids if (isset($item['triggerid']) && is_null($options['selectTriggers'])) { if (!isset($result[$item['itemid']]['triggers'])) { $result[$item['itemid']]['triggers'] = array(); } $result[$item['itemid']]['triggers'][] = array('triggerid' => $item['triggerid']); unset($item['triggerid']); } // graphids if (isset($item['graphid']) && is_null($options['selectGraphs'])) { if (!isset($result[$item['itemid']]['graphs'])) { $result[$item['itemid']]['graphs'] = array(); } $result[$item['itemid']]['graphs'][] = array('graphid' => $item['graphid']); unset($item['graphid']); } // discoveryids if (isset($item['discoveryids'])) { if (!isset($result[$item['itemid']]['discovery'])) { $result[$item['itemid']]['discovery'] = array(); } $result[$item['itemid']]['discovery'][] = array('ruleid' => $item['item_parentid']); unset($item['item_parentid']); } $result[$item['itemid']] += $item; } } } if (!is_null($options['countOutput'])) { return $result; } // Adding Objects // Adding hosts if (!is_null($options['selectHosts'])) { if (is_array($options['selectHosts']) || str_in_array($options['selectHosts'], $subselectsAllowedOutputs)) { $objParams = array('nodeids' => $nodeids, 'itemids' => $itemids, 'templated_hosts' => 1, 'output' => $options['selectHosts'], 'nopermissions' => 1, 'preservekeys' => 1); $hosts = API::Host()->get($objParams); foreach ($hosts as $host) { $hitems = $host['items']; unset($host['items']); foreach ($hitems as $inum => $item) { $result[$item['itemid']]['hosts'][] = $host; } } $templates = API::Template()->get($objParams); foreach ($templates as $template) { $titems = $template['items']; unset($template['items']); foreach ($titems as $inum => $item) { $result[$item['itemid']]['hosts'][] = $template; } } } } // Adding triggers if (!is_null($options['selectTriggers'])) { $objParams = array('nodeids' => $nodeids, 'itemids' => $itemids, 'preservekeys' => true); if (in_array($options['selectTriggers'], $subselectsAllowedOutputs)) { $objParams['output'] = $options['selectTriggers']; $triggers = API::TriggerPrototype()->get($objParams); if (!is_null($options['limitSelects'])) { order_result($triggers, 'description'); } $count = array(); foreach ($triggers as $triggerid => $trigger) { unset($triggers[$triggerid]['items']); foreach ($trigger['items'] as $item) { if (!is_null($options['limitSelects'])) { if (!isset($count[$item['itemid']])) { $count[$item['itemid']] = 0; } $count[$item['itemid']]++; if ($count[$item['itemid']] > $options['limitSelects']) { continue; } } $result[$item['itemid']]['triggers'][] =& $triggers[$triggerid]; } } } elseif (API_OUTPUT_COUNT == $options['selectTriggers']) { $objParams['countOutput'] = 1; $objParams['groupCount'] = 1; $triggers = API::TriggerPrototype()->get($objParams); $triggers = zbx_toHash($triggers, 'parent_itemid'); foreach ($result as $itemid => $item) { if (isset($triggers[$itemid])) { $result[$itemid]['triggers'] = $triggers[$itemid]['rowscount']; } else { $result[$itemid]['triggers'] = 0; } } } } // Adding applications if (!is_null($options['selectApplications']) && str_in_array($options['selectApplications'], $subselectsAllowedOutputs)) { $objParams = array('nodeids' => $nodeids, 'output' => $options['selectApplications'], 'itemids' => $itemids, 'preservekeys' => 1); $applications = API::Application()->get($objParams); foreach ($applications as $applicationid => $application) { $aitems = $application['items']; unset($application['items']); foreach ($aitems as $inum => $item) { $result[$item['itemid']]['applications'][] = $application; } } } // Adding graphs if (!is_null($options['selectGraphs'])) { $objParams = array('nodeids' => $nodeids, 'itemids' => $itemids, 'preservekeys' => true); if (in_array($options['selectGraphs'], $subselectsAllowedOutputs)) { $objParams['output'] = $options['selectGraphs']; $graphs = API::GraphPrototype()->get($objParams); if (!is_null($options['limitSelects'])) { order_result($graphs, 'name'); } $count = array(); foreach ($graphs as $graphid => $graph) { unset($graphs[$graphid]['items']); foreach ($graph['items'] as $item) { if (!is_null($options['limitSelects'])) { if (!isset($count[$item['itemid']])) { $count[$item['itemid']] = 0; } $count[$item['itemid']]++; if ($count[$item['itemid']] > $options['limitSelects']) { continue; } } $result[$item['itemid']]['graphs'][] =& $graphs[$graphid]; } } } elseif (API_OUTPUT_COUNT == $options['selectGraphs']) { $objParams['countOutput'] = 1; $objParams['groupCount'] = 1; $graphs = API::GraphPrototype()->get($objParams); $graphs = zbx_toHash($graphs, 'parent_itemid'); foreach ($result as $itemid => $item) { if (isset($graphs[$itemid])) { $result[$itemid]['graphs'] = $graphs[$itemid]['rowscount']; } else { $result[$itemid]['graphs'] = 0; } } } } if (is_null($options['preservekeys'])) { $result = zbx_cleanHashes($result); } return $result; }
/** * Select template ids for previously added template names. */ protected function selectTemplates() { if (!empty($this->templates)) { $this->templatesRefs = array(); $dbTemplates = API::Template()->get(array('output' => array('host', 'templateid'), 'preservekeys' => true, 'editable' => true, 'filter' => array('host' => $this->templates))); foreach ($dbTemplates as $template) { $this->templatesRefs[$template['host']] = $template['templateid']; } $this->templates = array(); } }
function getCopyElementsFormData($elementsField, $title = null) { $data = array('title' => $title, 'elements_field' => $elementsField, 'elements' => getRequest($elementsField, array()), 'copy_type' => getRequest('copy_type', COPY_TYPE_TO_HOST_GROUP), 'copy_groupid' => getRequest('copy_groupid', 0), 'copy_targetid' => getRequest('copy_targetid', array()), 'hostid' => getRequest('hostid', 0), 'groups' => array(), 'hosts' => array(), 'templates' => array()); // validate elements if (empty($data['elements']) || !is_array($data['elements'])) { error(_('Incorrect list of items.')); return null; } if ($data['copy_type'] == COPY_TYPE_TO_HOST_GROUP) { // get groups $data['groups'] = API::HostGroup()->get(array('output' => array('groupid', 'name'))); order_result($data['groups'], 'name'); } else { // hosts or templates $params = array('output' => array('name', 'groupid')); if ($data['copy_type'] == COPY_TYPE_TO_HOST) { $params['real_hosts'] = true; } else { $params['templated_hosts'] = true; } $data['groups'] = API::HostGroup()->get($params); order_result($data['groups'], 'name'); $groupIds = zbx_objectValues($data['groups'], 'groupid'); if (!in_array($data['copy_groupid'], $groupIds) || $data['copy_groupid'] == 0) { $data['copy_groupid'] = reset($groupIds); } if ($data['copy_type'] == COPY_TYPE_TO_TEMPLATE) { $data['templates'] = API::Template()->get(array('output' => array('name', 'templateid'), 'groupids' => $data['copy_groupid'])); order_result($data['templates'], 'name'); } elseif ($data['copy_type'] == COPY_TYPE_TO_HOST) { $data['hosts'] = API::Host()->get(array('output' => array('name', 'hostid'), 'groupids' => $data['copy_groupid'])); order_result($data['hosts'], 'name'); } } return $data; }
/** * Additionally allows to unlink templates from hosts and other templates. * * Checks write permissions for templates. * * Additional supported $data parameters are: * - hostids - an array of host or template IDs to unlink the given templates from * * @param array $data * * @return array */ public function massRemove(array $data) { $templateids = zbx_toArray($data['templateids']); // check permissions if (!$this->isWritable($templateids)) { self::exception(ZBX_API_ERROR_PERMISSIONS, _('You do not have permission to perform this operation.')); } if (isset($data['hostids'])) { API::Template()->unlink($templateids, zbx_toArray($data['hostids'])); } $data['hostids'] = array(); return parent::massRemove($data); }
} $caption = OPERATION_TYPE_GROUP_ADD == $this->data['new_operation']['operationtype'] ? _('Add to host groups') : _('Remove from host groups'); $newOperationsTable->addRow(array($caption, new CDiv($groupList, 'objectgroup inlineblock border_dotted ui-corner-all'))); break; case OPERATION_TYPE_TEMPLATE_ADD: case OPERATION_TYPE_TEMPLATE_REMOVE: if (!isset($this->data['new_operation']['optemplate'])) { $this->data['new_operation']['optemplate'] = array(); } $templateList = new CTable(); $templateList->setAttribute('id', 'opTemplateList'); $templateList->addRow(new CRow(new CCol(array(new CMultiSelect(array('name' => 'discoveryTemplates', 'objectName' => 'templates', 'objectOptions' => array('editable' => true))), new CButton('add', _('Add'), 'return addDiscoveryTemplates();', 'link_menu')), null, 2), null, 'opTemplateListFooter')); // load templates $templateIds = isset($this->data['new_operation']['optemplate']) ? zbx_objectValues($this->data['new_operation']['optemplate'], 'templateid') : array(); if ($templateIds) { $templates = API::Template()->get(array('templateids' => $templateIds, 'output' => array('templateid', 'name'))); order_result($templates, 'name'); $jsInsert = ''; $jsInsert .= 'addPopupValues(' . zbx_jsvalue(array('object' => 'dsc_templateid', 'values' => $templates)) . ');'; zbx_add_post_js($jsInsert); } $caption = OPERATION_TYPE_TEMPLATE_ADD == $this->data['new_operation']['operationtype'] ? _('Link with templates') : _('Unlink from templates'); $newOperationsTable->addRow(array($caption, new CDiv($templateList, 'objectgroup inlineblock border_dotted ui-corner-all'))); break; } // append operation conditions to form list if ($this->data['eventsource'] == 0) { if (!isset($this->data['new_operation']['opconditions'])) { $this->data['new_operation']['opconditions'] = array(); } else { zbx_rksort($this->data['new_operation']['opconditions']);
/** * Mass update hosts * * @param array $hosts multidimensional array with Hosts data * @param array $hosts ['hosts'] Array of Host objects to update * @param string $hosts ['fields']['host'] Host name. * @param array $hosts ['fields']['groupids'] HostGroup IDs add Host to. * @param int $hosts ['fields']['port'] Port. OPTIONAL * @param int $hosts ['fields']['status'] Host Status. OPTIONAL * @param int $hosts ['fields']['useip'] Use IP. OPTIONAL * @param string $hosts ['fields']['dns'] DNS. OPTIONAL * @param string $hosts ['fields']['ip'] IP. OPTIONAL * @param int $hosts ['fields']['proxy_hostid'] Proxy Host ID. OPTIONAL * @param int $hosts ['fields']['ipmi_authtype'] IPMI authentication type. OPTIONAL * @param int $hosts ['fields']['ipmi_privilege'] IPMI privilege. OPTIONAL * @param string $hosts ['fields']['ipmi_username'] IPMI username. OPTIONAL * @param string $hosts ['fields']['ipmi_password'] IPMI password. OPTIONAL * * @return boolean */ public function massUpdate($data) { $hosts = zbx_toArray($data['hosts']); $hostids = zbx_objectValues($hosts, 'hostid'); $updHosts = $this->get(array('hostids' => $hostids, 'editable' => true, 'output' => API_OUTPUT_EXTEND, 'preservekeys' => true)); foreach ($hosts as $host) { if (!isset($updHosts[$host['hostid']])) { self::exception(ZBX_API_ERROR_PERMISSIONS, _('You do not have permission to perform this operation.')); } } // check if hosts have at least 1 group if (isset($data['groups']) && empty($data['groups'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('No groups for hosts.')); } /* * Update hosts properties */ if (isset($data['name'])) { if (count($hosts) > 1) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot mass update visible host name.')); } } if (isset($data['host'])) { if (!preg_match('/^' . ZBX_PREG_HOST_FORMAT . '$/', $data['host'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect characters used for host name "%s".', $data['host'])); } if (count($hosts) > 1) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot mass update host name.')); } $curHost = reset($hosts); $hostExists = $this->get(array('filter' => array('host' => $curHost['host']), 'output' => API_OUTPUT_SHORTEN, 'editable' => true, 'nopermissions' => true)); $hostExist = reset($hostExists); if ($hostExist && bccomp($hostExist['hostid'], $curHost['hostid']) != 0) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Host "%1$s" already exists.', $data['host'])); } // can't add host with the same name as existing template if (API::Template()->exists(array('host' => $curHost['host']))) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Template "%1$s" already exists.', $curHost['host'])); } } if (isset($data['groups'])) { $updateGroups = $data['groups']; unset($data['groups']); } if (isset($data['interfaces'])) { $updateInterfaces = $data['interfaces']; unset($data['interfaces']); } if (isset($data['templates_clear'])) { $updateTemplatesClear = zbx_toArray($data['templates_clear']); unset($data['templates_clear']); } if (isset($data['templates'])) { $updateTemplates = $data['templates']; unset($data['templates']); } if (isset($data['macros'])) { $updateMacros = $data['macros']; unset($data['macros']); } if (isset($data['inventory'])) { $updateInventory = $data['inventory']; unset($data['inventory']); } if (isset($data['inventory_mode'])) { if (!isset($updateInventory)) { $updateInventory = array(); } $updateInventory['inventory_mode'] = $data['inventory_mode']; unset($data['inventory_mode']); } if (isset($data['status'])) { $updateStatus = $data['status']; unset($data['status']); } unset($data['hosts']); if (!zbx_empty($data)) { $update = array('values' => $data, 'where' => array('hostid' => $hostids)); DB::update('hosts', $update); } if (isset($updateStatus)) { updateHostStatus($hostids, $updateStatus); } /* * Update hostgroups linkage */ if (isset($updateGroups)) { $updateGroups = zbx_toArray($updateGroups); $hostGroups = API::HostGroup()->get(array('hostids' => $hostids)); $hostGroupids = zbx_objectValues($hostGroups, 'groupid'); $newGroupids = zbx_objectValues($updateGroups, 'groupid'); $result = $this->massAdd(array('hosts' => $hosts, 'groups' => $updateGroups)); if (!$result) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot create host group.')); } $groupidsToDel = array_diff($hostGroupids, $newGroupids); if (!empty($groupidsToDel)) { $result = $this->massRemove(array('hostids' => $hostids, 'groupids' => $groupidsToDel)); if (!$result) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot delete host group.')); } } } /* * Update interfaces */ if (isset($updateInterfaces)) { $hostInterfaces = API::HostInterface()->get(array('hostids' => $hostids, 'output' => API_OUTPUT_EXTEND, 'preservekeys' => true, 'nopermissions' => true)); $this->massRemove(array('hostids' => $hostids, 'interfaces' => $hostInterfaces)); $this->massAdd(array('hosts' => $hosts, 'interfaces' => $updateInterfaces)); } if (isset($updateTemplatesClear)) { $templateidsClear = zbx_objectValues($updateTemplatesClear, 'templateid'); if (!empty($updateTemplatesClear)) { $this->massRemove(array('hostids' => $hostids, 'templateids_clear' => $templateidsClear)); } } else { $templateidsClear = array(); } /* * Update template linkage */ if (isset($updateTemplates)) { $hostTemplates = API::Template()->get(array('hostids' => $hostids, 'output' => API_OUTPUT_SHORTEN, 'preservekeys' => true)); $hostTemplateids = array_keys($hostTemplates); $newTemplateids = zbx_objectValues($updateTemplates, 'templateid'); $templatesToDel = array_diff($hostTemplateids, $newTemplateids); $templatesToDel = array_diff($templatesToDel, $templateidsClear); if (!empty($templatesToDel)) { $result = $this->massRemove(array('hostids' => $hostids, 'templateids' => $templatesToDel)); if (!$result) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot unlink template')); } } $result = $this->massAdd(array('hosts' => $hosts, 'templates' => $updateTemplates)); if (!$result) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot link template')); } } // macros if (isset($updateMacros)) { DB::delete('hostmacro', array('hostid' => $hostids)); $this->massAdd(array('hosts' => $hosts, 'macros' => $updateMacros)); } /* * Inventory */ if (isset($updateInventory)) { if ($updateInventory['inventory_mode'] == HOST_INVENTORY_DISABLED) { $sql = 'DELETE FROM host_inventory WHERE ' . dbConditionInt('hostid', $hostids); if (!DBexecute($sql)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot delete inventory.')); } } else { $hostsWithInventories = array(); $existingInventoriesDb = DBselect('SELECT hostid FROM host_inventory WHERE ' . dbConditionInt('hostid', $hostids)); while ($existingInventory = DBfetch($existingInventoriesDb)) { $hostsWithInventories[] = $existingInventory['hostid']; } // when hosts are being updated to use automatic mode for host inventories, // we must check if some items are set to populate inventory fields of every host. // if they do, mass update for those fields should be ignored if ($updateInventory['inventory_mode'] == HOST_INVENTORY_AUTOMATIC) { // getting all items on all affected hosts $itemsToInventories = API::item()->get(array('output' => array('inventory_link', 'hostid'), 'filter' => array('hostid' => $hostids), 'nopermissions' => true)); // gathering links to array: 'hostid'=>array('inventory_name_1'=>true, 'inventory_name_2'=>true) $inventoryLinksOnHosts = array(); $inventoryFields = getHostInventories(); foreach ($itemsToInventories as $hinv) { if ($hinv['inventory_link'] != 0) { // 0 means 'no link' if (isset($inventoryLinksOnHosts[$hinv['hostid']])) { $inventoryLinksOnHosts[$hinv['hostid']][$inventoryFields[$hinv['inventory_link']]['db_field']] = true; } else { $inventoryLinksOnHosts[$hinv['hostid']] = array($inventoryFields[$hinv['inventory_link']]['db_field'] => true); } } } // now we have all info we need to determine, which inventory fields should be saved $inventoriesToSave = array(); foreach ($hostids as $hostid) { $inventoriesToSave[$hostid] = $updateInventory; $inventoriesToSave[$hostid]['hostid'] = $hostid; foreach ($updateInventory as $inventoryName => $hinv) { if (isset($inventoryLinksOnHosts[$hostid][$inventoryName])) { unset($inventoriesToSave[$hostid][$inventoryName]); } } } } else { // if mode is not automatic, all fields can be saved $inventoriesToSave = array(); foreach ($hostids as $hostid) { $inventoriesToSave[$hostid] = $updateInventory; $inventoriesToSave[$hostid]['hostid'] = $hostid; } } $hostsWithoutInventory = array_diff($hostids, $hostsWithInventories); // hosts that have no inventory yet, need it to be inserted foreach ($hostsWithoutInventory as $hostid) { DB::insert('host_inventory', array($inventoriesToSave[$hostid]), false); } // those hosts that already have an inventory, need it to be updated foreach ($hostsWithInventories as $hostid) { DB::update('host_inventory', array('values' => $inventoriesToSave[$hostid], 'where' => array('hostid' => $hostid))); } } } return array('hostids' => $hostids); }
/** * Import templates. * * @throws Exception * * @param array $templates * * @return void */ public function import(array $templates) { $templates = zbx_toHash($templates, 'host'); $this->checkCircularTemplateReferences($templates); foreach ($templates as &$template) { if (!$this->options['templateLinkage']['createMissing']) { unset($template['templates']); } } unset($template); do { $independentTemplates = $this->getIndependentTemplates($templates); $templatesToCreate = []; $templatesToUpdate = []; $templateLinkage = []; foreach ($independentTemplates as $name) { $template = $templates[$name]; unset($templates[$name]); $template = $this->resolveTemplateReferences($template); // if we need to add linkages, save linked templates to massAdd later if ($this->options['templateLinkage']['createMissing'] && !empty($template['templates'])) { $templateLinkage[$template['host']] = $template['templates']; unset($template['templates']); } if (!empty($template['templateid'])) { $templatesToUpdate[] = $template; } else { $templatesToCreate[] = $template; } } if ($this->options['templates']['createMissing'] && $templatesToCreate) { $newTemplateIds = API::Template()->create($templatesToCreate); foreach ($templatesToCreate as $num => $createdTemplate) { $templateId = $newTemplateIds['templateids'][$num]; $this->referencer->addTemplateRef($createdTemplate['host'], $templateId); $this->processedTemplateIds[$templateId] = $templateId; if (!empty($templateLinkage[$createdTemplate['host']])) { API::Template()->massAdd(['templates' => ['templateid' => $templateId], 'templates_link' => $templateLinkage[$createdTemplate['host']]]); } } } if ($this->options['templates']['updateExisting'] && $templatesToUpdate) { API::Template()->update($templatesToUpdate); foreach ($templatesToUpdate as $updatedTemplate) { $this->processedTemplateIds[$updatedTemplate['templateid']] = $updatedTemplate['templateid']; if (!empty($templateLinkage[$updatedTemplate['host']])) { API::Template()->massAdd(['templates' => $updatedTemplate, 'templates_link' => $templateLinkage[$updatedTemplate['host']]]); } } } } while (!empty($independentTemplates)); // if there are templates left in $templates, then they have unresolved references foreach ($templates as $template) { $unresolvedReferences = []; foreach ($template['templates'] as $linkedTemplate) { if (!$this->referencer->resolveTemplate($linkedTemplate['name'])) { $unresolvedReferences[] = $linkedTemplate['name']; } } throw new Exception(_n('Cannot import template "%1$s", linked template "%2$s" does not exist.', 'Cannot import template "%1$s", linked templates "%2$s" do not exist.', $template['host'], implode(', ', $unresolvedReferences), count($unresolvedReferences))); } }
/** * Mass update hosts. * * @param array $hosts multidimensional array with Hosts data * @param array $hosts['hosts'] Array of Host objects to update * @param string $hosts['fields']['host'] Host name. * @param array $hosts['fields']['groupids'] HostGroup IDs add Host to. * @param int $hosts['fields']['port'] Port. OPTIONAL * @param int $hosts['fields']['status'] Host Status. OPTIONAL * @param int $hosts['fields']['useip'] Use IP. OPTIONAL * @param string $hosts['fields']['dns'] DNS. OPTIONAL * @param string $hosts['fields']['ip'] IP. OPTIONAL * @param int $hosts['fields']['proxy_hostid'] Proxy Host ID. OPTIONAL * @param int $hosts['fields']['ipmi_authtype'] IPMI authentication type. OPTIONAL * @param int $hosts['fields']['ipmi_privilege'] IPMI privilege. OPTIONAL * @param string $hosts['fields']['ipmi_username'] IPMI username. OPTIONAL * @param string $hosts['fields']['ipmi_password'] IPMI password. OPTIONAL * * @return boolean */ public function massUpdate($data) { $hosts = zbx_toArray($data['hosts']); $inputHostIds = zbx_objectValues($hosts, 'hostid'); $hostids = array_unique($inputHostIds); sort($hostids); $updHosts = $this->get(array('hostids' => $hostids, 'editable' => true, 'output' => API_OUTPUT_EXTEND, 'preservekeys' => true)); foreach ($hosts as $host) { if (!isset($updHosts[$host['hostid']])) { self::exception(ZBX_API_ERROR_PERMISSIONS, _('You do not have permission to perform this operation.')); } } // check if hosts have at least 1 group if (isset($data['groups']) && empty($data['groups'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _('No groups for hosts.')); } /* * Update hosts properties */ if (isset($data['name'])) { if (count($hosts) > 1) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot mass update visible host name.')); } } if (isset($data['host'])) { if (!preg_match('/^' . ZBX_PREG_HOST_FORMAT . '$/', $data['host'])) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect characters used for host name "%s".', $data['host'])); } if (count($hosts) > 1) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot mass update host name.')); } $curHost = reset($hosts); $hostExists = $this->get(array('filter' => array('host' => $curHost['host']), 'output' => array('hostid'), 'editable' => true, 'nopermissions' => true)); $hostExist = reset($hostExists); if ($hostExist && bccomp($hostExist['hostid'], $curHost['hostid']) != 0) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Host "%1$s" already exists.', $data['host'])); } // can't add host with the same name as existing template if (API::Template()->exists(array('host' => $curHost['host']))) { self::exception(ZBX_API_ERROR_PARAMETERS, _s('Template "%1$s" already exists.', $curHost['host'])); } } if (isset($data['groups'])) { $updateGroups = $data['groups']; } if (isset($data['interfaces'])) { $updateInterfaces = $data['interfaces']; } if (isset($data['templates_clear'])) { $updateTemplatesClear = zbx_toArray($data['templates_clear']); } if (isset($data['templates'])) { $updateTemplates = $data['templates']; } if (isset($data['macros'])) { $updateMacros = $data['macros']; } // second check is necessary, because import incorrectly inputs unset 'inventory' as empty string rather than null if (isset($data['inventory']) && $data['inventory']) { if (isset($data['inventory_mode']) && $data['inventory_mode'] == HOST_INVENTORY_DISABLED) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot set inventory fields for disabled inventory.')); } $updateInventory = $data['inventory']; $updateInventory['inventory_mode'] = null; } if (isset($data['inventory_mode'])) { if (!isset($updateInventory)) { $updateInventory = array(); } $updateInventory['inventory_mode'] = $data['inventory_mode']; } if (isset($data['status'])) { $updateStatus = $data['status']; } unset($data['hosts'], $data['groups'], $data['interfaces'], $data['templates_clear'], $data['templates'], $data['macros'], $data['inventory'], $data['inventory_mode'], $data['status']); if (!zbx_empty($data)) { DB::update('hosts', array('values' => $data, 'where' => array('hostid' => $hostids))); } if (isset($updateStatus)) { updateHostStatus($hostids, $updateStatus); } /* * Update interfaces */ if (isset($updateInterfaces)) { $hostInterfaces = API::HostInterface()->get(array('hostids' => $hostids, 'output' => API_OUTPUT_EXTEND, 'preservekeys' => true, 'nopermissions' => true)); $this->massRemove(array('hostids' => $hostids, 'interfaces' => $hostInterfaces)); $this->massAdd(array('hosts' => $hosts, 'interfaces' => $updateInterfaces)); } if (isset($updateTemplatesClear)) { $templateidsClear = zbx_objectValues($updateTemplatesClear, 'templateid'); if ($updateTemplatesClear) { $this->massRemove(array('hostids' => $hostids, 'templateids_clear' => $templateidsClear)); } } else { $templateidsClear = array(); } /* * Update template linkage */ if (isset($updateTemplates)) { $hostTemplates = API::Template()->get(array('hostids' => $hostids, 'output' => array('templateid'), 'preservekeys' => true)); $hostTemplateids = array_keys($hostTemplates); $newTemplateids = zbx_objectValues($updateTemplates, 'templateid'); $templatesToDel = array_diff($hostTemplateids, $newTemplateids); $templatesToDel = array_diff($templatesToDel, $templateidsClear); if ($templatesToDel) { $result = $this->massRemove(array('hostids' => $hostids, 'templateids' => $templatesToDel)); if (!$result) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot unlink template')); } } $result = $this->massAdd(array('hosts' => $hosts, 'templates' => $updateTemplates)); if (!$result) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot link template')); } } // macros if (isset($updateMacros)) { DB::delete('hostmacro', array('hostid' => $hostids)); $this->massAdd(array('hosts' => $hosts, 'macros' => $updateMacros)); } /* * Inventory */ if (isset($updateInventory)) { // disabling inventory if ($updateInventory['inventory_mode'] == HOST_INVENTORY_DISABLED) { $sql = 'DELETE FROM host_inventory WHERE ' . dbConditionInt('hostid', $hostids); if (!DBexecute($sql)) { self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot delete inventory.')); } } else { $existingInventoriesDb = DBfetchArrayAssoc(DBselect('SELECT hostid,inventory_mode' . ' FROM host_inventory' . ' WHERE ' . dbConditionInt('hostid', $hostids)), 'hostid'); // check existing host inventory data $automaticHostIds = array(); if ($updateInventory['inventory_mode'] === null) { foreach ($hostids as $hostId) { // if inventory is disabled for one of the updated hosts, throw an exception if (!isset($existingInventoriesDb[$hostId])) { $host = get_host_by_hostid($hostId); self::exception(ZBX_API_ERROR_PARAMETERS, _s('Inventory disabled for host "%1$s".', $host['host'])); } elseif ($existingInventoriesDb[$hostId]['inventory_mode'] == HOST_INVENTORY_AUTOMATIC) { $automaticHostIds[] = $hostId; } } } $inventoriesToSave = array(); foreach ($hostids as $hostId) { $hostInventory = $updateInventory; $hostInventory['hostid'] = $hostId; // if no 'inventory_mode' has been passed, set inventory 'inventory_mode' from DB if ($updateInventory['inventory_mode'] === null) { $hostInventory['inventory_mode'] = $existingInventoriesDb[$hostId]['inventory_mode']; } $inventoriesToSave[$hostId] = $hostInventory; } // when updating automatic inventory, ignore fields that have items linked to them if ($updateInventory['inventory_mode'] == HOST_INVENTORY_AUTOMATIC || $updateInventory['inventory_mode'] === null && $automaticHostIds) { $itemsToInventories = API::item()->get(array('output' => array('inventory_link', 'hostid'), 'hostids' => $automaticHostIds ? $automaticHostIds : $hostids, 'nopermissions' => true)); $inventoryFields = getHostInventories(); foreach ($itemsToInventories as $hinv) { // 0 means 'no link' if ($hinv['inventory_link'] != 0) { $inventoryName = $inventoryFields[$hinv['inventory_link']]['db_field']; unset($inventoriesToSave[$hinv['hostid']][$inventoryName]); } } } // save inventory data foreach ($inventoriesToSave as $inventory) { $hostId = $inventory['hostid']; if (isset($existingInventoriesDb[$hostId])) { DB::update('host_inventory', array('values' => $inventory, 'where' => array('hostid' => $hostId))); } else { DB::insert('host_inventory', array($inventory), false); } } } } /* * Update host and host group linkage. This procedure should be done the last because user can unlink * him self from a group with write permissions leaving only read premissions. Thus other procedures, like * host-template linkage, inventory update, macros update, must be done before this. */ if (isset($updateGroups)) { $updateGroups = zbx_toArray($updateGroups); $hostGroups = API::HostGroup()->get(array('output' => array('groupid'), 'hostids' => $hostids)); $hostGroupids = zbx_objectValues($hostGroups, 'groupid'); $newGroupids = zbx_objectValues($updateGroups, 'groupid'); $groupsToAdd = array_diff($newGroupids, $hostGroupids); if ($groupsToAdd) { $this->massAdd(array('hosts' => $hosts, 'groups' => zbx_toObject($groupsToAdd, 'groupid'))); } $groupidsToDel = array_diff($hostGroupids, $newGroupids); if ($groupidsToDel) { $this->massRemove(array('hostids' => $hostids, 'groupids' => $groupidsToDel)); } } return array('hostids' => $inputHostIds); }