Sidebar

Zabbix Summit 2022
Register for Zabbix Summit 2022

20. 模块

概述

可以通过添加第三方模块或开发自己的模块来增强Zabbix前端功能,而无需更改Zabbix的源代码。

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

  • 第三方模块可能是有害的。您必须信任您正在安装的模块;
  • 第三方模块代码中的错误可能会使前端崩溃。如果发生这种情况,只需从前端删除模块代码即可。重新加载Zabbix前端后,您会看到一条消息,指出某些模块不存在。转到 Module administration (在 AdministrationGeneralModules) 然后再次单击 Scan directory 以从数据库中删除不存在的模块。

安装

请始终阅读特定模块的安装手册。建议逐个安装新模块,以便更容易的找到故障。

在安装模块之前:

  • 确保您已从受信任的来源下载了该模块。安装有害代码可能会导致后果,例如数据丢失
  • 同一模块的不同版本(相同的ID)可以并行安装,但一次只能启用一个版本

安装模块的步骤:

  • 将模块解压缩到Zabbix前端的"modules"文件夹中的自己的文件夹中
  • 确保您的模块文件夹至少包含 manifest.json 文件
  • 导航到 Module administration 并且单击 Scan directory 按钮
  • 新模块将与其版本,作者,描述和状态一起出现在列表中
  • 通过单击其状态启用模块

排错:

问题 解决方案
模块未出现在列表中 确保 manifest.json 文件存在于 Zabbix 前端的 'modules/your-module/' 文件夹中。如果这样做,则意味着该模块不适合当前的Zabbix版本。如果 manifest.json 文件不存在,则可能是因为您解压到了错误的目录中。
前端崩溃 模块代码与当前的Zabbix版本或服务器配置不兼容。请删除模块文件并重新加载前端。您将收到一条通知,指出某些模块不存在。转到 Module administration 然后再次单击 Scan directory 以从数据库中删除不存在的模块。
出现有关相同命名空间、ID 或操作的错误消息 这是由于新模块尝试注册已由其他已启用模块注册的命名空间、ID 或操作。在启用新模块之前,禁用冲突的模块(在错误消息中提到的)。
出现技术错误消息 向默块开发者报告错误

开发模块

模块是用PHP语言编写的。Model-view-controller(MVC)软件模式设计是首选,因为它也用于Zabbix前端,并且将简化开发。PHP严格输入也是受欢迎的,但不是强制性的。

请注意,使用模块,您可以轻松地将新菜单项以及相应的视图和操作添加到Zabbix前端。目前无法通过模块注册新的 API 或创建新的数据库表。

模块结构

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

example_module_directory/           (必需的)
           manifest.json                   (必需的)  元数据和动作定义。
           Module.php                                  模块初始化和事件处理。
           actions/                                    动作控制器文件。
               SomethingView.php
               SomethingCreate.php
               SomethingDelete.php
               data_export/                                 
                   ExportAsXml.php
                   ExportAsExcel.php
           views/                                      视图文件。
               example.something.view.php
               example.something.delete.php
               js/                                     视图中使用的JavaScript文件。
                   example.something.view.js.php
           partials/                                   部分视图文件。
               example.something.reusable.php
               js/                                     部分视图中使用的JavaScript文件。
                   example.something.reusable.js.php

如您所见,自定义模块目录中唯一必需的文件是manifest.json。如果没有此文件,模块将无法注册。Module.php负责注册菜单项和处理诸如'onBeforeAction'和'onTerminate'之类的事件。actionsviewspartials 目录包含模块操作所需的 PHP 和 JavaScript 代码。

命名约定

在创建模块之前,重要的是要就不同模块项(如目录和文件)的命名约定达成一致,以便我们可以保持良好的组织状态。您也可以在上面的 模块结构 部分找到示例。

项目 命名规则 示例
模块目录 小写字母 [a-z], 下划线和小数 example_v2
动作子目录 小写字母 [a-z], 下划线和小数 data_export
动作文件 骆驼拼写法,以动作类型结尾 SomethingView.php
视图和部分文件 小写字母 [a-z]
用点分隔的单词
前缀为module.后跟模块名称
结尾,显示操作类型和.php文件扩展名
module.example.something.view.php
Javascript 文件 与视图文件和部分文件的规则相同,但文件扩展名.js.php除外。 module.example.something.view.js.php

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

清单准备

每个模块都应该有一个 manifest.json 文件,其中包含以下 JSON 格式的字段:

参数 必填 类型 默认值 描述
manifest_version Double - 模块的清单版本。当前支持的版本为 1
id String - 模块标识。只能同时启用一个具有给定 ID 的模块。
name String - “管理”部分中显示的模块名称。
version String - “管理”部分中显示的模块版本。
namespace String - Module.php和操作类的 PHP 命名空间。
author String "" “管理”部分中显示的模块作者。
url String "" “管理”部分中显示的模块URL。
description String "" “管理”部分中显示的模块描述。
actions Object {} 注册此模块的操作。查看“动作”
config Object {} 模块配置

有关参考,请参阅 Reference部分中 manifest.json 的示例。

动作

该模块将控制在 manifest.json 文件中的 actions 对象中定义的前端操作。这样可以定义新操作。同样,您可以重新定义现有操作。每个操作键应表示操作名称,相应的值应包含class以及可选的layoutview 键。

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

操作模块必须在 manifest.json 文件中定义为 actions 对象:

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

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

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

For reference, please see an example action controller file in the Reference section. Please do not hesitate to explore current actions of Zabbix source code, located in the app/ directory. 有关参考,请参阅Reference 部分中的示例操作控制器文件。请不要犹豫,探索Zabbix源代码的当前操作,文件位于app/目录中。

Module.php

此可选 PHP 文件负责模块初始化和事件处理。类'Module' 应在此文件中定义,用以扩展基类 \Core\CModule。必须在 manifest.json 文件中指定的命名空间中定义 Module 类。

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

有关参考,请参阅Reference 部分中Module.php的示例。

Reference

本节包含前面各节中介绍的不同模块元素的基本版本。

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 (Sessoin ID) validation. Session ID validation should only be used for actions which involde 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();