如何创建一个zenpack

发布时间:2014-02-12 13:10:19   来源:文档文库   
字号:

如何创建一个zenpack来添加新属性来扩展device

 

这篇文章你能获取到什么信息

这篇文章解释了如果创建一个zenpack来扩展device 增加一个componet。如何增加一个新的snmpoidzenoss中,如何在gui上看到新的component(其实gui的部分坐着没写完)。

 

一个新的zenpack会包括:

1)一个device的子类

2)一个DeviceComponent的子类(里面包括了新的字段)

3)一个modeler 来获取新的oid提供给DeviceComponent

4)一个zope模板来生成试图展现在前端页面上(zeoss3.0 使用javascript来写了)

 

背景介绍

 

我已经阅读了zenoss的开发者文档和admin文档,但是任何地方都没发现一段描述创建一个zenpack完整的流程的章节。我搜索了网上能找到的代码,但是没有一个zenpack中的modeler会生成一些新的属性到device里。因为网上能找到的发布的zenpack里都没有扩展device和生成一个modeler。我在zenoos的论坛上找到了一篇名为《 Custom ZenPack Rough Guide》的帖子描述的内容正是我想要的,但是这个帖子唯一的问题是作者仅仅建议修改变量名,类名,和oid。这篇文章的另个问题是它正对的是老版本的zenpack,所以一些类名,包名,必须要修改才能在当前的系统中运行

 

Zenpack的目录结构

Zenpacks必须有3python包名来组成,用“.”来分开(例如ZenPacks.test.ZPool)第一个包名一般都是Zenpack。文件之后会自动生成。

 

 

对于一个名叫Zenpacks.test.ZPoolzenpack来说目录结构一般为

/zenoss/ZenPacks/

    ZenPacks.test.ZPool/  

        ZenPacks.test.ZPool.egg-info

        ZenPacks              

            __init__.py

            test

                __init__.py

                ZPool     <任何model对象都应该放在此目录下>

                    __init__.py

                    daemons

                    datasources

                    lib

                    migrate

                    modeler          <存放modeler module 通过oid来收集一些snmp信息>

                        __init__.py

                        plugins

                            __init__.py

                            ZPoolDeviceDetailsModeler.py   collector>

                    objects

                    reports

                    skins           <存放视图模板,用在GUI上展示数据>

                        __init__.py

                        ZenPacks.test.ZPool  

                            ZPoolDeviceDetailTemplate.pt

 

Model objects

 

model object 应该被存放在zenpack名最后一个点后面那个名字的文件夹中。(Zenpack.test.ZPool的话就是在ZPool文件夹)

增加一个componentdevice中,我们需要做如下事:

1)创建一个继承device的对象(它增加一个新的关系到device中),在这个例子中,我命名它为ZPoolDevice

2)创建一个对象继承DeviceComponentManagedEntity(里面同时定义了一个新的关系链接到ZPoolDevice),命名为ZPoolComponet

 

ZPoolDevice内容

Python代码  

1. from Globals import InitializeClass  

2. from Products.ZenRelations.RelSchema import *  

3. from Products.ZenModel.Device import Device  

4. from Products.ZenModel.ZenossSecurity import ZEN_VIEW  

5. from copy import deepcopy  

6. class ZPoolDevice(Device):  

7.     "An APC Switched PDU"  

8.     #增加一组关系,将ZPoolChildZPoolParent绑定起来,ZPoolParentcomponent  

9.     _relations = Device._relations + (  

10.         ('ZPoolChild', ToManyCont(ToOne,  

11.             'ZenPacks.test.ZPool.ZPoolComponent''ZPoolParent')),  

12.         )  

13.     # add to Device relations the relation to ZPoolComponent  

14.     # The relation is initialized with 5 params, relation name from this side, relation type(ToOne, ToManyCont... etc), component module, and the  

15.     # relation name from the other side of the realtion  

16.     # next we will define a new tab in the Gui which will preview zope template  

17.     factory_type_information = deepcopy(Device.factory_type_information)  

