def updateTrigger(self, **data): data['rule']['api_version'] = 1 data['rule']['type'] = RULE_TYPE_JYTHON triggerUid = data['uuid'] response = self._getFacade().updateTrigger(**data) audit('UI.Trigger.Edit', triggerUid, data_=data) return DirectResponse.succeed(msg="Trigger updated successfully.", data=response)
def manage_editAdministrativeRoles(self, ids=(), role=(), REQUEST=None): """Edit list of admin roles. """ if isinstance(ids, basestring): ids = [ids] role = [role] else: ids = list(ids) for ar in self.adminRoles(): mobj = ar.managedObject() try: i = ids.index(mobj.managedObjectName()) except ValueError: continue mobj = mobj.primaryAq() mobj.manage_editAdministrativeRoles(self.id, role[i]) if REQUEST: audit('UI.User.EditAdministrativeRole', username=self.id, data_={mobj.meta_type:mobj.getPrimaryId()}, role=role[i]) if REQUEST: if ids: messaging.IMessageSender(self).sendToBrowser( 'Roles Updated', "Administrative roles were updated." ) return self.callZenScreen(REQUEST)
def manage_deleteBackups(self, fileNames=(), REQUEST=None): """ Delete the specified files from $ZENHOME/backups """ backupsDir = zenPath('backups') removed = [] if os.path.isdir(backupsDir): for dirPath, dirNames, dirFileNames in os.walk(backupsDir): dirNames[:] = [] for fileName in fileNames: if fileName in dirFileNames: toRemove = os.path.join(dirPath, fileName) res = os.remove(toRemove) if not res: removed.append(toRemove) if REQUEST: audit('UI.Backup.Delete', files=removed) messaging.IMessageSender(self).sendToBrowser( 'Backups Deleted', '%s backup files have been deleted.' % len(removed) ) else: if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Backup Directory Missing', 'Unable to find $ZENHOME/backups.', messaging.WARNING ) if REQUEST: return self.callZenScreen(REQUEST)
def deleteNode(self, uid): """ Remove a report or report organizer. @type uid: string @param uid: The UID of the node to delete @rtype: [dictionary] @return: B{Properties}: - tree: (dictionary) Object representing the new Reports tree """ # make sure we are not deleting a required node if uid in essentialReportOrganizers: raise Exception('You cannot delete this organizer') # Getting all of the child nodes for auditing purposes node = self.context.dmd.unrestrictedTraverse(uid) brains = ICatalogTool(node).search((ReportClass,BaseReport)) family = [] for brain in brains: family.append([brain.getPath(), isinstance(brain.getObject(), ReportClass)]) self._getFacade().deleteNode(uid) # Audit messaging for name, isOrganizer in family: if isOrganizer: audit('UI.Organizer.Delete', name) else: audit('UI.Report.Delete', name) contextUid = '/'.join(uid.split('/')[:-1]) return self._getTreeUpdates(contextUid)
def addNode(self, contextUid='', id='', type=''): """ Add an organizer or new blank MIB. @type contextUid: string @param contextUid: Context to attach new node @type id: string @param id: Id of the new orgainzer or blank MIB @type type: string @param type: Type of new node. Can be 'organizer' or 'MIB' @rtype: DirectResponse @return: B{Properties}: - tree: ([dictionary]) Object representing the new tree """ # GAH! JS passes back a keyword of 'type' nodeType = type if nodeType not in ['organizer', 'MIB']: return DirectResponse.fail('Not creating "%s"' % nodeType) try: if nodeType == 'organizer': uid = contextUid + '/' + id maoUid = uid.replace('/zport/dmd', '') self.context.dmd.Mibs.manage_addOrganizer(maoUid) self.context.dmd.restrictedTraverse(uid) audit('UI.Organizer.Add', uid) else: container = self.context.dmd.restrictedTraverse(contextUid) container.manage_addMibModule(id) audit('UI.Mib.Add', contextUid + '/' + id) return DirectResponse.succeed(tree=self.getTree()) except Exception, e: return DirectResponse.exception(e)
def manage_deleteMaintenanceWindow(self, maintenanceIds=(), REQUEST=None): "Delete a Maintenance Window to this device" if isinstance(maintenanceIds, basestring): maintenanceIds = [maintenanceIds] for id in maintenanceIds: mw = getattr(self.maintenanceWindows, id) if mw.started: if REQUEST: msg = "Closing and removing maintenance window " \ "%s which affects %s" % ( mw.displayName(), self.id) log.info(msg) messaging.IMessageSender(self).sendToBrowser( 'Window Stopping', msg, ) mw.end() if REQUEST: audit('UI.MaintenanceWindow.Delete', mw) self.maintenanceWindows._delObject(id) if hasattr(self, 'setLastChange'): # Only Device and DeviceClass have setLastChange for now. self.setLastChange() if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Windows Deleted', 'Maintenance windows deleted: %s' % ', '.join(maintenanceIds) ) return self.callZenScreen(REQUEST)
def deleteTrap(self, uid): if uid.find('/notifications/') == -1: return DirectResponse.fail('"%s" does not appear to refer to a trap' % uid) mibUid, trapId = uid.split('/notifications/') self.api.deleteTrap(mibUid, trapId) audit('UI.Mib.DeleteTrap', mibUid, trap=trapId) return DirectResponse.succeed()
def setInfo(self, **data): """ Set attributes on an object. This method accepts any keyword argument for the property that you wish to set. The only required property is "uid". @type uid: string @keyword uid: Unique identifier of an object @rtype: DirectResponse @return: B{Properties}: - data: (dictionary) The modified object """ uid = data['uid'] del data['uid'] obj = self._getFacade()._getObject(uid) passwordFields = self._getPasswordFields(obj) oldData = self._getInfoData(obj, data) info = self._getFacade().setInfo(uid, data) newData = self._getInfoData(obj, data) # Trac #29376: Consistently show thresholdType with threshold operations. thresholdType = obj.getTypeName() if isinstance(obj, ThresholdClass) else None audit(['UI', getDisplayType(obj), 'Edit'], obj, thresholdType=thresholdType, data_=newData, oldData_=oldData, skipFields_=('newId',), # special case in TemplateFacade.setInfo() maskFields_=passwordFields) return DirectResponse.succeed(data=Zuul.marshal(info))
def clear_device_heartbeats(self, params, limit=None): """ @type params: dictionary @param params: Key-value pair of filters for this search. """ if isinstance(params, basestring): params = loads(params) device = params['device'] log.debug('Clearing heartbeats for device: {device}'.format(device=device)) params['eventState'] = [STATUS_NEW, STATUS_ACKNOWLEDGED] params['eventClass'] = '/Status/Heartbeat' includeFilter, excludeFilter = self._buildRequestFilters(None, params, None, None) status, summaryUpdateResponse = self.zep.closeEventSummaries( eventFilter=includeFilter, exclusionFilter=excludeFilter, limit=limit, ) log.debug('Done clearing heartbeats for device: {device}'.format(device=device)) log.debug(summaryUpdateResponse) audit('UI.Device.ClearHeartbeats', device=device) return DirectResponse.succeed(data=summaryUpdateResponse)
def manage_deleteOrganizers(self, organizerPaths=None, REQUEST=None): """ Delete a list of Organizers from the database using their ids. @param organizerPaths: Names of organizer to be deleted @type organizerPaths: list @permission: ZEN_DELETE >>> dmd.Devices.manage_deleteOrganizers(['/Devices/Server/Linux', ... '/Devices/Server/Windows']) """ if not organizerPaths: messaging.IMessageSender(self).sendToBrowser( 'Error', 'No organizers were specified.', priority=messaging.WARNING ) return self.callZenScreen(REQUEST) for organizerName in organizerPaths: if REQUEST: audit(('UI',getDisplayType(self),'Delete'), organizerName) self.manage_deleteOrganizer(organizerName) if REQUEST: plural = '' if len(organizerPaths) > 1: plural = 's' messaging.IMessageSender(self).sendToBrowser( 'Organizers Deleted', '%s%s %s were deleted.' % (getDisplayType(self), plural, ', '.join(organizerPaths)) ) return self.callZenScreen(REQUEST)
def addThreshold(self, **data): """ Add a threshold. @type uid: string @keyword uid: Unique identifier of template to add threshold to @type thresholdType: string @keyword thresholdType: Type of the new threshold. From getThresholdTypes() @type thresholdId: string @keyword thresholdId: ID of the new threshold @type dataPoints: [string] @keyword dataPoints: List of data points to select for this threshold @rtype: DirectResponse @return: Success message """ uid = data['uid'] thresholdType = data['thresholdType'] thresholdId = data['thresholdId'] dataPoints = data.get('dataPoints', None) facade = self._getFacade() facade.addThreshold(uid, thresholdType, thresholdId, dataPoints) thresholdUid = uid + '/thresholds/' + thresholdId audit('UI.Threshold.Add', thresholdUid, thresholdtype=thresholdType, datapoints=dataPoints) return DirectResponse.succeed()
def updateTrigger(self, **data): data["rule"]["api_version"] = 1 data["rule"]["type"] = RULE_TYPE_JYTHON triggerUid = data["uuid"] response = self._getFacade().updateTrigger(**data) audit("UI.Trigger.Edit", triggerUid, data_=data) return DirectResponse.succeed(msg="Trigger updated successfully.", data=response)
def deleteNode(self, uid): """ Deletes a node from the tree. B{NOTE}: You can not delete a root node of a tree @type uid: string @param uid: Unique identifier of the node we wish to delete @rtype: DirectResponse @return: B{Properties}: - msg: (string) Status message """ # make sure we are not deleting a root node if not self._canDeleteUid(uid): raise Exception('You cannot delete the root node') facade = self._getFacade() node = facade._getObject(uid) # Audit first so it can display details like "name" while they exist. # Trac #29148: When we delete a DeviceClass we also delete its devices # and child device classes and their devices, so audit them all. if isinstance(node, DeviceClass): childBrains = ICatalogTool(node).search(( 'Products.ZenModel.DeviceClass.DeviceClass', 'Products.ZenModel.Device.Device', )) for child in childBrains: audit(['UI', getDisplayType(child), 'Delete'], child.getPath()) else: audit(['UI', getDisplayType(node), 'Delete'], node) facade.deleteNode(uid) msg = "Deleted node '%s'" % uid return DirectResponse.succeed(msg=msg)
def manage_removeMonitor(self, ids=None, submon="", REQUEST=None): """ Remove an object of sub_class, from a module of the same name. """ if isinstance(ids, basestring): ids = (ids,) child = self.get(submon, self) monitors = child.objectValues(spec="PerformanceConf") num = 0 for monitor in (m for m in monitors if m.id in ids): if REQUEST: audit("UI.Collector.Delete", monitor.id) del child[monitor.id] num += 1 if REQUEST: if num: messaging.IMessageSender(self).sendToBrowser( 'Collectors Deleted', 'Deleted collectors: %s' % (', '.join(ids)) ) else: messaging.IMessageSender(self).sendToBrowser( 'Error', 'You must select at least one collector.', priority=messaging.WARNING ) return self.callZenScreen(REQUEST)
def remove(self, uid, id=None, properties=None): """Removes the local instance of the each property in properties. Note that the property will only be deleted if a hasProperty is true @param uid {str} Path to the object owning the properties. @param id {str} The ID of the property to delete. @param properties {list[str]} List of property IDs to delete. Note that specifying both 'id' and 'properties' is valid. Duplicate property IDs skipped. """ facade = self._getFacade() names = set() if id is not None: names.add(id) if properties is not None: if not isinstance(properties, (list, tuple)): properties = [properties] names.update(properties) for name in names: facade.deleteZenProperty(uid, name) obj = facade._getObject(uid) audit('UI.zProperty.Delete', name, data_={obj.meta_type: uid}) if len(names) == 1: return DirectResponse.succeed( msg="Property %s successfully deleted." % names.pop() ) return DirectResponse.succeed( msg="Successfully deleted %s properties." % len(names) )
def manage_resequenceGraphGroups(self, seqmap=(), origseq=(), REQUEST=None): """Reorder the sequence of the groups. """ retval = resequence(self, self.graphGroups(), seqmap, origseq, REQUEST) if REQUEST: audit('UI.Report.ResequenceGraphGroups', self.id, sequence=seqmap, oldData_={'sequence':origseq}) return retval
def updateConfigFiles(self, id, configFiles): """ Updates the configuration files for an application specified by id. The configFiles parameters is an array of dictionaries of the form: { filename: "blah", content: "line 1\nline 2\n..." } The filename parameter serves as the "id" of each configFile passed in. """ if not Zuul.checkPermission('Manage DMD'): return DirectResponse.fail("You don't have permission to set update config files", sticky=False) facade = self._getFacade() deployedApp = facade.get(id) newConfigs = [] for deployedAppConfig in deployedApp.configurations: if deployedAppConfig.filename in [ cf['filename'] for cf in configFiles ]: audit('UI.Applications.UpdateConfigFiles', service=id, servicename=deployedApp.name, filename=deployedAppConfig.filename) deployedAppConfig.content = next((cf['content'] for cf in configFiles if cf['filename'] == deployedAppConfig.filename)) newConfigs.append(deployedAppConfig) deployedApp.configurations = newConfigs return DirectResponse.succeed()
def manage_editEventClassTransform(self, transform='', REQUEST=None): """Save the transform""" oldTransform = self.transform self.transform = transform if REQUEST: audit('UI.EventClass.EditTransform', self, transform=transform, oldData_={'transform':oldTransform}) return self.callZenScreen(REQUEST)
def addClass(self, contextUid, id, posQuery=None): """ Add a new service class. @type contextUid: string @param contextUid: Unique ID of the service ogranizer to add new class to @type id: string @param id: ID of the new service @type posQuery: dictionary @param posQuery: Object defining a query where the returned position will lie @rtype: DirectResponse @return: B{Properties}: - newIndex: (integer) Index of the newly added class in the query defined by posQuery """ newUid = self.api.addClass(contextUid, id) if isinstance(posQuery.get('params'), basestring): posQuery['params'] = unjson(posQuery['params']) result = self.api.getList(**posQuery) for count, serviceInfo in enumerate(result['serviceInfos']): if serviceInfo.uid == newUid: newIndex = count break else: raise Exception('The new service was added, but the system was ' 'unable to add it to the list.') audit('UI.Service.Add', contextUid + '/' + id) return DirectResponse(newIndex=newIndex)
def deleteOidMapping(self, uid): if uid.find('/nodes/') == -1: return DirectResponse.fail('"%s" does not appear to refer to an OID Mapping' % uid) mibUid, mappingId = uid.split('/nodes/') self.api.deleteOidMapping(mibUid, mappingId) audit('UI.Mib.DeleteOidMapping', mibUid, mapping=mappingId) return DirectResponse.succeed()
def manage_addUsersToGroups(self, userids=(), groupids=(), REQUEST=None): """ Add users to a group """ if isinstance(userids, basestring): userids = [userids] if isinstance(groupids, basestring): groupids = [groupids] for groupid in groupids: self._getOb(groupid).manage_addUsersToGroup(userids) if REQUEST: if not groupids: messaging.IMessageSender(self).sendToBrowser( 'Error', 'No groups were selected.', priority=messaging.WARNING ) else: messaging.IMessageSender(self).sendToBrowser( 'Groups Modified', 'Users %s were added to group %s.' % ( ', '.join(userids), ', '.join(groupids)) ) for userid in userids: for groupid in groupids: audit('UI.User.AddToGroup', username=userid, group=groupid) return self.callZenScreen(REQUEST)
def manage_addReport(context, id, title = None, text=None, REQUEST = None, submit=None): """make a Report""" id = str(id) if REQUEST is None: context._setObject(id, Report(id, text)) ob = getattr(context, id) if title: ob.pt_setTitle(title) return ob else: file = REQUEST.form.get('file') headers = getattr(file, 'headers', None) if headers is None or not file.filename: zpt = Report(id) else: zpt = Report(id, file, headers.get('content_type')) context._setObject(id, zpt) audit('UI.Report.Add', zpt.id, title=title, text=text, reportType=getDisplayType(zpt), organizer=context) try: u = context.DestinationURL() except AttributeError: u = REQUEST['URL1'] if submit == " Add and Edit ": u = "%s/%s" % (u, quote(id)) REQUEST.RESPONSE.redirect(u+'/manage_main') return ''
def setGraphDefinition(self, **data): """ Set attributes on an graph definition. This method accepts any keyword argument for the property that you wish to set. Properties are enumerated via getGraphDefinition(). The only required property is "uid". @type uid: string @keyword uid: Unique identifier of an object @rtype: DirectResponse @return: B{Properties}: - data: (dictionary) The modified object """ uid = data['uid'] del data['uid'] for axis_vals in ('miny', 'maxy'): try: x = float(data[axis_vals]) except (ValueError, KeyError): x = -1 data[axis_vals] = x obj = self._getFacade()._getObject(uid) oldData = self._getInfoData(obj, data) self._getFacade().setInfo(uid, data) newData = self._getInfoData(obj, data) audit(['UI', getDisplayType(obj), 'Edit'], data_=newData, oldData_=oldData, skipFields_=('newId',)) # special case in TemplateFacade.setInfo() return DirectResponse.succeed()
def addTrap(self, uid, id, oid, nodetype='notification'): if not self._validateOid(oid): msg = "Invalid OID value %s" % oid return DirectResponse.fail(msg) self.api.addTrap(uid, id, oid, nodetype) audit('UI.Mib.AddTrap', uid, id=id, oid=oid, nodetype=nodetype) return DirectResponse.succeed()
def saveZenProperties(self, pfilt=iszprop, REQUEST=None): """Save all ZenProperties found in the REQUEST.form object. """ maskFields=[] for name, value in REQUEST.form.items(): if pfilt(name): if self.zenPropIsPassword(name): maskFields.append(name) if self._onlystars(value): continue if name == 'zCollectorPlugins': if tuple(getattr(self, name, ())) != tuple(value): self.setZenProperty(name, value) else: self.setZenProperty(name, value) if REQUEST: audit(('UI', getDisplayType(self), 'EditProperties'), self, data_=REQUEST.form, skipFields_=['savezenproperties','zenscreenname'], maskFields_=maskFields) IMessageSender(self).sendToBrowser( 'Configuration Propeties Updated', 'Configuration properties have been updated.' ) return self.callZenScreen(REQUEST)
def addNode(self, nodeType, contextUid, id): """ Add a new report or report organizer. @type nodeType: string @param nodeType: Type of new node. Can either be 'organizer' or one of the report types returned from getReportTypes() @type contextUid: string @param contextUid: The organizer where the new node should be added @type id: string @param id: The new node's ID @rtype: DirectResponse @return: B{Properties}: - tree: (dictionary) Object representing the new Reports tree - newNode: (dictionary) Object representing the added node """ facade = self._getFacade() if nodeType in reportTypes: facade.addReport(nodeType, contextUid, id) audit('UI.Report.Add', contextUid + '/' + id, reporttype=nodeType) else: facade.addOrganizer(contextUid, id, None) audit('UI.Organizer.Add', contextUid + '/' + id) return self._getTreeUpdates(contextUid, id)
def manage_resequenceGraphPoints(self, seqmap=(), origseq=(), REQUEST=None): """Reorder the sequence of the GraphPoints. """ retval = resequence(self, self.graphPoints(), seqmap, origseq, REQUEST) if REQUEST: audit('UI.GraphDefinition.ResequenceGraphPoints', self.id, sequence=seqmap, oldData_={'sequence':origseq}) return retval
def manage_editAdministrativeRoles(self, ids=(), role=(), REQUEST=None): """ Edit list of admin roles. """ if isinstance(ids, basestring): ids = [ids] role = [role] editedRoles = [] for i, id in enumerate(ids): roleEdit = (id, role[i]) editedRoles.append(roleEdit) ar = self.adminRoles._getOb(roleEdit[0]) ar.update(roleEdit[1]) self.setAdminLocalRoles() self.index_object() notify(IndexingEvent(self)) if REQUEST: for roleEdit in editedRoles: audit(['UI', getDisplayType(self), 'EditAdministrativeRole'], self, id=roleEdit[0], role=roleEdit[1]) messaging.IMessageSender(self).sendToBrowser( 'Admin Roles Updated', ('The following administrative roles have been updated: ' '%s' % ", ".join(ids)) ) return self.callZenScreen(REQUEST)
def manage_deleteOrganizer(self, orgname, REQUEST=None): """ Deletes an organizer underneath this organizer @param orgname: Name of the organizer to delete @type orgname: string @raise: KeyError @permission: ZEN_DELETE >>> dmd.Devices.manage_deleteOrganizer('/Devices/Server/Linux') """ if REQUEST: audit(('UI', getDisplayType(self), 'Delete'), orgname) if orgname.startswith("/"): try: orgroot = self.getDmdRoot(self.dmdRootName) organizer = orgroot.getOrganizer(orgname) parent = aq_parent(organizer) parent._delObject(organizer.getId()) except KeyError: pass # we may have already deleted a sub object else: self._delObject(orgname) if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Organizer Deleted', '%s "%s" was deleted.' % (getDisplayType(self), orgname) ) return self.callZenScreen(REQUEST)
def setProdState(self, state, ending=False): """ At any one time there is one production state for each device to be in, and that is the state that is the most 'blacked out' in all of the active maintenance windows affecting that device. When the last maintenance window affecting a device has ended, the original production state of the device is used to determine the end state of the device. Maintenance windows are processed by zenjobs in batch so the ordering of when two maintenance windows that end at the same time get processed is non-deterministic. Since there is only one stop production state now, this is not an issue. @parameter state: hint from the maint window about device's start or stop state @type state: integer @parameter ending: are we ending a maintenance window? @type ending: boolean """ # Note: self.begin() starts our window before we get called, so the # following takes into account our window state too. # Conversely, self.end() ends the window before calling this code. devices = self.fetchDevices() minDevProdStates = self.fetchDeviceMinProdStates( devices ) for device in devices: if ending: # Note: If no maintenance windows apply to a device, then the # device won't exist in minDevProdStates # This takes care of the case where there are still active # maintenance windows. minProdState = minDevProdStates.get(device.id, device.preMWProductionState) elif device.id in minDevProdStates: minProdState = minDevProdStates[device.id] else: # This is impossible for us to ever get here as minDevProdStates # has been added by self.fetchDeviceMinProdStates() log.error("The device %s does not appear in any maintenance" " windows (including %s -- which is just starting).", device.id, self.displayName()) continue if device.productionState < 300: continue self._p_changed = 1 # Changes the current state for a device, but *not* # the preMWProductionState oldProductionState = self.dmd.convertProdState(device.productionState) newProductionState = self.dmd.convertProdState(minProdState) log.info("MW %s changes %s's production state from %s to %s", self.displayName(), device.id, oldProductionState, newProductionState) audit('System.Device.Edit', device, starting=str(not ending), maintenanceWindow=self.displayName(), productionState=newProductionState, oldData_={'productionState':oldProductionState}) device.setProdState(minProdState, maintWindowChange=True)
def editInstance(self, params=None): """ Edit an event class instance """ oldData = self.getInstanceData(params['uid']).data self.testCompileTransform(params.get('transform')) self.testRegex(params['regex'], params['example']) self.testRule(params['rule']) facade = self._getFacade() facade.editInstance(params) audit('UI.EventClasses.EditInstance', params['uid'], data_=params, oldData_=oldData) return DirectResponse.succeed()
def discoverDevices(self, uid, collector=None): """ Discover devices on a network. @type uid: string @param uid: Unique identifier of the network to discover @rtype: DirectResponse @return: B{Properties}: - jobId: (integer) The id of the discovery job """ jobStatus = self.api.discoverDevices(uid, collector) if jobStatus: audit('UI.Network.DiscoverDevices', uid) return DirectResponse.succeed(new_jobs=Zuul.marshal( [jobStatus], keys=('uuid', 'description', 'started'))) else: return DirectResponse.fail()
def clear_heartbeat(self, monitor, daemon): """ Clears a specific heartbeat event. @type monitor: basestring @param monitor: The heartbeat monitor (i.e. 'localhost'). @type daemon: basestring @param daemon: The heartbeat daemon (i.e. 'zenhub'). @rtype: DirectResponse @return: A DirectResponse indicating success or failure. """ self.zep.deleteHeartbeat(monitor, daemon) audit('UI.Event.ClearHeartbeat', self.context, monitor=monitor, daemon=daemon) return DirectResponse.succeed()
def edit_portlet_perms(self, REQUEST=None): """ Update the portlet permissions """ for portlet in REQUEST.form: if not portlet.endswith('_permission'): continue portname = portlet.split('_')[0] p = self.find(id=portname) p.permission = REQUEST.form[portlet] if REQUEST: from Products.ZenUtils.Time import SaveMessage messaging.IMessageSender(self).sendToBrowser( 'Permissions Saved', SaveMessage() ) REQUEST['RESPONSE'].redirect('/zport/dmd/editPortletPerms') audit('UI.Portlet.Edit', data_=REQUEST.form)
def addUser(self, id, password, email, roles=('ZenUser',)): """ Adds a new user to the system. @type id: string @param id: The unique identifier of the user, same as their login @type password: string @param password: the password of the new user @type roles: list of strings @param roles: (optional) roles to be applied to the new user @rtype: DirectResponse @return: B{Properties}: - data: properties of the new users """ facade = self._getFacade() newUser = facade.addUser(id, password, email, roles) audit('UI.Users.Add', id, email=email, roles=roles) return DirectResponse.succeed(data=Zuul.marshal(newUser))
def moveNode(self, uid, target): """ Move a report or report organizer from one organizer to another. @type uid: string @param uid: The UID of node to move @type target: string @param target: The UID of the target Report organizer @rtype: [dictionary] @return: B{Properties}: - tree: (dictionary) Object representing the new Reports tree - newNode: (dictionary) Object representing the moved node """ uid = getUtility(IVirtualRoot).strip_virtual_root(uid) self._getFacade().moveNode(uid, target) audit('UI.Report.Move', uid, target=target) return self._treeMoveUpdates(uid, target)
def setInfo(self, **data): """ Set attributes on a process. This method accepts any keyword argument for the property that you wish to set. The only required property is "uid". @type uid: string @keyword uid: Unique identifier of a process @rtype: DirectResponse @return: B{Properties} - data: (dictionary) Object representing a process's new properties """ facade = self._getFacade() processUid = data['uid'] process = facade.getInfo(processUid) audit('UI.Process.Edit', processUid, data_=data, skipFields_=('uid')) return DirectResponse.succeed(data=Zuul.unmarshal(data, process))
def moveNode(self, uids, target): """ Move an organizer or MIB from one organizer to another. @type uids: [string] @param uids: UIDs of organizers and MIBs to move @type target: string @param target: UID of the organizer to move to @rtype: DirectResponse @return: B{Properties}: - data: (dictionary) Object representing the new parent organizer """ parent = self.api.moveMibs(uids, target) parent = IInfo(parent) for uid in uids: audit('UI.Mib.Move', uid, target=target) return DirectResponse.succeed(data=Zuul.marshal(parent))
def manage_addZenPack(self, packId, REQUEST=None, devDir=''): """ Create a new zenpack on the filesystem with the given info. Install the pack. If REQUEST then render the REQUEST otherwise return the new zenpack. """ import Products.ZenUtils.ZenPackCmd as ZenPackCmd if not getattr(self.dmd, 'ZenPackManager'): msg = 'Your Zenoss database appears to be out of date. Try ' \ 'running zenmigrate to update.' if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Error', msg, priority=messaging.WARNING) return self.callZenScreen(REQUEST) from ZenPack import ZenPackNeedMigrateException raise ZenPackNeedMigrateException(msg) # Make sure a zenpack can be created with given info canCreate, msgOrId = ZenPackCmd.CanCreateZenPack(self, packId) if canCreate: packId = msgOrId else: if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Add ZenPack', msgOrId) return self.callZenScreen(REQUEST, redirect=False) from ZenPack import ZenPackException raise ZenPackException(msgOrId) # Create it zpDir = ZenPackCmd.CreateZenPack(packId, devDir=devDir) # Install it zenPacks = ZenPackCmd.InstallEggAndZenPack(self.dmd, zpDir, link=True, forceRunExternal=True) zenPack = self.packs._getOb(packId, None) audit('UI.ZenPack.Create', packId) if REQUEST: if zenPack: return REQUEST['RESPONSE'].redirect(zenPack.getPrimaryUrlPath()) messaging.IMessageSender(self).sendToBrowser( 'Error', 'There was an error creating the ZenPack.', priority=messaging.WARNING) return self.callZenScreen(REQUEST) return zenPack
def manage_addGraphGroup(self, new_id, collectionId='', graphDefId='', REQUEST=None): """ Add a new graph group """ from GraphGroup import GraphGroup gg = GraphGroup(new_id, collectionId, graphDefId, len(self.graphGroups())) self.graphGroups._setObject(gg.id, gg) gg = self.graphGroups._getOb(gg.id) if REQUEST: audit('UI.Report.AddGraphGroup', self.id, graphGroup=gg.id) return REQUEST['RESPONSE'].redirect( '%s/graphGroups/%s' % (self.getPrimaryUrlPath(), gg.id)) return gg
def manage_addUser(self, userid, password=None,roles=("ZenUser",), REQUEST=None,**kw): """ Add a Zenoss user to the system and set the user's default properties. @parameter userid: username to add @parameter password: password for the username @parameter roles: tuple of role names @parameter REQUEST: Zope object containing details about this request """ if not userid: return userid= userid.strip() illegal_usernames= [ 'user', ] user_name= userid.lower() if user_name in illegal_usernames: if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Error', 'The username "%s" is reserved.' % userid, priority=messaging.WARNING ) return self.callZenScreen(REQUEST) else: return None if password is None: password = self.generatePassword() self.acl_users._doAddUser(userid,password,roles,"") user = self.acl_users.getUser(userid) ufolder = self.getUserSettings(userid) if REQUEST: kw = REQUEST.form ufolder.updatePropsFromDict(kw) if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'User Added', 'User "%s" has been created.' % userid ) audit('UI.User.Add', username=userid, roles=roles) # don't send password return self.callZenScreen(REQUEST) else: return user
def setAutoStart(self, uids, enabled): """ Enables or disables autostart on all applications passed into uids. If it is already in that state it is a noop. @type uids: Array[Strings] @param uids: List of valid daemon ids that will need to enabled @type enabled: boolean @param uids: true for enabled or false for disabled @rtype: DirectResposne @return: DirectReponse of success if no errors are encountered """ facade = self._getFacade() applications = facade.query() for app in applications: if app.id in uids: app.autostart = enabled audit('UI.Applications.AutoStart', id, {'autostart': enabled}) return DirectResponse.succeed()
def manage_editUserCommand(self, commandId, REQUEST): ''' Want to redirect back to management tab after a save ''' command = self.getUserCommand(commandId) if command: password = REQUEST.form.get('password', '') if not self.dmd.ZenUsers.authenticateCredentials( self.dmd.ZenUsers.getUser().getId(), password): messaging.IMessageSender(self).sendToBrowser( 'Password Error', 'Invalid or empty password.', priority=messaging.WARNING ) return REQUEST.RESPONSE.redirect(command.absolute_url_path()) del REQUEST.form['password'] command.manage_changeProperties(**REQUEST.form) audit('UI.Command.Edit', commandId, action=REQUEST.form.get('command','')) return self.redirectToUserCommands(REQUEST)
def removeIpAddresses(self, uids=None): """ Removes every ip address specified by uids that are not attached to any device. @type uids: Array of Strings @param uids: unique identfiers of the ip addresses to delete """ if uids: removedCount, errorCount = self.api.removeIpAddresses(uids) audit( "UI.IPAddress.Remove", ips=uids, numremoved=removedCount, numerrors=errorCount, ) return DirectResponse.succeed(removedCount=removedCount, errorCount=errorCount)
def moveOrganizer(self, targetUid, organizerUid): """ Move the organizer uid to be underneath the organizer specified by the targetUid. @type targetUid: string @param targetUid: New parent of the organizer @type organizerUid: string @param organizerUid: The organizer to move @rtype: DirectResponse @return: B{Properties}: - data: (dictionary) Moved organizer """ facade = self._getFacade() display_type = getDisplayType(facade._getObject(organizerUid)) audit(['UI', display_type, 'Move'], organizerUid, to=targetUid) data = facade.moveOrganizer(targetUid, organizerUid) return DirectResponse.succeed(data=Zuul.marshal(data))
def setInfo(self, **data): """ Set attributes on a MIB. This method accepts any keyword argument for the property that you wish to set. The only required property is "uid". @type uid: string @keyword uid: Unique identifier of a MIB @rtype: DirectResponse @return: B{Properties} - data: (dictionary) Object representing a MIB's new properties """ uid = data['uid'] del data['uid'] facade = self._getFacade() info = facade.setInfo(uid, data) audit('UI.Mib.Edit', uid, data_=data) return DirectResponse.succeed(data=Zuul.marshal(info))
def addClass(self, contextUid, id, posQuery=None): """ Add a new service class. @type contextUid: string @param contextUid: Unique ID of the service ogranizer to add new class to @type id: string @param id: ID of the new service @type posQuery: dictionary @param posQuery: Object defining a query where the returned position will lie @rtype: DirectResponse @return: B{Properties}: - newIndex: (integer) Index of the newly added class in the query defined by posQuery """ newUid = self.api.addClass(contextUid, id) audit('UI.Service.Add', contextUid + '/' + id) return DirectResponse()
def addDataSource(self, templateUid, name, type): """ Add a new data source to a template. @type templateUid: string @param templateUid: Unique ID of the template to add data source to @type name: string @param name: ID of the new data source @type type: string @param type: Type of the new data source. From getDataSourceTypes() @rtype: DirectResponse @return: Success message """ facade = self._getFacade() ds = facade.addDataSource(templateUid, name, type) audit('UI.DataSource.Add', ds.getPrimaryId(), name=name, dstype=type, template=templateUid) return DirectResponse.succeed()
def manage_deleteGraphPoints(self, ids=(), REQUEST=None): """ Deleted given graphpoints """ num = 0 for id in ids: if getattr(self.graphPoints, id, False): num += 1 self.graphPoints._delObject(id) self.manage_resequenceGraphPoints() if REQUEST: for id in ids: audit('UI.GraphDefinition.DeleteGraphPoint', self.id, graphPoint=id) messaging.IMessageSender(self).sendToBrowser( 'Graph Points Deleted', '%s graph point%s were deleted.' % (num, num > 1 and 's' or '')) return self.callZenScreen(REQUEST)
def setInfo(self, **data): """ Set attributes on a service. This method accepts any keyword argument for the property that you wish to set. The only required property is "uid". @type uid: string @keyword uid: Unique identifier of a service @rtype: DirectResponse @return: Success message """ serviceUid = data['uid'] service = self.api.getInfo(serviceUid) if 'serviceKeys' in data and isinstance(data['serviceKeys'], str): data['serviceKeys'] = tuple(l.strip() for l in data['serviceKeys'].split(',')) Zuul.unmarshal(data, service) # removes data['uid'] audit('UI.Service.Edit', serviceUid, data_=data) return DirectResponse.succeed()
def manage_addMaintenanceWindow(self, newId=None, REQUEST=None): "Add a Maintenance Window to this device" mw = None if newId: preppedId = prepId(newId) mw = MaintenanceWindow(preppedId) mw.name = newId self.maintenanceWindows._setObject(preppedId, mw) if hasattr(self, 'setLastChange'): # Only Device and DeviceClass have setLastChange for now. self.setLastChange() if REQUEST: if mw: messaging.IMessageSender(self).sendToBrowser( 'Window Added', 'Maintenance window "%s" has been created.' % mw.name) audit('UI.MaintenanceWindow.Add', mw) return self.callZenScreen(REQUEST)
def manage_daemonAction(self, REQUEST): """ Start, stop, or restart Zenoss daemons from a web interface. """ legalValues = ['start', 'restart', 'stop'] action = (REQUEST.form.get('action') or '').lower() if action not in legalValues: return self.callZenScreen(REQUEST) daemonName = REQUEST.form.get('daemon') if not self.isValidDaemon(daemonName): messaging.IMessageSender(self).sendToBrowser( 'Internal Error', "%r is not a valid daemon name" % daemonName, priority=messaging.CRITICAL ) return self.callZenScreen(REQUEST) if self.doDaemonAction(daemonName, action): audit(['UI.Daemon', action], daemonName) return self.callZenScreen(REQUEST)
def importConfiguration(self, triggers=None, notifications=None): try: tcount = len(triggers) if triggers is not None else 0 ncount = len(notifications) if notifications is not None else 0 facade = self._getFacade() itcount, incount = facade.importConfiguration( triggers, notifications) msg = "Imported %d of %d triggers and %d of %d notifications" % ( tcount, itcount, ncount, incount) audit('UI.TriggerNotification.Import', msg) return DirectResponse.succeed(msg=msg) except Exception as ex: audit('UI.TriggerNotification.Import', "Failed to import trigger/notification data") log.exception( "Unable to import data:\ntriggers=%s\nnotifications=%s", repr(triggers), repr(notifications)) return DirectResponse.fail(str(ex))
def addNode(self, newSubnet, contextUid): """ Add a new subnet. @type newSubnet: string @param newSubnet: New subnet to add @type contextUid: string @param contextUid: Unique identifier of the network parent of the new subnet @rtype: DirectResponse @return: B{Properties}: - newNode: (dictionary) An object representing the new subnet node """ # If the user doesn't include a mask, reject the request. if '/' not in newSubnet: response = DirectResponse.fail('You must include a subnet mask.') else: try: contextUid = getUtility(IVirtualRoot).strip_virtual_root( contextUid) netip, netmask = newSubnet.split('/') netmask = int(netmask) foundSubnet = self.api.findSubnet(netip, netmask, contextUid) if foundSubnet is not None: response = DirectResponse.fail( 'Did not add duplicate subnet: %s (%s/%s)' % (newSubnet, foundSubnet.id, foundSubnet.netmask)) else: newNet = self.api.addSubnet(newSubnet, contextUid) node = ITreeNode(newNet) audit('UI.Network.AddSubnet', contextUid, subnet=newSubnet) response = DirectResponse.succeed( newNode=Zuul.marshal(node)) except IpAddressError as error: response = DirectResponse.exception(error, 'Error adding subnet.') except Exception as error: log.exception("Error adding subnet.") response = DirectResponse.exception(error, 'Error adding subnet.') return response
def manage_removeZenPacks(self, ids=(), REQUEST=None): """ Uninstall the given zenpacks. Uninstall the zenpack egg. If not in development mode then also delete the egg from the filesystem. """ import Products.ZenUtils.ZenPackCmd as ZenPackCmd # avoid circular imports from Products.ZenMessaging.queuemessaging.schema import removeZenPackQueuesExchanges if not getattr(self.dmd, 'ZenPackManager'): msg = 'Your Zenoss database appears to be out of date. Try ' \ 'running zenmigrate to update.' if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Error', msg, priority=messaging.WARNING) return self.callZenScreen(REQUEST) from ZenPack import ZenPackNeedMigrateException raise ZenPackNeedMigrateException(msg) canRemove, dependents = ZenPackCmd.CanRemoveZenPacks(self.dmd, ids) if not canRemove: msg = 'The following ZenPacks depend on one or more of the ' + \ ' ZenPacks you are trying to remove: %s' % ','.join(dependents) if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Error', msg, priority=messaging.WARNING) return self.callZenScreen(REQUEST) from ZenPack import ZenPackDependentsException raise ZenPackDependentsException(msg) for zpId in ids: zp = self.packs._getOb(zpId, None) if zp: if zp.isEggPack(): ZenPackCmd.RemoveZenPack(self.dmd, zpId, skipDepsCheck=True) audit('UI.ZenPack.Remove', zpId) else: os.system('%s --remove %s' % (binPath('zenpack'), zpId)) self._p_jar.sync() removeZenPackQueuesExchanges(zp.path()) if REQUEST: return self.callZenScreen(REQUEST)
def moveOrganizer(self, moveTarget, organizerPaths=None, REQUEST=None): """ Move organizers under this organizer to another organizer @param moveTarget: Name of the destination organizer @type moveTarget: string @param organizerPaths: Paths of organizers to be moved @type organizerPaths: list >>> dmd.Events.Status.moveOrganizer('/Events/Ignore', ... ['Ping', 'Snmp']) """ if not moveTarget or not organizerPaths: return self() target = self.getDmdRoot(self.dmdRootName).getOrganizer(moveTarget) movedStuff = False for organizerName in organizerPaths: if moveTarget.find(organizerName) > -1: continue obj = self._getOb(organizerName, None) if obj is None: continue obj._operation = 1 #move object self._delObject(organizerName) target._setObject(organizerName, obj) movedStuff = True if REQUEST: if movedStuff: plural = '' if len(organizerPaths) > 1: plural = 's' for organizerName in organizerPaths: audit(('UI', getDisplayType(self), 'Move'), organizerName, data_={ 'from': getDisplayName(self), 'to': getDisplayName(target) }) messaging.IMessageSender(self).sendToBrowser( 'Organizers Moved', '%s%s %s were moved to %s.' % (getDisplayType(self), plural, ', '.join(organizerPaths), moveTarget)) else: messaging.IMessageSender(self).sendToBrowser( 'Error', 'No %s were moved.' % getDisplayType(self), priority=messaging.WARNING) return target.callZenScreen(REQUEST)
def setPerformanceMonitor(self, performanceMonitor=None, deviceNames=None, REQUEST=None): """ Provide a method to set performance monitor from any organizer @param performanceMonitor: DMD object that collects from a device @type performanceMonitor: DMD object @param deviceNames: list of device names @type deviceNames: list @param REQUEST: Zope REQUEST object @type REQUEST: Zope REQUEST object """ if not performanceMonitor: if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Error', 'No monitor was selected.', priority=messaging.WARNING) return self.callZenScreen(REQUEST) if deviceNames is None: if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Error', 'No devices were selected.', priority=messaging.WARNING) return self.callZenScreen(REQUEST) for devName in deviceNames: dev = self.devices._getOb(devName) dev = dev.primaryAq() dev.setPerformanceMonitor(performanceMonitor) if REQUEST: audit('UI.Device.ChangeCollector', dev, collector=performanceMonitor) if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Monitor Set', 'Performance monitor was set to %s.' % performanceMonitor) if REQUEST.has_key('oneKeyValueSoInstanceIsntEmptyAndEvalToFalse'): return REQUEST['message'] else: return self.callZenScreen(REQUEST)
def deleteJobs(self, jobids): # Make sure they have permission to delete. if not Zuul.checkPermission('Manage DMD'): return DirectResponse.fail( "You don't have permission to execute this command", sticky=False) deletedJobs = [] for id_ in jobids: try: self.api.deleteJob(id_) except NoSuchJobException: log.debug("Unable to delete job: %s No such job found.", id_) else: deletedJobs.append(id_) if deletedJobs: audit('UI.Jobs.Delete', ids=deletedJobs) return DirectResponse.succeed( deletedJobs=Zuul.marshal(deletedJobs))
def addDataPointToGraph(self, dataPointUid, graphUid, includeThresholds=False): """ Add a data point to a graph. @type dataPointUid: string @param dataPointUid: Unique ID of the data point to add to graph @type graphUid: string @param graphUid: Unique ID of the graph to add data point to @type includeThresholds: boolean @param includeThresholds: (optional) True to include related thresholds (default: False) @rtype: DirectResponse @return: Success message """ facade = self._getFacade() facade.addDataPointToGraph(dataPointUid, graphUid, includeThresholds) audit('UI.Graph.AddDataPoint', graphUid, datapoint=dataPointUid, includeThresholds=includeThresholds) return DirectResponse.succeed()
def deleteZenProperty(self, propname=None, REQUEST=None): """ Delete device tree properties from the this DeviceClass object. """ if propname: try: self._delProperty(propname) except AttributeError: #occasional object corruption where the propName is in #_properties but not set as an attribute. filter out the prop #and create a new _properties tuple newProps = [x for x in self._properties if x['id'] != propname] self._properties=tuple(newProps) except ValueError: raise ZenPropertyDoesNotExist() if REQUEST: if propname: audit(('UI',getDisplayType(self),'DeleteZProperty'), self, property=propname) return self.callZenScreen(REQUEST)