Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Correctly add the dir

  • Loading branch information...
commit 318a71a700686422bf2706e1f124d29639ae0860 0 parents
kkearney authored
Showing with 2,186 additions and 0 deletions.
  1. +52 −0 GNUmakefile.example
  2. +8 −0 MANIFEST.in
  3. +164 −0 README.txt
  4. +10 −0 ZenPacks.zenoss.RedHatEVM.egg-info/PKG-INFO
  5. +100 −0 ZenPacks.zenoss.RedHatEVM.egg-info/SOURCES.txt
  6. +1 −0  ZenPacks.zenoss.RedHatEVM.egg-info/dependency_links.txt
  7. +3 −0  ZenPacks.zenoss.RedHatEVM.egg-info/entry_points.txt
  8. +2 −0  ZenPacks.zenoss.RedHatEVM.egg-info/namespace_packages.txt
  9. +1 −0  ZenPacks.zenoss.RedHatEVM.egg-info/not-zip-safe
  10. +1 −0  ZenPacks.zenoss.RedHatEVM.egg-info/requires.txt
  11. +4 −0 ZenPacks.zenoss.RedHatEVM.egg-info/test_info.txt
  12. +1 −0  ZenPacks.zenoss.RedHatEVM.egg-info/top_level.txt
  13. +1 −0  ZenPacks/__init__.py
  14. BIN  ZenPacks/zenoss/RedHatEVM/.__init__.py.swp
  15. +13 −0 ZenPacks/zenoss/RedHatEVM/Device.py
  16. +25 −0 ZenPacks/zenoss/RedHatEVM/__init__.py
  17. +31 −0 ZenPacks/zenoss/RedHatEVM/analytics.py
  18. 0  ZenPacks/zenoss/RedHatEVM/bin/placeholder.txt
  19. 0  ZenPacks/zenoss/RedHatEVM/browser/__init__.py
  20. +23 −0 ZenPacks/zenoss/RedHatEVM/browser/configure.zcml
  21. 0  ZenPacks/zenoss/RedHatEVM/browser/resources/css/placeholder.txt
  22. 0  ZenPacks/zenoss/RedHatEVM/browser/resources/img/placeholder.txt
  23. +81 −0 ZenPacks/zenoss/RedHatEVM/browser/resources/js/ExampleDevice.js
  24. 0  ZenPacks/zenoss/RedHatEVM/componenttypes/__init__.py
  25. +3 −0  ZenPacks/zenoss/RedHatEVM/componenttypes/configure.zcml
  26. +107 −0 ZenPacks/zenoss/RedHatEVM/componenttypes/ovirt/CollectionTask.py
  27. +95 −0 ZenPacks/zenoss/RedHatEVM/componenttypes/ovirt/ComponentDefinition.py
  28. +47 −0 ZenPacks/zenoss/RedHatEVM/componenttypes/ovirt/DeviceProxyConfig.py
  29. +90 −0 ZenPacks/zenoss/RedHatEVM/componenttypes/ovirt/ModelerPlugin.py
  30. +23 −0 ZenPacks/zenoss/RedHatEVM/componenttypes/ovirt/ServiceConfig.py
  31. 0  ZenPacks/zenoss/RedHatEVM/componenttypes/ovirt/__init__.py
  32. +35 −0 ZenPacks/zenoss/RedHatEVM/componenttypes/ovirt/configure.zcml
  33. +18 −0 ZenPacks/zenoss/RedHatEVM/componenttypes/ovirt/info.py
  34. +14 −0 ZenPacks/zenoss/RedHatEVM/componenttypes/ovirt/interfaces.py
  35. +191 −0 ZenPacks/zenoss/RedHatEVM/configure.zcml
  36. +16 −0 ZenPacks/zenoss/RedHatEVM/daemons/zenexample
  37. +37 −0 ZenPacks/zenoss/RedHatEVM/datasources/ExampleDataSource.py.example
  38. +2 −0  ZenPacks/zenoss/RedHatEVM/datasources/__init__.py
  39. +42 −0 ZenPacks/zenoss/RedHatEVM/dynamicview.py
  40. +16 −0 ZenPacks/zenoss/RedHatEVM/events.py
  41. +132 −0 ZenPacks/zenoss/RedHatEVM/impact.py
  42. +53 −0 ZenPacks/zenoss/RedHatEVM/info.py
  43. +45 −0 ZenPacks/zenoss/RedHatEVM/interfaces.py
  44. +1 −0  ZenPacks/zenoss/RedHatEVM/lib/__init__.py
  45. 0  ZenPacks/zenoss/RedHatEVM/libexec/placeholder.txt
  46. +34 −0 ZenPacks/zenoss/RedHatEVM/migrate/ExampleMigration.py
  47. +1 −0  ZenPacks/zenoss/RedHatEVM/migrate/__init__.py
  48. 0  ZenPacks/zenoss/RedHatEVM/modeler/__init__.py
  49. 0  ZenPacks/zenoss/RedHatEVM/modeler/plugins/__init__.py
  50. 0  ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/__init__.py
  51. +81 −0 ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/cmd/ExampleCMD.py.example
  52. 0  ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/cmd/__init__.py
  53. +121 −0 ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/snmp/ExampleSNMP.py.example
  54. 0  ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/snmp/__init__.py
  55. +3 −0  ZenPacks/zenoss/RedHatEVM/objects/objects.xml
  56. +66 −0 ZenPacks/zenoss/RedHatEVM/reports/Example_Reports/Example_Report.rpt.example
  57. +23 −0 ZenPacks/zenoss/RedHatEVM/reports/plugins/example_plugin.py
  58. +94 −0 ZenPacks/zenoss/RedHatEVM/services/ExampleConfigService.py
  59. 0  ZenPacks/zenoss/RedHatEVM/services/__init__.py
  60. 0  ZenPacks/zenoss/RedHatEVM/tests/__init__.py
  61. +36 −0 ZenPacks/zenoss/RedHatEVM/tests/testExample.py
  62. +108 −0 ZenPacks/zenoss/RedHatEVM/zenrhevm.py
  63. +37 −0 ZenPacks/zenoss/RedHatEVM/zep/actions.json.example
  64. +14 −0 ZenPacks/zenoss/RedHatEVM/zep/zep.json.example
  65. +1 −0  ZenPacks/zenoss/__init__.py
  66. +79 −0 setup.py
  67. 0  src/placeholder.txt