18.     factory_type_information[0]['actions'] += (  

19.             { 'id'              : 'ZPoolChild'  #tab id  

20.             , 'name'            : 'ZPool'      #tab name (appears from the device status tab)  

21.             , 'action'          : 'ZPoolDeviceDetailTemplate'    #the zope template to call when this tab is selected  

22.             , 'permissions'     : (ZEN_VIEW, ) },  

23.             )  

24.     def __init__(self, *args, **kw):  

25.         Device.__init__(self, *args, **kw)  

26.         self.buildRelations()  

27. InitializeClass(ZPoolDevice)   #must initialize class  

 

 

 

ZPoolComponent内容

 

Python代码  

1. import locale  

2. from Globals import DTMLFile  

3. from Globals import InitializeClass  

4. from Products.ZenUtils.Utils import convToUnits  

5. from Products.ZenRelations.RelSchema import *  

6. from Products.ZenModel.ZenossSecurity import ZEN_VIEW, ZEN_CHANGE_SETTINGS  

7. from Products.ZenModel.DeviceComponent import DeviceComponent  

8. from Products.ZenModel.ManagedEntity import ManagedEntity  

9. from Products.ZenUtils.Utils import prepId  

10. class ZPoolComponent(DeviceComponent, ManagedEntity):  

11.     #define the type (name to be used in zenoss, most probably as a database table name)  

12.     portal_type = meta_type = 'ZPoolComponent'  

13.     zPoolName = ""  

14.     health = ""  

15.     #define component fields  

16.     #新类的属性,zPoolNamehealth  

17.     _properties = (  

18.         {'id':'zPoolName''type':'string''mode':''},  

19.         {'id':'health''type':'string''mode':''}  

20.         )  

21.     #define relation the same as in the Device but only inverted  

22.     _relations = (  

23.         ("ZPoolParent", ToOne(ToManyCont,  

24.             "ZenPacks.test.ZPool.ZPoolDevice""ZPoolChild")),  

25.         )  

26.     #some getters to be called from the zope template  

27.     def viewName(self):  

28.         return self.zPoolName  

29.     def getZPoolName(self):  

30.                return self.zPoolName  

31.     def isOnline(self):  

32.     #用过modeler收集到的health属性来判断状态  

33.         return self.health == 'ONLINE'  

34.     #return a new 'Relation' object (the object will be populated at runtime)  

35.     def device(self):  

36.         return self.ZPoolParent()  

37.     def getRRDNames(self):  

38.         return []  

39. InitializeClass(ZPoolComponent)  

 

Modeler

modeler 的作用是获取snmp结果,然后存储字段信息。它应该存放在/ZenPacks.test.ZPool/ZenPacks/test/ZPool/modeler/plugins/下。modeler2中模式,一种是映射snmp表,另一种是映射定义好的oid。在这个例子中我使用第二种方式。

 

在这个modeler中,它的oid.1.3.6.1.4.1.2021.55.1,是自己定义的snmp脚本,会返回字符串“data1 ONLINE|data2 DEGRADED|rpool ONLINE”

 

modeler代码:

Python代码  

1. from Products.DataCollector.plugins.CollectorPlugin import SnmpPlugin, GetTableMap, GetMap  

2. from Products.DataCollector.plugins.DataMaps import ObjectMap  

3. class ZPoolDeviceDetailsModeler(SnmpPlugin):  

4.     relname = "ZPoolChild"  #The ralation name from the Device side  

5.     modname = "ZenPacks.test.ZPool.ZPoolComponent"   #the module of the component to be populated  

6.     #list of oids to get, and their respective name, here zenoss will call that oid and will call process() with a parameter result containing map ['zPoolHealth': ]  

7.     snmpGetMap = GetMap({'.1.3.6.1.4.1.2021.55.1' : 'zPoolHealth',  

8.                          })  

9.     #for the case of one to may relation process should return a list of relations mappings relMap  

10.     def process(self, device, results, log):  

11.         """collect snmp information from this device 

12.         @param device: device that is currently modeled 

13.         @param results: tuple of (non snmp table data, snmp table data) both as dict 

14.         @param log: logger"""  

15.         log.info('processing %s for device %s', self.name(), device.id)  

