1
2
3
4
5
6
7
8
9
10
11
12
13
14 __doc__="""DataRoot
15
16 DataRoot is the object manager which contains all confmon
17 data objects. It can be used as a global acquisition
18 name space.
19 """
20
21 import re
22 from AccessControl import ClassSecurityInfo
23 from AccessControl import getSecurityManager
24 from OFS.OrderedFolder import OrderedFolder
25 from OFS.CopySupport import CopyError, eNotSupported
26 from Products.CMFCore.DirectoryView import registerDirectory
27 from ImageFile import ImageFile
28 from Globals import HTMLFile, DTMLFile
29 from Globals import InitializeClass
30 from Acquisition import aq_base
31 from Products.PageTemplates.PageTemplateFile import PageTemplateFile
32 from Products.ZenModel.SiteError import SiteError
33 from ImageFile import ImageFile
34 from Products.ZenModel.ZenModelBase import ZenModelBase
35 from Products.ZenModel.ZenMenuable import ZenMenuable
36 from Products.ZenRelations.RelSchema import *
37 from Products.ZenUtils.IpUtil import IpAddressError
38 from Commandable import Commandable
39 import DateTime
40 import socket
41
42 from Products.ZenUtils.Utils import zenPath
43 from Products.ZenUtils.Utils import extractPostContent
44
45 from AccessControl import Permissions as permissions
46
47 from ZenModelRM import ZenModelRM
48 from ZenossSecurity import ZEN_COMMON
49
57
58
59 addDataRoot = DTMLFile('dtml/addDataRoot',globals())
60
61 -class DataRoot(ZenModelRM, OrderedFolder, Commandable, ZenMenuable):
62 meta_type = portal_type = 'DataRoot'
63
64 manage_main = OrderedFolder.manage_main
65
66 manage_options = OrderedFolder.manage_options
67
68
69
70 uuid = None
71 availableVersion = None
72 lastVersionCheck = 0
73 lastVersionCheckAttempt = 0
74 versionCheckOptIn = True
75 reportMetricsOptIn = True
76 acceptedTerms = True
77 smtpHost = 'localhost'
78 snppHost = 'localhost'
79 smtpPort = 25
80 snppPort = 444
81 smtpUser = ''
82 smtpPass = ''
83 smtpUseTLS = 0
84 emailFrom = ''
85 iconMap = {}
86 geomapapikey = ''
87 geocache = ''
88 version = ""
89
90 _properties=(
91 {'id':'title', 'type': 'string', 'mode':'w'},
92 {'id':'prodStateDashboardThresh','type':'int','mode':'w'},
93 {'id':'prodStateConversions','type':'lines','mode':'w'},
94 {'id':'priorityConversions','type':'lines','mode':'w'},
95 {'id':'priorityDashboardThresh','type':'int','mode':'w'},
96 {'id':'statusConversions','type':'lines','mode':'w'},
97 {'id':'interfaceStateConversions','type':'lines','mode':'w'},
98 {'id':'administrativeRoles','type':'lines','mode':'w'},
99 {'id':'uuid', 'type': 'string', 'mode':'w'},
100 {'id':'availableVersion', 'type': 'string', 'mode':'w'},
101 {'id':'lastVersionCheck', 'type': 'long', 'mode':'w'},
102 {'id':'lastVersionCheckAttempt', 'type': 'long', 'mode':'w'},
103 {'id':'versionCheckOptIn', 'type': 'boolean', 'mode':'w'},
104 {'id':'reportMetricsOptIn', 'type': 'boolean', 'mode':'w'},
105 {'id':'smtpHost', 'type': 'string', 'mode':'w'},
106 {'id':'smtpPort', 'type': 'int', 'mode':'w'},
107 {'id':'snppHost', 'type': 'string', 'mode':'w'},
108 {'id':'snppPort', 'type': 'int', 'mode':'w'},
109 {'id':'smtpUser', 'type': 'string', 'mode':'w'},
110 {'id':'smtpPass', 'type': 'string', 'mode':'w'},
111 {'id':'smtpUseTLS', 'type': 'int', 'mode':'w'},
112 {'id':'emailFrom', 'type': 'string', 'mode':'w'},
113 {'id':'geomapapikey', 'type': 'string', 'mode':'w'},
114 {'id':'geocache', 'type': 'string', 'mode':'w'},
115 )
116
117 _relations = (
118 ('userCommands', ToManyCont(ToOne, 'Products.ZenModel.UserCommand', 'commandable')),
119 ('packs', ToManyCont(ToOne, 'Products.ZenModel.ZenPack', 'root')),
120 ('zenMenus', ToManyCont(
121 ToOne, 'Products.ZenModel.ZenMenu', 'menuable')),
122 )
123
124
125 factory_type_information = (
126 {
127 'id' : 'DataRoot',
128 'meta_type' : 'DataRoot',
129 'description' : """Arbitrary device grouping class""",
130 'icon' : 'DataRoot_icon.gif',
131 'product' : 'ZenModel',
132 'factory' : 'manage_addStatusMonitorconf',
133 'immediate_view' : 'Dashboard',
134 'actions' :
135 (
136 { 'id' : 'settings'
137 , 'name' : 'Settings'
138 , 'action' : 'editSettings'
139 , 'permissions' : ( "Manage DMD", )
140 },
141 { 'id' : 'manage'
142 , 'name' : 'Commands'
143 , 'action' : 'dataRootManage'
144 , 'permissions' : ('Manage DMD',)
145 },
146 { 'id' : 'users'
147 , 'name' : 'Users'
148 , 'action' : 'ZenUsers/manageUserFolder'
149 , 'permissions' : ( 'Manage DMD', )
150 },
151 { 'id' : 'packs'
152 , 'name' : 'ZenPacks'
153 , 'action' : 'viewZenPacks'
154 , 'permissions' : ( "Manage DMD", )
155 },
156 { 'id' : 'menus'
157 , 'name' : 'Menus'
158 , 'action' : 'editMenus'
159 , 'permissions' : ( "Manage DMD", )
160 },
161 { 'id' : 'portlets'
162 , 'name' : 'Portlets'
163 , 'action' : 'editPortletPerms'
164 , 'permissions' : ( "Manage DMD", )
165 },
166 { 'id' : 'daemons'
167 , 'name' : 'Daemons'
168 , 'action' : '../About/zenossInfo'
169 , 'permissions' : ( "Manage DMD", )
170 },
171 { 'id' : 'versions'
172 , 'name' : 'Versions'
173 , 'action' : '../About/zenossVersions'
174 , 'permissions' : ( "Manage DMD", )
175 },
176 )
177 },
178 )
179
180 security = ClassSecurityInfo()
181
182
183 prodStateDashboardThresh = 1000
184
185
186 priorityDashboardThresh = 2
187
188 prodStateConversions = [
189 'Production:1000',
190 'Pre-Production:500',
191 'Test:400',
192 'Maintenance:300',
193 'Decommissioned:-1',
194 ]
195
196 priorityConversions = [
197 'Highest:5',
198 'High:4',
199 'Normal:3',
200 'Low:2',
201 'Lowest:1',
202 'Trivial:0',
203 ]
204
205 statusConversions = [
206 'Up:0',
207 'None:-1',
208 'No DNS:-2',
209 ]
210
211 interfaceStateConversions = [
212 'up:1',
213 'down:2',
214 'testing:3',
215 'unknown:4',
216 'dormant:5',
217 'notPresent:6',
218 'lowerLayerDown:7',
219 ]
220
221 administrativeRoles = (
222 "Administrator",
223 "Analyst",
224 "Engineer",
225 "Tester",
226 )
227
228 defaultDateRange = 129600
229 performanceDateRanges = [
230 ('Hourly',129600,),
231 ('Daily',864000,),
232 ('Weekly',3628800,),
233 ('Monthly',41472000,),
234 ('Yearly',62208000,)
235 ]
236
237
238
239 zPrimaryBasePath = ("", "zport")
240
241
246
247
249 """Return the current event list for this managed entity.
250 """
251 return self.ZenEventManager.getEventCount(**kwargs)
252
253
256
257
260
261
262 security.declareProtected(ZEN_COMMON, 'getProdStateConversions')
267
268
269 security.declareProtected(ZEN_COMMON, 'convertProdState')
271 '''convert a numeric production state to a
272 textual representation using the prodStateConversions
273 map'''
274 return self.convertAttribute(prodState, self.prodStateConversions)
275
276
277 security.declareProtected(ZEN_COMMON, 'getStatusConversions')
281
282
283 security.declareProtected(ZEN_COMMON, 'convertStatus')
287
288 security.declareProtected(ZEN_COMMON, 'getPriorityConversions')
291
292 security.declareProtected(ZEN_COMMON, 'convertPriority')
295
296 security.declareProtected(ZEN_COMMON, 'getInterfaceStateConversions')
301
302
303 security.declareProtected(ZEN_COMMON, 'convertAttribute')
305 '''convert a numeric production state to a
306 textual representation using the prodStateConversions
307 map'''
308 numbValue = int(numbValue)
309 for line in conversions:
310 line = line.rstrip()
311 (name, number) = line.split(':')
312 if int(number) == numbValue:
313 return name
314 return numbValue
315
316
317 security.declareProtected(ZEN_COMMON, 'getConversions')
319 """get the text list of itmes that convert to ints"""
320 convs = []
321 for item in attribute:
322 tup = item.split(':')
323 tup[1] = int(tup[1])
324 convs.append(tup)
325 return convs
326
327 security.declarePublic('filterObjectsRegex')
330 """filter a list of objects based on a regex"""
331 filter = re.compile(filter).search
332 filteredObjects = []
333 for obj in objects:
334 value = getattr(obj, filteratt, None)
335 if callable(value):
336 value = value()
337 fvalue = filter(value)
338 if (fvalue and not negatefilter) or (not fvalue and negatefilter):
339 filteredObjects.append(obj)
340 return filteredObjects
341
342
343 security.declareProtected('View', 'myUserGroups')
345 user = self.REQUEST.get('AUTHENTICATED_USER')
346 if hasattr(user, 'getGroups'):
347 return user.getGroups()
348 else:
349 return ()
350
351
352 security.declareProtected('View', 'getAllUserGroups')
354 return self.acl_users.getGroups()
355
357 ''' send an email to the zenoss error email address
358 then send user to a thankyou page or an email error page.
359 '''
360 mailSent = SiteError.sendErrorEmail(
361 self.REQUEST.errorType,
362 self.REQUEST.errorValue,
363 self.REQUEST.errorTrace,
364 self.REQUEST.errorUrl,
365 self.About.getZenossRevision(),
366 self.About.getZenossVersionShort(),
367 self.REQUEST.contactName,
368 self.REQUEST.contactEmail,
369 self.REQUEST.comments)
370 if not mailSent:
371 toAddress = SiteError.ERRORS_ADDRESS
372 body = SiteError.createReport(
373 self.REQUEST.errorType,
374 self.REQUEST.errorValue,
375 self.REQUEST.errorTrace,
376 self.REQUEST.errorUrl,
377 self.About.getZenossRevision(),
378 self.About.getZenossVersionShort(),
379 True,
380 self.REQUEST.contactName,
381 self.REQUEST.contactEmail,
382 self.REQUEST.comments)
383 return getattr(self, 'errorEmailFailure')(
384 toAddress=SiteError.ERRORS_ADDRESS,
385 body=body)
386 return getattr(self, 'errorEmailThankYou')()
387
388
389
391 '''Write out csv rows with the given objects and fields.
392 If out is not None then call out.write() with the result and return None
393 otherwise return the result.
394 Each item in fieldsAndLabels is either a string representing a
395 field/key/index (see getDataField) or it is a tuple of (field, label)
396 where label is the string to be used in the first row as label
397 for that column.
398 Objects can be either dicts, lists/tuples or other objects. Field
399 is interpreted as a key, index or attribute depending on what
400 object is.
401 Method names can be passed instead of attribute/key/indices as field.
402 In this case the method is called and the return value is used in
403 the export.
404 '''
405 import csv
406 import StringIO
407 if out:
408 buffer = out
409 else:
410 buffer = StringIO.StringIO()
411 fields = []
412 labels = []
413 if not fieldsAndLabels:
414 fieldsAndLabels = []
415 if not objects:
416 objects = []
417 for p in fieldsAndLabels:
418 if isinstance(p, tuple):
419 fields.append(p[0])
420 labels.append(p[1])
421 else:
422 fields.append(p)
423 labels.append(p)
424 writer = csv.writer(buffer)
425 writer.writerow(labels)
426 def getDataField(thing, field):
427 if isinstance(thing, dict):
428 value = thing.get(field, '')
429 elif isinstance(thing, list) or isinstance(thing, tuple):
430 value = thing[int(field)]
431 else:
432 value = getattr(thing, field, '')
433 if isinstance(value, ZenModelBase):
434 value = value.id
435 elif callable(value):
436 value = value()
437 if value == None:
438 value = ''
439 return str(value)
440 for o in objects:
441 writer.writerow([getDataField(o,f) for f in fields])
442 if out:
443 result = None
444 else:
445 result = buffer.getvalue()
446 return result
447
448
450 ''' Called by Commandable.doCommand() to ascertain objects on which
451 a UserCommand should be executed.
452 '''
453 raise 'Not supported on DataRoot'
454
455
458
459
461 ''' Return self.emailFrom or a suitable default
462 '''
463 return self.emailFrom or 'zenossuser_%s@%s' % (
464 getSecurityManager().getUser().getId(), socket.getfqdn())
465
466 - def manage_addZenPack(self, id,
467 author="",
468 organization="",
469 version="",
470 REQUEST = None):
471 """make a new ZenPack"""
472 from ZenPack import ZenPack
473 pack = ZenPack(id)
474 pack.author = author
475 pack.organization = organization
476 pack.version = version
477 self.packs._setObject(id, pack)
478 import os
479 zp = zenPath('Products', id)
480 if not os.path.isdir(zp):
481 os.makedirs(zp, 0750)
482 for d in ['objects', 'skins', 'modeler/plugins',
483 'reports', 'daemons']:
484 os.makedirs(os.path.join(zp, d), 0750)
485 skinsDir = os.path.join(zp, 'skins')
486 skinsDir2 = os.path.join(skinsDir, id)
487 if not os.path.isdir(skinsDir2):
488 os.makedirs(skinsDir2, 0750)
489 registerDirectory(skinsDir, globals())
490
491 pack.install(self.getPhysicalRoot())
492 if REQUEST is not None:
493 return self.callZenScreen(REQUEST, redirect=True)
494
496 """remove a ZenPack"""
497 import os
498 zp = zenPath('bin', 'zenpack')
499 import os
500 for pack in ids:
501 os.system('%s run --remove %s' % (zp, pack))
502 self._p_jar.sync()
503 if REQUEST is not None:
504 return self.callZenScreen(REQUEST, redirect=True)
505
506
508 ''' Extract the zenpack name from the broken module
509 '''
510 return pack.__class__.__module__.split('.')[1]
511
513 """ Retrieve the appropriate image path associated
514 with a given object.
515 """
516 try:
517 return obj.primaryAq().zIcon
518 except AttributeError:
519 return '/zport/dmd/img/icons/noicon.png'
520
528
529 security.declareProtected(ZEN_COMMON, 'getGeoCache')
531 cachestr = self.geocache
532 for char in ('\\r', '\\n'):
533 cachestr = cachestr.replace(char, ' ')
534 return cachestr
535
536 - def goToStatusPage(self, objid, REQUEST=None):
537 """ Find a device or network and redirect
538 to its status page.
539 """
540 import urllib
541 objid = urllib.unquote(objid)
542 try:
543 devid = objid
544 if not devid.endswith('*'): devid += '*'
545 obj = self.Devices.findDevice(devid)
546 except:
547 obj=None
548 if not obj:
549 try:
550 obj = self.Networks.getNet(objid)
551 except IpAddressError:
552 return None
553 if not obj: return None
554 if REQUEST is not None:
555 REQUEST['RESPONSE'].redirect(obj.getPrimaryUrlPath())
556
557
559 """ Get the XML representation of network nodes
560 and edges using the obj with objid as a root
561 """
562 import urllib
563 objid = urllib.unquote(objid)
564 try:
565 devid = objid
566 if not devid.endswith('*'): devid += '*'
567 obj = self.Devices.findDevice(devid)
568 except: obj=None
569 if not obj:
570 obj = self.Networks.getNet(objid)
571 if not obj:
572 return '<graph><Start name="%s"/></graph>' % objid
573 return obj.getXMLEdges(int(depth), filter,
574 start=(obj.id,obj.getPrimaryUrlPath()))
575
576 InitializeClass(DataRoot)
577