家用NAS系统openmediavault插件开发

openmediavault 插件开发

OpenMediaVault,简称omv,是一个开源的基于Debian Linux的下一代网络附加存储(NAS)解决方案。它包含众多服务,如SSH,(S)FTP,SMB / CIFS,DAAP媒体服务器,RSync,BitTorrent客户机等。 并具有通过插件可增强的模块化设计框架特性。

OMV的插件开发,由三个部分组成

  • GUI
  • 配置文件与RPC
  • 模块与shell脚本

GUI(web界面)

后台自动扫描以下目录及其子目录

/var/www/openmediavault/js/omv/module/admin/
/var/www/openmediavault/js/omv/module/user/
/var/www/openmediavault/js/omv/module/public/

1.在service目录下新加一个目录example

/var/www/openmediavault/js/omv/module/admin/service/example

2.新增一个node(左侧导航栏的一个tree对象),创建/var/www/openmediavault/js/omv/module/admin/service/example/EXample.js

// Register a node in the navigation tree.
//
// id: 
//     Set the ID of the node.
// path: 
//     Parent path in the navigation view.
// Text: 
//     Service name/title. This is displayed in the navigation.
// icon16: 
//     16x16 pixel icon that is displayed in the navigation tree.
// iconSvg:
 //     SVG icon that is displayed in the navigation view.
 
 OMV.WorkspaceManager.registerNode({
    id: ‘example‘,
    path: ‘/service‘,
    text: _(‘Example‘),
    icon16: ‘images/example.png‘,
    iconSvg: ‘images/example.svg‘});

注:test:_()这里面的内容能跟随页面自动翻译成各国语言

3.node的主视图(workspace)

从workspace类派生,创建Settings.js

Ext.define(‘OMV.module.admin.service.example.Settings‘, {
    extend: ‘OMV.workspace.form.Panel‘,    
    
    // This path tells which RPC module and methods this panel will call to get 
    // and fetch its form values.
    
    rpcService: ‘Example‘,
    rpcGetMethod: ‘getSettings‘,
    rpcSetMethod: ‘setSettings‘,    
    
    // getFormItems is a method which is automatically called in the 
    // instantiation of the panel. This method returns all fields for 
    // the panel.
    
    getFormItems: function() {        
            return [{           
            
             // xtype defines the type of this entry. Some different types
            // is: fieldset, checkbox, textfield and numberfield. 
            
            xtype: ‘fieldset‘,
            title: _(‘General‘),
            fieldDefaults: {
                labelSeparator: ‘‘
            },            
            // The items array contains items inside the fieldset xtype.
            items: [{
                xtype: ‘checkbox‘,              
                  
                // The name option is sent together with is value to RPC
                // and is also used when fetching from the RPC.
                
                name: ‘enable‘,
                fieldLabel: _(‘Enable‘),                
                // checked sets the default value of a checkbox.
                checked: false
            },
            {
                xtype: ‘numberfield‘,
                name: ‘max_value‘,
                fieldLabel: _(‘Max value‘),
                minValue: 0,
                maxValue: 100,
                allowDecimals: false,
                allowBlank: true
            }]
        }];
    }
});
// Register a panel into the GUI.
//
// path: 
//     We want to add the panel in our example node. 
//     The node was configured with the path /service and the id example.
//     The path is therefore /service/example.//// className: 
//     The panel which should be registered and added (refers to
 //     the class name).
 
 OMV.WorkspaceManager.registerPanel({
    id: ‘settings‘,
    path: ‘/service/example‘,
    text: _(‘Settings‘),
    position: 10,
    className: ‘OMV.module.admin.service.example.Settings‘});

注:定义了rpc,此时在页面刷新会报错。“RPC service not found (name=Example)”,此时需要添加rpc文件/usr/share/openmediavault/engined/rpc/example.inc,内容见第二部分

配置文件config.xml和RPC

Config.xml

/etc/openmediavault/config.xml储存了插件设置项,可以在制作debian包时,写在postinst脚本里

#!/bin/shset -e

. /etc/default/openmediavault
. /usr/share/openmediavault/scripts/helper-functions

case "$1" in
    configure)
        SERVICE_XPATH_NAME="example"
        SERVICE_XPATH="/config/services/${SERVICE_XPATH_NAME}"

        # Add the default configuration
        if ! omv_config_exists "${SERVICE_XPATH}"; then
            omv_config_add_element "/config/services" "${SERVICE_XPATH_NAME}"
            omv_config_add_element "${SERVICE_XPATH}" "enable" "0"
            omv_config_add_element "${SERVICE_XPATH}" "max_value" "0"
        fi

        # Activate package triggers. These triggers are only set during the
        # package installation.
        dpkg-trigger update-fixperms
        dpkg-trigger update-locale
    ;;

    abort-upgrade|abort-remove|abort-deconfigure)
    ;;

    *)        echo "postinst called with unknown argument" >&2
        exit 1
    ;;esac
    
    #DEBHELPER#
    
    exit 0