16.         getdata, tabledata = results  

17.         rm = self.relMap()  

18.         zPoolHealth = getdata['zPoolHealth']  

19.         # create a different object model for each relation model and append it to relation model list  

20.         for zPool in zPoolHealth.split('|'):  

21.             om = self.objectMap()  

22.             zpoolFields = zPool.split()  

23.             om.zPoolName = zpoolFields[0]  

24.             om.health = zpoolFields[1]  

25.             rm.append(om)  

26.             om.id = self.prepId(str(om.zPoolName))  

27.             log.info('Health for ZPool %s Collected health is %s'%(om.zPoolName, om.health))  

28.         return rm  

 

此时在zenpack的日志里可以看到‘Health for ZPool %s Collected health is %s’,的内容,但是还不能通过GUI看到。(因为作者没有完成GUI部分的代码)

 

其实我觉得翻的还是比较烂的,大家看的不舒服可以看原文。

原文出处:http://georgefakhri.wordpress.com/2009/07/15/how-to-create-a-zenpack/

 

我跟作者开始写这篇文章时的感受一样,在zenoss的开发文档中没有一段比较简单的讲述一个最基本的zenpack的开发流程,它将很多功能拆分开来将,而且代码也没很详细的解释,大多数都是贴出其中的一段。最后在作者的这篇文章的评论中发现了一份相对详细的zenpack的文档地址:http://community.zenoss.org/docs/DOC-10268,我看完之后我自己对zenpack大致上有了粗略的一些了解。

 

zenpack最基本的开发如上所说的就4部分

1device文件,用来创建一个对象,链接到device,此例中是ZPoolDevice

2component文件,新device的新属性在此文件中定义,GUI中页面的下拉选项也在次定于,还有一些函数用来当调用数据库中对象属性时初始化用(我自己还没找到modeler中获取到的数据存在哪里了,很苦恼)见ZPoolComponent.py

3modeler 文件及时一个collector,用过snmp来获取数据,用process()方法来解析,处理,存储数据,见ZPoolDeviceDetailModeler.py

4)最后需要一个文件来将获取的数据展示到页面上,在zenoss3之前是用过skin中的。pt文件,是html写的,zenoss3开始通过使用javascript来写。

 

我自己现在将作者这篇没写完的部分写好了,但是一直界面上看不到,很郁闷。国内,即使是国外zenpack的资料实在太少,官方文档也比较烂。。。没啥多说的。很郁闷。

bypakoo

emailzealzpc@gmial.com

已经写完GUI部分顺利调试通过,过几天写份完整的开发介绍。

 

先附上GUI代码

info.py

Python代码  

1. __doc__="""info.py 

2.  

3. Representation of Bridge components. 

4.  

5. $Id: info.py,v 1.2 2010/12/14 20:45:46 jc Exp $"""  

6.   

7. __version__ = "$Revision: 1.4 $"[11:-2]  

8.   

9. from zope.interface import implements  

10. from Products.Zuul.infos import ProxyProperty  

11. from Products.Zuul.infos.component import ComponentInfo  

12. from Products.Zuul.decorators import info  

13. #from Products.ZenUtils.Utils import convToUnits  

14. from ZenPacks.test.ZPool import interfaces  

15.   

16.   

17. class ZPoolInterfaceInfo(ComponentInfo):  

18.     implements(interfaces.IBridgeInterfaceInfo)  

19.   

20.     zPoolName = ProxyProperty("zPoolName")  

21.     health = ProxyProperty("health")  

22.  

23.  

24.     @property  

25.     def ZPoolName(self):  

26.         return self._object.getZPoolName()  

27.     @property         

28.     def health(self):  

29.         return self._object.gethealth()  

30.  

31.     @property  

32.     def isOnline(self):  

33.         return self._object.isOnline()  

 interfaces.py

Python代码  

1. __doc__="""interfaces 

2.  

3. describes the form field to the user interface. 

4.  

5. $Id: interfaces.py,v 1.2 2010/12/14 20:46:34 jc Exp $"""  

6.   

7. __version__ = "$Revision: 1.4 $"[11:-2]  

