家用NAS系统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/example2.新增一个node(左侧导航栏的一个tree对象),创建/var/www/openmediavault/js/omv/module/admin/service/example/EXample.js
//Registeranodeinthenavigationtree.////id://SettheIDofthenode.//path://Parentpathinthenavigationview.//Text://Servicename/title.Thisisdisplayedinthenavigation.//icon16://16x16pixeliconthatisdisplayedinthenavigationtree.//iconSvg://SVGiconthatisdisplayedinthenavigationview.OMV.WorkspaceManager.registerNode({id:'example',path:'/service',text:_('Example'),icon16:'p_w_picpaths/example.png',iconSvg:'p_w_picpaths/example.svg'});
注:test:_()这里面的内容能跟随页面自动翻译成各国语言
3.node的主视图(workspace)从workspace类派生,创建Settings.js
Ext.define('OMV.module.admin.service.example.Settings',{extend:'OMV.workspace.form.Panel',//ThispathtellswhichRPCmoduleandmethodsthispanelwillcalltoget//andfetchitsformvalues.rpcService:'Example',rpcGetMethod:'getSettings',rpcSetMethod:'setSettings',//getFormItemsisamethodwhichisautomaticallycalledinthe//instantiationofthepanel.Thismethodreturnsallfieldsfor//thepanel.getFormItems:function(){return[{//xtypedefinesthetypeofthisentry.Somedifferenttypes//is:fieldset,checkbox,textfieldandnumberfield.xtype:'fieldset',title:_('General'),fieldDefaults:{labelSeparator:''},//Theitemsarraycontainsitemsinsidethefieldsetxtype.items:[{xtype:'checkbox',//ThenameoptionissenttogetherwithisvaluetoRPC//andisalsousedwhenfetchingfromtheRPC.name:'enable',fieldLabel:_('Enable'),//checkedsetsthedefaultvalueofacheckbox.checked:false},{xtype:'numberfield',name:'max_value',fieldLabel:_('Maxvalue'),minValue:0,maxValue:100,allowDecimals:false,allowBlank:true}]}];}});//RegisterapanelintotheGUI.////path://Wewanttoaddthepanelinourexamplenode.//Thenodewasconfiguredwiththepath/serviceandtheidexample.//Thepathistherefore/service/example.////className://Thepanelwhichshouldberegisteredandadded(refersto//theclassname).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和RPCConfig.xml/etc/openmediavault/config.xml储存了插件设置项,可以在制作debian包时,写在postinst脚本里
#!/bin/shset-e./etc/default/openmediavault./usr/share/openmediavault/scripts/helper-functionscase"$1"inconfigure)SERVICE_XPATH_NAME="example"SERVICE_XPATH="/config/services/${SERVICE_XPATH_NAME}"#Addthedefaultconfigurationif!omv_config_exists"${SERVICE_XPATH}";thenomv_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#Activatepackagetriggers.Thesetriggersareonlysetduringthe#packageinstallation.dpkg-triggerupdate-fixpermsdpkg-triggerupdate-locale;;abort-upgrade|abort-remove|abort-deconfigure);;*)echo"postinstcalledwithunknownargument">&2exit1;;esac#DEBHELPER#exit0The RPC = Remote Procedure Call
RPC文件存储在/usr/share/openmediavault/engined/rpc目录下,inc结尾的php文件,rpc文件连接了web GUI和config.xml,使得界面可以控制config文件
example.inc
<?phprequire_once'openmediavault/config.inc';require_once'openmediavault/error.inc';require_once'openmediavault/notify.inc';require_once'openmediavault/rpcservice.inc';classOMVRpcServiceExampleextendsOMVRpcServiceAbstract{/***Themaineventmessagepath.**@varstring*/private$eventMessagePath='org.openmediavault.services.example';/***GetthebaseXPathoftheservice.Thisisahelperfunctiontoavoid*"magicnumbers".**@returnstring*/privatefunctiongetXpath(){return'/config/services/example';}/***GetthenameoftheRPCservice.**@returnstring*/publicfunctiongetName(){return'Example';}/***InitializetheRPCservice.TheRPCmethodsareregisteredinthis*functionwith$this->registerMethod.**@returnvoid*/publicfunctioninitialize(){$this->registerMethod('getSettings');$this->registerMethod('setSettings');}publicfunctiongetSettings($params,$context){//$xmlConfigisneededwhenreadingandwritingfromtheconfiguration.global$xmlConfig;//ValidatetheRPCcallercontext.////validateMethodContexttakesthecurrentcontextasthefirst//parameter.Thesecondparamteristhevalidcontextandthatcanbe//OMV_ROLE_ADMINISTRATOR,OMV_ROLE_USERorOMV_ROLE_EVERYONE.//Thisisusedtomakesurethattherightuseraccessesthemethod.$this->validateMethodContext($context,['role'=>OMV_ROLE_ADMINISTRATOR]);//Gettheconfigurationobject.$object=$xmlConfig->get($this->getXpath());//Ifnodatawasfound,throwanexceptionandprovidetheXPaththat//failed.if(is_null($object)){thrownewOMVException(OMVErrorMsg::E_CONFIG_GET_OBJECT_FAILED,$this->getXpath());}//Modifytheresultdata.//boolvalandintvalconvertsstringsandnumberstotheirboolean//andintegervalue.$object['enable']=boolval($object['enable']);$object['max_value']=intval($object['max_value']);return$object;}publicfunctionsetSettings($params,$context){global$xmlConfig;$this->validateMethodContext($context,array("role"=>OMV_ROLE_ADMINISTRATOR));//ValidatetheparametersoftheRPCservicemethod.////OpenMediavaultusesJSONSchematovalidateparameters.Amore//detailedspecificationisprovidedherehttp://json-schema.org/$this->validateMethodParams($params,'{"type":"object","properties":{"enable":{"type":"boolean"},"max_value":{"type":"integer","minimum":1,"maximum":100}}}');//Updatetheconfigurationobject.$object=['enable'=>boolval($params['enable']),'max_value'=>$params['max_value'],];//Updatetheconfigurationfile.Ifitfailsitthrowsanexception.if($xmlConfig->replace($this->getXpath(),$object)===false){thrownewOMVException(OMVErrorMsg::E_CONFIG_SET_OBJECT_FAILED,$this->getXpath());}//Notifyconfigurationchanges.////Thiswillnotifyeventlistenerssuchastheservicemodule//toperformcertaintasks.Themostcommononeistomarkthe//serviceasdirty.$dispatcher=&OMVNotifyDispatcher::getInstance();$dispatcher->notify(OMV_NOTIFY_MODIFY,$this->eventMessagePath,$object);return$object;}}//RegistertheRPCservice.$rpcServiceMgr=&OMVRpcServiceMgr::getInstance();$rpcServiceMgr->registerService(newOMVRpcServiceExample());模块与shell脚本module
RPC用来实现界面修改和获取配置文件,模块用来监控和使其修改生效。模块目录在/usr/share/openmediavault/engined/module
Example.inc
<?phprequire_once'openmediavault/config.inc';require_once'openmediavault/error.inc';require_once'openmediavault/initscript.inc';require_once'openmediavault/module.inc';classOMVModuleExampleextendsOMVModuleServiceAbstractimplementsOMVINotifyListener,OMVIModuleServiceStatus{/***Themaineventmessagepath.**@varstring*/private$eventMessagePath='org.openmediavault.services.example';}/***GetthebaseXPathoftheservice.Thisisahelperfunctiontoavoid*"magicnumbers".**@returnstring*/privatefunctiongetXpath(){return'/config/services/example';}/***Getthemodulename.**@returnstring*/publicfunctiongetName(){return'example';}/***Getthemodulestatus.**@returnarray**@throwsOMVException*/publicfunctiongetStatus(){global$xmlConfig;//Gettheconfigurationobject.$object=$xmlConfig->get($this->getXpath());if(is_null($object)){thrownewOMVException(OMVErrorMsg::E_CONFIG_GET_OBJECT_FAILED,$this->getXpath());}//Returnthestatusoftheservice.Thisinformationisdisplayed//underDiagnostics/Services.returnarray('name'=>$this->getName(),'title'=>gettext('Example'),'enabled'=>boolval($object['enable']),'running'=>false);}/***Generatetheconfiguration.**@returnvoid**@throwsOMVException*/publicfunctionapplyConfig(){global$xmlConfig;$cmd=sprintf('exportLANG=C;omv-mkconf%s2>&1',$this->getName());if(0!==$this->exec($cmd,$output)){thrownewOMVException(OMVErrorMsg::E_EXEC_FAILED,$cmd,implode(PHP_EOL,$output));}}/***Bindlisteners.**@paramOMVNotifyDispatcher$dispatcher*@returnvoid*/publicfunctionbindListeners(OMVNotifyDispatcher$dispatcher){$moduleMgr=&OMVModuleMgr::getInstance();//Addlistenershere.Themostcommonthingistomonitorconfiguration//changesontheservice.Whentheconfigischangedthemodule//setsitselfasdirty(asseenbelow).Settingamoduleasdirty//makestheapplybuttonappearinthewebinterface(whichinturn//callstheapplyConfigfunctiononeachmodulewithadirtystate).$dispatcher->addListener(OMV_NOTIFY_MODIFY,$this->eventMessagePath,[$this,'setDirty']);}}//Registerthemodule.$moduleMgr=&OMVModuleMgr::getInstance();$moduleMgr->registerModule(newOMVModuleExample());
注:模块注册了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-functionsOMV_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")EOFexit0
注:需要755权限,执行完该脚本将会生成/tmp/example.conf文件。
至此,一个openmediavault的简单插件源码已经制作完成,接下来只需要制作包就可以啦。
refer:https://forum.openmediavault.org/index.php/Thread/5600-DIY-Plugin-Development/
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。