如何创建一个zenpack来添加新属性来扩展device
这篇文章你能获取到什么信息
这篇文章解释了如果创建一个zenpack来扩展device 增加一个componet。如何增加一个新的snmpoid到zenoss中,如何在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必须有3个python包名来组成,用“.”来分开(例如ZenPacks.test.ZPool)第一个包名一般都是Zenpack。文件之后会自动生成。
对于一个名叫Zenpacks.test.ZPool的zenpack来说目录结构一般为
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
objects
reports
skins <存放视图模板,用在GUI上展示数据>
__init__.py
ZenPacks.test.ZPool
ZPoolDeviceDetailTemplate.pt
Model objects
model object 应该被存放在zenpack名最后一个点后面那个名字的文件夹中。(Zenpack.test.ZPool的话就是在ZPool文件夹)
增加一个component到device中,我们需要做如下事:
1)创建一个继承device的对象(它增加一个新的关系到device中),在这个例子中,我命名它为ZPoolDevice。
2)创建一个对象继承DeviceComponent和ManagedEntity(里面同时定义了一个新的关系链接到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. #增加一组关系,将ZPoolChild和ZPoolParent绑定起来,ZPoolParent是component
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. #新类的属性,zPoolName和health
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结果,然后存储字段信息。它应该存放在
在这个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部分
1)device文件,用来创建一个对象,链接到device,此例中是ZPoolDevice。
2)component文件,新device的新属性在此文件中定义,GUI中页面的下拉选项也在次定于,还有一些函数用来当调用数据库中对象属性时初始化用(我自己还没找到modeler中获取到的数据存在哪里了,很苦恼)见ZPoolComponent.py
3)modeler 文件及时一个collector,用过snmp来获取数据,用process()方法来解析,处理,存储数据,见ZPoolDeviceDetailModeler.py
4)最后需要一个文件来将获取的数据展示到页面上,在zenoss3之前是用过skin中的。pt文件,是html写的,zenoss3开始通过使用javascript来写。
我自己现在将作者这篇没写完的部分写好了,但是一直界面上看不到,很郁闷。国内,即使是国外zenpack的资料实在太少,官方文档也比较烂。。。没啥多说的。很郁闷。
by:pakoo
email:zealzpc@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.
3. xmlns:browser="http://namespaces.zope.org/browser"
4. xmlns:zcml="http://namespaces.zope.org/zcml">
5.
6.
7.
8.
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
文档为doc格式