20 模块

概述

无需修改Zabbix源代码,即可通过添加第三方模块或开发自定义模块来增强Zabbix前端功能。

请注意模块代码将run与Zabbix源代码相同的权限。这意味着:

  • 第三方模块可能具有危害性。您必须信任所安装的模块;
  • 第三方模块代码中的错误可能导致前端崩溃。若发生此情况,只需从前端移除该模块代码。当您重新加载Zabbix前端时,会看到提示某些模块缺失的通知。前往模块 (位于管理常规模块)并再次点击扫描目录,即可从数据库中移除不存在的模块。

安装

请务必阅读特定模块的安装手册。 建议逐个安装新模块以便轻松捕获故障。

在安装模块前请注意:

  • 确保从可信来源下载模块。 安装有害代码可能导致数据丢失等后果

  • 相同模块的不同版本(相同ID)可以安装在

    parallel, but only a single version can be enabled at once

模块安装步骤:

  • 将模块解压到Zabbix前端modules文件夹内的独立目录中
  • 确保模块目录至少包含manifest.json文件 file
  • 访问模块 并点击扫描目录按钮
  • 新模块将出现在列表中,显示其version、作者、 描述和状态信息
  • 点击状态启用模块

故障排除:

问题 解决方案
模块未出现在列表中 确保Zabbix前端的modules/your-module/目录中存在manifest.json文件file。若存在则表示模块不兼容当前Zabbixversion。若manifest.jsonfile不存在,可能是解压到了错误目录。
前端崩溃 模块代码与当前Zabbixversion或服务器配置不兼容。请delete模块文件并重新加载前端。您将看到某些模块缺失的提示。访问模块再次点击扫描目录以从数据库中移除不存在的模块。
出现关于重复命名空间、ID或操作的错误消息 新模块尝试注册的命名空间、ID或操作已被其他启用模块占用。根据错误提示先禁用冲突模块再启用新模块。
出现技术错误消息 将错误报告给模块开发者。

开发模块

模块采用PHP语言编写。推荐使用模型-视图-控制器(MVC)软件设计模式,这与Zabbix前端架构一致,能简化开发流程。虽然不强制要求,但建议启用PHP严格类型模式。

请注意,通过模块可以轻松为Zabbix前端添加新菜单监控项及对应的视图和操作。但目前无法通过模块注册新的API或create新的数据库表。

模块结构

每个模块都是一个目录(位于modules目录内), 其中包含控制器、视图及其他代码的子目录:

example_module_directory/           (required)
           manifest.json                   (required)  Metadata and action definition.
           Module.php                                  Module initialization and event handling.
           actions/                                    Action controller files.
               SomethingView.php
               SomethingCreate.php
               SomethingDelete.php
               data_export/                                 
                   ExportAsXml.php
                   ExportAsExcel.php
           views/                                      View files.
               example.something.view.php
               example.something.delete.php
               js/                                     JavaScript files used in views.
                   example.something.view.js.php
           partials/                                   View partial files.
               example.something.reusable.php
               js/                                     JavaScript files used in partials.
                   example.something.reusable.js.php

如你所见,自定义模块目录中唯一必需的file是 manifest.json。若缺少此file,模块将无法注册。 Module.php负责注册菜单监控项并处理诸如'onBeforeAction' 和'onTerminate'等事件。actionsviewspartials目录包含 模块操作所需的PHP和JavaScript代码。

命名规范

在create模块之前,必须就不同模块监控项(如目录和文件)的命名规范达成一致,以便保持组织有序。您也可以在模块结构章节中找到相关示例。

监控项 命名规则 示例
模块目录 小写字母[a-z]、下划线和数字 example_v2
操作子目录 小写字母[a-z]和下划线字符 data_export
操作文件 驼峰命名法,以操作类型结尾 SomethingView.php
视图和局部文件 小写字母[a-z]
单词间用点号分隔
module.前缀开头后接模块名称
以操作类型和.phpfile扩展名结尾
module.example.something.view.php
Javascript文件 适用与视图和局部文件相同的规则,但扩展名为.js.phpfile。 module.example.something.view.js.php

请注意,对于视图和局部file名称,'模块'前缀和名称包含是强制要求的,除非您需要覆盖Zabbix核心视图或局部文件。但此规则不适用于操作file名称。

清单准备

每个模块都应包含一个manifest.json file文件,其中需以JSON格式声明以下字段:

参数 必填 类型 默认值 描述
manifest_version Double - 模块清单version。当前支持的version为1
id String - 模块ID。同一时间只能启用一个具有相同ID的模块。
name String - 在管理界面显示的模块名称。
version String - 在管理界面显示的模块version。
namespace String - Module.php及动作类使用的PHP命名空间。
author String "" 在管理界面显示的模块作者。
url String "" 在管理界面显示的模块URL。
description String "" 在管理界面显示的模块描述。
actions Object {} 需通过该模块注册的动作。参见Actions章节。
config Object {} 模块配置项。

具体示例可参阅参考章节中的manifest.json范例。

动作

该模块将控制manifest.jsonfile中actionsobject定义的前端操作。通过这种方式定义新操作。同样地,您可以重定义现有操作。actions的每个键应表示操作名称,对应的值应包含class,并可选择性地包含layoutview键。

一个操作由四个部分组成:名称、控制器、视图和布局。数据验证和准备通常在控制器中完成,输出格式化在视图或部分视图中完成,布局负责用菜单、页眉、页脚等元素装饰页面。

模块操作必须在manifest.jsonfile中定义为actionsobject:

