1
2
3
4
5
6
7
8
9
10
11
12
13
14 import os
15 import re
16 import time
17 import logging
18 log = logging.getLogger("zen.ZenossInfo")
19
20 from Globals import InitializeClass
21 from OFS.SimpleItem import SimpleItem
22 from AccessControl import ClassSecurityInfo
23
24 from Products.ZenModel.ZenModelItem import ZenModelItem
25 from Products.ZenUtils import Time
26 from Products.ZenUtils.Version import *
27 from Products.ZenUtils.Utils import zenPath
28
29 from Products.ZenEvents.UpdateCheck import UpdateCheck, parseVersion
30
39
41
42 portal_type = meta_type = 'ZenossInfo'
43
44 security = ClassSecurityInfo()
45
46 _properties = (
47 {'id':'id', 'type':'string'},
48 {'id':'title', 'type':'string'},
49 )
50
51 factory_type_information = (
52 {
53 'immediate_view' : 'zenossInfo',
54 'actions' :
55 (
56 { 'id' : 'settings'
57 , 'name' : 'Settings'
58 , 'action' : '../dmd/editSettings'
59 , 'permissions' : ( "Manage DMD", )
60 },
61 { 'id' : 'manage'
62 , 'name' : 'Commands'
63 , 'action' : '../dmd/dataRootManage'
64 , 'permissions' : ('Manage DMD',)
65 },
66 { 'id' : 'users'
67 , 'name' : 'Users'
68 , 'action' : '../dmd/ZenUsers/manageUserFolder'
69 , 'permissions' : ( 'Manage DMD', )
70 },
71 { 'id' : 'packs'
72 , 'name' : 'ZenPacks'
73 , 'action' : '../dmd/viewZenPacks'
74 , 'permissions' : ( "Manage DMD", )
75 },
76 { 'id' : 'menus'
77 , 'name' : 'Menus'
78 , 'action' : '../dmd/editMenus'
79 , 'permissions' : ( "Manage DMD", )
80 },
81 { 'id' : 'portlets'
82 , 'name' : 'Portlets'
83 , 'action' : '../dmd/editPortletPerms'
84 , 'permissions' : ( "Manage DMD", )
85 },
86 { 'id' : 'daemons'
87 , 'name' : 'Daemons'
88 , 'action' : 'zenossInfo'
89 , 'permissions' : ( "Manage DMD", )
90 },
91 { 'id' : 'versions'
92 , 'name' : 'Versions'
93 , 'action' : 'zenossVersions'
94 , 'permissions' : ( "Manage DMD", )
95 },
96 )
97 },
98 )
99
100
101 security.declarePublic('getZenossVersion')
106
107
108 security.declarePublic('getZenossVersionShort')
111
112
114 """
115 This function returns a Version-ready tuple. For use with the Version
116 object, use extended call syntax:
117
118 v = Version(*getOSVersion())
119 v.full()
120 """
121 if os.name == 'posix':
122 sysname, nodename, version, build, arch = os.uname()
123 name = "%s (%s)" % (sysname, arch)
124 major, minor, micro = getVersionTupleFromString(version)
125 comment = ' '.join(os.uname())
126 elif os.name == 'nt':
127 from win32api import GetVersionEx
128 major, minor, micro, platformID, additional = GetVersionEx()
129 name = 'Windows %s (%s)' % (os.name.upper(), additional)
130 comment = ''
131 else:
132 raise VersionNotSupported
133 return Version(name, major, minor, micro, 0, comment)
134
135
137 """
138 This function returns a Version-ready tuple. For use with the Version
139 object, use extended call syntax:
140
141 v = Version(*getPythonVersion())
142 v.full()
143 """
144 name = 'Python'
145 major, minor, micro, releaselevel, serial = sys.version_info
146 return Version(name, major, minor, micro)
147
148
150 """
151 This function returns a Version-ready tuple. For use with the Version
152 object, use extended call syntax:
153
154 v = Version(*getMySQLVersion())
155 v.full()
156
157 The regex was tested against the following output strings:
158 mysql Ver 14.12 Distrib 5.0.24, for apple-darwin8.5.1 (i686) using readline 5.0
159 mysql Ver 12.22 Distrib 4.0.24, for pc-linux-gnu (i486)
160 mysql Ver 14.12 Distrib 5.0.24a, for Win32 (ia32)
161 """
162 cmd = 'mysql --version'
163 fd = os.popen(cmd)
164 output = fd.readlines()
165 version = "0"
166 if fd.close() is None and len(output) > 0:
167 output = output[0].strip()
168 regexString = '(mysql).*Ver [0-9]{2}\.[0-9]{2} '
169 regexString += 'Distrib ([0-9]+.[0-9]+.[0-9]+)(.*), for (.*\(.*\))'
170 regex = re.match(regexString, output)
171 if regex:
172 name, version, release, info = regex.groups()
173 comment = 'Ver %s' % version
174
175 name = 'MySQL'
176 major, minor, micro = getVersionTupleFromString(version)
177 return Version(name, major, minor, micro, 0, comment)
178
179
197
198
200 """
201 This function returns a Version-ready tuple. For use with the Version
202 object, use extended call syntax:
203
204 v = Version(*getTwistedVersion())
205 v.full()
206 """
207 from twisted._version import version as v
208
209 return Version('Twisted', v.major, v.minor, v.micro)
210
211
213 """
214 This function returns a Version-ready tuple. For use with the Version
215 object, use extended call syntax:
216
217 v = Version(*getpySNMPVersion())
218 v.full()
219 """
220 from pysnmp.version import getVersion
221 return Version('PySNMP', *getVersion())
222
223
225 """
226 This function returns a Version-ready tuple. For use with the Version
227 object, use extended call syntax:
228
229 v = Version(*getTwistedSNMPVersion())
230 v.full()
231 """
232 from twistedsnmp.version import version
233 return Version('TwistedSNMP', *version)
234
235
237 """
238 This function returns a Version-ready tuple. For use with the Version
239 object, use extended call syntax:
240
241 v = Version(*getZopeVersion())
242 v.full()
243 """
244 from App import version_txt as version
245
246 name = 'Zope'
247 major, minor, micro, status, release = version.getZopeVersion()
248 return Version(name, major, minor, micro)
249
250
252 try:
253 os.chdir(zenPath('Products'))
254 fd = os.popen("svn info 2>/dev/null | grep Revision | awk '{print $2}'")
255 return fd.readlines()[0].strip()
256 except:
257 return ''
258
259
261 from pynetsnmp.netsnmp import lib
262 return Version.parse('NetSnmp %s ' % lib.netsnmp_get_version())
263
264
266 """
267 Return a list of version numbers for currently tracked component
268 software.
269 """
270 versions = (
271 {'header': 'Zenoss', 'data': self.getZenossVersion().full()},
272 {'header': 'OS', 'data': self.getOSVersion().full()},
273 {'header': 'Zope', 'data': self.getZopeVersion().full()},
274 {'header': 'Python', 'data': self.getPythonVersion().full()},
275 {'header': 'Database', 'data': self.getMySQLVersion().full()},
276 {'header': 'RRD', 'data': self.getRRDToolVersion().full()},
277 {'header': 'Twisted', 'data': self.getTwistedVersion().full()},
278 {'header': 'SNMP', 'data': self.getPySNMPVersion().full()},
279 {'header': 'Twisted SNMP', 'data': self.getTwistedSNMPVersion().full()},
280 )
281 try:
282 versions += (
283 {'header': 'NetSnmp', 'data': self.getNetSnmpVersion().full() },
284 )
285 except:
286 pass
287 return versions
288
289 security.declareProtected('View','getAllVersions')
290
291
293 """
294 Return a list of daemons with their uptimes.
295 """
296 app = self.getPhysicalRoot()
297 uptimes = []
298 zope = {
299 'header': 'Zope',
300 'data': app.Control_Panel.process_time(),
301 }
302 uptimes.append(zope)
303 return uptimes
304 security.declareProtected('View','getAllUptimes')
305
306
308 """
309 Return a data structures representing the states of the supported
310 Zenoss daemons.
311 """
312 states = []
313 activeButtons = {'button1': 'Restart', 'button2': 'Stop', 'button2state': True}
314 inactiveButtons = {'button1': 'Start', 'button2': 'Stop', 'button2state': False}
315 for daemon in self._getDaemonList():
316 pid = self._getDaemonPID(daemon)
317 if pid:
318 buttons = activeButtons
319 msg = 'Up'
320 color = '#0F0'
321 else:
322 buttons = inactiveButtons
323 msg = 'Down'
324 color = '#F00'
325 states.append({
326 'name': daemon,
327 'pid': pid,
328 'msg': msg,
329 'color': color,
330 'buttons': buttons})
331 return states
332
333
335 try:
336 os.kill(pid, 0)
337 return pid
338 except OSError, ex:
339 import errno
340 errnum, msg = ex.args
341 if errnum == errno.EPERM:
342 return pid
343
344
346 """
347 For a given daemon name, return its PID from a .pid file.
348 """
349 if name == 'zopectl':
350 name = 'Z2'
351 elif name == 'zeoctl':
352 name = 'ZEO'
353 else:
354 name = "%s.py" % name
355 pidFile = zenPath('var', '%s.pid' % name)
356 if os.path.exists(pidFile):
357 pid = open(pidFile).read()
358 try:
359 pid = int(pid)
360 except ValueError:
361 return None
362 return self._pidRunning(int(pid))
363 else:
364 pid = None
365 return pid
366
367
369 """
370 Get the list of supported Zenoss daemons.
371 """
372 masterScript = zenPath('bin', 'zenoss')
373 daemons = []
374 for line in os.popen("%s list" % masterScript).readlines():
375 daemons.append(line.strip())
376 return daemons
377
378
380 """
381 Return a data structures representing the config infor for the
382 supported Zenoss daemons.
383 """
384 return [ dict(name=x) for x in self._getDaemonList() ]
385
387 fh = open(filename)
388 try:
389 size = os.path.getsize(filename)
390 if size > maxBytes:
391 fh.seek(-maxBytes, 2)
392
393 fh.readline()
394 return fh.read()
395 finally:
396 fh.close()
397
399 """
400 Get the last kb kilobytes of a daemon's log file contents.
401 """
402 maxBytes = 1024 * int(kb)
403 if daemon == 'zopectl':
404 daemon = 'event'
405 elif daemon == 'zeoctl':
406 daemon = 'zeo'
407 if daemon == 'zopectl':
408 daemon = 'event'
409 elif daemon == 'zeoctl':
410 daemon = 'zeo'
411 filename = zenPath('log', "%s.log" % daemon)
412
413
414
415 data = ' '
416 try:
417 data = self._readLogFile(filename, maxBytes) or ' '
418 except IOError:
419 data = 'Error reading log file'
420 return data
421
422
424 if daemon == 'zopectl':
425 daemon = 'zope'
426 elif daemon == 'zeoctl':
427 daemon = 'zeo'
428 return zenPath('etc', "%s.conf" % daemon)
429
436
451
452
466
467
483 security.declareProtected('Manage DMD','manage_daemonAction')
484
485
501 security.declareProtected('Manage DMD','manage_checkVersion')
502
503
508
509
516
517
518 InitializeClass(ZenossInfo)
519