Package DataCollector :: Module Plugins
[hide private]
[frames] | no frames]

Source Code for Module DataCollector.Plugins

  1  ########################################################################### 
  2  # 
  3  # This program is part of Zenoss Core, an open source monitoring platform. 
  4  # Copyright (C) 2007, Zenoss Inc. 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify it 
  7  # under the terms of the GNU General Public License version 2 as published by 
  8  # the Free Software Foundation. 
  9  # 
 10  # For complete information please visit: http://www.zenoss.com/oss/ 
 11  # 
 12  ########################################################################### 
 13   
 14  __doc__= """Plugins 
 15  Load plugins from standard locations and from ZenPacks 
 16  """ 
 17   
 18  from Products.ZenUtils.Utils import importClass, zenPath 
 19  import sys 
 20  import os 
 21  import exceptions 
 22  import imp 
 23  import logging 
 24  log = logging.getLogger('zen.plugins') 
 25   
 26  _pluginskip = ("CollectorPlugin.py", "DataMaps.py") 
27 -def _plfilter(f):
28 """ 29 Return a filtered list of plugins 30 31 @param f: plugin name 32 @type f: string 33 """ 34 return (f.endswith(".py") and 35 not f.startswith('.') and 36 f.find('#') < 0 and 37 not f.startswith("_") and 38 not f in _pluginskip)
39 40
41 -class pluginImportError(exceptions.ImportError):
42 """ 43 Capture extra data from plugin exceptions 44 """ 45
46 - def __init__(self, plugin='', traceback='' ):
47 """ 48 Initializer 49 50 @param plugin: plugin name 51 @type plugin: string 52 @param traceback: traceback from an exception 53 @type traceback: traceback object 54 """ 55 self.plugin = plugin 56 self.traceback = traceback 57 # The following is needed for zendisc 58 self.args = traceback
59 60 61 62 from twisted.spread import pb
63 -class PluginLoader(pb.Copyable, pb.RemoteCopy):
64 """ 65 Class to load plugins 66 """ 67
68 - def __init__(self, package, modpath):
69 """ 70 Initializer 71 72 @param package: package path where the plugins may be located 73 @type package: string 74 @param modpath: plugin path inside of the package 75 @type modpath: string 76 """ 77 self.package = package 78 self.modpath = modpath
79 80
81 - def pluginName(self):
82 """ 83 Return the name of the plugin 84 85 @return: name of the plugin 86 @rtype: string 87 """ 88 return self.modpath.split('plugins.').pop()
89 90
91 - def create(self):
92 """ 93 Load and compile the code contained in the given plugin 94 """ 95 try: 96 try: 97 # Load the plugins package using its path as the name to avoid 98 # conflicts. Since we're kicking in the back door slashes in 99 # the name don't matter. 100 plugin_pkg = imp.find_module('.', [self.package]) 101 plugin_pkg_mod = imp.load_module(self.package, *plugin_pkg) 102 103 # Modify sys.path (unfortunately, some plugins depend on this) 104 sys.path.insert(0, self.package) 105 106 # Import the module, using the plugins package 107 # 108 # Equivalent to, for example: 109 # from mypackage.zenoss.snmp import DeviceMap 110 # 111 clsname = self.modpath.split('.')[-1] 112 if self.modpath.startswith('ZenPacks'): 113 # ZenPack plugins are specified absolutely; we can import 114 # them using the old method 115 const = importClass(self.modpath) 116 else: 117 mod = __import__(self.package + '.' + self.modpath, 118 globals(), 119 locals(), 120 [clsname]) 121 122 # Finally, get at the class 123 const = getattr(mod, clsname) 124 125 except (SystemExit, KeyboardInterrupt): 126 raise 127 128 except: 129 import traceback 130 raise pluginImportError( 131 plugin=self.modpath, traceback=traceback.format_exc() ) 132 133 finally: 134 try: 135 sys.path.remove(self.package) 136 except ValueError: 137 # It's already been removed 138 pass 139 140 # The whole point: instantiate the plugin 141 plugin = const() 142 return plugin
143 144 pb.setUnjellyableForClass(PluginLoader, PluginLoader) 145 146
147 -def _loadPluginDir(pdir):
148 """ 149 Load the Zenoss default collector plugins 150 151 @param pdir: plugin path parent directory 152 @type pdir: string 153 @return: list of loadable plugins 154 @rtype: list 155 """ 156 collectorPlugins = [] 157 log.debug("Loading collector plugins from: %s", pdir) 158 lpdir = len(pdir)+1 159 for path, dirname, filenames in os.walk(pdir): 160 path = path[lpdir:] 161 for filename in filter(_plfilter, filenames): 162 modpath = os.path.join(path,filename[:-3]).replace("/",".") 163 log.debug("Loading: %s", modpath) 164 try: 165 this_plugin= PluginLoader(pdir, modpath) 166 if this_plugin is not None: 167 collectorPlugins.append( this_plugin ) 168 except ImportError: 169 log.exception("Problem loading plugin:%s" % modpath) 170 171 return collectorPlugins
172 173 174
175 -def loadPlugins(dmd):
176 """ 177 Load plugins from the Zenoss plugin directory and from the plugin 178 directory from each ZenPack. 179 Returns them as a list of PluginLoader instances. 180 181 @param dmd: Device Management Database (DMD) reference 182 @type dmd: dmd object 183 @return: list of loadable plugins 184 @rtype: list 185 """ 186 plugins = [x for x in sys.modules if x.startswith("plugins")] 187 PDIR = os.path.join(os.path.dirname(__file__), "plugins") 188 for key in ['zenoss'] + plugins: 189 log.debug("Clearing plugin %s", key) 190 if sys.modules.has_key(key): 191 del sys.modules[key] 192 193 plugins = _loadPluginDir(PDIR) 194 plugins += _loadPluginDir(zenPath('Products/ZenWin/modeler/plugins')) 195 196 try: 197 for pack in dmd.ZenPackManager.packs(): 198 try: 199 if pack.isEggPack(): 200 eggPlugins = _loadPluginDir(pack.path('modeler', 'plugins')) 201 for eggPlugin in eggPlugins: 202 eggPlugin.modpath = '%s.modeler.plugins.%s' % \ 203 (pack.moduleName(), eggPlugin.modpath) 204 plugins += eggPlugins 205 else: 206 plugins += _loadPluginDir(pack.path('modeler', 'plugins')) 207 except: 208 log.error('Could not load modeler plugins from the %s ZenPack.' \ 209 % str(pack) ) 210 211 except: 212 log.error('Could not load modeler plugins from ZenPacks.' 213 ' One of the ZenPacks is missing or broken.') 214 return plugins
215