参数 必填 类型 默认值 描述
key String - 操作名称,小写字母[a-z],用点分隔单词。
class String - 操作类名,包括actions目录内的子目录路径(如果使用)。
layout String "layout.htmlpage" 操作布局。
view String null 操作视图。

有几种预定义的布局,如layout.jsonlayout.xml。这些适用于产生不同于HTML结果的操作。您可以在app/views/目录中探索预定义的布局,甚至可以create自己的布局。

有时只需要重定义某些操作的视图部分,而保持控制器不变。在这种情况下,只需将必要的视图和/或部分文件放在模块的views目录中。

作为参考,请参阅参考部分中的示例操作控制器file。请不要犹豫探索Zabbix源代码中位于app/目录下的当前操作。

Module.php

这个可选的PHPfile负责模块初始化以及事件处理。类'模块'应在此file中定义,扩展基类\Core\CModule。Module类必须在manifest.jsonfile中指定的命名空间中定义。

<?php
       
       namespace Modules\Example;
       use Core\CModule as BaseModule;
       
       class Module extends BaseModule {
           ...
       }

作为参考,请参阅参考部分中的Module.php示例。

参考

本节包含前文介绍的不同模块元素的基础版本

manifest.json

{
           "manifest_version": 1.0,
           "id": "example_module",
           "name": "Example module",
           "version": "1.0",
           "namespace": "Example",
           "author": "John Smith",
           "url": "http://module.example.com",
           "description": "Short description of the module.",
           "actions": {
               "example.something.view": {
                   "class": "SomethingView",
                   "view": "module.example.something.view"
               },
               "example.something.create": {
                   "class": "SomethingCreate",
                   "layout": null
               },
               "example.something.delete": {
                   "class": "SomethingDelete",
                   "layout": null
               },
               "example.something.export.xml": {
                   "class": "data_export/ExportAsXml",
                   "layout": null
               },
               "example.something.export.excel": {
                   "class": "data_export/ExportAsExcel",
                   "layout": null
               }
           },
           "config": {
               "username": "john_smith"
           }
       }

Module.php

<?php declare(strict_types = 1);
       
       namespace Modules\Example;
       
       use APP;
       use CController as CAction;
       
       /**
        * Please see Core\CModule class for additional reference.
        */
       class Module extends \Core\CModule {
       
           /**
            * Initialize module.
            */
           public function init(): void {
               // Initialize main menu (CMenu class instance).
               APP::Component()->get('menu.main')
                   ->findOrAdd(_('Reports'))
                       ->getSubmenu()
                           ->add((new \CMenuItem(_('Example wide report')))
                               ->setAction('example.report.wide.php')
                           )
                           ->add((new \CMenuItem(_('Example narrow report')))
                               ->setAction('example.report.narrow.php')
                           );
           }
       
           /**
            * Event handler, triggered before executing the action.
            *
            * @param CAction $action  Action instance responsible for current request.
            */
           public function onBeforeAction(CAction $action): void {
           }
       
           /**
            * Event handler, triggered on application exit.
            *
            * @param CAction $action  Action instance responsible for current request.
            */
           public function onTerminate(CAction $action): void {
           }
       }

动作控制器

<?php declare(strict_types = 1);
       
       namespace Modules\Example\Actions;
       
       use CControllerResponseData;
       use CControllerResponseFatal;
       use CController as CAction;
       
       /**
        * Example module action.
        */
       class SomethingView extends CAction {
       
           /**
            * Initialize action. Method called by Zabbix core.
            *
            * @return void
            */
           public function init(): void {
               /**
                * Disable SID (Session ID) validation. Session ID validation should only be used for actions which involve data
                * modification, such as update or delete actions. In such case Session ID must be presented in the URL, so that
                * the URL would expire as soon as the session expired.
                */
               $this->disableSIDvalidation();
           }
       
           /**
            * Check and sanitize user input parameters. Method called by Zabbix core. Execution stops if false is returned.
            *
            * @return bool true on success, false on error.
            */
           protected function checkInput(): bool {
               $fields = [
                   'name'  => 'required|string',
                   'email' => 'required|string',
                   'phone' => 'string'
               ];
       
               // Only validated data will further be available using $this->hasInput() and $this->getInput().
               $ret = $this->validateInput($fields);
       
               if (!$ret) {
                   $this->setResponse(new CControllerResponseFatal());
               }
       
               return $ret;
           }
       
           /**
            * Check if the user has permission to execute this action. Method called by Zabbix core.
            * Execution stops if false is returned.
            *
            * @return bool
            */
           protected function checkPermissions(): bool {
               $permit_user_types = [USER_TYPE_ZABBIX_ADMIN, USER_TYPE_SUPER_ADMIN];
       
               return in_array($this->getUserType(), $permit_user_types);
           }
       
           /**
            * Prepare the response object for the view. Method called by Zabbix core.
            *
            * @return void
            */
           protected function doAction(): void {
               $contacts = $this->getInput('email');
       
               if ($this->hasInput('phone')) {
                   $contacts .= ', '.$this->getInput('phone');
               }
       
               $data = [
                   'name' => $this->getInput('name'),
                   'contacts' => $contacts
               ];
       
               $response = new CControllerResponseData($data);
       
               $this->setResponse($response);
           }
       }

动作视图

<?php declare(strict_types = 1);
       
       /**
        * @var CView $this
        */
       
       $this->includeJsFile('example.something.view.js.php');
       
       (new CWidget())
           ->setTitle(_('Something view'))
           ->addItem(new CDiv($data['name']))
           ->addItem(new CPartial('module.example.something.reusable', [
               'contacts' => $data['contacts']
           ])
           ->show();