def _loadThresholdClasses(self, thresholdClasses): self.log.debug("Loading classes %s", thresholdClasses) for c in thresholdClasses: try: importClass(c) except ImportError: log.exception("Unable to import class %s", c)
def _getService(self, name, instance): """Utility method to create the service (like PingConfig) for instance (like localhost) @type name: string @param name: the dotted-name of the module to load (uses @L{Products.ZenUtils.Utils.importClass}) @param instance: string @param instance: each service serves only one specific collector instances (like 'localhost'). instance defines the collector's instance name. @return: a service loaded from ZenHub/services or one of the zenpacks. """ try: return self.services[name, instance] except KeyError: from Products.ZenUtils.Utils import importClass try: ctor = importClass(name) except ImportError: ctor = importClass('Products.ZenHub.services.%s' % name, name) svc = ctor(self.dmd, instance) self.services[name, instance] = svc # dict for tracking statistics on method calls invoked on this service, # including number of times called and total elapsed time, keyed # by method name svc.callStats = defaultdict(_CumulativeWorkerStats) return svc
def _importPluginClass(self, name): """ Find the named plugin and import it. """ klass = None if name.startswith('/'): if name.endswith('.py'): name = name.replace('.py', '') if os.path.exists(name + '.py'): try: d, name = name.rsplit('/', 1) sys.path.insert(0, d) klass = importClass(name) finally: sys.path.remove(d) else: for d in self._getPluginDirectories(): if os.path.exists('%s/%s.py' % (d, name)): try: sys.path.insert(0, d) klass = importClass(name) break finally: sys.path.remove(d) return klass
def remote_updateThresholdClasses(self, classes): from Products.ZenUtils.Utils import importClass self.log.debug("Loading classes %s", classes) for c in classes: try: importClass(c) except ImportError: self.log.error("Unable to import class %s", c)
def migrate(self, previousVersion=None): """ Migrate to a new version @param previousVersion: previous version number @type previousVersion: string """ instances = [] # find all the migrate modules root = self.path("migrate") for p, ds, fs in os.walk(root): for f in fs: if f.endswith('.py') and not f.startswith("__"): path = os.path.join(p[len(root) + 1:], f) log.debug("Loading %s", path) sys.path.insert(0, p) try: try: c = importClass(path[:-3].replace("/", ".")) instances.append(c()) finally: sys.path.remove(p) except ImportError, ex: log.exception("Problem loading migration step %s", path)
def testClassLoading(self): """ Test that the class can be imported from the module dynamically """ moduleName = "ZenPacks.zenoss.NtpMonitor.datasources.NtpMonitorDataSource" className = "NtpMonitorDataSource" constructor = importClass(moduleName, className) self.assert_(constructor is not None)
def createObject(self, attrs): """ Create an object and set it into its container @param attrs: attrs @type attrs: string @return: newly created object @rtype: object """ # Does the object exist already? id = attrs.get('id') obj = None try: if id.startswith('/'): obj = getObjByPath2(self.app, id) else: obj = self.context()._getOb(id) except (KeyError, AttributeError, NotFound): pass if obj is None: klass = importClass(attrs.get('module'), attrs.get('class')) if id.find('/') > -1: (contextpath, id) = os.path.split(id) try: pathobj = getObjByPath(self.context(), contextpath) except (KeyError, AttributeError, NotFound): self.log.warn( "Unable to find context path %s (line %s ?) for %s" % ( contextpath, self._locator.getLineNumber(), id )) if not self.options.noCommit: self.log.warn( "Not committing any changes" ) self.options.noCommit = True return None self.objstack.append(pathobj) self.log.debug('Building instance %s of class %s',id,klass.__name__) try: if klass.__name__ == 'AdministrativeRole': user = [x for x in self.dmd.ZenUsers.objectValues() if x.id == id] if user: obj = klass(user[0], self.context().device()) else: msg = "No AdminRole user %s exists (line %s)" % ( id, self._locator.getLineNumber()) self.log.error(msg) raise Exception(msg) else: obj = klass(id) except TypeError, ex: # This happens when the constructor expects more arguments self.log.exception("Unable to build %s instance of class %s (line %s)", id, klass.__name__, self._locator.getLineNumber()) raise self.context()._setObject(obj.id, obj) obj = self.context()._getOb(obj.id) self.objectnumber += 1 self.uncommittedObjects += 1 self.log.debug('Added object %s to database' % obj.getPrimaryId())
def getService(self, name, instance): """ Helper method to load services dynamically for a collector. Returned instances are cached: reconnecting collectors will get the same service object. @type name: string @param name: the dotted-name of the module to load (uses @L{Products.ZenUtils.Utils.importClass}) @param instance: string @param instance: each service serves only one specific collector instances (like 'localhost'). instance defines the collector's instance name. @return: a service loaded from ZenHub/services or one of the zenpacks. """ # Sanity check the names given to us if not self.dmd.Monitors.Performance._getOb(instance, False): raise RemoteBadMonitor( "The provided performance monitor '%s'" % instance + " is not in the current list", None) try: return self.services[name, instance] except KeyError: from Products.ZenUtils.Utils import importClass try: ctor = importClass(name) except ImportError: ctor = importClass('Products.ZenHub.services.%s' % name, name) try: svc = ctor(self.dmd, instance) except Exception: self.log.exception("Failed to initialize %s", ctor) # Module can't be used, so unload it. if ctor.__module__ in sys.modules: del sys.modules[ctor.__module__] return None else: if self.options.workers: svc = WorkerInterceptor(self, svc) self.services[name, instance] = svc notify(ServiceAddedEvent(name, instance)) return svc
def _createRelObject(self, device, objmap, relname): """Create an object on a relationship using its objmap. """ constructor = importClass(objmap.modname, objmap.classname) if hasattr(objmap, 'id'): remoteObj = constructor(objmap.id) else: remoteObj = constructor(device, objmap) if remoteObj is None: log.debug("Constructor returned None") return False, None id = remoteObj.id if not remoteObj: raise ObjectCreationError( "failed to create object %s in relation %s" % (id, relname)) realdevice = device.device() if realdevice.isLockedFromUpdates(): objtype = "" try: objtype = objmap.modname.split(".")[-1] except: pass msg = "Add Blocked: %s '%s' on %s" % (objtype, id, realdevice.id) log.warn(msg) if realdevice.sendEventWhenBlocked(): self.logEvent(realdevice, id, Change_Add_Blocked, msg, Event.Warning) return False, None rel = device._getOb(relname, None) if not rel: raise ObjectCreationError( "No relation %s found on device %s (%s)" % (relname, device.id, device.__class__)) #"No relation %s found on device %s" % (relname, device.id)) changed = False try: remoteObj = rel._getOb(remoteObj.id) except AttributeError: self.logChange( realdevice, remoteObj, Change_Add, "adding object %s to relationship %s" % (remoteObj.id, relname)) rel._setObject(remoteObj.id, remoteObj) remoteObj = rel._getOb(remoteObj.id) changed = True if not isinstance(rel, ToManyContRelationship): notify( ObjectMovedEvent(remoteObj, rel, remoteObj.id, rel, remoteObj.id)) up_changed = self._updateObject(remoteObj, objmap) self.num_obj_changed += 1 if not up_changed and changed else 0 return up_changed or changed, remoteObj
def getTargetPythonClass(self): """ Returns the python class object that this template can be bound to. """ from Products.ZenModel.Device import Device cname = getattr(self, "targetPythonClass", None) if cname: try: return importClass(cname) except ImportError: log.exception("Unable to import class " + cname) return Device
def run(self): service = self.options.service if not service: raise RuntimeError("You must specify a service") try: cls = importClass(service) except ImportError: path = os.path.abspath(service) if os.path.isfile(service): dir_ = os.path.dirname(path) sys.path.append(dir_) name = re.findall(r"/?([A-Za-z]+[A-Za-z0-9])*\.", service)[0] cls = importClass(name) service = cls(self.dmd, "localhost") method = getattr(service, self.options.method) results = method(self.args) for result in results: pp(vars(result))
def __addservice(self, name, monitor): try: cls = importClass(name) except ImportError: try: cls = importClass("Products.ZenHub.services.%s" % name, name) except ImportError: raise UnknownServiceError(str(name)) try: # Will it construct/initialize? svc = cls(self.__dmd, monitor) except Exception: # Module can't be used, so unload it. if cls.__module__ in sys.modules: del sys.modules[cls.__module__] raise else: svc = self.__factory.build(svc, name, monitor) self.__services[name, monitor] = svc notify(ServiceAddedEvent(name, monitor)) return svc
def get_imported_class(self, classname): """import target class by reference""" # this might be provided by the ZenPack but not defined in the YAML if '.' not in classname: classname = '{}.{}.{}'.format(self.zenpack_spec.name, classname, classname) if '.' in classname and classname.split('.')[-1] not in self.zenpack_spec.classes: module = ".".join(classname.split('.')[0:-1]) try: kls = importClass(module) self.zenpack_spec.imported_classes[classname] = kls except ImportError as e: self.LOG.error('Failed to import class {} from {} ({})'.format(classname, module, e)) pass
def _getClassesByPath(self, name): dsClasses = [] for path, dirs, files in os.walk(self.path(name)): dirs[:] = [d for d in dirs if not d.startswith('.')] for f in files: if not f.startswith('.') \ and f.endswith('.py') \ and not f == '__init__.py': subPath = path[len(self.path()):] parts = subPath.strip('/').split('/') parts.append(f[:f.rfind('.')]) modName = '.'.join([self.moduleName()] + parts) dsClasses.append(importClass(modName)) return dsClasses
def get_imported_class(self, classname): """import target class by reference""" # this might be provided by the ZenPack but not defined in the YAML if '.' not in classname: classname = '{}.{}.{}'.format(self.zenpack_spec.name, classname, classname) if '.' in classname and classname.split( '.')[-1] not in self.zenpack_spec.classes: module = ".".join(classname.split('.')[0:-1]) try: kls = importClass(module) self.zenpack_spec.imported_classes[classname] = kls except ImportError as e: self.LOG.error('Failed to import class {} from {} ({})'.format( classname, module, e)) pass
def _createRelObject(self, device, objmap, relname): """Create an object on a relationship using its objmap. """ constructor = importClass(objmap.modname, objmap.classname) if hasattr(objmap, 'id'): remoteObj = constructor(objmap.id) else: remoteObj = constructor(device, objmap) if remoteObj is None: log.debug("Constructor returned None") return False, None id = remoteObj.id if not remoteObj: raise ObjectCreationError( "failed to create object %s in relation %s" % (id, relname)) realdevice = device.device() if realdevice.isLockedFromUpdates(): objtype = "" try: objtype = objmap.modname.split(".")[-1] except Exception: pass msg = "Add Blocked: %s '%s' on %s" % ( objtype, id, realdevice.id) log.warn(msg) if realdevice.sendEventWhenBlocked(): self.logEvent(realdevice, id, Change_Add_Blocked, msg, Event.Warning) return False, None rel = device._getOb(relname, None) if not rel: raise ObjectCreationError( "No relation %s found on object %s (%s)" % (relname, device.id, device.__class__ )) changed = False try: remoteObj = rel._getOb(remoteObj.id) except AttributeError: self.logChange(realdevice, remoteObj, Change_Add, "adding object %s to relationship %s" % (remoteObj.id, relname)) rel._setObject(remoteObj.id, remoteObj) remoteObj = rel._getOb(remoteObj.id) changed = True if not isinstance(rel, ToManyContRelationship): notify(ObjectMovedEvent(remoteObj, rel, remoteObj.id, rel, remoteObj.id)) up_changed = self._updateObject(remoteObj, objmap) self.num_obj_changed += 1 if not up_changed and changed else 0 return up_changed or changed, remoteObj
def _create_object(object_map, parent_device=None): '''Create a new zodb object from an ObjectMap ''' parent = getattr(object_map, '_parent', None) constructor = importClass(object_map.modname, object_map.classname) if hasattr(object_map, 'id'): new_object = constructor(object_map.id) elif parent: new_object = constructor(parent, object_map) elif parent_device: new_object = constructor(parent_device, object_map) else: log.error('_create_object requires object_map.id or parent_device') new_object = None return new_object
def getPythonDeviceClass(self): """ Return the Python class object to be used for device instances in this device class. This is done by walking up the aq_chain of a deviceclass to find a node that has the same name as a Python class or has an attribute named zPythonClass that matches a Python class. @return: device class @rtype: device class """ from Device import Device cname = getattr(self, "zPythonClass", None) if cname: try: return importClass(cname) except ImportError: log.exception("Unable to import class " + cname) return Device
def remove(self, app, leaveObjects=False): if self._v_specparams is None: return from Products.Zuul.interfaces import ICatalogTool if leaveObjects: # Check whether the ZPL-managed monitoring templates have # been modified by the user. If so, those changes will # be lost during the upgrade. # # Ideally, I would inspect self.packables() to find these # objects, but we do not have access to that relationship # at this point in the process. for dcname, dcspec in self._v_specparams.device_classes.iteritems(): deviceclass = dcspec.get_organizer(app.zport.dmd) if not deviceclass: self.LOG.warning( "DeviceClass {} has been removed at some point " "after the {} ZenPack was installed. It will be " "reinstated if this ZenPack is upgraded or reinstalled".format( dcname, self.id)) continue for orig_mtname, orig_mtspec in dcspec.templates.iteritems(): # attempt to find an existing template template = self.get_object(deviceclass, 'rrdTemplates', orig_mtname) # back it up if it exists if template: self.get_or_create_backup(deviceclass, 'rrdTemplates', orig_mtname) else: self.LOG.warning( "Monitoring template {}/{} has been removed at some point " "after the {} ZenPack was installed. It will be " "reinstated if this ZenPack is upgraded or reinstalled".format( dcname, orig_mtname, self.id)) else: dc = app.Devices for catalog in self.GLOBAL_CATALOGS: catObj = getattr(dc, catalog, None) if catObj: self.LOG.info('Removing Catalog {}'.format(catalog)) dc._delObject(catalog) if self.NEW_COMPONENT_TYPES: self.LOG.info('Removing {} components'.format(self.id)) cat = ICatalogTool(app.zport.dmd) for brain in cat.search(types=self.NEW_COMPONENT_TYPES): try: component = brain.getObject() except Exception as e: self.LOG.error("Trying to remove non-existent object {}".format(e)) continue else: component.getPrimaryParent()._delObject(component.id) # Remove our Device relations additions. from Products.ZenUtils.Utils import importClass for device_module_id in self.NEW_RELATIONS: Device = importClass(device_module_id) Device._relations = tuple([x for x in Device._relations if x[0] not in self.NEW_RELATIONS[device_module_id]]) self.LOG.info('Removing {} relationships from existing devices.'.format(self.id)) self._buildDeviceRelations(app) for dcname, dcspec in self.device_classes.iteritems(): dcspec.remove_organizer(app.zport.dmd, self) for ecname, ecspec in self.event_classes.iteritems(): ecspec.remove_organizer(app.zport.dmd, self) for pcname, pcspec in self.process_class_organizers.iteritems(): pcspec.remove_organizer_or_subs( app.zport.dmd, 'process_classes', 'removeOSProcessClasses', self) super(ZenPack, self).remove(app, leaveObjects=leaveObjects)
def importPlugin(self, package, modPath): # ZenPack plugins are specified absolutely; we can import # them using the old method return importClass(modPath)
def createObject(self, attrs): """ Create an object and set it into its container @param attrs: attrs @type attrs: string @return: newly created object @rtype: object """ # Does the object exist already? id = attrs.get('id') obj = None try: if id.startswith('/'): obj = getObjByPath(self.app, id) else: obj = self.context()._getOb(id) except (KeyError, AttributeError, NotFound): pass if obj is None: klass = importClass(attrs.get('module'), attrs.get('class')) if id.find('/') > -1: (contextpath, id) = os.path.split(id) try: pathobj = getObjByPath(self.context(), contextpath) except (KeyError, AttributeError, NotFound): self.log.warn( "Unable to find context path %s (line %s ?) for %s" % (contextpath, self._locator.getLineNumber(), id)) if not self.options.noCommit: self.log.warn("Not committing any changes") self.options.noCommit = True return None self.objstack.append(pathobj) self.log.debug('Building instance %s of class %s', id, klass.__name__) try: if klass.__name__ == 'AdministrativeRole': user = [ x for x in self.dmd.ZenUsers.objectValues() if x.id == id ] if user: obj = klass(user[0], self.context().device()) else: msg = "No AdminRole user %s exists (line %s)" % ( id, self._locator.getLineNumber()) self.log.error(msg) raise Exception(msg) else: obj = klass(id) except TypeError, ex: # This happens when the constructor expects more arguments self.log.exception( "Unable to build %s instance of class %s (line %s)", id, klass.__name__, self._locator.getLineNumber()) raise self.context()._setObject(obj.id, obj) obj = self.context()._getOb(obj.id) self.objectnumber += 1 self.log.debug('Added object %s to database' % obj.getPrimaryId())
def remove(self, app, leaveObjects=False): if self._v_specparams is None: return from Products.Zuul.interfaces import ICatalogTool if leaveObjects: # Check whether the ZPL-managed monitoring templates have # been modified by the user. If so, those changes will # be lost during the upgrade. # # Ideally, I would inspect self.packables() to find these # objects, but we do not have access to that relationship # at this point in the process. for dcname, dcspec in self._v_specparams.device_classes.iteritems( ): deviceclass = dcspec.get_organizer(app.zport.dmd) if not deviceclass: self.LOG.warning( "DeviceClass {} has been removed at some point " "after the {} ZenPack was installed. It will be " "reinstated if this ZenPack is upgraded or reinstalled" .format(dcname, self.id)) continue for orig_mtname, orig_mtspec in dcspec.templates.iteritems(): # attempt to find an existing template template = self.get_object(deviceclass, 'rrdTemplates', orig_mtname) # back it up if it exists if template: self.get_or_create_backup(deviceclass, 'rrdTemplates', orig_mtname) else: self.LOG.warning( "Monitoring template {}/{} has been removed at some point " "after the {} ZenPack was installed. It will be " "reinstated if this ZenPack is upgraded or reinstalled" .format(dcname, orig_mtname, self.id)) else: dc = app.Devices for catalog in self.GLOBAL_CATALOGS: catObj = getattr(dc, catalog, None) if catObj: self.LOG.info('Removing Catalog {}'.format(catalog)) dc._delObject(catalog) if self.NEW_COMPONENT_TYPES: self.LOG.info('Removing {} components'.format(self.id)) cat = ICatalogTool(app.zport.dmd) for brain in cat.search(types=self.NEW_COMPONENT_TYPES): try: component = brain.getObject() except Exception as e: self.LOG.error( "Trying to remove non-existent object {}".format( e)) continue else: component.getPrimaryParent()._delObject(component.id) # Remove our Device relations additions. from Products.ZenUtils.Utils import importClass for device_module_id in self.NEW_RELATIONS: Device = importClass(device_module_id) Device._relations = tuple([ x for x in Device._relations if x[0] not in self.NEW_RELATIONS[device_module_id] ]) self.LOG.info( 'Removing {} relationships from existing devices.'.format( self.id)) self._buildDeviceRelations(app) for dcname, dcspec in self.device_classes.iteritems(): if dcspec.remove: self.remove_device_class(app, dcspec) # Remove EventClasses with remove flag set self.remove_organizer_or_subs(app.zport.dmd.Events, self.event_classes, 'mappings', 'removeInstances') # Remove Process Classes/Organizers with remove flag set self.remove_organizer_or_subs(app.zport.dmd.Processes, self.process_class_organizers, 'process_classes', 'removeOSProcessClasses') super(ZenPack, self).remove(app, leaveObjects=leaveObjects)