✏️ 正在编辑: CTemplateImporter.php
路径:
/usr/share/zabbix/include/classes/import/importers/CTemplateImporter.php
提示:
您可以编辑任何文件(包括二进制文件),但请注意不当修改可能导致文件损坏。
<?php /* ** Zabbix ** Copyright (C) 2001-2021 Zabbix SIA ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ class CTemplateImporter extends CImporter { /** * @var array a list of template IDs which were created or updated */ protected $processedTemplateIds = []; /** * Import templates. * * @throws Exception * * @param array $templates */ public function import(array $templates) { $templates = zbx_toHash($templates, 'host'); $this->checkCircularTemplateReferences($templates); if (!$this->options['templateLinkage']['createMissing'] && !$this->options['templateLinkage']['deleteMissing']) { foreach ($templates as $name => $template) { unset($templates[$name]['templates']); } } do { $independentTemplates = $this->getIndependentTemplates($templates); $templatesToCreate = []; $templatesToUpdate = []; $templateLinkage = []; $tmpls_to_clear = []; foreach ($independentTemplates as $name) { $template = $templates[$name]; unset($templates[$name]); $template = $this->resolveTemplateReferences($template); /* * Save linked templates for 2 purposes: * - save linkages to add in case if 'create new' linkages is checked; * - calculate missing linkages in case if 'delete missing' is checked. */ if (!empty($template['templates'])) { $templateLinkage[$template['host']] = $template['templates']; } unset($template['templates']); if (array_key_exists('templateid', $template) && ($this->options['templates']['updateExisting'] || $this->options['process_templates'])) { $templatesToUpdate[] = $template; } else if ($this->options['templates']['createMissing']) { if (array_key_exists('templateid', $template)) { throw new Exception(_s('Template "%1$s" already exists.', $name)); } $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 ($this->options['templateLinkage']['createMissing'] && !empty($templateLinkage[$createdTemplate['host']])) { API::Template()->massAdd([ 'templates' => ['templateid' => $templateId], 'templates_link' => $templateLinkage[$createdTemplate['host']] ]); } } } if ($templatesToUpdate) { // Get template linkages to unlink and clear. if ($this->options['templateLinkage']['deleteMissing']) { // Get already linked templates. $db_template_links = API::Template()->get([ 'output' => ['templateid'], 'selectParentTemplates' => ['templateid'], 'templateids' => zbx_objectValues($templatesToUpdate, 'templateid'), 'preservekeys' => true ]); foreach ($db_template_links as &$db_template_link) { $db_template_link = zbx_objectValues($db_template_link['parentTemplates'], 'templateid'); } unset($db_template_link); foreach ($templatesToUpdate as $tmpl) { if (array_key_exists($tmpl['host'], $templateLinkage)) { $tmpls_to_clear[$tmpl['templateid']] = array_diff($db_template_links[$tmpl['templateid']], zbx_objectValues($templateLinkage[$tmpl['host']], 'templateid') ); } else { $tmpls_to_clear[$tmpl['templateid']] = $db_template_links[$tmpl['templateid']]; } } } if ($this->options['templates']['updateExisting']) { API::Template()->update($templatesToUpdate); } foreach ($templatesToUpdate as $updatedTemplate) { $this->processedTemplateIds[$updatedTemplate['templateid']] = $updatedTemplate['templateid']; // Drop existing template linkages if 'delete missing' is selected. if (array_key_exists($updatedTemplate['templateid'], $tmpls_to_clear) && $tmpls_to_clear[$updatedTemplate['templateid']]) { API::Template()->massRemove([ 'templateids' => [$updatedTemplate['templateid']], 'templateids_clear' => $tmpls_to_clear[$updatedTemplate['templateid']] ]); } // Make new template linkages. if ($this->options['templateLinkage']['createMissing'] && !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))); } } /** * Get a list of created or updated template IDs. * * @return array */ public function getProcessedTemplateIds() { return $this->processedTemplateIds; } /** * Check if templates have circular references. * * @throws Exception * @see checkCircularRecursive * * @param array $templates */ protected function checkCircularTemplateReferences(array $templates) { foreach ($templates as $name => $template) { if (empty($template['templates'])) { continue; } foreach ($template['templates'] as $linkedTemplate) { $checked = [$name]; if ($circTemplates = $this->checkCircularRecursive($linkedTemplate, $templates, $checked)) { throw new Exception(_s('Circular reference in templates: %1$s.', implode(' - ', $circTemplates))); } } } } /** * Recursive function for searching for circular template references. * If circular reference exist it return array with template names with circular reference. * * @param array $linkedTemplate template element to inspect on current recursive loop * @param array $templates all templates where circular references should be searched * @param array $checked template names that already were processed, * should contain unique values if no circular references exist * * @return array|bool */ protected function checkCircularRecursive(array $linkedTemplate, array $templates, array $checked) { $linkedTemplateName = $linkedTemplate['name']; // if current element map name is already in list of checked map names, // circular reference exists if (in_array($linkedTemplateName, $checked)) { // to have nice result containing only maps that have circular reference, // remove everything that was added before repeated map name $checked = array_slice($checked, array_search($linkedTemplateName, $checked)); // add repeated name to have nice loop like m1->m2->m3->m1 $checked[] = $linkedTemplateName; return $checked; } else { $checked[] = $linkedTemplateName; } // we need to find map that current element reference to // and if it has selements check all them recursively if (!empty($templates[$linkedTemplateName]['templates'])) { foreach ($templates[$linkedTemplateName]['templates'] as $tpl) { return $this->checkCircularRecursive($tpl, $templates, $checked); } } return false; } /** * Get templates that don't have not existing linked templates i.e. all templates that must be linked to these templates exist. * Returns array with template names (host). * * @param array $templates * * @return array */ protected function getIndependentTemplates(array $templates) { foreach ($templates as $num => $template) { if (empty($template['templates'])) { continue; } foreach ($template['templates'] as $linkedTpl) { if (!$this->referencer->resolveTemplate($linkedTpl['name'])) { unset($templates[$num]); continue 2; } } } return zbx_objectValues($templates, 'host'); } /** * Change all references in template to database ids. * * @throws Exception * * @param array $template * * @return array */ protected function resolveTemplateReferences(array $template) { if ($templateId = $this->referencer->resolveTemplate($template['host'])) { $template['templateid'] = $templateId; // if we update template, existing macros should have hostmacroid if (array_key_exists('macros', $template)) { foreach ($template['macros'] as &$macro) { if ($hostMacroId = $this->referencer->resolveMacro($templateId, $macro['macro'])) { $macro['hostmacroid'] = $hostMacroId; } } unset($macro); } } foreach ($template['groups'] as $gnum => $group) { if (!$this->referencer->resolveGroup($group['name'])) { throw new Exception(_s('Group "%1$s" does not exist.', $group['name'])); } $template['groups'][$gnum] = ['groupid' => $this->referencer->resolveGroup($group['name'])]; } if (isset($template['templates'])) { foreach ($template['templates'] as $tnum => $parentTemplate) { $template['templates'][$tnum] = [ 'templateid' => $this->referencer->resolveTemplate($parentTemplate['name']) ]; } } return $template; } }
💾 保存文件
← 返回文件管理器