8.   

9. from Products.Zuul.interfaces import IComponentInfo  

10. from Products.Zuul.form import schema  

11. from Products.Zuul.utils import ZuulMessageFactory as _t  

12.   

13.   

14. class IBridgeInterfaceInfo(IComponentInfo):  

15.     """ 

16. Info adapter for Bridge Interface component 

17. """  

18.     zPoolName = schema.Text(title=u"zPoolName", readonly=True, group='Details')  

19.     health = schema.Text(title=u"health", readonly=True, group='Details')  

 

configure.zcml

 

Xml代码  

1.  version="1.0" encoding="utf-8"?>  

2.  xmlns="http://namespaces.zope.org/zope"  

3.            xmlns:browser="http://namespaces.zope.org/browser"  

4.            xmlns:zcml="http://namespaces.zope.org/zcml">  

5.   

6.      zcml:condition="installed Products.Zuul">  

7.   

8.          factory=".info.ZPoolInterfaceInfo"  

9.                  for=".ZPoolComponent.ZPoolComponent"  

10.                  provides=".interfaces.IBridgeInterfaceInfo"  

11.                  />  

12.   

13.           

14.                  name="ZPool"  

15.                  directory="resources"  

16.                  />  

17.   

18.           

19.                  name="js-ZPool"  

20.                  paths="/++resource++ZPool/ZPool.js"  

21.                  weight="10"  

22.                  manager="Products.ZenUI3.browser.interfaces.IJavaScriptSrcManager"  

23.                  class="Products.ZenUI3.browser.javascript.JavaScriptSrcBundleViewlet"  

24.                  permission="zope2.Public"  

25.                  />  

26.       

27.   

 

ZPool.js

Js代码  

1. (function(){  

2.   

3. var ZC = Ext.ns('Zenoss.component');  

4.   

5.   

6. function render_link(ob) {  

7.     if (ob && ob.uid) {  

8.         return Zenoss.render.link(ob.uid);  

9.     } else {  

10.         return ob;  

11.     }  

12. }  

13.   

14. ZC.ZPoolInterfacePanel = Ext.extend(ZC.ComponentGridPanel, {  

15.     constructor: function(config) {  

16.         config = Ext.applyIf(config||{}, {  

17.             componentType: 'ZPool',  

18.             fields: [  

19.                 {name: 'zPoolName'},  

20.                 {name: 'health'},  

21.                 {name: 'uid'},  

22.                 {name: 'name'},  

23.                 {name: 'severity'},  

24.                 {name: 'status'},  

25.                 {name: 'hasMonitor'},  

26.                 {name: 'monitor'},  

27.             ],  

28.             columns: [  

29.             {  

30.                 id: 'severity',  

31.                 dataIndex: 'severity',  

32.                 header: _t('Events'),  

33.                 renderer: Zenoss.render.severity,  

34.                 width: 60  

35.             },  

36.             {  

37.                 id: 'zPoolName',  

38.                 dataIndex: 'zPoolName',  

39.                 header: _t('zPoolName'),  

40.                 sortable: true  

41.             },{  

42.                 id: 'health',  

43.                 dataIndex: 'health',  

44.                 header: _t('health'),  

45.                 sortable: true,  

46.             },  

47.             {  

48.                 id: 'name',  

49.                 dataIndex: 'name',  

50.                 header: _t('Name'),  

51.                 width: 120,  

52.                 sortable: true  

53.             },{  

54.                 id: 'monitored',  

55.                 dataIndex: 'monitored',  

56.                 header: _t('Monitored'),  

57.                 width: 60  

58.             }]  

59.         });  

60.         ZC.ZPoolInterfacePanel.superclass.constructor.call(this, config);  

61.     }  

62. });  

63.   

64. Ext.reg('ZPoolComponent', ZC.ZPoolInterfacePanel);  

65. ZC.registerName('ZPoolComponent', _t('ZPool Component'), _t('ZPool Component'));  

66. })();  

 

本文来源:https://www.2haoxitong.net/k/doc/be020526c281e53a5802ff8a.html

《如何创建一个zenpack.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

文档为doc格式