The RPC = Remote Procedure Call

RPC文件存储在/usr/share/openmediavault/engined/rpc目录下,inc结尾的php文件,rpc文件连接了web GUI和config.xml,使得界面可以控制config文件
example.inc

<?php

require_once ‘openmediavault/config.inc‘;
require_once ‘openmediavault/error.inc‘;
require_once ‘openmediavault/notify.inc‘;
require_once ‘openmediavault/rpcservice.inc‘;

class OMVRpcServiceExample extends OMVRpcServiceAbstract{    

      /**
     * The main event message path.
     *
     * @var string
     */
    private $eventMessagePath = ‘org.openmediavault.services.example‘;    /**
     * Get the base XPath of the service. This is a helper function to avoid 
     * "magic numbers".
     *
     * @return string
     */
     
    private function getXpath()
    {        return ‘/config/services/example‘;
    }   
    
     /**
     * Get the name of the RPC service.
     *
     * @return string
     */
     
    public function getName()
    {        return ‘Example‘;
    }   
    
     /**
     * Initialize the RPC service. The RPC methods are registered in this
     * function with $this->registerMethod.
     *
     * @return void
     */
     
    public function initialize()
    {        $this->registerMethod(‘getSettings‘);        
             $this->registerMethod(‘setSettings‘);
    }    
    
    public function getSettings($params, $context)
    {        
       // $xmlConfig is needed when reading and writing from the configuration.
        global $xmlConfig;        
        
        // Validate the RPC caller context.
        //
        // validateMethodContext takes the currentcontext as the first
        // parameter. The second paramter is the valid context and that can be
        // OMV_ROLE_ADMINISTRATOR, OMV_ROLE_USER or OMV_ROLE_EVERYONE.
        // This is used to make sure that the right user accesses the method.
        $this->validateMethodContext($context, [‘role‘ => OMV_ROLE_ADMINISTRATOR]);        
        // Get the configuration object.
        $object = $xmlConfig->get($this->getXpath());        
        
        // If no data was found, throw an exception and provide the XPath that
        // failed.
        if (is_null($object)) {            
                throw new OMVException(
                OMVErrorMsg::E_CONFIG_GET_OBJECT_FAILED,                
                $this->getXpath()
            );
        }        
        
        // Modify the result data.
        // boolval and intval converts strings and numbers to their boolean
        // and integer value.
        $object[‘enable‘] = boolval($object[‘enable‘]);        
        $object[‘max_value‘] = intval($object[‘max_value‘]);       
         return $object;
    }    
    
    public function setSettings($params, $context)
    {        
            global $xmlConfig;       
            $this->validateMethodContext($context, array(            
                   "role" => OMV_ROLE_ADMINISTRATOR
        ));       
        
         // Validate the parameters of the RPC service method.
        //
        // OpenMediavault uses JSON Schema to validate parameters. A more
        // detailed specification is provided here http://json-schema.org/
        $this->validateMethodParams(            
             $params,            ‘{
                "type": "object",
                "properties": {
                    "enable": {
                        "type": "boolean"
                    },
                    "max_value":{ 
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 100
                    }
                }
            }‘
        );        
        
        // Update the configuration object.
        $object = [            
                   ‘enable‘ => boolval($params[‘enable‘]),            
                   ‘max_value‘ => $params[‘max_value‘],
        ];        
        
        // Update the configuration file. If it fails it throws an exception.
        if ($xmlConfig->replace($this->getXpath(), $object) === false) {            
                     throw new OMVException(
                                OMVErrorMsg::E_CONFIG_SET_OBJECT_FAILED,                
                                $this->getXpath()
            );
        }        
        
        // Notify configuration changes.
        //
        // This will notify event listeners such as the service module
        // to perform certain tasks. The most common one is to mark the
        // service as dirty.
        
        $dispatcher = &OMVNotifyDispatcher::getInstance();        
        $dispatcher->notify(OMV_NOTIFY_MODIFY, $this->eventMessagePath, $object);        
        
        return $object;
    }
}

// Register the RPC service.
$rpcServiceMgr = &OMVRpcServiceMgr::getInstance();
$rpcServiceMgr->registerService(new OMVRpcServiceExample());

模块与shell脚本

module

RPC用来实现界面修改和获取配置文件,模块用来监控和使其修改生效。模块目录在/usr/share/openmediavault/engined/module
Example.inc

<?php

require_once ‘openmediavault/config.inc‘;
require_once ‘openmediavault/error.inc‘;
require_once ‘openmediavault/initscript.inc‘;
require_once ‘openmediavault/module.inc‘;

