1
2
3
4
5
6
7
8
9
10
11
12
13
14 __doc__ = """Organizer
15 Base class for all Zenoss organizers
16 """
17
18 from Globals import InitializeClass
19 from Acquisition import aq_parent
20 from AccessControl import ClassSecurityInfo, getSecurityManager
21
22 from Products.ZenRelations.RelSchema import *
23 from Products.ZenUtils.Exceptions import ZentinelException
24 from Products.ZenWidgets import messaging
25
26 from EventView import EventView
27 from ZenModelRM import ZenModelRM
28 from ZenossSecurity import *
29
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: kids.sort(lambda x,y: cmp(x.primarySortKey(),
127 y.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')
203
204
205 security.declareProtected(ZEN_DELETE, 'manage_deleteOrganizer')
207 """
208 Deletes an organizer underneath this organizer
209
210 @param orgname: Name of the organizer to delete
211 @type orgname: string
212 @raise: KeyError
213 @permission: ZEN_DELETE
214
215 >>> dmd.Devices.manage_deleteOrganizer('/Devices/Server/Linux')
216 """
217 if orgname.startswith("/"):
218 try:
219 orgroot = self.getDmdRoot(self.dmdRootName)
220 organizer = orgroot.getOrganizer(orgname)
221 parent = aq_parent(organizer)
222 parent._delObject(organizer.getId())
223 except KeyError:
224 pass
225 else:
226 self._delObject(orgname)
227 if REQUEST:
228 messaging.IMessageSender(self).sendToBrowser(
229 'Organizer Deleted',
230 '%s "%s" was deleted.' % (self.__class__.__name__, orgname)
231 )
232 return self.callZenScreen(REQUEST)
233
234
235 security.declareProtected(ZEN_DELETE, 'manage_deleteOrganizers')
237 """
238 Delete a list of Organizers from the database using their ids.
239
240 @param organizerPaths: Names of organizer to be deleted
241 @type organizerPaths: list
242 @permission: ZEN_DELETE
243
244 >>> dmd.Devices.manage_deleteOrganizers(['/Devices/Server/Linux',
245 ... '/Devices/Server/Windows'])
246 """
247 if not organizerPaths:
248 messaging.IMessageSender(self).sendToBrowser(
249 'Error',
250 'No organizers were specified.',
251 priority=messaging.WARNING
252 )
253 return self.callZenScreen(REQUEST)
254 for organizerName in organizerPaths:
255 self.manage_deleteOrganizer(organizerName)
256 if REQUEST:
257 plural = ''
258 if len(organizerPaths) > 1: plural = 's'
259 messaging.IMessageSender(self).sendToBrowser(
260 'Organizers Deleted',
261 '%s%s %s were deleted.' % (self.__class__.__name__,
262 plural, ', '.join(organizerPaths))
263 )
264 return self.callZenScreen(REQUEST)
265
266
268 """
269 DEPRECATED - see childMoveTargets
270 Return list of all organizers excluding our self.
271
272 @return: A sorted list of organizers excluding our self.
273 @rtype: list
274 @todo: We should be using either deviceMoveTargets or childMoveTargets
275 """
276 targets = filter(lambda x: x != self.getOrganizerName(),
277 self.getDmdRoot(self.dmdRootName).getOrganizerNames())
278 targets.sort(lambda x,y: cmp(x.lower(), y.lower()))
279 return targets
280
281
282 - def moveOrganizer(self, moveTarget, organizerPaths=None, REQUEST=None):
283 """
284 Move organizers under this organizer to another organizer
285
286 @param moveTarget: Name of the destination organizer
287 @type moveTarget: string
288 @param organizerPaths: Paths of organizers to be moved
289 @type organizerPaths: list
290
291 >>> dmd.Events.Status.moveOrganizer('/Events/Ignore',
292 ... ['Ping', 'Snmp'])
293 """
294 if not moveTarget or not organizerPaths: return self()
295 target = self.getDmdRoot(self.dmdRootName).getOrganizer(moveTarget)
296 movedStuff = False
297 for organizerName in organizerPaths:
298 if moveTarget.find(organizerName) > -1: continue
299 obj = self._getOb(organizerName, None)
300 if obj is None: continue
301 obj._operation = 1
302 self._delObject(organizerName)
303 target._setObject(organizerName, obj)
304 movedStuff = True
305 if REQUEST:
306 if movedStuff:
307 plural = ''
308 if len(organizerPaths) > 1: plural = 's'
309 messaging.IMessageSender(self).sendToBrowser(
310 'Organizers Moved',
311 '%s%s %s were moved to %s.' % (self.__class__.__name__,
312 plural, ', '.join(organizerPaths), moveTarget)
313 )
314 else:
315 messaging.IMessageSender(self).sendToBrowser(
316 'Error',
317 'No %s were moved.' % self.__class__.__name__,
318 priority=messaging.WARNING
319 )
320 return target.callZenScreen(REQUEST)
321
322
324 """
325 Creates an organizer with a specified path.
326 Use manage_addOrganizer instead
327
328 @param path: Path of the organizer to create
329 @type path: string
330 @return: Organizer created with the specified path
331 @rtype: Organizer
332 """
333 return self.createHierarchyObj(self.getDmdRoot(self.dmdRootName),
334 path,self.__class__)
335
336
338 """
339 Get an organizer by path under the same root
340
341 @param path: Path of the organizer to retrieve
342 @type path: string
343 @return: Organizer with the specified path
344 @rtype: Organizer
345
346 >>> dmd.Events.Status.getOrganizer('/Status/Snmp')
347 <EventClass at /zport/dmd/Events/Status/Snmp>
348 >>> dmd.Events.Status.getOrganizer('Status/Snmp')
349 <EventClass at /zport/dmd/Events/Status/Snmp>
350 >>> dmd.Events.Status.getOrganizer('/Events/Status/Snmp')
351 <EventClass at /zport/dmd/Events/Status/Snmp>
352 """
353 if path.startswith("/"): path = path[1:]
354 return self.getDmdRoot(self.dmdRootName).getObjByPath(path)
355
356
357 security.declareProtected(ZEN_COMMON, "getOrganizerName")
359 """
360 Return the DMD path of an Organizer without its dmdSubRel names.
361
362 @return: Name of this organizer
363 @rtype: string
364 @permission: ZEN_COMMON
365
366 >>> dmd.Events.Status.Snmp.getOrganizerName()
367 '/Status/Snmp'
368 """
369 return self.getPrimaryDmdId(self.dmdRootName)
370 getDmdKey = getOrganizerName
371
372
373 security.declareProtected(ZEN_COMMON, "getOrganizerNames")
375 """
376 Returns a list of all organizer names under this organizer
377
378 @param addblank: If True, add a blank item in the list.
379 @type addblank: boolean
380 @return: The DMD paths of all Organizers below this instance.
381 @rtype: list
382 @permission: ZEN_COMMON
383
384 >>> dmd.Events.Security.getOrganizerNames()
385 ['/Security', '/Security/Auth', '/Security/Conn',
386 '/Security/Conn/Close', '/Security/Conn/Open', '/Security/Login',
387 '/Security/Login/BadPass', '/Security/Login/Fail', '/Security/Sudo',
388 '/Security/Virus']
389 """
390 groupNames = []
391 user = getSecurityManager().getUser()
392 if user.has_permission(ZEN_VIEW, self) or not checkPerm:
393 groupNames.append(self.getOrganizerName())
394 for subgroup in self.children(checkPerm=False):
395 groupNames.extend(subgroup.getOrganizerNames())
396 if self.id == self.dmdRootName:
397 if addblank: groupNames.append("")
398 groupNames.sort(lambda x,y: cmp(x.lower(), y.lower()))
399 return groupNames
400
401
403 """
404 Returns a catalog instance for this organizer.
405
406 @return: The catalog instance for this Organizer.
407 @rtype: ZCatalog
408 @note: Catalog is found using the attribute default_catalog.
409 """
410 catalog = None
411 if hasattr(self, self.default_catalog):
412 catalog = getattr(self, self.default_catalog)
413 return catalog
414
415
416 security.declareProtected(ZEN_COMMON, "getSubOrganizers")
418 """
419 Returns all the organizers under this organizer
420
421 @return: Organizers below this instance
422 @rtype: list
423 @permission: ZEN_COMMON
424
425 >>> dmd.Events.Security.getSubOrganizers()
426 [<EventClass at /zport/dmd/Events/Security/Login>,
427 <EventClass at /zport/dmd/Events/Security/Sudo>,
428 <EventClass at /zport/dmd/Events/Security/Conn>,
429 <EventClass at /zport/dmd/Events/Security/Virus>,
430 <EventClass at /zport/dmd/Events/Security/Auth>,
431 <EventClass at /zport/dmd/Events/Security/Login/BadPass>,
432 <EventClass at /zport/dmd/Events/Security/Login/Fail>,
433 <EventClass at /zport/dmd/Events/Security/Conn/Open>,
434 <EventClass at /zport/dmd/Events/Security/Conn/Close>]
435 """
436 orgs = self.children()
437 for child in self.children():
438 orgs.extend(child.getSubOrganizers())
439 return orgs
440
441 security.declareProtected(ZEN_COMMON, "getSubInstances")
443 """
444 Returns the object ids of all the instances of a specific relation
445 under this organizer
446
447 @param rel: The name of the relation to traverse
448 @type rel: string
449 @return: The object ids of instances under an relation of this org
450 @rtype: list
451 @raise: AttributeError
452 @permission: ZEN_COMMON
453
454 >>> dmd.Events.Security.Login.getSubInstanceIds('instances')
455 ['MSExchangeIS Mailbox Store_1009', 'MSExchangeIS Mailbox Store_1011',
456 'defaultmapping', 'dropbear', 'sshd', 'MSFTPSVC_100', 'W3SVC_100',
457 'dropbear', 'remote(pam_unix)']
458 """
459 relobj = getattr(self, rel, None)
460 if not relobj:
461 raise AttributeError( "%s not found on %s" % (rel, self.id) )
462 objs = relobj.objectIds()
463 for suborg in self.children():
464 objs.extend(suborg.getSubInstanceIds(rel))
465 return objs
466
467 security.declareProtected(ZEN_COMMON, "getSubInstances")
469 """
470 Returns the object isntances of a specific relation
471 under this organizer
472
473 @param rel: The name of the relation to traverse
474 @type rel: string
475 @return: The object instances under an relation of this org
476 @rtype: list
477 @raise: AttributeError
478 @permission: ZEN_COMMON
479
480 >>> dmd.Events.Security.Login.getSubInstances('instances')
481 [<EventClassInst at /zport/dmd/Events/Security/Login/instances/MSExchangeIS Mailbox Store_1009>,
482 <EventClassInst at /zport/dmd/Events/Security/Login/instances/MSExchangeIS Mailbox Store_1011>,
483 <EventClassInst at /zport/dmd/Events/Security/Login/instances/defaultmapping>,
484 <EventClassInst at /zport/dmd/Events/Security/Login/BadPass/instances/dropbear>,
485 <EventClassInst at /zport/dmd/Events/Security/Login/BadPass/instances/sshd>,
486 <EventClassInst at /zport/dmd/Events/Security/Login/Fail/instances/MSFTPSVC_100>,
487 <EventClassInst at /zport/dmd/Events/Security/Login/Fail/instances/W3SVC_100>,
488 <EventClassInst at /zport/dmd/Events/Security/Login/Fail/instances/dropbear>,
489 <EventClassInst at /zport/dmd/Events/Security/Login/Fail/instances/remote(pam_unix)>]
490 """
491 relobj = getattr(self, rel, None)
492 if not relobj:
493 raise AttributeError( "%s not found on %s" % (rel, self.id) )
494 objs = relobj()
495 if not objs: objs = []
496 for suborg in self.children():
497 objs.extend(suborg.getSubInstances(rel))
498 return objs
499
500 security.declareProtected(ZEN_COMMON, "getSubInstancesGen")
502 """
503 Returns the object isntances of a specific relation
504 under this organizer
505
506 @param rel: The name of the relation to traverse
507 @type rel: string
508 @return: The object ids of instances under an relation of this org
509 @rtype: generator
510 @raise: AttributeError
511 @permission: ZEN_COMMON
512 """
513 relobj = getattr(self, rel, None)
514 if not relobj:
515 raise AttributeError( "%s not found on %s" % (rel, self.id) )
516 for obj in relobj.objectValuesGen():
517 yield obj
518 for suborg in self.children():
519 for obj in suborg.getSubInstancesGen(rel):
520 yield obj
521
523 """
524 Calls exportXml on the children of this organizer
525
526 @param ofile: The file to output
527 @type ofile: File
528 @param ignorerels: Relations to ignore
529 @type ignorerels: list
530 """
531 map(lambda o: o.exportXml(ofile, ignorerels), self.children())
532
533
534 InitializeClass(Organizer)
535