`

如何创建一个zenpack(翻译)

阅读更多

 

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

 

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

这篇文章解释了如果创建一个zenpack来扩展device 增加 一个componet。如何增加一个新的snmp oid 到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来说目录结构一般为

<Zenoss home>/zenoss/ZenPacks/

    ZenPacks.test.ZPool/  <Zenpack root directory>

        ZenPacks.test.ZPool.egg-info

        ZenPacks              <The following directories will reflect the Zenpack name as python packages>

            __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   <modeler module(collector)>

                    objects

                    reports

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

                        __init__.py

                        ZenPacks.test.ZPool  <name of Zenpack>

                            ZPoolDeviceDetailTemplate.pt

 

Model objects

 

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

增加一个component到device中,我们需要做如下事:

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

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

 

ZPoolDevice 内容

from Globals import InitializeClass
from Products.ZenRelations.RelSchema import *
from Products.ZenModel.Device import Device
from Products.ZenModel.ZenossSecurity import ZEN_VIEW
from copy import deepcopy
class ZPoolDevice(Device):
    "An APC Switched PDU"
    #增加一组关系,将ZPoolChild和ZPoolParent绑定起来,ZPoolParent是component
    _relations = Device._relations + (
        ('ZPoolChild', ToManyCont(ToOne,
            'ZenPacks.test.ZPool.ZPoolComponent', 'ZPoolParent')),
        )
    # add to Device relations the relation to ZPoolComponent
    # The relation is initialized with 5 params, relation name from this side, relation type(ToOne, ToManyCont... etc), component module, and the
    # relation name from the other side of the realtion
    # next we will define a new tab in the Gui which will preview zope template
    factory_type_information = deepcopy(Device.factory_type_information)
    factory_type_information[0]['actions'] += (
            { 'id'              : 'ZPoolChild'  #tab id
            , 'name'            : 'ZPool'      #tab name (appears from the device status tab)
            , 'action'          : 'ZPoolDeviceDetailTemplate'    #the zope template to call when this tab is selected
            , 'permissions'     : (ZEN_VIEW, ) },
            )
    def __init__(self, *args, **kw):
        Device.__init__(self, *args, **kw)
        self.buildRelations()
InitializeClass(ZPoolDevice)   #must initialize class
 

 

 

ZPoolComponent 内容

 

import locale
from Globals import DTMLFile
from Globals import InitializeClass
from Products.ZenUtils.Utils import convToUnits
from Products.ZenRelations.RelSchema import *
from Products.ZenModel.ZenossSecurity import ZEN_VIEW, ZEN_CHANGE_SETTINGS
from Products.ZenModel.DeviceComponent import DeviceComponent
from Products.ZenModel.ManagedEntity import ManagedEntity
from Products.ZenUtils.Utils import prepId
class ZPoolComponent(DeviceComponent, ManagedEntity):
    #define the type (name to be used in zenoss, most probably as a database table name)
    portal_type = meta_type = 'ZPoolComponent'
    zPoolName = ""
    health = ""
    #define component fields
	#新类的属性,zPoolName和health
    _properties = (
        {'id':'zPoolName', 'type':'string', 'mode':''},
        {'id':'health', 'type':'string', 'mode':''}
        )
    #define relation the same as in the Device but only inverted
    _relations = (
        ("ZPoolParent", ToOne(ToManyCont,
            "ZenPacks.test.ZPool.ZPoolDevice", "ZPoolChild")),
        )
    #some getters to be called from the zope template
    def viewName(self):
        return self.zPoolName
    def getZPoolName(self):
               return self.zPoolName
    def isOnline(self):
    #用过modeler收集到的health属性来判断状态
        return self.health == 'ONLINE'
    #return a new 'Relation' object (the object will be populated at runtime)
    def device(self):
        return self.ZPoolParent()
    def getRRDNames(self):
        return []
InitializeClass(ZPoolComponent)
 

Modeler

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

 

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

 

modeler代码:

from Products.DataCollector.plugins.CollectorPlugin import SnmpPlugin, GetTableMap, GetMap
from Products.DataCollector.plugins.DataMaps import ObjectMap
class ZPoolDeviceDetailsModeler(SnmpPlugin):
    relname = "ZPoolChild"  #The ralation name from the Device side
    modname = "ZenPacks.test.ZPool.ZPoolComponent"   #the module of the component to be populated
    #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': <value returned>]
    snmpGetMap = GetMap({'.1.3.6.1.4.1.2021.55.1' : 'zPoolHealth',
                         })
    #for the case of one to may relation process should return a list of relations mappings relMap
    def process(self, device, results, log):
        """collect snmp information from this device
        @param device: device that is currently modeled
        @param results: tuple of (non snmp table data, snmp table data) both as dict
        @param log: logger"""
        log.info('processing %s for device %s', self.name(), device.id)
        getdata, tabledata = results
        rm = self.relMap()
        zPoolHealth = getdata['zPoolHealth']
        # create a different object model for each relation model and append it to relation model list
        for zPool in zPoolHealth.split('|'):
            om = self.objectMap()
            zpoolFields = zPool.split()
            om.zPoolName = zpoolFields[0]
            om.health = zpoolFields[1]
            rm.append(om)
            om.id = self.prepId(str(om.zPoolName))
            log.info('Health for ZPool %s Collected health is %s'%(om.zPoolName, om.health))
        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

__doc__="""info.py

Representation of Bridge components.

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

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

from zope.interface import implements
from Products.Zuul.infos import ProxyProperty
from Products.Zuul.infos.component import ComponentInfo
from Products.Zuul.decorators import info
#from Products.ZenUtils.Utils import convToUnits
from ZenPacks.test.ZPool import interfaces


class ZPoolInterfaceInfo(ComponentInfo):
    implements(interfaces.IBridgeInterfaceInfo)

    zPoolName = ProxyProperty("zPoolName")
    health = ProxyProperty("health")


    @property
    def ZPoolName(self):
        return self._object.getZPoolName()
    @property		
    def health(self):
        return self._object.gethealth()

    @property
    def isOnline(self):
        return self._object.isOnline()

 interfaces.py

__doc__="""interfaces

describes the form field to the user interface.

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

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

from Products.Zuul.interfaces import IComponentInfo
from Products.Zuul.form import schema
from Products.Zuul.utils import ZuulMessageFactory as _t


class IBridgeInterfaceInfo(IComponentInfo):
    """
Info adapter for Bridge Interface component
"""
    zPoolName = schema.Text(title=u"zPoolName", readonly=True, group='Details')
    health = schema.Text(title=u"health", readonly=True, group='Details')

 

configure.zcml

 

<?xml version="1.0" encoding="utf-8"?>
<configure xmlns="http://namespaces.zope.org/zope"
           xmlns:browser="http://namespaces.zope.org/browser"
           xmlns:zcml="http://namespaces.zope.org/zcml">

    <configure zcml:condition="installed Products.Zuul">

        <adapter factory=".info.ZPoolInterfaceInfo"
                 for=".ZPoolComponent.ZPoolComponent"
                 provides=".interfaces.IBridgeInterfaceInfo"
                 />

        <browser:resourceDirectory
                 name="ZPool"
                 directory="resources"
                 />

        <browser:viewlet
                 name="js-ZPool"
                 paths="/++resource++ZPool/ZPool.js"
                 weight="10"
                 manager="Products.ZenUI3.browser.interfaces.IJavaScriptSrcManager"
                 class="Products.ZenUI3.browser.javascript.JavaScriptSrcBundleViewlet"
                 permission="zope2.Public"
                 />
    </configure>
</configure>

 

ZPool.js

(function(){

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


function render_link(ob) {
    if (ob && ob.uid) {
        return Zenoss.render.link(ob.uid);
    } else {
        return ob;
    }
}

ZC.ZPoolInterfacePanel = Ext.extend(ZC.ComponentGridPanel, {
    constructor: function(config) {
        config = Ext.applyIf(config||{}, {
            componentType: 'ZPool',
            fields: [
                {name: 'zPoolName'},
                {name: 'health'},
                {name: 'uid'},
                {name: 'name'},
                {name: 'severity'},
                {name: 'status'},
                {name: 'hasMonitor'},
                {name: 'monitor'},
            ],
            columns: [
			{
                id: 'severity',
                dataIndex: 'severity',
                header: _t('Events'),
                renderer: Zenoss.render.severity,
                width: 60
            },
			{
                id: 'zPoolName',
                dataIndex: 'zPoolName',
                header: _t('zPoolName'),
                sortable: true
            },{
                id: 'health',
                dataIndex: 'health',
                header: _t('health'),
                sortable: true,
            },
			{
                id: 'name',
                dataIndex: 'name',
                header: _t('Name'),
                width: 120,
                sortable: true
            },{
				id: 'monitored',
				dataIndex: 'monitored',
				header: _t('Monitored'),
				width: 60
			}]
        });
        ZC.ZPoolInterfacePanel.superclass.constructor.call(this, config);
    }
});

Ext.reg('ZPoolComponent', ZC.ZPoolInterfacePanel);
ZC.registerName('ZPoolComponent', _t('ZPool Component'), _t('ZPool Component'));
})();

 
分享到:
评论

相关推荐

    如何创建zenpack

    在本文中,我们将深入探讨如何创建一个自定义的ZenPack,以便在Zenoss监控软件中扩展设备的功能。ZenPack是Zenoss系统中的一个重要组件,它允许用户根据需求添加新的设备属性、SNMP OID以及GUI界面元素。让我们逐一...

    ZenPacks.SteelHouseLabs.EnhancedEthernetCsmacd:ZenPack 可显着增强现有以太网模板

    这个 ZenPack 极大地改进了 /Network/etherCscmacd、/Network/etherCscmacd_64 和 /Devices/etherCscmacd 模板。 特征 这个 ZenPack 极大地改进了 /Network/etherCscmacd、/Network/etherCscmacd_64 和 /Devices/...

    ZenPacks.SteelHouseLabs.EventForwarder:ZenPack 提供将事件转发到扇出队列的工具

    这个 ZenPack 添加了zenactiond守护进程使用的新事件通知操作。 特征 Event Forwarder 操作将事件转发到 eventForwarder 兔子队列。 目标扩展包,例如 ZenPacks.SteelHouseLabs.SplunkForwarder 和 ZenPacks....

    zenoss developer guide

    Zenoss有一个活跃的社区,开发者可以利用这个社区共享和获取已有的ZenPack,加速开发进程。同时,社区也提供了许多有用的工具和资源,帮助开发者更好地理解和使用Zenoss。 通过深入学习和实践《Zenoss Developer ...

    zenoss安装指南

    #### 知识点一:Zenoss简介与下载 - **Zenoss**是一款开源的企业级网络监控系统,它可以帮助管理员监控网络设备、服务器和其他IT资源的状态。 - 官方提供了多种安装方式,包括虚拟机镜像、RPM包、Debian包以及源码...

    europa-formula:salt states 以 zenpack 开发模式安装 europa

    创建一个基本框 如果需要,可以使用打包程序文件夹中提供的打包程序脚本在本地生成基本框。 vagrant_config.yml 文件使用本地生成的基本框。 如果需要,可以使用任何 URI 重新配置它。 (cd packer && packer build ...

    ZenPacks.community.Nimble:ZenPacks.community.Nimble

    ZenPack管理Nimble存储阵列描述当前,这是一个BETA ZENPACK。 仅应将其安装在测试环境中!!! 该ZenPack用于使用SNMP协议管理Nimble存储阵列。 使用新的组件类型创建新的灵活设备类型来表示卷。 Nimble MIB(1.3....

    ZenPacks.community.A10:ZenPacks.community.A10

    ZenPack支持A10负载平衡器 描述 此ZenPack支持A10负载平衡器。 它为以下各项创建新的组件类型: 虚拟服务器 服务组 服务器 这些组件都是A10Device类型的直接子组件。...虚拟服务器的组件显示包括相关的服务组和一个

    ZenPacks.JanGaraj.DataMirroring:Mirror实时收集Zenoss数据

    它仅提供示例代码以将Zenoss数据镜像到另一个(监视)系统中。 它是Products.ZenRRD.RRDUtil.RRDUtil.put()方法的猴子补丁,因此您必须100%确定ZenPack代码。 镜像任务在新线程中执行,它们不会阻止Zenoss ...

    product-assembly

    每个子目录core 、 resmgr和product-base都有一个 makefile,用于构建zenoss/product-base镜像zenoss/product-base镜像必须首先构建。 该镜像包含和运行 Zenoss 所需的所有第三方服务(Zope、RabbitMQ、redis 等)...

    ZenPacks.daviswr.NCPA:使用Nagios跨平台代理监视Zenoss的设备

    首先,ZenPacks是一个Zenoss社区提供的扩展框架,它允许开发者创建自定义的监控插件和解决方案,以增强Zenoss的核心功能。ZenPacks.daviswr.NCPA是由用户daviswr开发的一款特定的ZenPack,旨在使Zenoss能够与Nagios...

    txwinrm:异步Python WinRM客户端

    txwinrm:异步Python WinRM客户端在Zenoss,我们正在进行一个项目,以提高本机Windows监视的可靠性,性能和功能。 该项目的核心是该Python库,用于使用WinRM和WinRS服务异步管理Windows。 然后,Zenoss将使用该库来...

    zendev-scripts:帮助Zenoss开发的脚本

    开发的一系列工具。 目前,这仅限于使ZenPacks的使用更加容易的脚本组合。 由于广泛的命名空间,ZenPacks当前具有非常深的目录结构,例如$ ZENHOME / ZenPacks / ZenPacks.zenoss....

Global site tag (gtag.js) - Google Analytics