1
2
3
4
5
6
7
8
9
10
11 __doc__ = """Organizer
12 Base class for all Zenoss organizers
13 """
14
15 from Globals import InitializeClass
16 from Acquisition import aq_parent
17 from AccessControl import ClassSecurityInfo, getSecurityManager
18
19 from Products.ZenRelations.RelSchema import *
20 from Products.ZenUtils.Exceptions import ZentinelException
21 from Products.ZenWidgets import messaging
22 from Products.ZenMessaging.audit import audit
23 from Products.ZenUtils.Utils import getDisplayType, getDisplayName
24 from Products.ZenUtils.deprecated import deprecated
25
26 from EventView import EventView
27 from ZenModelRM import ZenModelRM
28 from ZenossSecurity import *
31 """
32 The base for all hierarchical organization classes. It allows Organizers
33 to be addressed and created with file system like paths like
34 /Devices/Servers. Organizers have a containment relation called children.
35 Subclasses must define the attribute:
36
37 dmdRootName - root in the dmd database for this organizer
38 """
39
40 _properties = (
41 {'id':'description', 'type':'string', 'mode':'w'},
42 )
43
44 _relations = ZenModelRM._relations
45
46 security = ClassSecurityInfo()
47 security.declareObjectProtected(ZEN_VIEW)
48
49 - def __init__(self, id, description = ''):
50 """
51 @param id: Name of this organizer
52 @type id: string
53 @param description: A decription of this organizer
54 @type description: string
55 @rtype: Organizer
56 """
57 ZenModelRM.__init__(self, id)
58 self.description = description
59
60 - def urlLink(self, text=None, url=None, attrs={}):
61 """
62 Override urlLink to return a link with the full path of the organizer.
63
64 >>> dmd.Devices.Server.urlLink()
65 '<a href="/zport/dmd/Devices/Server">/Server</a>'
66 """
67 if text is None: text = self.getOrganizerName()
68 return ZenModelRM.urlLink(self, text=text, url=url, attrs=attrs)
69
70
72 """
73 Returns a list of all organizer names
74 under the same root excluding ourselves
75
76 @return: A list of organizers excluding our self.
77 @rtype: list
78 @todo: We should be using either deviceMoveTargets or childMoveTargets
79
80 >>> dmd.Events.getOrganizerName() in dmd.Events.childMoveTargets()
81 False
82 """
83 myname = self.getOrganizerName()
84 return filter(lambda x: x != myname,
85 self.getDmdRoot(self.dmdRootName).getOrganizerNames())
86
88 """
89 Returns an organizer under the same root.
90
91 @param moveTargetName: Name of the organizer
92 @type moveTargetName: string
93 @rtype: Organizer
94
95 >>> dmd.Devices.getChildMoveTarget('Server')
96 <DeviceClass at /zport/dmd/Devices/Server>
97 """
98 return self.getDmdRoot(self.dmdRootName).getOrganizer(moveTargetName)
99
100
101 security.declareProtected(ZEN_COMMON, "children")
102 - def children(self, sort=False, checkPerm=True, spec=None):
103 """
104 Returns the immediate children of an organizer
105
106 @param sort: If True, sorts the returned children.
107 @type sort: boolean
108 @param checkPerm: If True, checks if the user has the permission
109 to view each child.
110 @type checkPerm: boolean
111 @param spec: If set, returns children of the specified meta_type.
112 @type spec: string
113 @return: A list of children of the organizer
114 @rtype: list
115 @permission: ZEN_COMMON
116
117 >>> dmd.Devices.Printer.children()
118 [<DeviceClass at /zport/dmd/Devices/Printer/Laser>,
119 <DeviceClass at /zport/dmd/Devices/Printer/InkJet>]
120 """
121 if spec is None:
122 spec = self.meta_type
123 kids = self.objectValues(spec=spec)
124 if checkPerm:
125 kids = [ kid for kid in kids if self.checkRemotePerm(ZEN_VIEW, kid)]
126 if sort:
127 kids.sort(key=lambda x: x.primarySortKey())
128 return kids
129
130
132 """
133 Returns the ids of the immediate children of an organizer
134
135 @param spec: If set, returns children of the specified meta_type.
136 @type spec: string
137 @return: Ids of children within our organizer
138 @rtype: list
139
140 >>> 'Discovered' in dmd.Devices.childIds()
141 True
142 """
143 if spec is None:
144 spec = self.meta_type
145
146 return self.objectIds(spec=spec)
147
148
149 security.declareProtected(ZEN_COMMON, "countChildren")
151 """
152 Returns the number of all the children underneath an organizer
153
154 @param spec: If set, returns children of the specified meta_type.
155 @type spec: string
156 @return: A count of all our contained children.
157 @rtype: integer
158 @permission: ZEN_COMMON
159
160 """
161 if spec is None:
162 spec = self.meta_type
163
164 count = len(self.objectIds(spec=spec))
165 for child in self.children(spec=spec):
166 count += child.countChildren(spec=spec)
167 return count
168
169
170 security.declareProtected(ZEN_ADD, 'manage_addOrganizer')
204
205
206 security.declareProtected(ZEN_DELETE, 'manage_deleteOrganizer')
207 @deprecated
209 """
210 Deletes an organizer underneath this organizer
211
212 @param orgname: Name of the organizer to delete
213 @type orgname: string
214 @raise: KeyError
215 @permission: ZEN_DELETE
216
217 >>> dmd.Devices.manage_deleteOrganizer('/Devices/Server/Linux')
218 """
219 if REQUEST:
220 audit(('UI', getDisplayType(self), 'Delete'), orgname)
221 if orgname.startswith("/"):
222 try:
223 orgroot = self.getDmdRoot(self.dmdRootName)
224 organizer = orgroot.getOrganizer(orgname)
225 parent = aq_parent(organizer)
226 parent._delObject(organizer.getId())
227 except KeyError:
228 pass
229 else:
230 self._delObject(orgname)
231 if REQUEST:
232 messaging.IMessageSender(self).sendToBrowser(
233 'Organizer Deleted',
234 '%s "%s" was deleted.' % (getDisplayType(self), orgname)
235 )
236 return self.callZenScreen(REQUEST)
237
238
239 security.declareProtected(ZEN_DELETE, 'manage_deleteOrganizers')
241 """
242 Delete a list of Organizers from the database using their ids.
243
244 @param organizerPaths: Names of organizer to be deleted
245 @type organizerPaths: list
246 @permission: ZEN_DELETE
247
248 >>> dmd.Devices.manage_deleteOrganizers(['/Devices/Server/Linux',
249 ... '/Devices/Server/Windows'])
250 """
251 if not organizerPaths:
252 messaging.IMessageSender(self).sendToBrowser(
253 'Error',
254 'No organizers were specified.',
255 priority=messaging.WARNING
256 )
257 return self.callZenScreen(REQUEST)
258 for organizerName in organizerPaths:
259 if REQUEST:
260 audit(('UI',getDisplayType(self),'Delete'), organizerName)
261 self.manage_deleteOrganizer(organizerName)
262 if REQUEST:
263 plural = ''
264 if len(organizerPaths) > 1: plural = 's'
265 messaging.IMessageSender(self).sendToBrowser(
266 'Organizers Deleted',
267 '%s%s %s were deleted.' % (getDisplayType(self),
268 plural, ', '.join(organizerPaths))
269 )
270 return self.callZenScreen(REQUEST)
271
272
274 """
275 DEPRECATED - see childMoveTargets
276 Return list of all organizers excluding our self.
277
278 @return: A sorted list of organizers excluding our self.
279 @rtype: list
280 @todo: We should be using either deviceMoveTargets or childMoveTargets
281 """
282 targets = filter(lambda x: x != self.getOrganizerName(),
283 self.getDmdRoot(self.dmdRootName).getOrganizerNames())
284 return sorted(targets, key=lambda x: x.lower())
285
286
287 - def moveOrganizer(self, moveTarget, organizerPaths=None, REQUEST=None):
288 """
289 Move organizers under this organizer to another organizer
290
291 @param moveTarget: Name of the destination organizer
292 @type moveTarget: string
293 @param organizerPaths: Paths of organizers to be moved
294 @type organizerPaths: list
295
296 >>> dmd.Events.Status.moveOrganizer('/Events/Ignore',
297 ... ['Ping', 'Snmp'])
298 """
299 if not moveTarget or not organizerPaths: return self()
300 target = self.getDmdRoot(self.dmdRootName).getOrganizer(moveTarget)
301 movedStuff = False
302 for organizerName in organizerPaths:
303 if moveTarget.find(organizerName) > -1: continue
304 obj = self._getOb(organizerName, None)
305 if obj is None: continue
306 obj._operation = 1
307 self._delObject(organizerName)
308 target._setObject(organizerName, obj)
309 movedStuff = True
310 if REQUEST:
311 if movedStuff:
312 plural = ''
313 if len(organizerPaths) > 1: plural = 's'
314 for organizerName in organizerPaths:
315 audit(('UI', getDisplayType(self), 'Move'), organizerName, data_={'from':getDisplayName(self), 'to':getDisplayName(target)})
316 messaging.IMessageSender(self).sendToBrowser(
317 'Organizers Moved',
318 '%s%s %s were moved to %s.' % (getDisplayType(self),
319 plural, ', '.join(organizerPaths), moveTarget)
320 )
321 else:
322 messaging.IMessageSender(self).sendToBrowser(
323 'Error',
324 'No %s were moved.' % getDisplayType(self),
325 priority=messaging.WARNING
326 )
327 return target.callZenScreen(REQUEST)
328
329
331 """
332 Creates an organizer with a specified path.
333 Use manage_addOrganizer instead
334
335 @param path: Path of the organizer to create
336 @type path: string
337 @return: Organizer created with the specified path
338 @rtype: Organizer
339 """
340 return self.createHierarchyObj(self.getDmdRoot(self.dmdRootName),
341 path,self.__class__)
342
343
345 """
346 Get an organizer by path under the same root
347
348 @param path: Path of the organizer to retrieve
349 @type path: string
350 @return: Organizer with the specified path
351 @rtype: Organizer
352
353 >>> dmd.Events.Status.getOrganizer('/Status/Snmp')
354 <EventClass at /zport/dmd/Events/Status/Snmp>
355 >>> dmd.Events.Status.getOrganizer('Status/Snmp')
356 <EventClass at /zport/dmd/Events/Status/Snmp>
357 >>> dmd.Events.Status.getOrganizer('/Events/Status/Snmp')
358 <EventClass at /zport/dmd/Events/Status/Snmp>
359 """
360 if path.startswith("/"): path = path[1:]
361 return self.getDmdRoot(self.dmdRootName).unrestrictedTraverse(path)
362
363
364 security.declareProtected(ZEN_COMMON, "getOrganizerName")
366 """
367 Return the DMD path of an Organizer without its dmdSubRel names.
368
369 @return: Name of this organizer
370 @rtype: string
371 @permission: ZEN_COMMON
372
373 >>> dmd.Events.Status.Snmp.getOrganizerName()
374 '/Status/Snmp'
375 """
376 return self.getPrimaryDmdId(self.dmdRootName)
377 getDmdKey = getOrganizerName
378
379
380 security.declareProtected(ZEN_COMMON, "getOrganizerNames")
382 """
383 Returns a list of all organizer names under this organizer
384
385 @param addblank: If True, add a blank item in the list.
386 @type addblank: boolean
387 @return: The DMD paths of all Organizers below this instance.
388 @rtype: list
389 @permission: ZEN_COMMON
390
391 >>> dmd.Events.Security.getOrganizerNames()
392 ['/Security', '/Security/Auth', '/Security/Conn',
393 '/Security/Conn/Close', '/Security/Conn/Open', '/Security/Login',
394 '/Security/Login/BadPass', '/Security/Login/Fail', '/Security/Sudo',
395 '/Security/Virus']
396 """
397 groupNames = []
398 user = getSecurityManager().getUser()
399 if user.has_permission(ZEN_VIEW, self) or not checkPerm:
400 groupNames.append(self.getOrganizerName())
401 for subgroup in self.children(checkPerm=False):
402 groupNames.extend(subgroup.getOrganizerNames())
403 if self.id == self.dmdRootName:
404 if addblank: groupNames.append("")
405 groupNames.sort(key=lambda x: x.lower())
406 return groupNames
407
408
410 """
411 Returns a catalog instance for this organizer.
412
413 @return: The catalog instance for this Organizer.
414 @rtype: ZCatalog
415 @note: Catalog is found using the attribute default_catalog.
416 """
417 catalog = None
418 if hasattr(self, self.default_catalog):
419 catalog = getattr(self, self.default_catalog)
420 return catalog
421
422
423 security.declareProtected(ZEN_COMMON, "getSubOrganizers")
425 """
426 Returns all the organizers under this organizer
427
428 @return: Organizers below this instance
429 @rtype: list
430 @permission: ZEN_COMMON
431
432 >>> dmd.Events.Security.getSubOrganizers()
433 [<EventClass at /zport/dmd/Events/Security/Login>,
434 <EventClass at /zport/dmd/Events/Security/Sudo>,
435 <EventClass at /zport/dmd/Events/Security/Conn>,
436 <EventClass at /zport/dmd/Events/Security/Virus>,
437 <EventClass at /zport/dmd/Events/Security/Auth>,
438 <EventClass at /zport/dmd/Events/Security/Login/BadPass>,
439 <EventClass at /zport/dmd/Events/Security/Login/Fail>,
440 <EventClass at /zport/dmd/Events/Security/Conn/Open>,
441 <EventClass at /zport/dmd/Events/Security/Conn/Close>]
442 """
443 orgs = self.children()
444 for child in self.children():
445 orgs.extend(child.getSubOrganizers())
446 return orgs
447
448 security.declareProtected(ZEN_COMMON, "getSubInstances")
450 """
451 Returns the object ids of all the instances of a specific relation
452 under this organizer
453
454 @param rel: The name of the relation to traverse
455 @type rel: string
456 @return: The object ids of instances under an relation of this org
457 @rtype: list
458 @raise: AttributeError
459 @permission: ZEN_COMMON
460
461 >>> dmd.Events.Security.Login.getSubInstanceIds('instances')
462 ['MSExchangeIS Mailbox Store_1009', 'MSExchangeIS Mailbox Store_1011',
463 'defaultmapping', 'dropbear', 'sshd', 'MSFTPSVC_100', 'W3SVC_100',
464 'dropbear', 'remote(pam_unix)']
465 """
466 relobj = getattr(self, rel, None)
467 if not relobj:
468 raise AttributeError( "%s not found on %s" % (rel, self.id) )
469 objs = relobj.objectIds()
470 for suborg in self.children():
471 objs.extend(suborg.getSubInstanceIds(rel))
472 return objs
473
474 security.declareProtected(ZEN_COMMON, "getSubInstances")
476 """
477 Returns the object isntances of a specific relation
478 under this organizer
479
480 @param rel: The name of the relation to traverse
481 @type rel: string
482 @return: The object instances under an relation of this org
483 @rtype: list
484 @raise: AttributeError
485 @permission: ZEN_COMMON
486
487 >>> dmd.Events.Security.Login.getSubInstances('instances')
488 [<EventClassInst at /zport/dmd/Events/Security/Login/instances/MSExchangeIS Mailbox Store_1009>,
489 <EventClassInst at /zport/dmd/Events/Security/Login/instances/MSExchangeIS Mailbox Store_1011>,
490 <EventClassInst at /zport/dmd/Events/Security/Login/instances/defaultmapping>,
491 <EventClassInst at /zport/dmd/Events/Security/Login/BadPass/instances/dropbear>,
492 <EventClassInst at /zport/dmd/Events/Security/Login/BadPass/instances/sshd>,
493 <EventClassInst at /zport/dmd/Events/Security/Login/Fail/instances/MSFTPSVC_100>,
494 <EventClassInst at /zport/dmd/Events/Security/Login/Fail/instances/W3SVC_100>,
495 <EventClassInst at /zport/dmd/Events/Security/Login/Fail/instances/dropbear>,
496 <EventClassInst at /zport/dmd/Events/Security/Login/Fail/instances/remote(pam_unix)>]
497 """
498 relobj = getattr(self, rel, None)
499 if not relobj:
500 raise AttributeError( "%s not found on %s" % (rel, self.id) )
501 objs = relobj()
502 if not objs: objs = []
503 for suborg in self.children():
504 objs.extend(suborg.getSubInstances(rel))
505 return objs
506
507 security.declareProtected(ZEN_COMMON, "getSubInstancesGen")
509 """
510 Returns the object isntances of a specific relation
511 under this organizer
512
513 @param rel: The name of the relation to traverse
514 @type rel: string
515 @return: The object ids of instances under an relation of this org
516 @rtype: generator
517 @raise: AttributeError
518 @permission: ZEN_COMMON
519 """
520 relobj = getattr(self, rel, None)
521 if not relobj:
522 raise AttributeError( "%s not found on %s" % (rel, self.id) )
523 for obj in relobj.objectValuesGen():
524 yield obj
525 for suborg in self.children():
526 for obj in suborg.getSubInstancesGen(rel):
527 yield obj
528
530 """
531 Calls exportXml on the children of this organizer
532
533 @param ofile: The file to output
534 @type ofile: File
535 @param ignorerels: Relations to ignore
536 @type ignorerels: list
537 """
538 map(lambda o: o.exportXml(ofile, ignorerels), self.children())
539
540
541 InitializeClass(Organizer)
542