Permalink
Browse files

Initial commit by nyeates publishing script; Code was supplied only f…

…rom .egg; May be missing setup.py
  • Loading branch information...
0 parents commit a5b9eaecbe7f1c1dc1de6c486e1180807b41ec47 Nick Yeates committed Nov 21, 2011
9 .gitignore
@@ -0,0 +1,9 @@
+*~
+*.pyc
+*.pyo
+build
+setuptools*
+*.egg
+*.egg-info
+*EGG-INFO*
+*dist
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
172 README.markdown
@@ -0,0 +1,172 @@
+# !! UPDATE THIS DOC !!
+This file should contain documentation that is specific to what your ZenPack does.
+It should give example screenshots, explain how to install it, amongst other topics.
+Please see http://community.zenoss.org/docs/DOC-8495#README for details.
+
+This file was automatically pulled from https://raw.github.com/zenoss/ZenPackTemplate/master/README.markdown
+It contains general comments, not specific to this ZenPack
+
+# 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.
66 ZenPacks/ShaneScott/DeviceSearch/__init__.py
@@ -0,0 +1,66 @@
+import logging
+log = logging.getLogger('zen.DeviceSearch')
+
+import os
+import Globals
+from Products.CMFCore.DirectoryView import registerDirectory
+
+skinsDir = os.path.join(os.path.dirname(__file__), 'skins')
+if os.path.isdir(skinsDir):
+ registerDirectory(skinsDir, globals())
+
+from Products.ZenModel.ZenPack import ZenPack as ZenPackBase
+
+class ZenPack(ZenPackBase):
+ def install(self, dmd):
+ super(ZenPack, self).install(dmd)
+
+ def remove(self, dmd, leaveObjects=False):
+ super(ZenPack, self).remove(dmd, leaveObjects)
+
+
+from Products.ZenUtils.Utils import monkeypatch
+
+try:
+ from Products.Zuul.catalog.global_catalog import DeviceWrapper, IpInterfaceWrapper
+
+ @monkeypatch('Products.Zuul.catalog.global_catalog.DeviceWrapper')
+ def searchKeywords(self):
+ device = self._context.primaryAq()
+ return super(DeviceWrapper, self).searchKeywords() + (device.zSnmpCommunity,)
+ # ^ Add other indexable properties (cProp, zProp, Attr) here as context device
+
+ @monkeypatch('Products.Zuul.catalog.global_catalog.IpInterfaceWrapper')
+ def searchKeywordsForChildren(self):
+ """
+ When searching, what things to search on
+ """
+ if self._context.titleOrId() in ('lo', 'sit0'):
+ # ^ Add other interface names which are ignored from indexing
+ return ()
+
+ try:
+ # If we find an interface IP address, link it to an interface
+ ipAddresses = [x for x in self._context.getIpAddresses() \
+ if not x.startswith('127.0.0.1/') and \
+ not x.startswith('::1/')]
+ except Exception:
+ ipAddresses = []
+
+ return super(IpInterfaceWrapper, self).searchKeywordsForChildren() + (
+ self._context.description, self._context.titleOrId(),
+ # ^ Add other indexable properties (cProp, zProp, Attr) here as context self._context
+ )
+
+ @monkeypatch('Products.Zuul.catalog.global_catalog.IpInterfaceWrapper')
+ def searchExcerpt(self):
+ """
+ How the results are displayed in the search drop-down
+ """
+ return super(IpInterfaceWrapper, self).searchExcerpt() + ' ' + ' '.join([
+ self._context.description, self._context.titleOrId(),
+ ])
+ # ^ Add other indexable properties (cProp, zProp, Attr) here as context self._context
+
+except ImportError:
+ pass
7 ZenPacks/ShaneScott/DeviceSearch/configure.zcml
@@ -0,0 +1,7 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+ xmlns:five="http://namespaces.zope.org/five"
+ xmlns:browser="http://namespaces.zope.org/browser">
+
+ <include package=".device"/>
+
+</configure>
0 ZenPacks/ShaneScott/DeviceSearch/device/__init__.py
No changes.
104 ZenPacks/ShaneScott/DeviceSearch/device/adapters.py
@@ -0,0 +1,104 @@
+##Modified copy of zenoss DeviceSearch
+
+from zope.component import adapts
+from zope.interface import implements
+from Products.AdvancedQuery import MatchGlob, And, Or, Eq, In, RankByQueries_Max
+from Products.ZCatalog.interfaces import ICatalogBrain
+from Products.ZenModel.DataRoot import DataRoot
+from Products.Zuul.utils import allowedRolesAndGroups
+from Products.Zuul.search import ISearchProvider
+from Products.Zuul.search import ISearchResult
+
+class DeviceSearchProvider(object):
+ """
+ Provider which searches Zenoss's global catalog for matching devices
+ """
+ implements(ISearchProvider)
+ adapts(DataRoot)
+
+ def __init__(self, dmd):
+ self._dmd = dmd
+
+
+ def getSearchResults(self, parsedQuery,
+ sorter=None, unrestricted=False):
+ """
+ Queries the catalog. Searches the searchKeywords index
+ using *keyword1* AND *keyword2* AND so on.
+ If there are preferred categories, find maxResults # of instances
+ before searching other categories.
+
+ @rtype generator of BrainSearchResult objects
+ """
+ operators = parsedQuery.operators
+ keywords = parsedQuery.keywords
+
+ if not keywords:
+ return
+
+ results = self.doMySearch( keywords, unrestricted )
+
+ if sorter is not None:
+ results = sorter.limitSort(results)
+
+ return results
+
+ def doMySearch( self, keywords, unrestricted=False ):
+
+ def listMatchGlob(op, index, list):
+ return op(*[ MatchGlob(index, '*%s*' % i ) for i in list ])
+
+ full_query = listMatchGlob(And, 'searchKeywords', keywords)
+
+ querySet = full_query
+ if not unrestricted:
+ # take permissions into account
+ roles = In('allowedRolesAndUsers', allowedRolesAndGroups(self._dmd))
+ querySet = [full_query, roles]
+ querySet = And(*querySet)
+
+ catalogItems = self._dmd.global_catalog.evalAdvancedQuery(querySet)
+ brainResults = [DeviceSearchResult(catalogItem)
+ for catalogItem in catalogItems
+ if catalogItem.searchExcerpt is not None]
+ return brainResults
+
+ def getQuickSearchResults(self, parsedQuery, maxResults=None):
+ """
+ Currently just calls getSearchResults
+ """
+ return self.getSearchResults( parsedQuery, maxResults )
+
+
+class DeviceSearchResult(object):
+ """
+ Wraps a brain from the search catalog for inclusion in search results.
+ """
+
+ implements(ISearchResult)
+
+ def __init__(self, brain):
+ self._brain = brain
+
+ @property
+ def url(self):
+ return self._brain.getPath()
+
+ @property
+ def category(self):
+ return self._brain.meta_type
+
+ @property
+ def excerpt(self):
+ return self._brain.searchExcerpt
+
+ iconTemplate = '<img src="%s"/>'
+
+ @property
+ def icon(self):
+ return self.iconTemplate % self._brain.searchIcon
+
+ @property
+ def popout(self):
+ return False
+
8 ZenPacks/ShaneScott/DeviceSearch/device/configure.zcml
@@ -0,0 +1,8 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+
+ <subscriber provides="Products.Zuul.search.ISearchProvider"
+ for="Products.ZenModel.DataRoot.DataRoot"
+ factory=".adapters.DeviceSearchProvider"
+ />
+
+</configure>
1 ZenPacks/ShaneScott/__init__.py
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)
1 ZenPacks/__init__.py
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)

0 comments on commit a5b9eae

Please sign in to comment.