52 GNUmakefile.example
@@ -0,0 +1,52 @@
+# GNUmakefile Example
+
+# A GNUmakefile is only required for ZenPacks that need to bundle external
+# dependencies that need to be built when the ZenPack is built instead of when
+# the ZenPack is installed. This normally means binary packages that must be
+# built, but could also be used to save time at install time.
+
+# The following template can be used to get started. Note that we want files
+# resulting from the build activity to land under the ZENPACK_DIR so that they
+# will be included in the resulting ZenPack. You should copy or rename this
+# file to "GNUmakefile" if you want it to be automatically executed by the
+# ZenPack build and --link installation process.
+
+PYTHON=python
+SRC_DIR=$(PWD)/src
+YOURPACKAGE_DIR=$(SRC_DIR)/yourpackage-1.2.3
+ZENPACK_DIR=$(PWD)/ZenPacks/NAMESPACE/PACKNAME
+BIN_DIR=$(ZENPACK_DIR)/bin
+LIB_DIR=$(ZENPACK_DIR)/lib
+
+# Default target. This won't be used by any automated process, but would be
+# used if you simply ran "make" in this directory.
+default: build
+
+# The build target it specifically executed each time setup.py executes.
+# Typically this is when the ZenPack is being built into an egg, or when it is
+# installed using the zenpack --link option to install in development mode.
+build:
+ # Example for building a configure+make style dependency.
+ cd $(YOURPACKAGE_DIR) ; \
+ ./configure --prefix=$(ZENPACK_DIR) ; \
+ make ; \
+ make install
+
+ # Example for building a Python package depedency.
+ cd $(YOURPACKAGE_DIR) ; \
+ PYTHONPATH="$(PYTHONPATH):$(LIB_DIR)" \
+ $(PYTHON) setup.py install \
+ --install-lib="$(LIB_DIR)" \
+ --install-scripts="$(BIN_DIR)"
+
+# The clean target won't be used by any automated process.
+clean:
+ rm -rf build dist *.egg-info
+ find . -name '*.pyc' | xargs rm
+
+ # Example for cleaning a configure+make style depedency.
+ cd $(YOURPACKAGE_DIR) ; make clean
+
+ # Example for cleaning a Python package depdency.
+ cd $(YOURPACKAGE_DIR) ; rm -rf build dist *.egg-info
+
8 MANIFEST.in
@@ -0,0 +1,8 @@
+# This graft causes all files located under the ZenPacks/ subdirectory to be
+# included in the built ZenPack .egg. Files located in the top-level directory
+# of the ZenPack will not be explicitly included.
+#
+# You can read more about the format and available options available in this
+# MANIFEST.in file at the following URL.
+# http://docs.python.org/distutils/sourcedist.html
+graft ZenPacks
164 README.txt
@@ -0,0 +1,164 @@
+# ZenPack Template
+This README describes the structure of the ZenPack template that gets
+automatically created by Zenoss when you add a ZenPack through the web
+interface.
+
+## Files
+At the top-level a ZenPack must have a setup.py. Almost always a MANIFEST.in
+file should exist, and in cases where external dependencies must be built for
+inclusion in the ZenPack, a GNUmakefile. Examples of these files with inline
+comments are included in this template.
+
+Also included in the ZenPackTemplate is a configure.zcml. As more of Zenoss'
+extensibility moves to using ZCA (Zope Component Architecture) this file
+becomes crucial to hooking into various aspects of Zenoss.
+
+## Files and Subdirectories
+The following sections describe the purpose and use for each of the default
+subdirectories. Note that if the described functionality is not of use in your
+ZenPack it is safe to remove any of the default directories.
+
+### src/
+The src/ top-level directory in ZenPacks is the conventional place to add
+third-party dependencies to your ZenPack. It should only be used as a staging
+area to do any build work necessary for the dependency.
+
+See GNUmakefile (or GNUmakefile.example) for examples of how to have
+your third-party dependencies automatically compiled and installed at the right
+time and into the right location.
+
+### ZenPacks/NAMESPACE/PACKNAME/
+The following sections describe the directories contained within the
+namespaced ZenPacks/NAMESPACE/PACKNAME/ subdirectories.
+
+#### bin/
+Any general tools delivered by your ZenPack that would be used by the Zenoss
+administrator at the command line should go into this directory by convention.
+When the ZenPack is installed all files in this directory will be made
+executable.
+
+#### browser/
+The browser subdirectory should contain all code and configuration that's
+specific to the Zenoss web interface. The provided configure.zcml will
+automatically load the example browser/configure.zcml and register the
+browser/resources/ subdirectory to serve static web content.
+
+#### daemons/
+All files in the daemons/ subdirectory get special handling. Upon installing
+the ZenPack, the following actions will occur.
+
+ 1. The file will be made executable (chmod 0755)
+ 2. A symlink to the file will be created in $ZENHOME/bin/
+ 3. An configuration file will be generated at $ZENHOME/etc/DAEMON_NAME.conf
+
+Assuming that you don't have a $ZENHOME/etc/DAEMONS_TXT_ONLY file this daemon
+will also become part of the normal zenoss start and stop processes.
+
+You can find an example daemon control script in daemons/zenexample. For most
+purposes this file can be renamed to the name of the daemon you want to create
+and modified to change the DAEMON_NAME. No other modifications are typically
+needed. Note that this example control script does expect to launch the real
+daemon code which should be located at ../DAEMON_NAME.py.
+
+#### datasources/
+Any new datasource types you want to add must be added as classes into the
+datasources/ subdirectory. When Zenoss is building the list of available
+datasources it will scan the datasources/ subdirectory for all installed
+ZenPacks.
+
+An example datasource at datasources/ExampleDataSource.py.example.
+
+#### lib/
+The lib/ directory should be the installation target for any third-party
+libraries that are built by the GNUmakefile. It can also be used as the
+conventional location to drop Python-only libraries that don't require
+any compilation or special installation.
+
+#### libexec/
+Any scripts executed by COMMAND datasources in your ZenPack go in this
+directory by convention. When the ZenPack is installed all files in this
+directory will be made executable.
+
+#### migrate/
+ZenPacks can include migrate scripts that allow you to run custom code to
+handle any tasks that are needed to upgrade your ZenPack from one version to
+another. All .py files in this migrate/ subdirectory will be evaluated when the
+ZenPack is installed.
+
+You can find an example migrate script at migrate/ExampleMigration.py.
+
+#### modeler/
+Any modeler plugins distributed with your ZenPack must be located under the
+plugins/ subdirectory. The directory structure and filenames under plugins/
+map directly to the plugins' name in the user interface. For example, if you
+wanted to create a modeler plugin called "community.snmp.ExampleMap" you would
+create the following directory structure.
+
+It is recommended that the first portion of the namespace be a short lowercase
+form of your name, or organization's name. Alternatively you can choose to use
+"community" if you plan to publish the ZenPack and are open to outside
+contributions. Zenoss, Inc. will always use "zenoss." The second portion of the
+namespace can be the protocol that is used to collect the data. If you are not
+using a common protocol it is acceptable to skip the second portion of the
+namespace and have something like "community.MongoDB" instead.
+
+plugins/
+ __init__.py
+ community/
+ __init__.py
+ snmp/
+ __init__.py
+ ExampleMap.py
+
+Note that the __init__.py files must exist and should be empty files. Otherwise
+your modeler plugins won't be imported and usable within Zenoss.
+
+#### objects/
+All .xml files in this objects/ directory will be loaded into the object
+database when the ZenPack installs. All of the objects defined in the XML files
+will be automatically associated with the ZenPack.
+
+When you export the ZenPack from the user interface all objects associated with
+the ZenPack will be exported into a file called "objects.xml" specifically. For
+this reason it is recommended to let Zenoss manage the objects.xml file and to
+never manually create or modify any .xml files in this directory unless you
+know what you're doing.
+
+When a ZenPack is removed, any objects associated with the ZenPack will be
+recursively removed from Zenoss. For example, if you associated the /Server
+device class with your ZenPack and removed the ZenPack, the /Server device
+class, and all devices within it would also be deleted.
+
+When a ZenPack is upgraded, or re-installed on top of itself, all objects in
+the XML files are overlaid on the existing object database. This results in a
+merge of the existing objects and what are defined in the XML files with the
+XML file properties and relationships winning any conflicts.
+
+#### reports/
+Custom reports will be loaded from this directory when the ZenPack is
+installed. Subdirectories (with the exception of plugins/) will be mapped
+directly to the report folders in the web interface. So if you add a .rpt file
+into a subdirectory named "Performance Reports" you will find your report in
+the Performance Reports folder in the web interface after installing the
+ZenPack.
+
+The plugins/ subdirectory should include any Python plugins your custom reports
+call. So if your .rpt file contains a line such as the following..
+
+objects python:here.ReportServer.plugin('myplugin', tableState);
+
+There should be a corresponding myplugin.py file in the plugins/ subdirectory.
+
+You can find an example report at Example Reports/Example Report.rpt.example
+that uses a plugin which can be found at plugins/example_plugin.py.
+
+#### services/
+ZenHub services will be loaded from the services/ directory. These services
+run inside the zenhub daemon and are responsible from all interaction with
+collector daemons.
+
+You can find an example service at services/ExampleConfigService.py.
+
+#### tests/
+All unit tests for your ZenPack should live in this directory. You can find an
+example test suite at tests/testExample.py.
10 ZenPacks.zenoss.RedHatEVM.egg-info/PKG-INFO
@@ -0,0 +1,10 @@
+Metadata-Version: 1.0
+Name: ZenPacks.zenoss.RedHatEVM
+Version: 1.0.0
+Summary: UNKNOWN
+Home-page: UNKNOWN
+Author: UNKNOWN
+Author-email: UNKNOWN
+License: UNKNOWN
+Description: UNKNOWN
+Platform: UNKNOWN
100 ZenPacks.zenoss.RedHatEVM.egg-info/SOURCES.txt
@@ -0,0 +1,100 @@
+MANIFEST.in
+README.txt
+setup.py
+ZenPacks/__init__.py
+ZenPacks/__init__.pyc
+ZenPacks.zenoss.RedHatEVM.egg-info/PKG-INFO
+ZenPacks.zenoss.RedHatEVM.egg-info/SOURCES.txt
+ZenPacks.zenoss.RedHatEVM.egg-info/dependency_links.txt
+ZenPacks.zenoss.RedHatEVM.egg-info/entry_points.txt
+ZenPacks.zenoss.RedHatEVM.egg-info/namespace_packages.txt
+ZenPacks.zenoss.RedHatEVM.egg-info/not-zip-safe
+ZenPacks.zenoss.RedHatEVM.egg-info/requires.txt
+ZenPacks.zenoss.RedHatEVM.egg-info/test_info.txt
+ZenPacks.zenoss.RedHatEVM.egg-info/top_level.txt
+ZenPacks/zenoss/__init__.py
+ZenPacks/zenoss/__init__.pyc
+ZenPacks/zenoss/RedHatEVM/ExampleComponent.py
+ZenPacks/zenoss/RedHatEVM/ExampleComponent.pyc
+ZenPacks/zenoss/RedHatEVM/ExampleComponent.pyo
+ZenPacks/zenoss/RedHatEVM/ExampleDevice.py
+ZenPacks/zenoss/RedHatEVM/ExampleDevice.pyc
+ZenPacks/zenoss/RedHatEVM/ExampleDevice.pyo
+ZenPacks/zenoss/RedHatEVM/__init__.py
+ZenPacks/zenoss/RedHatEVM/__init__.pyc
+ZenPacks/zenoss/RedHatEVM/__init__.pyo
+ZenPacks/zenoss/RedHatEVM/analytics.py
+ZenPacks/zenoss/RedHatEVM/configure.zcml
+ZenPacks/zenoss/RedHatEVM/dynamicview.py
+ZenPacks/zenoss/RedHatEVM/events.py
+ZenPacks/zenoss/RedHatEVM/events.pyc
+ZenPacks/zenoss/RedHatEVM/events.pyo
+ZenPacks/zenoss/RedHatEVM/impact.py
+ZenPacks/zenoss/RedHatEVM/info.py
+ZenPacks/zenoss/RedHatEVM/info.pyc
+ZenPacks/zenoss/RedHatEVM/info.pyo
+ZenPacks/zenoss/RedHatEVM/interfaces.py
+ZenPacks/zenoss/RedHatEVM/interfaces.pyc
+ZenPacks/zenoss/RedHatEVM/interfaces.pyo
+ZenPacks/zenoss/RedHatEVM/zenexample.py
+ZenPacks/zenoss/RedHatEVM/zenexample.pyc
+ZenPacks/zenoss/RedHatEVM/zenexample.pyo
+ZenPacks/zenoss/RedHatEVM/bin/placeholder.txt
+ZenPacks/zenoss/RedHatEVM/browser/__init__.py
+ZenPacks/zenoss/RedHatEVM/browser/__init__.pyc
+ZenPacks/zenoss/RedHatEVM/browser/__init__.pyo
+ZenPacks/zenoss/RedHatEVM/browser/configure.zcml
+ZenPacks/zenoss/RedHatEVM/browser/resources/css/placeholder.txt
+ZenPacks/zenoss/RedHatEVM/browser/resources/img/placeholder.txt
+ZenPacks/zenoss/RedHatEVM/browser/resources/js/ExampleDevice.js
+ZenPacks/zenoss/RedHatEVM/daemons/zenexample
+ZenPacks/zenoss/RedHatEVM/datasources/ExampleDataSource.py.example
+ZenPacks/zenoss/RedHatEVM/datasources/__init__.py
+ZenPacks/zenoss/RedHatEVM/datasources/__init__.pyc
+ZenPacks/zenoss/RedHatEVM/datasources/__init__.pyo
+ZenPacks/zenoss/RedHatEVM/lib/__init__.py
+ZenPacks/zenoss/RedHatEVM/lib/__init__.pyc
+ZenPacks/zenoss/RedHatEVM/lib/__init__.pyo
+ZenPacks/zenoss/RedHatEVM/libexec/placeholder.txt
+ZenPacks/zenoss/RedHatEVM/migrate/ExampleMigration.py
+ZenPacks/zenoss/RedHatEVM/migrate/ExampleMigration.pyc
+ZenPacks/zenoss/RedHatEVM/migrate/ExampleMigration.pyo
+ZenPacks/zenoss/RedHatEVM/migrate/__init__.py
+ZenPacks/zenoss/RedHatEVM/migrate/__init__.pyc
+ZenPacks/zenoss/RedHatEVM/migrate/__init__.pyo
+ZenPacks/zenoss/RedHatEVM/modeler/__init__.py
+ZenPacks/zenoss/RedHatEVM/modeler/__init__.pyc
+ZenPacks/zenoss/RedHatEVM/modeler/__init__.pyo
+ZenPacks/zenoss/RedHatEVM/modeler/plugins/__init__.py
+ZenPacks/zenoss/RedHatEVM/modeler/plugins/__init__.pyc
+ZenPacks/zenoss/RedHatEVM/modeler/plugins/__init__.pyo
+ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/__init__.py
+ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/__init__.pyc
+ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/__init__.pyo
+ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/cmd/ExampleCMD.py.example
+ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/cmd/__init__.py
+ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/cmd/__init__.pyc
+ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/cmd/__init__.pyo
+ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/snmp/ExampleSNMP.py.example
+ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/snmp/__init__.py
+ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/snmp/__init__.pyc
+ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/snmp/__init__.pyo
+ZenPacks/zenoss/RedHatEVM/objects/objects.xml
+ZenPacks/zenoss/RedHatEVM/reports/Example_Reports/Example_Report.rpt.example
+ZenPacks/zenoss/RedHatEVM/reports/plugins/example_plugin.py
+ZenPacks/zenoss/RedHatEVM/reports/plugins/example_plugin.pyc
+ZenPacks/zenoss/RedHatEVM/reports/plugins/example_plugin.pyo
+ZenPacks/zenoss/RedHatEVM/services/ExampleConfigService.py
+ZenPacks/zenoss/RedHatEVM/services/ExampleConfigService.pyc
+ZenPacks/zenoss/RedHatEVM/services/ExampleConfigService.pyo
+ZenPacks/zenoss/RedHatEVM/services/__init__.py
+ZenPacks/zenoss/RedHatEVM/services/__init__.pyc
+ZenPacks/zenoss/RedHatEVM/services/__init__.pyo
+ZenPacks/zenoss/RedHatEVM/tests/__init__.py
+ZenPacks/zenoss/RedHatEVM/tests/__init__.pyc
+ZenPacks/zenoss/RedHatEVM/tests/__init__.pyo
+ZenPacks/zenoss/RedHatEVM/tests/testExample.py
+ZenPacks/zenoss/RedHatEVM/tests/testExample.pyc
+ZenPacks/zenoss/RedHatEVM/tests/testExample.pyo
+ZenPacks/zenoss/RedHatEVM/zep/actions.json.example
+ZenPacks/zenoss/RedHatEVM/zep/zep.json.example
1  ZenPacks.zenoss.RedHatEVM.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
3  ZenPacks.zenoss.RedHatEVM.egg-info/entry_points.txt
@@ -0,0 +1,3 @@
+[zenoss.zenpacks]
+ZenPacks.zenoss.RedHatEVM = ZenPacks.zenoss.RedHatEVM
+
2  ZenPacks.zenoss.RedHatEVM.egg-info/namespace_packages.txt
@@ -0,0 +1,2 @@
+ZenPacks
+ZenPacks.zenoss
1  ZenPacks.zenoss.RedHatEVM.egg-info/not-zip-safe
@@ -0,0 +1 @@
+
1  ZenPacks.zenoss.RedHatEVM.egg-info/requires.txt
@@ -0,0 +1 @@
+ZenPacks.zenoss.Liberator
4 ZenPacks.zenoss.RedHatEVM.egg-info/test_info.txt
@@ -0,0 +1,4 @@
+test_module = None
+test_suite = None
+test_loader = None
+tests_require =
1  ZenPacks.zenoss.RedHatEVM.egg-info/top_level.txt
@@ -0,0 +1 @@
+ZenPacks
1  ZenPacks/__init__.py
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)
BIN  ZenPacks/zenoss/RedHatEVM/.__init__.py.swp
Binary file not shown
13 ZenPacks/zenoss/RedHatEVM/Device.py
@@ -0,0 +1,13 @@
+######################################################################
+#
+# Copyright 2012 Zenoss, Inc. All Rights Reserved.
+#
+######################################################################
+
+from Products.ZenModel.Device import Device as BaseDevice
+from Products.ZenRelations.RelSchema import ToManyCont, ToOne
+
+
+class Device(BaseDevice):
+ meta_type = portal_type = 'Device'
+
25 ZenPacks/zenoss/RedHatEVM/__init__.py
@@ -0,0 +1,25 @@
+######################################################################
+#
+# Copyright 2012 Zenoss, Inc. All Rights Reserved.
+#
+######################################################################
+
+import Globals
+
+from Products.ZenModel.ZenPack import ZenPack as ZenPackBase
+from Products.ZenUtils.Utils import unused
+
+unused(Globals)
+
+
+class ZenPack(ZenPackBase):
+
+ packZProperties = [
+ ('zOvirtServerName', '', 'string'),
+ ('zOVirtUser', 'admin', 'string'),
+ ('zOVirtPassword', '', 'password'),
+ ('zOVirtDomain', 'internal', 'string'),
+ ('zOVirtPort', 8080, 'int'),
+ #('zOVirtProtocol', 'http', 'string'),
+ ]
+
31 ZenPacks/zenoss/RedHatEVM/analytics.py
@@ -0,0 +1,31 @@
+from zope.component import adapts
+from zope.interface import implements
+
+from Products.Zuul.interfaces import IReportable
+
+from ZenPacks.zenoss.ZenETL.reportable \
+ import Reportable, MARKER_LENGTH, DEFAULT_STRING_LENGTH
+
+from .ExampleComponent import ExampleComponent
+
+
+class ExampleComponentReportable(Reportable):
+ implements(IReportable)
+ adapts(ExampleComponent)
+
+ @property
+ def entity_class_name(self):
+ return 'example_component'
+
+ def reportProperties(self):
+ """
+ We want to export our two custom properties to the data warehouse for
+ reporting.
+ """
+ return [
+ ('attributeOne', 'int',
+ self.context.attribuetOne, MARKER_LENGTH),
+
+ ('attributeTwo', 'string',
+ self.context.attributeTwo, DEFAULT_STRING_LENGTH),
+ ]
0  ZenPacks/zenoss/RedHatEVM/bin/placeholder.txt
No changes.
0  ZenPacks/zenoss/RedHatEVM/browser/__init__.py
No changes.
23 ZenPacks/zenoss/RedHatEVM/browser/configure.zcml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configure xmlns="http://namespaces.zope.org/browser">
+
+ <!-- A resource directory contains static web content.
+ <resourceDirectory
+ name="example"
+ directory="resources"
+ />
+ -->
+
+ <!-- Register custom JavaScript for ExampleDevices.
+ <viewlet
+ name="js-exampledevice"
+ paths="/++resource++example/js/ExampleDevice.js"
+ weight="10"
+ for="..ExampleDevice.ExampleDevice"
+ manager="Products.ZenUI3.browser.interfaces.IJavaScriptSrcManager"
+ class="Products.ZenUI3.browser.javascript.JavaScriptSrcBundleViewlet"
+ permission="zope2.Public"
+ />
+ -->
+
+</configure>
0  ZenPacks/zenoss/RedHatEVM/browser/resources/css/placeholder.txt
No changes.
0  ZenPacks/zenoss/RedHatEVM/browser/resources/img/placeholder.txt
No changes.
81 ZenPacks/zenoss/RedHatEVM/browser/resources/js/ExampleDevice.js
@@ -0,0 +1,81 @@
+/*
+ * Based on the configuration in ../../configure.zcml this JavaScript will only
+ * be loaded when the user is looking at an ExampleDevice in the web interface.
+ */
+
+(function(){
+
+var ZC = Ext.ns('Zenoss.component');
+
+
+/*
+ * Friendly names for the components. First parameter is the meta_type in your
+ * custom component class. Second parameter is the singular form of the
+ * friendly name to be displayed in the UI. Third parameter is the plural form.
+ */
+ZC.registerName('ExampleComponent', _t('Example'), _t('Examples'));
+
+
+/*
+ * Custom component grid panel. This controls the grid that gets displayed for
+ * components of the type set in "componenType".
+ */
+ZC.ExampleComponentGridPanel = Ext.extend(ZC.ComponentGridPanel, {
+ subComponentGridPanel: false,
+
+ constructor: function(config) {
+ config = Ext.applyIf(config||{}, {
+ autoExpandColumn: 'name',
+ componentType: 'ExampleComponent',
+ sortInfo: {
+ field: 'name',
+ direction: 'ASC'
+ },
+ fields: [
+ {name: 'uid'},
+ {name: 'name'},
+ {name: 'severity'},
+ {name: 'attributeOne'},
+ {name: 'attributeTwo'},
+ {name: 'monitor'},
+ {name: 'monitored'}
+ ],
+ columns: [{
+ id: 'severity',
+ dataIndex: 'severity',
+ header: _t('Events'),
+ renderer: Zenoss.render.severity,
+ sortable: true,
+ width: 50
+ },{
+ id: 'name',
+ dataIndex: 'name',
+ header: _t('Name')
+ },{
+ id: 'attributeOne',
+ dataIndex: 'attributeOne',
+ header: _t('Attribute #1'),
+ sortable: true,
+ width: 70
+ },{
+ id: 'attributeTwo',
+ dataIndex: 'attributeTwo',
+ header: _t('Attribute #2'),
+ sortable: true,
+ width: 70
+ },{
+ id: 'monitored',
+ dataIndex: 'monitored',
+ header: _t('Monitored'),
+ renderer: Zenoss.render.checkbox,
+ sortable: true,
+ width: 65
+ }]
+ });
+ ZC.ExampleComponentGridPanel.superclass.constructor.call(this, config);
+ }
+});
+
+Ext.reg('ExampleComponentGridPanel', ZC.ExampleComponentGridPanel);
+
+})();
0  ZenPacks/zenoss/RedHatEVM/componenttypes/__init__.py
No changes.
3  ZenPacks/zenoss/RedHatEVM/componenttypes/configure.zcml
@@ -0,0 +1,3 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+ <include package=".ovirt"/>
+</configure>
107 ZenPacks/zenoss/RedHatEVM/componenttypes/ovirt/CollectionTask.py
@@ -0,0 +1,107 @@
+######################################################################
+#
+# Copyright 2012 Zenoss, Inc. All Rights Reserved.
+#
+######################################################################
+
+import logging
+from time import time
+from httplib import HTTPConnection, HTTPSConnection
+
+
+from twisted.internet import defer
+
+
+from zope.interface import implements
+
+from Products.ZenCollector.tasks import TaskStates
+
+from ZenPacks.zenoss.Liberator.zengenericmodeler import GenericModelerCollectionTask
+from ZenPacks.zenoss.Liberator.interfaces import IGenericCollectionTask
+
+COLLECTOR_NAME = "zengenericmodeler"
+TASK_NAME = "OVirtCollectionTask"
+
+log = logging.getLogger("zen.%s.%s" % (COLLECTOR_NAME, TASK_NAME))
+
+
+class CollectionTask(object):
+ implements(IGenericCollectionTask)
+
+ STATE_FETCH_MODEL = 'FETCH_MODEL_DATA'
+ STATE_PROCESS_MODEL = 'FETCH_PROCESS_MODEL_DATA'
+
+ def __init__(self, device):
+ self._device = device
+ self._manageIp = self._device.manageIp
+
+ self._serverName = device.zOvirtServerName
+ self._port = int(device.zOvirtPort)
+
+ creds = '%s@%s:%s' % (device.zOVirtUser, device.zOVirtDomain, device.zOVirtPassword)
+ creds = creds.encode('Base64').strip('\r\n')
+ self._headers = {
+ 'Authorization': 'Basic %s' % creds,
+ 'Accept': 'application/xml'
+ }
+ self._baseUrl = '/api/'
+
+ def doTask(self, parentTask, plugins):
+ self._parent = parentTask
+ self._parent.state = TaskStates.STATE_IDLE
+
+ self._plugins = plugins
+
+ self._tabledata = {}
+
+ # Used for nicer reporting
+ self._parent._lastCollectionTime = None
+ self._parent._startTime = None
+ self._parent._finishTime = None
+
+ self._parent._startTime = time()
+ d = self._collect()
+ return d
+
+ def _collect(self, result):
+ self._parent.state = GenericModelerCollectionTask.STATE_FETCH_MODEL
+ deferreds = []
+ for plugin in self._plugins:
+ url = plugin.compdef.virtualElement
+ log.debug("Collecting %s from %s", url, self._device.id)
+ self._tabledata[plugin] = {}
+ d = defer.maybeDeferred(self._httpGet, url)
+ d.addCallback(self._processResponse, plugin)
+ d.addErrback(self._getError, plugin)
+ deferreds.append(d)
+ dl = defer.DeferredList(deferreds)
+ dl.addCallback(self.clientFinished)
+
+ return dl
+
+ def _httpGet(self, url):
+ """
+ Open a HTTP connection to grab the information about a component and return the response.
+ """
+ conn = HTTPConnection(self._serverName, port=self._port)
+ conn.request('GET', self._baseUrl + url, headers=self._headers)
+ resp = conn.getresponse()
+ body = resp.read()
+ return body
+
+ def _processResponse(self, result, plugin):
+ log.debug("Processing response for %s", plugin.compdef.virtualElement)
+ self._tabledata[plugin] = result
+
+ def _getError(self, result, plugin):
+ log.warn("Error requesting URL for %s: %s", plugin.compdef.virtualElemen, result)
+
+ def clientFinished(self, result):
+ return self._parent.processResults(self.getResults())
+
+ def getResults(self):
+ data = {}
+ for plugin in self._plugins:
+ data[plugin] = ({}, self._tabledata.get(plugin, {}))
+ return data
+
95 ZenPacks/zenoss/RedHatEVM/componenttypes/ovirt/ComponentDefinition.py
@@ -0,0 +1,95 @@
+######################################################################
+#
+# Copyright 2012 Zenoss, Inc. All Rights Reserved.
+#
+######################################################################
+
+import logging
+
+from zope.interface import implements
+
+from Products.ZenModel.ZenModelRM import ZenModelRM
+
+from Products.ZenModel.BasicDataSource import BasicDataSource
+from ZenPacks.zenoss.Liberator.GenericComponentManager import (
+ GenericComponentDefinition, BadXmlDefinitionFileException)
+from ZenPacks.zenoss.Liberator.interfaces import IGenericComponentDefinition
+from .interfaces import IOVirtGenericComponentInfo
+
+log = logging.getLogger("zen.liberator.OVirtComponentDefinition")
+
+
+class ComponentDefinition(GenericComponentDefinition):
+ implements(IGenericComponentDefinition)
+
+ definition_type = "ovirt"
+ iinfoClass = IOVirtGenericComponentInfo
+
+ virtualElement = ''
+
+ _properties = GenericComponentDefinition._properties + (
+ {'id':'virtualElement', 'type':'string', 'mode':'rw'},
+ )
+
+ def parseNode(self, componentNode):
+ self.virtualElement = componentNode.get('virtualElement')
+
+ docNode = componentNode.find("documentation")
+ if docNode:
+ self.documentation = docNode.text
+ self.documentationType = docNode.get('type', '')
+
+ for tableNode in componentNode.findall("table"):
+ tableId = tableNode.get("id")
+ if not tableId:
+ msg = "The id attribute is not defined on table element (line %d)" % tableNode.lineno
+ raise BadXmlDefinitionFileException(msg)
+ table = self.getOrAdd(self, GenericComponentTableDefinition, tableId)
+ table.parseNode(tableNode)
+
+ def addDataPoint(self, template, perfNode):
+ perfId = perfNode.get("name")
+ if not perfId:
+ msg = "The name attribute is not defined on perf element (line %d)" % perfNode.lineno
+ raise BadXmlDefinitionFileException(msg)
+
+ ds = getattr(template.datasources, perfId, None)
+ if ds is None or not isinstance(ds,BasicDataSource):
+ ds = template.manage_addRRDDataSource(perfId, dsOption='BasicDataSource.Command')
+ dp = getattr(ds.datapoints, perfId, None)
+ if dp is None:
+ dp = ds.manage_addRRDDataPoint(id=perfId)
+ dp.rrdtype = perfNode.get("rrdType", "GAUGE")
+
+ if not dp.description:
+ # NB: This will not be viewable directly in the 3.x UI
+ # Look for a 'description' element in the XML first
+ desc = perfNode.get("description")
+ ds.description = desc
+ dp.description = desc
+
+ return dp
+
+ def getTableMaps(self):
+ components = [table.getTableMap() for table in self.objectValues("GenericComponentTableDefinition")]
+ subcomponents = [subcomp.getTableMaps() for subcomp in self.objectValues("GenericComponentDefinition")]
+ # sum(someListOfLists, []) -> flattens list of lists
+ return components + sum(subcomponents, [])
+
+ def validate(self, componentNode):
+ super(ComponentDefinition, self).validate(componentNode)
+
+
+class GenericComponentTableDefinition(ZenModelRM):
+ meta_type = "GenericComponentTableDefinition"
+ columns = []
+
+ def parseNode(self, tableNode):
+ self.columns = []
+ for column in tableNode.findall("column"):
+ self.columns.append(column.get("id"))
+
+ def getTableMap(self):
+ columns = {}
+ return self.id, columns
+
47 ZenPacks/zenoss/RedHatEVM/componenttypes/ovirt/DeviceProxyConfig.py
@@ -0,0 +1,47 @@
+######################################################################
+#
+# Copyright 2012 Zenoss, Inc. All Rights Reserved.
+#
+######################################################################
+
+from zope.interface import implements
+
+from Products.ZenHub.services.PerformanceConfig import ATTRIBUTES
+
+from ZenPacks.zenoss.Liberator.DeviceProxyConfig import DeviceProxyConfig
+from ZenPacks.zenoss.Liberator.interfaces import IDeviceProxyConfig
+
+
+class DeviceProxyConfig(DeviceProxyConfig):
+ implements(IDeviceProxyConfig)
+
+ attributes = ATTRIBUTES + (
+ 'zOvirtServerName', 'zOVirtPort',
+ 'zOVirtUser', 'zOVirtDomain', 'zOVirtPassword',
+ )
+
+ def filter(self, device):
+ include = True
+
+ if not getattr(device, 'zOvirtServerName', '').strip():
+ self.log.debug("Device %s skipped by Liberator (ovirt) because zOvirtServerName is not set.",
+ device.id)
+ include = False
+
+ if not getattr(device, 'zOVirtUser', '').strip():
+ self.log.debug("Device %s skipped by Liberator (ovirt) because zOVirtUser is not set.",
+ device.id)
+ include = False
+
+ if not getattr(device, 'zOVirtDomain', '').strip():
+ self.log.debug("Device %s skipped by Liberator (ovirt) because zOVirtDomain is not set.",
+ device.id)
+ include = False
+
+ if not getattr(device, 'zOVirtPassword', '').strip():
+ self.log.debug("Device %s skipped by Liberator (ovirt) because zOVirtPassword is not set.",
+ device.id)
+ include = False
+
+ return include
+
90 ZenPacks/zenoss/RedHatEVM/componenttypes/ovirt/ModelerPlugin.py
@@ -0,0 +1,90 @@
+######################################################################
+#
+# Copyright 2012 Zenoss, Inc. All Rights Reserved.
+#
+######################################################################
+
+__doc__ = """OvirtModelerPlugin
+Performs modeling of oVirt compatible systems.
+"""
+
+from string import Template
+from xml.etree import ElementTree
+
+from zope.interface import implements
+
+from Products.DataCollector.plugins.CollectorPlugin import PythonPlugin
+
+from ZenPacks.zenoss.Liberator.GenericModelerPlugin import GenericModelerPlugin
+from ZenPacks.zenoss.Liberator.interfaces import IGenericModelerPlugin
+from ZenPacks.zenoss.Liberator.TableHelper import TableSet
+
+
+class ModelerPlugin(GenericModelerPlugin, PythonPlugin):
+ implements(IGenericModelerPlugin)
+
+ def process(self, device, results, log):
+ log.debug("Results for %s/%s: %s", self.name(), device.id, results)
+
+ doc = ElementTree.fromstring(results)
+
+ tables = TableSet(tabledata)
+
+ relmaps = self.processComponent(tables, self.compdef, log)
+
+ log.debug(repr(relmaps))
+ return relmaps
+
+ def processComponent(self, tables, compdef, log):
+ def makeId(row):
+ return compdef.id + "_" + self.prepId(row[compdef.idField])
+ rm = self.relMap()
+
+ # Iterate over each row in the primary table
+ for row in tables.query("/" + compdef.primaryTable + "/snmpindex").values():
+ # Setup the object map
+ om = self.objectMap()
+ om.snmpindex = row['snmpindex']
+ om.title = str(row[compdef.idField])
+ om.id = makeId(row)
+ om.meta_type = "GenericComponent_" + compdef.id
+ om.component_type = compdef.id
+ om.setAttributes = {}
+ if compdef.parentRelation:
+ parentQuery = Template(compdef.parentRelation).substitute(row)
+ parentRow = tables.query(parentQuery)
+ if not parentRow:
+ log.warn("Found possible subcomponent at %s/%s, but could not find a parent.",
+ compdef.primaryTable, row['snmpindex'])
+ continue
+ om.parentSnmpindex = parentRow['snmpindex']
+ om.modname = "ZenPacks.zenoss.Liberator.GenericSubcomponent"
+
+ # These are the attribute tags defined in the component XML
+ for attribute in compdef.attributes:
+ query = attribute.get("valueQuery", None)
+ value = None
+ if query:
+ query = Template(query).substitute(row)
+ value = tables.query(query)
+ else:
+ value = row.get(attribute['id'], None)
+ om.setAttributes[attribute['id']] = value
+ log.info("Found %s: %s", compdef.id, om.title)
+ rm.append(om)
+
+ sorted_subcomp_relmaps = {}
+ for subcompdef in compdef.subcomponents:
+ subcomp_relmaps = self.processComponent(tables, subcompdef, log)
+ for subcomp_relmap in subcomp_relmaps:
+ for subcomp_objmap in subcomp_relmap:
+ parentRow = tables.query("python:%s['snmpindex']['%s']" % (compdef.primaryTable, subcomp_objmap.parentSnmpindex))
+ subcomp_objmap.compname = "genericComponents/" + makeId(parentRow)
+ sorted_subcomp_relmaps.setdefault(subcomp_objmap.compname, RelationshipMap(
+ compname=subcomp_objmap.compname,
+ relname="subcomponents",
+ modname="ZenPacks.zenoss.Liberator.GenericSubcomponent")).append(subcomp_objmap)
+ relmaps = [rm]
+ relmaps.extend(sorted_subcomp_relmaps.values())
+ return relmaps
+
23 ZenPacks/zenoss/RedHatEVM/componenttypes/ovirt/ServiceConfig.py
@@ -0,0 +1,23 @@
+######################################################################
+#
+# Copyright 2012 Zenoss, Inc. All Rights Reserved.
+#
+######################################################################
+
+from twisted.spread import pb
+
+from zope.interface import implements
+
+from ZenPacks.zenoss.Liberator.services.LiberatorService import ComponentConfig
+from ZenPacks.zenoss.Liberator.interfaces import IGenericServiceConfig
+
+
+class ServiceConfig(pb.Copyable, pb.RemoteCopy, ComponentConfig):
+ implements(IGenericServiceConfig)
+
+ def __init__(self, component):
+ ComponentConfig.__init__(self, component)
+ self.virtualElement = component.virtualElement
+
+pb.setUnjellyableForClass(ServiceConfig, ServiceConfig)
+
0  ZenPacks/zenoss/RedHatEVM/componenttypes/ovirt/__init__.py
No changes.
35 ZenPacks/zenoss/RedHatEVM/componenttypes/ovirt/configure.zcml
@@ -0,0 +1,35 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+
+ <adapter
+ factory=".ComponentDefinition.ComponentDefinition"
+ provides="ZenPacks.zenoss.Liberator.interfaces.IGenericComponentDefinition"
+ for="*"
+ name="snmp"/>
+
+ <adapter
+ factory=".ModelerPlugin.ModelerPlugin"
+ provides="ZenPacks.zenoss.Liberator.interfaces.IGenericModelerPlugin"
+ for=".ServiceConfig.ServiceConfig"/>
+
+ <adapter
+ factory=".CollectionTask.CollectionTask"
+ provides="ZenPacks.zenoss.Liberator.interfaces.IGenericCollectionTask"
+ for="Products.ZenCollector.services.config.DeviceProxy"
+ name="ovirt"/>
+
+ <adapter
+ factory=".ServiceConfig.ServiceConfig"
+ provides="ZenPacks.zenoss.Liberator.interfaces.IGenericServiceConfig"
+ for=".ComponentDefinition.ComponentDefinition"/>
+
+ <subscriber
+ provides="ZenPacks.zenoss.Liberator.interfaces.IDeviceProxyConfig"
+ factory=".DeviceProxyConfig.DeviceProxyConfig"
+ for="Products.ZenModel.Device.Device"/>
+
+ <adapter provides=".interfaces.IOvirtGenericComponentInfo"
+ for="ZenPacks.zenoss.Liberator.GenericComponent.GenericComponent"
+ factory=".info.OvirtGenericComponentInfo"
+ />
+
+</configure>
18 ZenPacks/zenoss/RedHatEVM/componenttypes/ovirt/info.py
@@ -0,0 +1,18 @@
+######################################################################
+#
+# Copyright 2012 Zenoss, Inc. All Rights Reserved.
+#
+######################################################################
+
+import logging
+log = logging.getLogger("zen.GenericComponentInfo")
+
+from Products.Zuul.infos import ProxyProperty
+
+
+class OvirtGenericComponentInfo(object):
+
+ def __init__(self, obj):
+ super(OvirtGenericComponentInfo, self).__init__()
+ self._object = obj
+
14 ZenPacks/zenoss/RedHatEVM/componenttypes/ovirt/interfaces.py
@@ -0,0 +1,14 @@
+######################################################################
+#
+# Copyright 2012 Zenoss, Inc. All Rights Reserved.
+#
+######################################################################
+
+from zope.interface import Interface
+from Products.Zuul.form import schema
+from Products.Zuul.utils import ZuulMessageFactory as _t
+
+
+class IOvirtGenericComponentInfo(Interface):
+ pass
+
191 ZenPacks/zenoss/RedHatEVM/configure.zcml
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:zcml="http://namespaces.zope.org/zcml">
+
+
+ <!-- Includes: Browser Configuration -->
+ <include package=".browser"/>
+
+
+ <!-- Info Adapters: DataSources
+
+ For ZenPacks that add new datasource types you must register their Info
+ adapter(s). The info adapters provide the API that the web interface needs
+ to show information about each instance of your datasource type that is
+ created. The info adapters are also used to set the properties of the
+ datasource instances.
+
+ <adapter
+ provides=".interfaces.IExampleDataSourceInfo"
+ for=".datasources.ExampleDataSource.ExampleDataSource"
+ factory=".info.ExampleDataSourceInfo"
+ />
+ -->
+
+
+ <!-- Event Plugins
+
+ These are useful when you want to manipulate events in a more bullet-proof
+ way than standard transforms allow. Users won't be able to change your
+ plugin code through the user interface like they could with transforms. You
+ can also more easily unit test these plugins than you can test transforms.
+
+ You can either register a preEventPlugin or a postEventPlugin.
+ preEventPlugins will be executed before any event processing is done. This
+ means that no tagging or enrichment of the event will be done. This is a
+ useful approach for early-dropping events you don't want to waste time
+ processing.
+
+ postEventPlugins will be executed after all normal event processing is
+ done. This is useful in circumstances where you need access to the tags and
+ other enrichment done during normal event processing in your plugin.
+
+ Using zcml:condition="have eventPlugins" will cause your plugins only to be
+ registered if the installed Zenoss versions supports them. Support
+ for eventPlugins was added in Zenoss 4.
+
+ See events.py for the plugin implementations.
+
+ <configure zcml:condition="have eventPlugins">
+ <preEventPlugin plugin=".events.ExamplePreEventPlugin">
+ <postEventPlugin plugin=".events.ExamplePostEventPlugin">
+ </configure>
+ -->
+
+
+ <!-- Dynamic View Adapters
+
+ Dynamic View adapters are how Zenoss shows relationships between objects in
+ the "Dynamic View" screens in the user interface. This capability was
+ introduced in Zenoss 3.0, but only in the commercial version. It is
+ recommended to enclose all Dynamic View configuration in a conditional as
+ shown below so the ZenPack will work in all Zenoss systems.
+
+ See dynamicview.py for the adapter implementations.
+
+ <configure zcml:condition="installed ZenPacks.zenoss.DynamicView">
+ <include package="ZenPacks.zenoss.DynamicView" file="meta.zcml"/>
+
+ <adapter
+ provides="ZenPacks.zenoss.DynamicView.interfaces.IRelatable"
+ for=".ExampleComponent.ExampleComponent"
+ factory=".dynamicView.ExampleComponentRelatable"
+ />
+
+ <subscriber
+ provides="ZenPacks.zenoss.DynamicView.interfaces.IRelationsProvider"
+ for="..ExampleDevice.ExampleDevice"
+ factory=".dynamicView.ExampleDeviceRelationsProvider"
+ />
+
+ <subscriber
+ provides="ZenPacks.zenoss.DynamicView.interfaces.IRelationsProvider"
+ for="..ExampleComponent.ExampleComponent"
+ factory=".dynamicView.ExampleComponentRelationsProvider"
+ />
+
+ <relatableGroup
+ name="Example Components"
+ groupType="example"
+ icon="/++resource++example/img/exampleComponent.png"
+ weight="35"
+ />
+
+ <dynamicViewToGroup
+ view="service_view"
+ group="Example Components"
+ weight="550"
+ />
+
+ <dynamicViewToGroup
+ view="component_view"
+ group="Example Components"
+ weight="215"
+ />
+
+ </configure>
+ -->
+
+
+ <!-- Impact Adapters
+
+ Impact adapters are much like the Dynamic View adapters above in that they
+ define relationships between objects. However, they are specifically for
+ controlling the "Zenoss Datacenter Impact" product and can be simpler to
+ configure because visualization is built-in and you only need to concern
+ yourself with defining edges (or relationships) between objects.
+
+ This section should be wrapped in a conditional so your ZenPack will work
+ whether or not Zenoss Datacenter Impact is installed.
+
+ IRelationshipDataProvider works much like the Dynamic View
+ IRelationsProvider above. It defines dependency relationships between
+ objects.
+
+ IStateProvider providers allow you to change how state is calculated for
+ certain types of objects. Normally only the events impacting an object are
+ used to calculate its state. IStateProvider allows you to bring in
+ information from other sources such as the model.
+
+ INodeTrigger providers allow you to define what triggers should be
+ configured for certain types of objects automatically. A good example of
+ where you'd use this is for port-channel interfaces. You'd likely want to
+ create impact edges to all of the member interfaces and setup a redundancy
+ policy on the port-channel.
+
+ See impact.py for the subscriber implementations.
+
+ <configure zcml:condition="installed ZenPacks.zenoss.Impact">
+ <include package="ZenPacks.zenoss.Impact" file="meta.zcml"/>
+
+ <subscriber
+ provides="ZenPacks.zenoss.Impact.impactd.interfaces.IRelationshipDataProvider"
+ for=".ExampleDevice.ExampleDevice"
+ factory=".impact.ExampleDeviceRelationsProvider"
+ />
+
+ <subscriber
+ provides="ZenPacks.zenoss.Impact.impactd.interfaces.IRelationshipDataProvider"
+ for=".ExampleComponent.ExampleComponent"
+ factory=".impact.ExampleComponentRelationsProvider"
+ />
+
+ <subscriber
+ provides="ZenPacks.zenoss.Impact.stated.interfaces.IStateProvider"
+ for=".ExampleComponent.ExampleComponent"
+ factory=".impact.ExampleComponentStateProvider"
+ />
+
+ <subscriber
+ provides="ZenPacks.zenoss.Impact.impactd.interfaces.INodeTriggers"
+ for=".ExampleComponent.ExampleComponent"
+ factory=".impact.ExampleComponentTriggers"
+ />
+
+ </configure>
+ -->
+
+
+ <!-- Analytics Adapters
+
+ The analytics subscribers and adapters are used to control the ETL
+ (extract, transform and load) process from Zenoss into the data warehouse
+ of the Zenoss Analytics product. It is recommended to enclose all analytics
+ adapters in a conditional block because Analytics may or may not be
+ installed.
+
+ See analytics.py for the subscriber implementations.
+
+ <configure zcml:condition="installed ZenPacks.zenoss.ZenETL">
+ <adapter
+ provides="Products.Zuul.interfaces.IReportable"
+ for=".ExampleComponent.ExampleComponent"
+ factory=".analytics.ExampleComponentReportable"
+ />
+
+ </configure>
+ -->
+
+</configure>
+
16 ZenPacks/zenoss/RedHatEVM/daemons/zenexample
@@ -0,0 +1,16 @@
+#! /usr/bin/env bash
+
+# You must change the name of your daemon to something other than zenexample.
+# The "zenexample" name is special and will be ignored by the ZenPack
+# installation routine.
+DAEMON_NAME="zenexample"
+
+. $ZENHOME/bin/zenfunctions
+
+MYPATH=`python -c "import os.path; print os.path.realpath('$0')"`
+THISDIR=`dirname $MYPATH`
+PRGHOME=`dirname $THISDIR`
+PRGNAME=$DAEMON_NAME.py
+CFGFILE=$CFGDIR/$DAEMON_NAME.conf
+
+generic "$@"
37 ZenPacks/zenoss/RedHatEVM/datasources/ExampleDataSource.py.example
@@ -0,0 +1,37 @@
+# Creating a custom datasource type requires defining a subclass of
+# Products.ZenModel.RRDDataSource.RRDDataSource as illustrated below. This
+# class gets instantiated, configured and stored in the ZODB everytime someone
+# adds this type of datasource to a template.
+
+# You will also need to add an IRRDDataSourceInfo subinterface to control how
+# the user interface for configuring this datasource is drawn. This interface
+# is typically defined in ../interfaces.py. You will then need to define a
+# RRDDataSourceInfo subclass to control how your datasource gets serialized
+# for passing through the API. This info adapter class is typically defined in
+# ../info.py.
+
+from Products.ZenModel.RRDDataSource import RRDDataSource
+from Products.ZenModel.ZenPackPersistence import ZenPackPersistence
+
+
+class ExampleDataSource(ZenPackPersistence, RRDDataSource):
+
+ # All subclasses of ZenPackPersistence need to set their ZENPACKID.
+ ZENPACKID = 'ZenPacks.NAMESPACE.PACKNAME'
+
+ # These define how this datasource type is displayed in the datasource type
+ # picker when adding a new datasource to a monitoring template. Keep it
+ # short and unambiguous.
+ sourcetypes = ('Example Protocol',)
+ sourcetype = sourcetypes[0]
+
+ # Set default values for properties inherited from RRDDataSource.
+ eventClass = '/Status/Example'
+ component = "${here/id}"
+
+ # Add default values for custom properties of this datasource.
+ exampleProperty = ''
+
+ _properties = RRDDataSource._properties + (
+ {'id': 'exampleProperty', 'type': 'string'},
+ )
2  ZenPacks/zenoss/RedHatEVM/datasources/__init__.py
@@ -0,0 +1,2 @@
+# __init__.py
+
42 ZenPacks/zenoss/RedHatEVM/dynamicview.py
@@ -0,0 +1,42 @@
+from zope.component import adapts
+
+from ZenPacks.zenoss.DynamicView import TAG_IMPACTED_BY, TAG_IMPACTS, TAG_ALL
+from ZenPacks.zenoss.DynamicView.model.adapters import DeviceComponentRelatable
+from ZenPacks.zenoss.DynamicView.model.adapters import BaseRelationsProvider
+
+from ..ExampleDevice import ExampleDevice
+from ..ExampleComponent import ExampleComponent
+
+
+### IRelatable Adapters
+
+class ExampleComponentRelatable(DeviceComponentRelatable):
+ adapts(ExampleComponent)
+
+ group = 'Example Components'
+
+
+### IRelationsProvider Adapters
+
+class ExampleDeviceRelationsProvider(BaseRelationsProvider):
+ adapts(ExampleDevice)
+
+ def relations(self, type=TAG_ALL):
+ """
+ ExampleDevices impact all of their ExampleComponents.
+ """
+ if type in (TAG_ALL, TAG_IMPACTS):
+ for exampleComponent in self._adapted.exampleComponents():
+ yield self.constructRelationTo(exampleComponent, TAG_IMPACTS)
+
+
+class ExampleComponentRelationsProvider(BaseRelationsProvider):
+ adapts(ExampleComponent)
+
+ def relations(self, type=TAG_ALL):
+ """
+ ExampleComponents are impacted by their ExampleDevice.
+ """
+ if type in (TAG_ALL, TAG_IMPACTED_BY):
+ yield self.constructRelationTo(
+ self._adapted.exampleDevice(), TAG_IMPACTED_BY)
16 ZenPacks/zenoss/RedHatEVM/events.py
@@ -0,0 +1,16 @@
+class ExamplePreEventPlugin(object):
+ def apply(self, eventProxy, dmd):
+ event = eventProxy._zepRawEvent.event
+
+ # Do something to the event. Any changes made to the event object will
+ # be saved to it. You should not return anything from this method.
+ event.summary = 'ExamplePreEventPlugin changed the summary'
+
+
+class ExamplePostEventPlugin(object):
+ def apply(self, eventProxy, dmd):
+ event = eventProxy._zepRawEvent.event
+
+ # Do something to the event. Any changes made to the event object will
+ # be saved to it. You should not return anything from this method.
+ event.summary = 'ExamplePostEventPlugin changed the summary'
132 ZenPacks/zenoss/RedHatEVM/impact.py
@@ -0,0 +1,132 @@
+from zope.component import adapts
+from zope.interface import implements
+
+from Products.ZenUtils.guid.interfaces import IGlobalIdentifier
+
+from ZenPacks.zenoss.Impact.impactd import Trigger
+from ZenPacks.zenoss.Impact.stated.interfaces import IStateProvider
+from ZenPacks.zenoss.Impact.impactd.relations import ImpactEdge
+from ZenPacks.zenoss.Impact.impactd.interfaces \
+ import IRelationshipDataProvider, INodeTriggers
+
+from .ExampleDevice import ExampleDevice
+from .ExampleComponent import ExampleComponent
+
+
+def getRedundancyTriggers(guid, format):
+ """
+ Helper method for generating a good general redunancy set of triggers.
+ """
+
+ availability = 'AVAILABILITY'
+ percent = 'policyPercentageTrigger'
+ threshold = 'policyThresholdTrigger'
+
+ return (
+ Trigger(guid, format % 'DOWN', percent, availability, dict(
+ state='DOWN', dependentState='DOWN', threshold='100',
+ )),
+ Trigger(guid, format % 'DEGRADED', threshold, availability, dict(
+ state='DEGRADED', dependentState='DEGRADED', threshold='1',
+ )),
+ Trigger(guid, format % 'ATRISK_1', threshold, availability, dict(
+ state='ATRISK', dependentState='DOWN', threshold='1',
+ )),
+ Trigger(guid, format % 'ATRISK_2', threshold, availability, dict(
+ state='ATRISK', dependentState='ATRISK', threshold='1',
+ )),
+ )
+
+
+class ExampleDeviceRelationsProvider(object):
+ implements(IRelationshipDataProvider)
+ adapts(ExampleDevice)
+
+ relationship_provider = "ExampleImpact"
+
+ def __init__(self, adapted):
+ self._object = adapted
+
+ def belongsInImpactGraph(self):
+ return True
+
+ def getEdges(self):
+ """
+ An ExampleDevice impacts all of its ExampleComponents.
+ """
+ guid = IGlobalIdentifier(self._object).getGUID()
+
+ for exampleComponent in self._object.exampleComponents():
+ c_guid = IGlobalIdentifier(exampleComponent).getGUID()
+ yield ImpactEdge(guid, c_guid, self.relationship_provider)
+
+
+class ExampleComponentRelationsProvider(object):
+ implements(IRelationshipDataProvider)
+ adapts(ExampleComponent)
+
+ relationship_provider = "ExampleImpact"
+
+ def __init__(self, adapted):
+ self._object = adapted
+
+ def belongsInImpactGraph(self):
+ return True
+
+ def getEdges(self):
+ """
+ An ExampleComponent is impacted by its ExampleDevice.
+ """
+ guid = IGlobalIdentifier(self._object).getGUID()
+
+ d_guid = IGlobalIdentifier(self._object.exampleDevice())
+ yield ImpactEdge(d_guid, guid, self.relationship_provider)
+
+
+class ExampleComponentStateProvider(object):
+ implements(IStateProvider)
+
+ def __init__(self, adapted):
+ self._object = adapted
+
+ @property
+ def eventClasses(self):
+ return ('/Status/',)
+
+ @property
+ def excludeClasses(self):
+ return None
+
+ @property
+ def eventHandlerType(self):
+ return "WORST"
+
+ @property
+ def stateType(self):
+ return 'AVAILABILITY'
+
+ def calcState(self, events):
+ status = None
+ if self._object.attributeOne < 1:
+ return 'DOWN'
+ else:
+ return 'UP'
+
+ cause = None
+ if status == 'DOWN' and events:
+ cause = events[0]
+
+ return status, cause
+
+
+class ExampleComponentTriggers(object):
+ implements(INodeTriggers)
+
+ def __init__(self, adapted):
+ self._object = adapted
+
+ def get_triggers(self):
+ return getRedundancyTriggers(
+ IGlobalIdentifier(self._object).getGUID(),
+ 'DEFAULT_EXAMPLECOMPONENT_TRIGGER_ID_%s',
+ )
53 ZenPacks/zenoss/RedHatEVM/info.py
@@ -0,0 +1,53 @@
+# This file is the conventional place for "Info" adapters. Info adapters are
+# a crucial part of the Zenoss API and therefore the web interface for any
+# custom classes delivered by your ZenPack. Examples of custom classes that
+# will almost certainly need info adapters include datasources, custom device
+# classes and custom device component classes.
+
+# Mappings of interfaces (interfaces.py) to concrete classes and the factory
+# (these info adapter classes) used to create info objects for them are managed
+# in the configure.zcml file.
+
+from zope.component import adapts
+from zope.interface import implements
+
+from Products.Zuul.infos import ProxyProperty
+from Products.Zuul.infos.component import ComponentInfo
+from Products.Zuul.infos.template import RRDDataSourceInfo
+
+from ZenPacks.NAMESPACE.PACKNAME.ExampleComponent import ExampleComponent
+from ZenPacks.NAMESPACE.PACKNAME.interfaces \
+ import IExampleDataSourceInfo, IExampleComponentInfo
+
+
+class ExampleDataSourceInfo(RRDDataSourceInfo):
+ """
+ Defines API access for this datasource.
+ """
+
+ implements(IExampleDataSourceInfo)
+
+ # ProxyProperty is a shortcut to mean that you want the getter/setter for
+ # this property to go directly to properties of the same name on the
+ # datasource class (ExampleDataSource).
+ exampleProperty = ProxyProperty('exampleProperty')
+
+ # RRDDataSourceInfo classes can create a property called "testable" that
+ # controls whether the datasource dialog in the web interface allows the
+ # user to test it. By default this property is set to True unless you
+ # override it as is done below.
+
+ @property
+ def testable(self):
+ """
+ This datasource is not testable.
+ """
+ return False
+
+
+class ExampleComponentInfo(ComponentInfo):
+ implements(IExampleComponentInfo)
+ adapts(ExampleComponent)
+
+ attributeOne = ProxyProperty("attributeOne")
+ attributeTwo = ProxyProperty("attributeTwo")
45 ZenPacks/zenoss/RedHatEVM/interfaces.py
@@ -0,0 +1,45 @@
+from Products.Zuul.form import schema
+from Products.Zuul.interfaces.component import IComponentInfo
+from Products.Zuul.interfaces.template import IRRDDataSourceInfo
+
+# ZuulMessageFactory is the translation layer. You will see strings intended to
+# been seen in the web interface wrapped in _t(). This is so that these strings
+# can be automatically translated to other languages.
+from Products.Zuul.utils import ZuulMessageFactory as _t
+
+# In Zenoss 3 we mistakenly mapped TextLine to Zope's multi-line text
+# equivalent and Text to Zope's single-line text equivalent. This was
+# backwards so we flipped their meanings in Zenoss 4. The following block of
+# code allows the ZenPack to work properly in Zenoss 3 and 4.
+
+# Until backwards compatibility with Zenoss 3 is no longer desired for your
+# ZenPack it is recommended that you use "SingleLineText" and "MultiLineText"
+# instead of schema.TextLine or schema.Text.
+from Products.ZenModel.ZVersion import VERSION as ZENOSS_VERSION
+from Products.ZenUtils.Version import Version
+if Version.parse('Zenoss %s' % ZENOSS_VERSION) >= Version.parse('Zenoss 4'):
+ SingleLineText = schema.TextLine
+ MultiLineText = schema.Text
+else:
+ SingleLineText = schema.Text
+ MultiLineText = schema.TextLine
+
+
+class IExampleDataSourceInfo(IRRDDataSourceInfo):
+ """
+ Defines what fields should be displayed on the edit dialog for this
+ datasource in the Zenoss web interface.
+ """
+
+ # We inherit common datasource fields like event class, severity and others
+ # from IRRDDataSourceInfo.
+
+ exampleProperty = SingleLineText(
+ title=_t(u'Example Property'),
+ group=_t(u'Example Protocol'),
+ )
+
+
+class IExampleComponentInfo(IComponentInfo):
+ attributeOne = schema.Int(title=_t(u"Attribute #1"))
+ attributeTwo = SingleLineText(title=_t(u"Attribute #2"))
1  ZenPacks/zenoss/RedHatEVM/lib/__init__.py
@@ -0,0 +1 @@
+# __init__.py
0  ZenPacks/zenoss/RedHatEVM/libexec/placeholder.txt
No changes.
34 ZenPacks/zenoss/RedHatEVM/migrate/ExampleMigration.py
@@ -0,0 +1,34 @@
+import logging
+log = logging.getLogger('zen.migrate')
+
+import Globals
+
+from Products.ZenModel.ZenPack import ZenPackMigration
+from Products.ZenModel.migrate.Migrate import Version
+from Products.ZenUtils.Utils import unused
+
+unused(Globals)
+
+
+# Your migration class must subclass ZenPackMigration.
+class ExampleMigration(ZenPackMigration):
+
+ # There are two scenarios under which this migrate script will execute.
+ # 1. Fresh Install - If this ZenPack is being installed for the first
+ # time and the migrate script version is greater than or equal to the
+ # ZenPack's version, it will execute.
+ #
+ # 2. Upgrade - If this ZenPack is being upgraded and the migrate script
+ # version is greater than or equal to the version of the ZenPack that
+ # is already installed, it will execute.
+ version = Version(0, 0, 1)
+
+ def migrate(self, dmd):
+ log.info("Running ExampleMigration")
+
+ # Do the migration work. No commit is needed.
+ pass
+
+
+# Run the migration when this file is imported.
+ExampleMigration()
1  ZenPacks/zenoss/RedHatEVM/migrate/__init__.py
@@ -0,0 +1 @@
+# __init__.py
0  ZenPacks/zenoss/RedHatEVM/modeler/__init__.py
No changes.
0  ZenPacks/zenoss/RedHatEVM/modeler/plugins/__init__.py
No changes.
0  ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/__init__.py
No changes.
81 ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/cmd/ExampleCMD.py.example
@@ -0,0 +1,81 @@
+# Module-level documentation will automatically be shown as additional
+# information for the modeler plugin in the web interface.
+"""
+ExampleCMD
+An example plugin that illustrates how to model devices using SSH.
+"""
+
+# This is an example of an CMD-based modeler plugin. It won't be recognized by
+# Zenoss as an available modeler plugin unless the .example extension is
+# removed.
+
+# When configuring modeler plugins for a device or device class, this plugin's
+# name would be community.snmp.ExampleCMD because its filesystem path within
+# the ZenPack is modeler/plugins/community/snmp/ExampleCMD.py. The name of the
+# class within this file must match the filename.
+
+import re
+
+# CommandPlugin is the base class that provides lots of help in modeling data
+# that's available by connecting to a remote machine, running command line
+# tools, and parsing their results.
+from Products.DataCollector.plugins.CollectorPlugin import CommandPlugin
+
+# Classes we'll need for returning proper results from our modeler plugin's
+# process method.
+from Products.DataCollector.plugins.DataMaps import ObjectMap, RelationshipMap
+
+
+class ExampleCMD(CommandPlugin):
+
+ # The command to run.
+ command = "/bin/cat /proc/partitions"
+
+ # Modeler plugins can optionally implement the "condition" method. This
+ # allows your plugin to determine if it should be run by looking at the
+ # configuration of the device that's about to be modeled. Return True if
+ # you want the modeler plugin to execute and False if you do not.
+ #
+ # The default is to return True. So ordinarily you wouldn't even implement
+ # the method if you were just going to blindly return True like this
+ # example.
+ def condition(self, device, log):
+ return True
+
+ def process(self, device, results, log):
+ log.info("Modeler %s processing data for device %s",
+ self.name(), device.id)
+
+ objectmaps = []
+
+ # For CommandPlugin, the results parameter to the process method will
+ # be a string containing all output from the command defined above.
+
+ # results contents..
+ # major minor #blocks name
+ #
+ # 8 0 41943040 sda
+ # 8 1 104391 sda1
+ # 8 2 41833260 sda2
+ # 253 0 41091072 dm-0
+ # 253 1 720896 dm-1
+
+ matcher = re.compile(r'^\d+\s+\d+\s+(?P<blocks>\d+)\s+(?P<name>\S+)')
+
+ for line in results.split('\n'):
+ line = line.strip()
+ match = matcher.search(line)
+ if match:
+ objectmaps.append(ObjectMap({
+ 'id': self.prepId(match.group('name')),
+ 'description': match.group('name'),
+ }))
+
+ # Return a RelationshipMap that describes the component, relationship
+ # on that component, and the module name for the created objects. Pass
+ # in the previously built list of ObjectMaps that will be used to
+ # populate the relationship.
+ return RelationshipMap(
+ compname="hw", relname="harddisks",
+ modname='Products.ZenModel.HardDisk',
+ objmaps=objectmaps)
0  ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/cmd/__init__.py
No changes.
121 ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/snmp/ExampleSNMP.py.example
@@ -0,0 +1,121 @@
+# Module-level documentation will automatically be shown as additional
+# information for the modeler plugin in the web interface.
+"""
+ExampleSNMP
+An example plugin that illustrates how to model devices using SNMP.
+"""
+
+# This is an example of an SNMP-based modeler plugin. It won't be recognized by
+# Zenoss as an available modeler plugin unless the .example extension is
+# removed.
+
+# When configuring modeler plugins for a device or device class, this plugin's
+# name would be community.snmp.ExampleSNMP because its filesystem path within
+# the ZenPack is modeler/plugins/community/snmp/ExampleSNMP.py. The name of the
+# class within this file must match the filename.
+
+# SnmpPlugin is the base class that provides lots of help in modeling data
+# that's available over SNMP.
+from Products.DataCollector.plugins.CollectorPlugin \
+ import SnmpPlugin, GetMap, GetTableMap
+
+# Classes we'll need for returning proper results from our modeler plugin's
+# process method.
+from Products.DataCollector.plugins.DataMaps import ObjectMap
+
+
+class ExampleSNMP(SnmpPlugin):
+
+ # SnmpPlugin will automatically collect OIDs described in the snmpGetMap
+ # property. You can make up the value for the OID key. It will be used in
+ # the process method to find the result for each value. snmpGetMap and
+ # GetMap should be used to request specific OIDs as you would in an
+ # snmpget.
+ snmpGetMap = GetMap({
+ '.1.3.6.1.4.1.2021.4.3.0': 'memTotalSwap',
+ '.1.3.6.1.4.1.2021.4.5.0': 'memTotalReal',
+ })
+
+ # snmpGetTableMaps and GetTableMap should be used to request SNMP tables.
+ # The first parameter to GetTableMap is whatever you want the results of
+ # this table to be stored in the results as. The second parameter is the
+ # base OID for the table. More specifically this should be the "entry" OID
+ # or more specifically the largest possible OID prefix that doesn't change
+ # when walking the table. The third paramter is a dictionary that maps
+ # columns in the table to names that will be used to access them in the
+ # results.
+ snmpGetTableMaps = (
+ GetTableMap('diskIOTable', '.1.3.6.1.4.1.2021.13.15.1.1', {
+ '.1': 'index',
+ '.2': 'device',
+ }),
+
+ # More GetTableMap definitions can be added to this tuple to query
+ # more SNMP tables.
+ )
+
+ # Modeler plugins can optionally implement the "condition" method. This
+ # allows your plugin to determine if it should be run by looking at the
+ # configuration of the device that's about to be modeled. Return True if
+ # you want the modeler plugin to execute and False if you do not.
+ #
+ # The default is to return True. So ordinarily you wouldn't even implement
+ # the method if you were just going to blindly return True like this
+ # example.
+ def condition(self, device, log):
+ return True
+
+ def process(self, device, results, log):
+ log.info("Modeler %s processing data for device %s",
+ self.name(), device.id)
+
+ # Results is a tuple with two items. The first (0) index contains a
+ # dictionary with the results of our "snmpGetMap" queries. The second
+ # (1) index contains a dictionary with the results of our
+ # "snmpGetTableMaps" queries.
+ getdata, tabledata = results
+
+ # getdata contents..
+ # {'memTotalReal': 2058776, 'memTotalSwap': 720888}
+
+ # tabledata contents..
+ # {'diskIOTable': {'1': {'device': 'ram0', 'index': 1},
+ # '2': {'device': 'ram1', 'index': 2},
+ # '3': {'device': 'ram2', 'index': 3},
+ # '4': {'device': 'ram4', 'index': 4}}}
+
+ # Create a list to fill up with our results.
+ maps = []
+
+ # First we build an ObjectMap to apply to the device's hardware (hw)
+ # component to set the total memory size. Multiple the returned value
+ # by 1024 because the SNMP result is in kilybytes and we want to store
+ # it in bytes.
+ maps.append(ObjectMap({
+ 'totalMemory': getdata['memTotalReal'] * 1024},
+ compname='hw'))
+
+ # Now do the same thing for total swap space. Zenoss stores this on the
+ # Operating System (os) component of the device.
+ maps.append(ObjectMap({
+ 'totalSwap': getdata['memTotalSwap'] * 1024},
+ compname='os'))
+
+ # Log for each disk returned from our GetTableMap. If we wanted to
+ # create new disks in the model we'd create a RelationshipMap for them
+ # and add an ObjectMap to it for each row in this table. See the
+ # ExampleCMD plugin for an example of this.
+ for snmpindex, disk in tabledata.get('diskIOTable').items():
+ log.info("Found disk %s", disk['device'])
+
+ # The process method of the modeler plugin class below is expected to
+ # return output in one of the following forms.
+ #
+ # 1. A single ObjectMap instance
+ # 2. A single RelationshipMap instance
+ # 3. A list of ObjectMap and RelationshipMap instances
+ # 4. None
+ #
+ # If your modeler plugin encounters a bad state and you don't want to
+ # affect Zenoss' model of the device you should return None.
+ return maps
0  ZenPacks/zenoss/RedHatEVM/modeler/plugins/community/snmp/__init__.py
No changes.
3  ZenPacks/zenoss/RedHatEVM/objects/objects.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<objects>
+</objects>
66 ZenPacks/zenoss/RedHatEVM/reports/Example_Reports/Example_Report.rpt.example
@@ -0,0 +1,66 @@
+<tal:block tal:define="
+ tabletitle string:Example Report;
+ tableName string:example_report;
+ tm here/ZenTableManager;
+ sts python:tm.setReqTableState;
+ tableState python:tm.getTableState(tableName, sortedSence='desc', sortedHeader='outputP');
+ objects python:here.ReportServer.plugin('example_plugin', tableState);
+ batch python:here.ZenTableManager.getBatch(tableName,objects,sortedHeader='device', sortedSence='asc');
+ exportFields python:['device', 'ip', 'hardware', 'software'];
+ ">
+
+<!-- Make the report exportable to CSV -->
+<tal:block metal:use-macro="here/reportMacros/macros/exportableReport">
+<tal:block metal:fill-slot="report">
+
+<tal:block metal:use-macro="here/templates/macros/page1">
+<tal:block metal:fill-slot="breadCrumbPane">
+ <span metal:use-macro="here/miscmacros/macros/reportBreadCrumbsList"/>
+</tal:block>
+
+<tal:block metal:fill-slot="contentPane">
+<tal:block metal:use-macro="here/zenuimacros/macros/zentable">
+<tal:block metal:fill-slot="zentablecontents">
+ <tr>
+ <!-- Define Column Headers - Clickable for Sorting -->
+ <th tal:replace="
+ structure python:here.ZenTableManager.getTableHeader(
+ tableName,'device','Device')"/>
+
+ <th tal:replace="
+ structure python:here.ZenTableManager.getTableHeader(
+ tableName,'ip','IP Address')"/>
+
+ <th tal:replace="
+ structure python:here.ZenTableManager.getTableHeader(
+ tableName,'hardware','Hardware')"/>
+
+ <th tal:replace="
+ structure python:here.ZenTableManager.getTableHeader(
+ tableName,'software','Software')"/>
+ </tr>
+ <tal:block tal:repeat="r batch">
+ <!-- Define Per-Row Display -->
+ <tr tal:define="odd repeat/r/odd"
+ tal:attributes="class python:test(odd,'odd','even')">
+
+ <td tal:content="r/device"/>
+ <td tal:content="r/ip"/>
+ <td tal:content="r/hardware"/>
+ <td tal:content="r/software"/>
+ </tr>
+ </tal:block>
+ <tr>
+ <!-- Update colspan to match your columns -->
+ <td colspan="4" class="tableheader" align='center'>
+ <form metal:use-macro="here/zenTableNavigation/macros/navtool"/>
+ </td>
+ </tr>
+</tal:block>
+</tal:block>
+</tal:block>
+
+</tal:block>
+</tal:block>
+</tal:block>
+</tal:block>
23 ZenPacks/zenoss/RedHatEVM/reports/plugins/example_plugin.py
@@ -0,0 +1,23 @@
+# ZenReports.Utils contains some useful helpers for creating records to return.
+from Products.ZenReports import Utils
+
+
+# The class name must patch the filename.
+class example_plugin:
+
+ # The run method will be executed when your report calls the plugin.
+ def run(self, dmd, args):
+ report = []
+ for device in dmd.Devices.getSubDevicesGen():
+ report.append(Utils.Record(
+ device=device.titleOrId(),
+ ip=device.manageIp,
+ hardware="%s %s" % (
+ device.hw.getManufacturerName(),
+ device.hw.getProductName()),
+ software="%s %s" % (
+ device.os.getManufacturerName(),
+ device.os.getProductName()),
+ ))
+
+ return report
94 ZenPacks/zenoss/RedHatEVM/services/ExampleConfigService.py
@@ -0,0 +1,94 @@
+"""
+ExampleConfigService
+ZenHub service for providing configuration to the zenexample collector daemon.
+
+ This provides the daemon with a dictionary of datapoints for every device.
+"""
+
+import logging
+log = logging.getLogger('zen.example')
+
+from Products.ZenCollector.services.config import CollectorConfigService
+
+
+# Your daemon configuration service should almost certainly subclass
+# CollectorConfigService to make it as easy as possible for you to implement.
+class ExampleConfigService(CollectorConfigService):
+ """
+ ZenHub service for the zenexample collector daemon.
+ """
+
+ # When the collector daemon requests a list of devices to poll from ZenHub
+ # your service can filter the devices that are returned by implementing
+ # this _filterDevice method. If _filterDevice returns True for a device,
+ # it will be returned to the collector. If _filterDevice returns False, the
+ # collector daemon won't collect from it.
+ def _filterDevice(self, device):
+ # First use standard filtering.
+ filter = CollectorConfigService._filterDevice(self, device)
+
+ # If the standard filtering logic said the device shouldn't be filtered
+ # we can setup some other contraint.
+ if filter:
+ # We only monitor devices that start with "z".
+ return device.id.startswith('z')
+
+ return filter
+
+ # The _createDeviceProxy method allows you to build up the DeviceProxy
+ # object that will be sent to the collector daemon. Whatever is returned
+ # from this method will be sent as the device's representation to the
+ # collector daemon. Use serializable types. DeviceProxy works, as do any
+ # simple Python types.
+ def _createDeviceProxy(self, device):
+ proxy = CollectorConfigService._createDeviceProxy(self, device)
+
+ proxy.datapoints = []
+ proxy.thresholds = []
+
+ perfServer = device.getPerformanceServer()
+
+ self._getDataPoints(proxy, device, device.id, None, perfServer)
+ proxy.thresholds += device.getThresholdInstances('Example Protocol')
+
+ for component in device.getMonitoredComponents():
+ self._getDataPoints(
+ proxy, component, component.device().id, component.id,
+ perfServer)
+
+ proxy.thresholds += component.getThresholdInstances(
+ 'Example Protocol')
+
+ return proxy
+
+ # This is not a method you must implement. It is used by the custom
+ # _createDeviceProxy method above.
+ def _getDataPoints(
+ self, proxy, deviceOrComponent, deviceId, componentId, perfServer
+ ):
+ for template in deviceOrComponent.getRRDTemplates():
+ dataSources = [ds for ds
+ in template.getRRDDataSources('Example Protocol')
+ if ds.enabled]
+
+ for ds in dataSources:
+ for dp in ds.datapoints():
+ path = '/'.join((deviceOrComponent.rrdPath(), dp.name()))
+ dpInfo = dict(
+ devId=deviceId,
+ compId=componentId,
+ dsId=ds.id,
+ dpId=dp.id,
+ path=path,
+ rrdType=dp.rrdtype,
+ rrdCmd=dp.getRRDCreateCommand(perfServer),
+ minv=dp.rrdmin,
+ maxv=dp.rrdmax,
+ exampleProperty=ds.exampleProperty,
+ )
+
+ if componentId:
+ dpInfo['componentDn'] = getattr(
+ deviceOrComponent, 'dn', None)
+
+ proxy.datapoints.append(dpInfo)
0  ZenPacks/zenoss/RedHatEVM/services/__init__.py
No changes.
0  ZenPacks/zenoss/RedHatEVM/tests/__init__.py
No changes.
36 ZenPacks/zenoss/RedHatEVM/tests/testExample.py
@@ -0,0 +1,36 @@
+# BaseTestCase is a subclass of ZopeTestCase which is ultimately a subclass of
+# Python's standard unittest.TestCase. Because of this the following
+# documentation on unit testing in Zope and Python are both applicable here.
+#
+# Python Unit testing framework
+# http://docs.python.org/library/unittest.html
+#
+# Zope Unit Testing
+# http://wiki.zope.org/zope2/Testing
+
+from Products.ZenTestCase.BaseTestCase import BaseTestCase
+
+
+class TestExample(BaseTestCase):
+ def afterSetup(self):
+ # You can use the afterSetup method to create a proper environment for
+ # your tests to execute in, or to run common code between the tests.
+ self.device = self.dmd.Devices.createInstance('testDevice')
+
+ def testExampleOne(self):
+ self.assertEqual("One", "One")
+ self.assertTrue(True)
+
+ def testExampleTwo(self):
+ self.assertEqual(self.device.id, "testDevice")
+ self.assertFalse(False)
+
+
+def test_suite():
+ from unittest import TestSuite, makeSuite
+ suite = TestSuite()
+
+ # Add your BaseTestCase subclasses here to have them executed.
+ # suite.addTest(makeSuite(TestExample))
+
+ return suite
108 ZenPacks/zenoss/RedHatEVM/zenrhevm.py
@@ -0,0 +1,108 @@
+# This is an example of a custom collector daemon.
+
+import logging
+log = logging.getLogger('zen.Example')
+
+import Globals
+import zope.component
+import zope.interface
+
+from twisted.internet import defer
+
+from Products.ZenCollector.daemon import CollectorDaemon
+from Products.ZenCollector.interfaces \
+ import ICollectorPreferences, IScheduledTask, IEventService, IDataService
+
+from Products.ZenCollector.tasks \
+ import SimpleTaskFactory, SimpleTaskSplitter, TaskStates
+
+from Products.ZenUtils.observable import ObservableMixin
+
+# unused is way to keep Python linters from complaining about imports that we
+# don't explicitely use. Occasionally there is a valid reason to do this.
+from Products.ZenUtils.Utils import unused
+
+# We must import our ConfigService here so zenhub will allow it to be
+# serialized and deserialized. We'll declare it unused to satisfy linters.
+from ZenPacks.NAMESPACE.PACKNAME.services.ExampleConfigService \
+ import ExampleConfigService
+
+unused(Globals)
+unused(ExampleConfigService)
+
+
+# Your implementation of ICollectorPreferences is where you can handle custom
+# command line (or config file) options and do global configuration of the
+# daemon.
+class ZenExamplePreferences(object):
+ zope.interface.implements(ICollectorPreferences)
+
+ def __init__(self):
+ self.collectorName = 'zenexample'
+ self.configurationService = \
+ "ZenPacks.NAMESPACE.PACKNAME.services.ExampleConfigService"
+
+ # How often the daemon will collect each device. Specified in seconds.
+ self.cycleInterval = 5 * 60
+
+ # How often the daemon will reload configuration. In seconds.
+ self.configCycleInterval = 5 * 60
+
+ self.options = None
+
+ def buildOptions(self, parser):
+ """
+ Required to implement the ICollectorPreferences interface.
+ """
+ pass
+
+ def postStartup(self):
+ """
+ Required to implement the ICollectorPreferences interface.
+ """
+ pass
+
+
+# The implementation of IScheduledTask for your daemon is usually where most
+# of the work is done. This is where you implement the specific logic required
+# to collect data.
+class ZenExampleTask(ObservableMixin):
+ zope.interface.implements(IScheduledTask)
+
+ def __init__(self, taskName, deviceId, interval, taskConfig):
+ super(ZenExampleTask, self).__init__()
+ self._taskConfig = taskConfig
+
+ self._eventService = zope.component.queryUtility(IEventService)
+ self._dataService = zope.component.queryUtility(IDataService)
+ self._preferences = zope.component.queryUtility(
+ ICollectorPreferences, 'zenexample')
+
+ # All of these properties are required to implement the IScheduledTask
+ # interface.
+ self.name = taskName
+ self.configId = deviceId
+ self.interval = interval
+ self.state = TaskStates.STATE_IDLE
+
+ # doTask is where the collector logic should go. It is also required to
+ # implement the IScheduledTask interface. It will be called directly by the
+ # framework when it's this task's turn to run.
+ def doTask(self):
+ # This method must return a deferred because the collector framework
+ # is asynchronous.
+ d = defer.Deferred()
+ return d
+
+ # cleanup is required to implement the IScheduledTask interface.
+ def cleanup(self):
+ pass
+
+
+if __name__ == '__main__':
+ myPreferences = ZenExamplePreferences()
+ myTaskFactory = SimpleTaskFactory(ZenExampleTask)
+ myTaskSplitter = SimpleTaskSplitter(myTaskFactory)
+
+ daemon = CollectorDaemon(myPreferences, myTaskSplitter)
+ daemon.run()
37 ZenPacks/zenoss/RedHatEVM/zep/actions.json.example
@@ -0,0 +1,37 @@
+// This file is used to load triggers and notifications when your ZenPack is
+// installed. If existing triggers and notifications are found with the same
+// name, they will be updated with the new properties specified im this file.
+//
+// The file should be renamed to actions.json to be picked up during the
+// ZenPack's installation.
+{
+ "triggers": [
+ {
+ "name": "CriticalProductionEvents",
+ "uuid": "A556B89C-F991-4A29-B7ED-F95643ADFD89",
+ "enabled": true,
+ "rule": {
+ "api_version": 1,
+ "source": "(prodState &gt;= 1000) and (eventState &gt;= 0) and (severity &gt;= 5)",
+ "type": 1
+ }
+ }
+ ],
+ "notifications": [
+ {
+ "id": "ExampleCommand",
+ "description": "Example command notification.",
+ "guid": "B4F091A8-F4C0-4C9D-A7A9-AF3AED2BD6C9",
+ "action": "command",
+ "enabled": false,
+ "action_timeout": 60,
+ "delay_seconds": 330,
+ "repeat_seconds": 0,
+ "send_initial_occurrence": true,
+ "send_clear": false,
+ "body_format": "echo ${evt/evid} &gt; $$ZENHOME/var/critical_evid.log",
+ "clear_body_format": "echo ${evt/evid} &gt; $$ZENHOME/var/cleared_evid.log",
+ "subscriptions": ["A556B89C-F991-4A29-B7ED-F95643ADFD89"]
+ }
+ ]
+}
14 ZenPacks/zenoss/RedHatEVM/zep/zep.json.example
@@ -0,0 +1,14 @@
+// This file is used to add custom event fields. It will be loaded when the
+// ZenPack is installed.
+//
+// The file should be renamed to zep.json to be picked up during the ZenPack's
+// installation.
+{
+ "EventDetailItem" : [
+ {
+ "name" : "Example",
+ "key" : "example_field",
+ "type" : 1
+ }
+ ]
+}
1  ZenPacks/zenoss/__init__.py
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)
79 setup.py
@@ -0,0 +1,79 @@
+################################
+# These variables are overwritten by Zenoss when the ZenPack is exported
+# or saved. Do not modify them directly here.
+# NB: PACKAGES is deprecated
+NAME = "ZenPacks.zenoss.RedHatEVM"
+VERSION = "1.0.0"
+AUTHOR = ""
+LICENSE = ""
+NAMESPACE_PACKAGES = ['ZenPacks', 'ZenPacks.zenoss']
+PACKAGES = ['ZenPacks', 'ZenPacks.zenoss', 'ZenPacks.zenoss.RedHatEVM']
+INSTALL_REQUIRES = ['ZenPacks.zenoss.Liberator']
+COMPAT_ZENOSS_VERS = ""
+PREV_ZENPACK_NAME = ""
+# STOP_REPLACEMENTS
+################################
+# Zenoss will not overwrite any changes you make below here.
+
+import os
+from subprocess import Popen, PIPE
+from setuptools import setup, find_packages
+
+# Run "make build" if a GNUmakefile is present.
+if os.path.isfile('GNUmakefile'):
+ print 'GNUmakefile found. Running "make build" ..'
+ p = Popen('make build', stdout=PIPE, stderr=PIPE, shell=True)
+ print p.communicate()[0]
+ if p.returncode != 0:
+ raise Exception('"make build" exited with an error: %s' % p.returncode)
+
+setup(
+ # This ZenPack metadata should usually be edited with the Zenoss
+ # ZenPack edit page. Whenever the edit page is submitted it will
+ # overwrite the values below (the ones it knows about) with new values.
+ name=NAME,
+ version=VERSION,
+ author=AUTHOR,
+ license=LICENSE,
+
+ # This is the version spec which indicates what versions of Zenoss
+ # this ZenPack is compatible with
+ compatZenossVers=COMPAT_ZENOSS_VERS,
+
+ # previousZenPackName is a facility for telling Zenoss that the name
+ # of this ZenPack has changed. If no ZenPack with the current name is
+ # installed then a zenpack of this name if installed will be upgraded.
+ prevZenPackName=PREV_ZENPACK_NAME,
+
+ # Indicate to setuptools which namespace packages the zenpack
+ # participates in
+ namespace_packages=NAMESPACE_PACKAGES,
+
+ # Tell setuptools what packages this zenpack provides.
+ packages=find_packages(),
+
+ # Tell setuptools to figure out for itself which files to include
+ # in the binary egg when it is built.
+ include_package_data=True,
+
+ # The MANIFEST.in file is the recommended way of including additional files
+ # in your ZenPack. package_data is another.
+ #package_data = {}
+
+ # Indicate dependencies on other python modules or ZenPacks. This line
+ # is modified by zenoss when the ZenPack edit page is submitted. Zenoss
+ # tries to put add/delete the names it manages at the beginning of this
+ # list, so any manual additions should be added to the end. Things will
+ # go poorly if this line is broken into multiple lines or modified to
+ # dramatically.
+ install_requires=INSTALL_REQUIRES,
+
+ # Every ZenPack egg must define exactly one zenoss.zenpacks entry point
+ # of this form.
+ entry_points={
+ 'zenoss.zenpacks': '%s = %s' % (NAME, NAME),
+ },
+
+ # All ZenPack eggs must be installed in unzipped form.