Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | Related Pages

gVersions.py

00001 #!/usr/local/bin/python
00002 #
00003 #                               Copyright 2002
00004 #                                     by
00005 #                        The Board of Trustees of the
00006 #                     Leland Stanford Junior University.
00007 #                            All rights reserved.
00008 #
00009 
00010 """Version retrieval utility class
00011 
00012 Contents:
00013 
00014   Provides accessor methods to retrieve version information from
00015   both the software and hardware.
00016   Displays version info from loaded libraries.
00017   Used for troubleshooting problems.
00018 
00019 Overview:
00020 
00021   Each driver on VxWorks side and each module on the client side
00022   provides its version number through functions. When the function
00023   cmd.getVersions() is called the command server packetizes this
00024   information and sends it over the socket to the command client
00025   which gets decoded into a tuple. The getModuleVersions() function
00026   converts this tuple to a dictionary and adds the python module
00027   versions to it.
00028 
00029 Usage:
00030 
00031   To retrieve version information one can write::
00032 
00033     python versions.py
00034 
00035     or
00036 
00037     import versions
00038     versions.Gversions.getModuleVersions()
00039 """
00040 
00041 __facility__ = "Online"
00042 __abstract__ = "Version retrieval utility"
00043 __author__   = "Selim Tuvi <stuvi@slac.stanford.edu> SLAC - GLAST I&T/Online"
00044 __date__     = ("$Date: 2006/07/03 21:03:14 $").split(' ')[1]
00045 __version__  = "$Revision: 2.35 $"
00046 __release__  = "$Name: R04-12-00 $"
00047 __credits__  = "SLAC"
00048 
00049 import LATTE.copyright_SLAC
00050 
00051 
00052 import sha
00053 import marshal
00054 import inspect
00055 import os
00056 import sys
00057 import glob
00058 import logging as log
00059 import compiler
00060 
00061 ROOT_DIR_ENVS = ['LATTE_ROOT','VXW_ROOT','LAT_ROOT','INT_ROOT','ACD_ROOT','CAL_ROOT','TKR_ROOT','ELX_ROOT','TRG_ROOT']
00062 
00063 class Gversions(object):
00064   def getModuleVersions(ocs=None):
00065     """Static class method which returns a dictionary of modules
00066        with their versions.
00067 
00068     \param ocs GOCS node
00069 
00070     \return Dictionary of modules with their versions
00071     """
00072     ignoreList =  [ 'scipy.gplt','ROOT'
00073                     #'__main__','_xmlplus','cPickle','pickle','sre','urllib',
00074                     #'xml','_xmlplus','xml.parsers.expat', 'xml.parsers.pyexpat',
00075                     #'pyexpat'
00076                   ]
00077     versions = {}
00078     if ocs is not None:
00079       (server_version, server_revision) = ocs.getVersion()
00080       versions['OCS(server)'] = '%d.%d' %(server_version, server_revision)
00081       for (name, data) in ocs.cmxAsBuilt().items():
00082         package = data[0]
00083         version = data[1]
00084         #user    = data[2]
00085         #time    = data[3]
00086         versions['%s[%s]' % (package, name)] = version
00087       startupScriptInfo = ocs.getStartupScriptInfo()
00088       if startupScriptInfo is not None:
00089         versions[startupScriptInfo[0]] = startupScriptInfo[1]
00090     mstrList = sys.modules.keys()
00091     mstrList.sort()
00092     for mStr in mstrList:
00093       if mStr in ignoreList: continue
00094       m = sys.modules[mStr]
00095       if hasattr(m, '__version__'):
00096         v = Gversions.extractVersion(str(getattr(m, '__version__')))
00097         if v.strip() != '' or Gversions.isModuleInReleases(m):
00098           versions[mStr] = v
00099       elif Gversions.isModuleInReleases(m):
00100         versions[mStr] = ''
00101 
00102     versions['Python'] = str(hex(sys.hexversion))
00103     try:
00104       import qt
00105       versions['Qt']     = qt.QT_VERSION_STR
00106     except: pass
00107     try:
00108       import sip
00109       if 'SIP_VERSION' in dir(sip):
00110         versions['SIP'] = hex(sip.SIP_VERSION)
00111     except: pass
00112     try:
00113       if 'PYQT_VERSION_STR' in dir(qt):
00114         versions['PyQt'] = qt.PYQT_VERSION_STR
00115       else:
00116         versions['PyQt']   = qt.PYQT_VERSION
00117     except: pass
00118     return versions
00119   getModuleVersions = staticmethod(getModuleVersions)
00120 
00121   def isModuleInReleases(m, rootDirEnvs=None):
00122     if rootDirEnvs is None:
00123       rootDirEnvs = ROOT_DIR_ENVS
00124     if hasattr(m, '__file__'):
00125       srcFile = inspect.getsourcefile(m)
00126       if srcFile is not None:
00127         srcFile = os.path.normpath(os.path.normcase(srcFile))
00128         for rootDirEnv in rootDirEnvs:
00129           if os.environ.has_key(rootDirEnv):
00130             rootDir = os.path.normpath(os.path.normcase(os.environ[rootDirEnv].strip()))
00131             if srcFile.startswith(rootDir):
00132               return True
00133     return False
00134   isModuleInReleases = staticmethod(isModuleInReleases)
00135 
00136 
00137   def extractVersion(verStr):
00138     """Static class method which extracts the version string from the CVS
00139     keyword string, if that's what it appears to be.  If it doesn't, just
00140     return the input."""
00141     colon  = verStr.find(':')
00142     if colon != -1:
00143       dollar = verStr.find('$', colon)
00144       if dollar != -1:
00145         return verStr[colon+2:dollar-1]
00146     return verStr
00147   extractVersion = staticmethod(extractVersion)
00148 
00149   def calcDigest(filePath):
00150     digest = sha.new()
00151     f = file(filePath, 'rb')
00152     data = f.read(65536)
00153     while len(data) != 0:
00154       digest.update(data)
00155       data = f.read(65536)
00156     f.close()
00157     #return digest.hexdigest()
00158     return digest.digest()
00159   calcDigest = staticmethod(calcDigest)
00160 
00161 
00162   def getModuleDigests():
00163     ignoreList = ['scipy.gplt','ROOT']
00164     digests = {}
00165     mstrList = sys.modules.keys()
00166     mstrList.sort()
00167     for mStr in mstrList:
00168       if mStr in ignoreList: continue
00169       m = sys.modules[mStr]
00170       if hasattr(m, '__version__') and hasattr(m, '__file__'):
00171         srcFile = inspect.getsourcefile(m)
00172         digest_value = Gversions.calcDigest(srcFile)
00173         if digest_value is not None:
00174           digests[mStr] = digest_value
00175     return digests
00176   getModuleDigests = staticmethod(getModuleDigests)
00177 
00178   def getReleaseFromDigest(digestDataFile=None, rootDirEnv='LATTE_ROOT'):
00179     if os.environ.has_key(rootDirEnv):
00180       rootDir = os.environ[rootDirEnv].strip()
00181     else:
00182       rootDir = ''
00183     if digestDataFile == None and rootDir == '':
00184       raise RuntimeError, "Can not find the digest database file at the indicated location: $%s" % rootDirEnv
00185     elif digestDataFile == None:
00186       digestDataFile = os.path.join(rootDir, 'digestData')
00187     f = file(digestDataFile,'rb')
00188     try:
00189       dc = marshal.load(f)
00190     except ValueError:
00191       log.exception("")
00192       Gversions.logBadMarshalDataMessage()
00193       return
00194     exec(dc)
00195     return _digestData._release
00196   getReleaseFromDigest = staticmethod(getReleaseFromDigest)
00197 
00198   def logBadMarshalDataMessage():
00199     log.error("If the above exception is a 'bad marshal data' error,")
00200     log.error("it is likely that you need to update one or more of the")
00201     log.error("digestData files pointed to by the XXX_ROOT environment")
00202     log.error("variables. To create the digestData file, enter the")
00203     log.error("following command for each of the XXX_ROOT that you have:")
00204     log.error("%%ONLINE_ROOT%%\LATTE\setup\createDigestData %%XXX_ROOT%% %s XXX_00_00_00" % sys.prefix)
00205   logBadMarshalDataMessage = staticmethod(logBadMarshalDataMessage)
00206 
00207   def verifyModuleDigests(digestDataFile=None, rootDirEnv='LATTE_ROOT', additionalFilesToVerify=[]):
00208     ignoreList = ['scipy.gplt','ROOT']
00209     failedModules = []
00210     rootDir = ''
00211     if os.environ.has_key(rootDirEnv):
00212       rootDir = os.environ[rootDirEnv].strip()
00213     if digestDataFile == None and rootDir == '':
00214       raise RuntimeError, "Can not find the digest database file at the indicated location: $%s" % rootDirEnv
00215     elif digestDataFile == None:
00216       digestDataFile = os.path.join(rootDir, 'digestData')
00217     f = file(digestDataFile,'rb')
00218     try:
00219       dc = marshal.load(f)
00220     except ValueError:
00221       log.exception("")
00222       Gversions.logBadMarshalDataMessage()
00223       return (None, [])
00224     exec(dc)
00225     mstrList = sys.modules.keys()
00226     mstrList.sort()
00227     for mStr in mstrList:
00228       if mStr in ignoreList: continue
00229       #raw_input("Entering %s}" % mStr)
00230       m = sys.modules[mStr]
00231       if hasattr(m, '__file__'):
00232         srcFile = inspect.getsourcefile(m)
00233         if srcFile is not None:
00234           srcFile = os.path.normpath(os.path.normcase(srcFile))
00235           if srcFile.startswith(os.path.normpath(os.path.normcase(rootDir))):
00236             found = False
00237             for (filename, digest) in _digestData._digests.items():
00238               if srcFile == os.path.normpath(os.path.normcase(filename)):
00239                 found = True
00240                 digest_value = Gversions.calcDigest(srcFile)
00241                 if digest_value is None or digest != digest_value:
00242                   failedModules.append(mStr)
00243                 break
00244             if not found:
00245               failedModules.append(mStr)
00246       #raw_input("Exiting %s}" % mStr)
00247 
00248     for fileSpec in additionalFilesToVerify:
00249       for filePath in glob.glob(fileSpec):
00250         normPath = os.path.normpath(os.path.normcase(filePath))
00251         if normPath.startswith(os.path.normpath(os.path.normcase(rootDir))):
00252           for (filename, digest) in _digestData._digests.items():
00253             if normPath == os.path.normpath(os.path.normcase(filename)):
00254               digest_value = Gversions.calcDigest(normPath)
00255               if digest_value is None or digest != digest_value:
00256                 failedModules.append(os.path.split(filePath)[1])
00257               break
00258 
00259     return (_digestData._release, failedModules)
00260   verifyModuleDigests = staticmethod(verifyModuleDigests)
00261 
00262   def findVersionSymbol(filePath):
00263     """\brief Find the __version__ symbol in the file.
00264 
00265     \param filePath Full path of the module source code
00266 
00267     \return Version number or None if not found.
00268     """
00269     found = False
00270     try:
00271       ast = compiler.parseFile(filePath)
00272       for node in ast.node.nodes:
00273         if node.__class__.__name__ == 'Assign':
00274           if sys.hexversion > 0x20305f0:
00275             if node.asList()[0].asList()[0] == '__version__':
00276               version = node.asList()[1].asList()[0]
00277             else:
00278               continue
00279           else:
00280             if node.asList()[0][0] == '__version__':
00281               version = node.asList()[1][0]
00282             else:
00283               continue
00284           if type(version) is str and version.startswith('$Revision:'):
00285             return Gversions.extractVersion(version)
00286           else:
00287             #print "*** %s: __version__ symbol found but does not begin with $Revision:" % filePath
00288             return None
00289     except:
00290       log.exception("Error in parsing file: %s" % filePath)
00291 
00292     if not found:
00293       #print "*** %s: Missing __version__" % filePath
00294       return None
00295   findVersionSymbol = staticmethod(findVersionSymbol)
00296 
00297   def verifyFileDigests(path=None, rootDirEnv='LATTE_ROOT', digestDataFile=None):
00298     skipVersionCheck = {'LATTE_ROOT': ['sipconfig.py', 'pyqtconfig.py', 'testAppNoVersion.py']}
00299     failedFiles = []
00300     rootDir = ''
00301     if os.environ.has_key(rootDirEnv):
00302       rootDir = os.environ[rootDirEnv].strip()
00303     if path is None and rootDir == '':
00304       raise RuntimeError, "Can not determine which path to verify"
00305     elif path is None:
00306       path = rootDir
00307     #digests = Gversions.collectDigests(path)
00308     if digestDataFile is None and rootDir == '':
00309       msg = "Can not find the digest database file at the indicated location: $%s" % rootDirEnv
00310       log.error(msg)
00311       raise RuntimeError, msg
00312     elif digestDataFile is None:
00313       digestDataFile = os.path.join(rootDir, 'digestData')
00314     f = file(digestDataFile,'rb')
00315     try:
00316       dc = marshal.load(f)
00317     except ValueError:
00318       log.exception("")
00319       Gversions.logBadMarshalDataMessage()
00320       return (None, [])
00321     exec(dc)
00322     for (filename, digest) in _digestData._digests.items():
00323       if os.path.exists(filename):
00324         fileDigest = Gversions.calcDigest(filename)
00325         if digest != fileDigest:
00326           failedFiles.append(filename)
00327         if os.path.splitext(filename)[1] == '.py':
00328           if rootDirEnv in skipVersionCheck:
00329             if os.path.split(filename)[1] in skipVersionCheck[rootDirEnv]:
00330               continue
00331           if Gversions.findVersionSymbol(filename) is None:
00332             failedFiles.append(filename)
00333       else:
00334         failedFiles.append(filename)
00335     return (_digestData._release, failedFiles)
00336   verifyFileDigests = staticmethod(verifyFileDigests)
00337 
00338   def collectDigests(path):
00339     def collectDigests2(digests, dir, files):
00340       ignoredDirs = ['CVS', 'cfitsio_swig']
00341       validExtensions = ['.py','.exe','.xml','.vx','.o']
00342       l = len(files)
00343       for i in range(l-1,-1,-1):
00344         if files[i] in ignoredDirs:
00345           del files[i]
00346         else:
00347           fullFilename = os.path.normpath(os.path.join(dir, files[i]))
00348           if not os.path.isdir(fullFilename) and not os.path.islink(fullFilename):
00349             if os.path.splitext(files[i])[1].lower() in validExtensions:
00350               digest = Gversions.calcDigest(fullFilename)
00351               if digest is not None:
00352                 if digests.has_key(fullFilename):
00353                   print "DUPLICATE ENTRY DETECTED:", fullFilename
00354                 else:
00355                   digests[fullFilename] = digest
00356               else:
00357                 print "NO DIGEST FOR", files[i]
00358     digests = {}
00359     path = os.path.normpath(os.path.abspath(path))
00360     if os.path.isdir(path):
00361       os.path.walk(path, collectDigests2, digests)
00362     #~ for (file, digest) in digests.items():
00363       #~ print file #, repr(digest)
00364     #~ x = digests.keys()
00365     #~ x.sort()
00366     #~ for f in x:
00367       #~ print f
00368       return digests
00369     else:
00370       return None
00371   collectDigests = staticmethod(collectDigests)
00372 
00373 
00374   def getHardwareVersions(lat, xbrd=None):
00375     """Static class method which retrieves
00376        hardware versions.
00377 
00378     Keyword arguments:
00379 
00380     cmd -- optional command client (default None)
00381 
00382     """
00383     versions = {}
00384     glt = None
00385     if xbrd is not None: glt = xbrd.GLT
00386     if glt is not None:
00387       glt.initialize()
00388       # set trigger mask to allow commanding
00389       glt.disableMask()
00390       save_busy_disable = glt.busy_disable
00391       glt.busy_disable = 0x0
00392     gtemVersions = []
00393     gcrcVersions = []
00394     gtrcVersions = []
00395     for (temId, tem) in lat.TEM.items():
00396       try:
00397         temVer = int((tem.status >> 16) & 0x3F)
00398         if temVer not in gtemVersions:
00399           gtemVersions.append(temVer)
00400         for (cccId, ccc) in tem.CCC.items():
00401           for (crcId, crc) in ccc.CRC.items():
00402             try:
00403               crcVer = int((crc.config >> 12) & 7)
00404               if crcVer not in gcrcVersions:
00405                 gcrcVersions.append(crcVer)
00406             except: pass
00407         for (tccId, tcc) in tem.TCC.items():
00408           for (trcId, trc) in tcc.TRC.items():
00409             try:
00410               trcVer = int((trc.csr >> 34) & 0x0F)
00411               if trcVer not in gtrcVersions:
00412                 gtrcVersions.append(trcVer)
00413             except: pass
00414       except: pass
00415     if len(gtemVersions) > 1:
00416       versions['TEM'] = str(gtemVersions)
00417     elif len(gtemVersions) == 1:
00418       versions['TEM'] = str(gtemVersions[0])
00419     if len(gcrcVersions) > 1:
00420       versions['GCRC'] = str(gcrcVersions)
00421     elif len(gcrcVersions) == 1:
00422       versions['GCRC'] = str(gcrcVersions[0])
00423     if len(gtrcVersions) > 1:
00424       versions['GTRC'] = str(gtrcVersions)
00425     elif len(gtrcVersions) == 1:
00426       versions['GTRC'] = str(gtrcVersions[0])
00427     aem = lat.AEM
00428     if aem is not None:
00429       try:
00430         versions['AEM'] = str(aem.configuration & 0xFF)
00431         garcVersions = []
00432         gafeVersions = []
00433         for (arcId, arc) in aem.ARC.items():
00434           try:
00435             arcVer = str(arc.garc_version)
00436             if arcVer not in garcVersions:
00437               garcVersions.append(arcVer)
00438             for (afeId, afe) in arc.AFE.items():
00439               try:
00440                 afeVer = afe.vers_addr
00441                 if afeVer not in gafeVersions:
00442                   gafeVersions.append(afeVer)
00443               except: pass
00444           except: pass
00445         if len(garcVersions) > 1:
00446           versions['GARC'] = str(garcVersions)
00447         elif len(garcVersions) == 1:
00448           versions['GARC'] = str(garcVersions[0])
00449         if len(gafeVersions) > 1:
00450           versions['GAFE'] = str(gafeVersions)
00451         elif len(gafeVersions) == 1:
00452           versions['GAFE'] = str(gafeVersions[0])
00453       except: pass
00454     if glt is not None:
00455       glt = xbrd.GLT
00456       glt.enableMask()
00457       glt.busy_disable = save_busy_disable
00458     #except IOError:
00459     #  pass
00460     return versions
00461   getHardwareVersions = staticmethod(getHardwareVersions)
00462 
00463   def printVersions(ocs, lat=None, xbrd=None):
00464     print "\nCurrent Release: %s\n" % Gversions.getReleaseFromDigest()
00465     print "%-30s %10.10s" % ("Module", "Version")
00466     print "%-30s %10.10s" % ("--------", "-------")
00467     versions = Gversions.getModuleVersions(ocs)
00468     modList = versions.keys()
00469     modList.sort()
00470     for module in modList:
00471       print "%-30s %10.10s" % (module, versions[module])
00472     if lat is not None:
00473       hw_versions = Gversions.getHardwareVersions(lat, xbrd)
00474       if hw_versions != {}:
00475         print
00476         print "%-30s %10.10s" % ("Component", "Version")
00477         print "%-30s %10.10s" % ("---------", "-------")
00478         for (hw_comp, version) in hw_versions.items():
00479           print "%-30s %10.10s" % (hw_comp, version)
00480   printVersions = staticmethod(printVersions)
00481 
00482 if __name__ == '__main__':
00483   # Imports here are specified so that the versions for
00484   # all loaded modules can be retrieved. Add any additional
00485   # module imports here if they are to be reported in the
00486   # output of versions.bat
00487   # In order for all module versions to be reported, the __all__
00488   # variable in __init__.py of each package needs to be fully
00489   # populated.
00490   from LATTE.client import *
00491   from LATTE.database import *
00492   from LATTE.browser import *
00493   from LATTE.client import *
00494   from LATTE.consumer import *
00495   from LATTE.dispatch import *
00496   from LATTE.gosed import *
00497   from LATTE.logger import *
00498   from LATTE.monitoring import *
00499   from LATTE.monitoring.tools import *
00500   from LATTE.power import *
00501   from LATTE.runcontrol import *
00502   from LATTE.start import *
00503   from LATTE.tests import *
00504   from LATTE.tools import *
00505   from LATTE.trigger import *
00506 
00507   import LDF
00508   import qt
00509   import sihippo
00510   import cfitsio
00511 
00512   options = gOptions.Options(['server'], ['schema'])
00513   try:
00514     options.parse()
00515   except Exception, msg:
00516     options.usage(str(msg))
00517   else:
00518     cmd = gCmdCli.CmdCli()
00519     ocs = gOCS.GOCS(cmd)
00520     if options.schema is not None:
00521       lat = gLAT.GLAT(cmd)
00522       lat.readSchema(options.schema)
00523       xbrd = gXBR.GXBRD(cmd)
00524       xbrd.readSchema(options.schema)
00525     else:
00526       lat = None
00527       xbrd = None
00528     cmd.connect(options.server)
00529     Gversions.printVersions(ocs, lat, xbrd)
00530     cmd.disconnect()

Generated on Fri Jul 21 13:26:29 2006 for LATTE R04-12-00 by doxygen 1.4.3