class OMVModuleExample extends OMVModuleServiceAbstract implements
    OMVINotifyListener,    
    OMVIModuleServiceStatus{    
    
    /**
     * The main event message path.
     *
     * @var string
     */
    private $eventMessagePath = ‘org.openmediavault.services.example‘;
    }   
    
     /**
     * Get the base XPath of the service. This is a helper function to avoid 
     * "magic numbers".
     *
     * @return string
     */
    private function getXpath()
    {        return ‘/config/services/example‘;
    }   
    
     /**
     * Get the module name.
     *
     * @return string
     */
    public function getName()
    {        return ‘example‘;
    }    
    
    /**
     * Get the module status.
     *
     * @return array
     *
     * @throws OMVException
     */
    public function getStatus()
    {        
         global $xmlConfig;        
         // Get the configuration object.
        $object = $xmlConfig->get($this->getXpath());  
             
         if (is_null($object)) {            
                 throw new OMVException(
                OMVErrorMsg::E_CONFIG_GET_OBJECT_FAILED,                
                $this->getXpath()
            );
        }        
        
        // Return the status of the service. This information is displayed
        // under Diagnostics/Services.
        return array(           
               ‘name‘ => $this->getName(),            
               ‘title‘ => gettext(‘Example‘),            
               ‘enabled‘ => boolval($object[‘enable‘]),            
               ‘running‘ => false
        );
    }   
    
     /**
     * Generate the configuration.
     *
     * @return void
     *
     * @throws OMVException
     */
    public function applyConfig()
    {        
                global $xmlConfig;        
                $cmd = sprintf(‘export LANG=C; omv-mkconf %s 2>&1‘, $this->getName());        
                if (0 !== $this->exec($cmd, $output)) {            
                      throw new OMVException(
                                OMVErrorMsg::E_EXEC_FAILED,                
                                $cmd,
                                implode(PHP_EOL, $output)
            );
        }
    }    
    
    /**
     * Bind listeners.
     *
     * @param OMVNotifyDispatcher $dispatcher
     * @return void
     */
    public function bindListeners(OMVNotifyDispatcher $dispatcher)
    {        
         $moduleMgr = &OMVModuleMgr::getInstance();        
         // Add listeners here. The most common thing is to monitor configuration
        // changes on the service. When the config is changed the module
        // sets itself as dirty (as seen below). Setting a module as dirty
        // makes the apply button appear in the web interface (which in turn
        // calls the applyConfig function on each module with a dirty state).
        
        $dispatcher->addListener(
            OMV_NOTIFY_MODIFY,           
             $this->eventMessagePath,
            [$this, ‘setDirty‘]
        );
    }
}

// Register the module.
$moduleMgr = &OMVModuleMgr::getInstance();
$moduleMgr->registerModule(new OMVModuleExample());

注:模块注册了notify,rpc在修改配置文件后会通知notify文件为dirty状态,从而在页面触发apply change提示。

Shell脚本生成配置文件

在module中的applyconfig函数中,执行了omv-mkconf example命令,该命令调用了/usr/share/openmediavault/mkconf/example脚本
example

set -e. /etc/default/openmediavault
. /usr/share/openmediavault/scripts/helper-functions
OMV_EXAMPLE_XPATH="/config/services/example"OMV_EXAMPLE_CONF="/tmp/example.conf"

cat <<EOF > ${OMV_EXAMPLE_CONF}enable    = $(omv_config_get "${OMV_EXAMPLE_XPATH}/enable")
max_value = $(omv_config_get "${OMV_EXAMPLE_XPATH}/max_value")
EOF

exit 0

注:需要755权限,执行完该脚本将会生成/tmp/example.conf文件。

至此,一个openmediavault的简单插件源码已经制作完成,接下来只需要制作包就可以啦。

refer:https://forum.openmediavault.org/index.php/Thread/5600-DIY-Plugin-Development/

时间: 2024-10-03 14:03:01

家用NAS系统openmediavault插件开发的相关文章

【我的技术我做主】IT屌丝DIY打造6盘位家用NAS服务器

