def checkRelation(self, repair=False): """Check to make sure that relationship bidirectionality is ok. """ if not self.obj: return log.debug("checking relation: %s", self.id) try: ppath = self.obj.getPrimaryPath() getObjByPath(self, ppath) except (KeyError, NotFound): log.error("object %s in relation %s has been deleted " \ "from its primary path", self.obj.getPrimaryId(), self.getPrimaryId()) if repair: log.warn("removing object %s from relation %s", self.obj.getPrimaryId(), self.getPrimaryId()) self.obj = None if not self.obj: return rname = self.remoteName() rrel = getattr(self.obj, rname) parobj = self.getPrimaryParent() if not rrel.hasobject(parobj): log.error("remote relation %s doesn't point back to %s", rrel.getPrimaryId(), self.getPrimaryId()) if repair: log.warn("reconnecting relation %s to relation %s", rrel.getPrimaryId(), self.getPrimaryId()) rrel._add(parobj)
def checkObjectRelation(self, obj, remoteName, parentObject, repair): deleted = False try: ppath = obj.getPrimaryPath() getObjByPath(self, ppath) except (KeyError, NotFound): log.error("object %s in relation %s has been deleted " \ "from its primary path", obj.getPrimaryId(), self.getPrimaryId()) if repair: log.warn("removing object %s from relation %s", obj.getPrimaryId(), self.getPrimaryId()) self._objects.remove(obj) self.__primary_parent__._p_changed = True deleted = True if not deleted: rrel = getattr(obj, remoteName) if not rrel.hasobject(parentObject): log.error("remote relation %s doesn't point back to %s", rrel.getPrimaryId(), self.getPrimaryId()) if repair: log.warn("reconnecting relation %s to relation %s", rrel.getPrimaryId(),self.getPrimaryId()) rrel._add(parentObject) return deleted
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 processLinks(self): """ Walk through all the links that we saved and link them up """ for (relid, objid) in self.links: try: self.log.debug('Linking relation %s to object %s', relid, objid) rel = getObjByPath(self.app, relid) obj = getObjByPath(self.app, objid) if not rel.hasobject(obj): rel.addRelation(obj) except: self.log.critical('Failed linking relation %s to object %s' % ( relid, objid))
def processLinks(self): """ Walk through all the links that we saved and link them up """ for (relid, objid) in self.links: try: self.log.debug('Linking relation %s to object %s', relid, objid) rel = getObjByPath(self.app, relid) obj = getObjByPath(self.app, objid) if not rel.hasobject(obj): rel.addRelation(obj) except: self.log.critical('Failed linking relation %s to object %s' % (relid, objid))
def _delObject(self, id, dp=1, suppress_events=False): """ Delete object by its absolute id (ie /zport/dmd/bla/bla) (this is sent out in the object*All API) """ obj = getObjByPath(self, id) self.removeRelation(obj, suppress_events=suppress_events)
def __call__(self, deviceIds=(), componentPaths=()): """ @param deviceIds: One ore more device ids under which graphs should be sought @type deviceIds: str, list @param componentPaths: Path(s) to components under which graphs should be sought @type componentPaths: str, list @return: A JSON representation of a list of ids @rtype: "['id1', 'id2', 'id3']" """ graphIds = set() if isinstance(deviceIds, basestring): deviceIds = [deviceIds] if isinstance(componentPaths, basestring): componentPaths = [componentPaths] if not componentPaths: componentPaths = ('',) for devId in deviceIds: thing = self.context.findDevice(devId) if thing: for compPath in componentPaths: if compPath: thing = getObjByPath(thing, compPath) for t in thing.getRRDTemplates(): for g in t.getGraphDefs(): graphIds.add(g.id) return sorted(graphIds)
def __call__(self, deviceIds=(), componentPaths=()): """ @param deviceIds: One ore more device ids under which graphs should be sought @type deviceIds: str, list @param componentPaths: Path(s) to components under which graphs should be sought @type componentPaths: str, list @return: A JSON representation of a list of ids @rtype: "['id1', 'id2', 'id3']" """ graphIds = set() if isinstance(deviceIds, basestring): deviceIds = [deviceIds] if isinstance(componentPaths, basestring): componentPaths = [componentPaths] if not componentPaths: componentPaths = ('', ) for devId in deviceIds: thing = self.context.findDevice(devId) if thing: for compPath in componentPaths: if compPath: thing = getObjByPath(thing, compPath) for t in thing.getRRDTemplates(): for g in t.getGraphDefs(): graphIds.add(g.id) return sorted(graphIds)
def manage_addGraphElement(self, deviceIds='', componentPaths='', graphIds=(), REQUEST=None): """ Add a new graph report element """ def GetId(deviceId, componentPath, graphId): component = componentPath.split('/')[-1] parts = [p for p in (deviceId, component, graphId) if p] root = ' '.join(parts) candidate = self.prepId(root) i = 2 while candidate in self.elements.objectIds(): candidate = self.prepId('%s-%s' % (root, i)) i += 1 return candidate if isinstance(deviceIds, basestring): deviceIds = [deviceIds] if isinstance(componentPaths, basestring): componentPaths = [componentPaths] componentPaths = componentPaths or ('') for devId in deviceIds: dev = self.dmd.Devices.findDevice(devId) # NOTE: There is no much sense to use component, which missed on # device, so we filred components to use only related to # device ones. for cPath in filter(lambda path: dev.id in path, componentPaths) or ['']: try: thing = getObjByPath(dev, cPath) except KeyError: continue else: for graphId in graphIds: graph = thing.getGraphDef(graphId) if graph: newId = thing.name if callable(newId): newId = newId() newId = GetId(devId, cPath, graphId) ge = GraphReportElement(newId) ge.deviceId = dev.titleOrId() ge.componentPath = cPath ge.graphId = graphId ge.sequence = len(self.elements()) self.elements._setObject(ge.id, ge) if REQUEST: audit('UI.Report.AddGraphElement', self.id, graphelement=ge.id) if REQUEST: return self.callZenScreen(REQUEST)
def getThing(self, deviceId, componentPath): """ Return either a device or a component, or None if not found """ thing = self.dmd.Devices.findDevice(deviceId) if thing and componentPath: try: return getObjByPath(thing, componentPath) except KeyError: return None return thing
def getComponentName(self): if self.componentPath: try: dev = self.getDevice() if not dev: return 'Not Found' name = getObjByPath(dev, self.componentPath).name return callable(name) and name() or name except KeyError: return 'Not Found' else: return ''
def checkRelation(self, repair=False): """Check to make sure that relationship bidirectionality is ok. """ if not self.obj: return log.debug("checking relation: %s", self.id) try: ppath = self.obj.getPrimaryPath() getObjByPath(self, ppath) except (KeyError, NotFound): log.error("object %s in relation %s has been deleted " \ "from its primary path", self.obj.getPrimaryId(), self.getPrimaryId()) if repair: log.warn("removing object %s from relation %s", self.obj.getPrimaryId(), self.getPrimaryId()) self.obj = None if not self.obj: return parobj = self.getPrimaryParent() try: rname = self.remoteName() except ZenSchemaError: path = parobj.getPrimaryUrlPath() log.exception("Object %s (parent %s) has a bad schema" % (self.obj, path)) log.warn("Might be able to fix by re-installing ZenPack") return rrel = getattr(self.obj, rname) if not rrel.hasobject(parobj): log.error("remote relation %s doesn't point back to %s", rrel.getPrimaryId(), self.getPrimaryId()) if repair: log.warn("reconnecting relation %s to relation %s", rrel.getPrimaryId(), self.getPrimaryId()) rrel._add(parobj)
def run(self): """Process collectorClients as they are passed in from a data collector. """ log.info("starting applyDataMap thread") while not self.done or not self.inputqueue.empty(): devpath = () try: devpath, collectorClient = self.inputqueue.get(True, 1) self.app._p_jar.sync() device = getObjByPath(self.app, devpath) ApplyDataMap.processClient(self, device, collectorClient) except Queue.Empty: pass except Exception: transaction.abort() log.exception("processing device %s", "/".join(devpath)) log.info("stopping applyDataMap thread")
def getObjByPath(self, path): """ Lookup and object by its path. Basically does a Zope unrestricted traverse on the path given. @type path: list or string /zport/dmd/Devices >>> dmd.getObjByPath(('zport','dmd','Devices')) <DeviceClass at /zport/dmd/Devices> >>> dmd.getObjByPath(('Devices','Server')) <DeviceClass at /zport/dmd/Devices/Server> >>> dmd.getObjByPath('/zport/dmd/Devices/Server') <DeviceClass at /zport/dmd/Devices/Server> >>> dmd.getObjByPath('Devices/Server') <DeviceClass at /zport/dmd/Devices/Server> """ return getObjByPath(self, path)
def manage_addGraphElement(self, deviceIds="", componentPaths="", graphIds=(), REQUEST=None): """ Add a new graph report element """ def GetId(deviceId, componentPath, graphId): component = componentPath.split("/")[-1] parts = [p for p in (deviceId, component, graphId) if p] root = " ".join(parts) candidate = self.prepId(root) i = 2 while candidate in self.elements.objectIds(): candidate = self.prepId("%s-%s" % (root, i)) i += 1 return candidate if isinstance(deviceIds, basestring): deviceIds = [deviceIds] if isinstance(componentPaths, basestring): componentPaths = [componentPaths] componentPaths = componentPaths or ("") for devId in deviceIds: dev = self.dmd.Devices.findDevice(devId) for cPath in componentPaths: try: thing = getObjByPath(dev, cPath) except KeyError: continue else: for graphId in graphIds: graph = thing.getGraphDef(graphId) if graph: newId = thing.name if callable(newId): newId = newId() newId = GetId(devId, cPath, graphId) ge = GraphReportElement(newId) ge.deviceId = dev.titleOrId() ge.componentPath = cPath ge.graphId = graphId ge.sequence = len(self.elements()) self.elements._setObject(ge.id, ge) if REQUEST: return self.callZenScreen(REQUEST)
def zodb(db, userid, log): """Return the DMD context via contextmanager protocol. :param db: ZODB database connection. :param str userid: The ID of the user to authenticate with. """ session = db.open() try: mlog.debug("Started ZODB session") root = session.root() application = _getContext(root["Application"]) dataroot = getObjByPath(application, "/zport/dmd") user = _login(dataroot, userid=userid) setDescriptors(dataroot) log_mesg = ("Authenticated as user %s", user.getUserName()) log.info(*log_mesg) mlog.debug(*log_mesg) try: yield dataroot finally: noSecurityManager() finally: session.close() mlog.debug("Finished ZODB session")
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 getDataRoot(self): if not self.app: self.opendb() if not self.dataroot: self.dataroot = getObjByPath(self.app, self.options.dataroot) self.dmd = self.dataroot
def transactional_actions(): # Instantiate ZenPack entryMap = pkg_resources.get_entry_map(dist, ZENPACK_ENTRY_POINT) if not entryMap or len(entryMap) > 1: raise ZenPackException('A ZenPack egg must contain exactly one' ' zenoss.zenpacks entry point. This egg appears to contain' ' %s such entry points.' % len(entryMap)) packName, packEntry = entryMap.items()[0] runExternalZenpack = True #if zenpack with same name exists we can't load both modules #installing new egg zenpack will be done in a sub process existing = dmd.ZenPackManager.packs._getOb(packName, None) if existing: log.info("Previous ZenPack exists with same name %s" % packName) if filesOnly or not existing: #running files only or zenpack by same name doesn't already exists # so no need to install the zenpack in an external process runExternalZenpack = False module = packEntry.load() if hasattr(module, 'ZenPack'): zenPack = module.ZenPack(packName) else: zenPack = ZenPack(packName) zenPack.eggPack = True CopyMetaDataToZenPackObject(dist, zenPack) if filesOnly: for loader in (ZPL.ZPLDaemons(), ZPL.ZPLBin(), ZPL.ZPLLibExec()): loader.load(zenPack, None) if fromUI and not zenPack.installableFromUI: raise ZenPackException("This ZenPack cannot be installed through the UI.") if not filesOnly: # Look for an installed ZenPack to be upgraded. In this case # upgraded means that it is removed before the new one is installed # but that its objects are not removed and the packables are # copied to the new instance. existing = dmd.ZenPackManager.packs._getOb(packName, None) if not existing and zenPack.prevZenPackName: existing = dmd.ZenPackManager.packs._getOb( zenPack.prevZenPackName, None) deferFileDeletion = False packables = [] upgradingFrom = None if existing: upgradingFrom = existing.version for p in existing.packables(): packables.append(p) existing.packables.removeRelation(p) if existing.isEggPack(): forceNoFileDeletion = existing.eggPath() == dist.location RemoveZenPack(dmd, existing.id, skipDepsCheck=True, leaveObjects=True, forceNoFileDeletion=forceNoFileDeletion, uninstallEgg=False) else: # Don't delete files, might still be needed for # migrate scripts to be run below. deferFileDeletion = True oldzenpack.RemoveZenPack(dmd, existing.id, skipDepsCheck=True, leaveObjects=True, deleteFiles=False) if runExternalZenpack or forceRunExternal: log.info("installing zenpack %s; launching process" % packName) cmd = [binPath('zenpack')] if link: cmd += ["--link"] cmd += ["--install", eggPath] if upgradingFrom: cmd += ['--previousversion', upgradingFrom] if fromUI: cmd += ["--fromui"] if serviceId: cmd += ['--service-id', serviceId] cmdStr = " ".join(cmd) log.debug("launching sub process command: %s" % cmdStr) p = subprocess.Popen(cmdStr, shell=True) out, err = p.communicate() p.wait() if p.returncode: raise ZenPackException('Error installing the egg (%s): %s' % (p.returncode, err)) dmd._p_jar.sync() else: dmd.ZenPackManager.packs._setObject(packName, zenPack) zenPack = dmd.ZenPackManager.packs._getOb(packName) #hack because ZenPack.install is overridden by a lot of zenpacks #so we can't change the signature of install to take the #previousVerison zenPack.prevZenPackVersion = previousVersion zenPack.install(dmd) zenPack.prevZenPackVersion = None try: zenPack = dmd.ZenPackManager.packs._getOb(packName) for p in packables: pId = p.getPrimaryId() try: # make sure packable still exists; could be deleted by a # migrate getObjByPath(dmd, pId) log.debug("adding packable relation for id %s", pId) zenPack.packables.addRelation(p) except (KeyError, zExceptions.NotFound): log.debug('did not find packable %s',pId) except AttributeError, e: # If this happens in the child process or during the non-upgrade # flow, reraise the exception if not runExternalZenpack: raise # This specific error will occur when the version of the ZenPack # being installed subclasses Products.ZenModel.ZenPack, but the # previous version of the ZenPack did not. if str(e) == "'ZenPack' object has no attribute '__of__'": zenPack = ZenPack(packName) else: # This is the signature error of class-loading issues # during zenpack upgrade. The final state should be okay, # except that modified packables may be lost. message = "There has been an error during the post-" + \ "installation steps for the zenpack %s. In " + \ "most cases, no further action is required. If " + \ "issues persist, please reinstall this zenpack." message = message % packName log.warning( message ) raise NonCriticalInstallError( message ) cleanupSkins(dmd) return zenPack, deferFileDeletion, existing
def transactional_actions(): # Instantiate ZenPack entryMap = pkg_resources.get_entry_map(dist, ZENPACK_ENTRY_POINT) if not entryMap or len(entryMap) > 1: raise ZenPackException( 'A ZenPack egg must contain exactly one' ' zenoss.zenpacks entry point. This egg appears to contain' ' %s such entry points.' % len(entryMap)) packName, packEntry = entryMap.items()[0] runExternalZenpack = True #if zenpack with same name exists we can't load both modules #installing new egg zenpack will be done in a sub process existing = dmd.ZenPackManager.packs._getOb(packName, None) if existing: log.info("Previous ZenPack exists with same name %s" % packName) if filesOnly or not existing: #running files only or zenpack by same name doesn't already exists # so no need to install the zenpack in an external process runExternalZenpack = False module = packEntry.load() if hasattr(module, 'ZenPack'): zenPack = module.ZenPack(packName) else: zenPack = ZenPack(packName) zenPack.eggPack = True CopyMetaDataToZenPackObject(dist, zenPack) if filesOnly: for loader in (ZPL.ZPLDaemons(), ZPL.ZPLBin(), ZPL.ZPLLibExec()): loader.load(zenPack, None) if fromUI and not zenPack.installableFromUI: raise ZenPackException( "This ZenPack cannot be installed through the UI.") if not filesOnly: # Look for an installed ZenPack to be upgraded. In this case # upgraded means that it is removed before the new one is installed # but that its objects are not removed and the packables are # copied to the new instance. existing = dmd.ZenPackManager.packs._getOb(packName, None) if not existing and zenPack.prevZenPackName: existing = dmd.ZenPackManager.packs._getOb( zenPack.prevZenPackName, None) deferFileDeletion = False packables = [] upgradingFrom = None if existing: upgradingFrom = existing.version for p in existing.packables(): packables.append(p) existing.packables.removeRelation(p) if existing.isEggPack(): forceNoFileDeletion = existing.eggPath() == dist.location RemoveZenPack(dmd, existing.id, skipDepsCheck=True, leaveObjects=True, forceNoFileDeletion=forceNoFileDeletion, uninstallEgg=False) else: # Don't delete files, might still be needed for # migrate scripts to be run below. deferFileDeletion = True oldzenpack.RemoveZenPack(dmd, existing.id, skipDepsCheck=True, leaveObjects=True, deleteFiles=False) if runExternalZenpack or forceRunExternal: log.info("installing zenpack %s; launching process" % packName) cmd = [binPath('zenpack')] if link: cmd += ["--link"] cmd += ["--install", eggPath] if upgradingFrom: cmd += ['--previousversion', upgradingFrom] if fromUI: cmd += ["--fromui"] cmdStr = " ".join(cmd) log.debug("launching sub process command: %s" % cmdStr) p = subprocess.Popen(cmdStr, shell=True) out, err = p.communicate() p.wait() if p.returncode: raise ZenPackException( 'Error installing the egg (%s): %s' % (p.returncode, err)) dmd._p_jar.sync() else: dmd.ZenPackManager.packs._setObject(packName, zenPack) zenPack = dmd.ZenPackManager.packs._getOb(packName) #hack because ZenPack.install is overridden by a lot of zenpacks #so we can't change the signature of install to take the #previousVerison zenPack.prevZenPackVersion = previousVersion zenPack.install(dmd) zenPack.prevZenPackVersion = None try: zenPack = dmd.ZenPackManager.packs._getOb(packName) for p in packables: pId = p.getPrimaryId() try: # make sure packable still exists; could be deleted by a # migrate getObjByPath(dmd, pId) log.debug("adding packable relation for id %s", pId) zenPack.packables.addRelation(p) except (KeyError, zExceptions.NotFound): log.debug('did not find packable %s', pId) except AttributeError, e: # If this happens in the child process or during the non-upgrade # flow, reraise the exception if not runExternalZenpack: raise # This specific error will occur when the version of the ZenPack # being installed subclasses Products.ZenModel.ZenPack, but the # previous version of the ZenPack did not. if str(e) == "'ZenPack' object has no attribute '__of__'": zenPack = ZenPack(packName) else: # This is the signature error of class-loading issues # during zenpack upgrade. The final state should be okay, # except that modified packables may be lost. message = "There has been an error during the post-" + \ "installation steps for the zenpack %s. In " + \ "most cases, no further action is required. If " + \ "issues persist, please reinstall this zenpack." message = message % packName log.warning(message) raise NonCriticalInstallError(message) cleanupSkins(dmd) return zenPack, deferFileDeletion, existing
def getDmdObj(self, path): """return an object based on a path starting from the dmd""" return getObjByPath(self.app, self.options.dataroot + path)
def getDmdObj(self, path): """return an object based on a path starting from the dmd""" return getObjByPath(self.app, self.options.dataroot+path)