一.为什么需要NAS存储? 一直以来用的百度云,并自己配置了一个2TB的硬盘做日常数据备份,后来发现百度云限速!而且存在各种各样的不安全(苹果事件.米国事件的都懂的啦!),而且自己2TB的硬盘一直没有做数据备份一直感觉不安全(搞IT人的心病),没有RAID数据安全无法保证,加上现在给孩子照相越来越多.蓝光高清.各种测试需要存储空间,NAS的需求越来越严重了,所以建立一个自己的NAS存储势在必行!当然在成本.造价.功能考虑,性价比当然是越高越好了! 二.硬件选型 1.主板 u 支持双千兆网口的(端

开源NAS系统使用总结

资料越来越多,几台电脑.手机.移动硬盘的文件多且又存在重复的情况,心中一直不快,于是从那时候起,就有一个想法,如果自己有一个随时随地可以访问的文件存储区域有,那生活多么美好呀!于是就不断的百度搜集相关的教程,在此在感谢那些牛人写的教程,让我也有幸安装使用这些软件. 有需求就有学习的动力,资料看的多了,就着手开始偿试了.期间了解到黑群晖.freenas.nas4free.openmediavault.openfiler等几种,以上除了群晖是收费系统,其他都是免费的开源系统,因为没有钱组个高大上的w

NAS系统收集

FreeNAS®,目前最受欢迎的开源免费 NAS 操作系统之一,基于以安全和稳定著称的 FreeBSD 系统开发,由 ixsystems 公司的技术团队维护.项目地址:www.freenas.org NAS4Free,基于 FreeNAS 0.7 开发的一个分支,由原 FreeNAS 系统开发者发起创建.许多恋旧的朋友忠实的跟随,安装要求没有 FreeNAS 高,版本更新也很及时.项目地址:www.nas4free.org OpenMediaVault,由原 FreeNAS 核心开发成员 Vol

树莓派版的家用NAS服务器

家里的文件越来越多,每个人的文件放得到处都是,需要的时候又找不到... 买个NAS服务器?太贵!太吵!太费电!... 好在我们有树莓派,自己动手,丰衣足食! ? 说做就做,主要分成以下三部分 加载双USB移动硬盘 在网络中共享 USB移动硬盘间同步 ? 加载双USB移动硬盘 为啥树莓派加USB?安静省电呗,你要弄主机和大硬盘24小时开着,估计没用几个月,让你白天看着电表哭,晚上听着机器吵... 为啥要双移动硬盘?一个用来网络共享,一个用来备份.不省电了?如果老婆的文件有一天不见了,估计你就不会想

【操作指引】铁威马NAS系统初始化安装指导步骤

1.使用机器前一定要记住,先连接好网络,保证设置的PC或者移动端与主机在同一个网络下! 2.软件的安装也是比较简单,全程根据网页的指导操作即可,安装完成之后会自动检测到设备,然后再安装系统. 3.软件安装完毕之后,第一次使用需要先进行初始化,安装过程大约十分钟. 4.安装完成后,进入铁威马TOS 4.0的界面,我们可以通过鼠标的左右键来操作.在界面上,我们还可以查看很多信息,内存空间.网速.运行时间等等. 原文地址:https://blog.51cto.com/13862190/2353140

EMC NS480 NAS系统修改data mover的时间

[[email protected] ~]$ server_date Error 2100: usage: server_date { <movername> | ALL }        [+<format>] [<yymmddhhmm>[<ss>]]        | timesvc start ntp [-sync_delay] [-interval <hh>[:<mm>]] [<host> [ <host&g

一次因NAS存储故障引起的Linux系统恢复案例

一. 故障现象描述 NAS操作系统内核为Linux,自带的存储有16块硬盘,总共分两组,每组做了RAID5,Linux操作系统无法正常启动,在服务启动到cups那里就停止了,按键ctrl+c强制断开也没有响应,查看硬盘状态,都是正常的,没有报警或者警告现象. 二. 问题判断思路 通过上面这些现象,首先判断NAS硬件应该没问题,NAS存储盘也应该正常,现在Linux无法启动,应该是Linux系统本身存在问题,因此,首先从Linux系统入手进行排查. 三. 问题处理过程 1.第一次处理过程 NAS系

阿里云文件存储(NAS)助力业务系统承载双十一尖峰流量

2018天猫双11全球狂欢节,全天成交额再次刷新纪录达到2135亿元,其中总成交额在开场后仅仅用了2分05秒即突破100亿元,峰值的交易量达到惊人的高度,背后离不开阿里云大数据计算和存储能力的支撑.在整个交易的链路上,账单业务是一个重要的环节,尤其对商家系统来说,需要定期对账,账单子系统出现一点点问题都会影响商家的运营,2018的双十一,承载账单的消息系统把全网卖家账单系统60%的流量托付给了阿里云文件存储.在11日0点的峰值交易时刻,账单消息系统的写入流量瞬间达到日常流量的60倍以上,阿里云文

利用NAS打造协同办公系统

  对于大多的初创企业.工作室来说,享受自有的协同办公系统不用说是提高工作效率的绝好方法,同时将文件集中存放在自己的服务器中,会更加安心,也不用担心私有内容的泄密等问题.  所以,大家是否有意愿了解下自行搭建的私有云端办公系统,实现文件共享,软件共享,并且拥有私有云的安全性呢?今天就有这么一个服务能实现这个需求,并且配置简单,稳定可靠,想必不用说大家都想着一睹为快了吧.  这个巧妇难为无米之炊,首先你得有个NAS,什么牌子不重要,就拿群晖NAS来说,除了文件同步.各种多媒体应用外,它更是可以轻松