ScriptEngineCommon.py

Go to the documentation of this file.
00001 #!/usr/local/bin/python
00002 #
00003 #                               Copyright 2005
00004 #                                     by
00005 #                        The Board of Trustees of the
00006 #                     Leland Stanford Junior University.
00007 #                            All rights reserved.
00008 #
00009 
00010 __facility__ = "Online"
00011 __abstract__ = "GLAST LAT run control common class"
00012 __author__   = "R. Claus <Claus@SLAC.Stanford.edu> SLAC - GLAST LAT I&T/Online"
00013 __date__     = "2005/07/23 00:08:27"
00014 __updated__  = "$Date: 2006/04/26 21:46:21 $"
00015 __version__  = "$Revision: 1.53 $"
00016 __release__  = "$Name: HEAD $"
00017 __credits__  = "SLAC"
00018 
00019 import LICOS.copyright_SLAC
00020 
00021 
00022 import sys
00023 import os
00024 import time
00025 import types
00026 import atexit
00027 import socket
00028 import logging as log
00029 import logging.handlers
00030 from   ConfigParser import ConfigParser, NoOptionError
00031 import threading
00032 
00033 from rcLoginImpl          import rcLoginImpl
00034 from rcSecurityMan        import rcSecurityMan
00035 from rcPreferencesManager import rcPreferencesManager
00036 from rcPreferencesGUIImpl import rcPreferencesGUIImpl
00037 
00038 from LICOS.scriptEngine.ScriptEngineConnector import ScriptEngineConnector
00039 from LICOS.lib.currValTable.ScriptClient      import ScriptClient
00040 from LICOS.lib.cmdTlmDb.LCATtlmDb             import LCATtlmDb
00041 from LICOS.lib.cmdTlmDb.LCATcmdDb             import LCATcmdDb
00042 from LICOS.util.gOptions                      import Options
00043 from LICOS.tools.logger.MSGLogGUIImpl         import MSGLogGUIImpl
00044 from LICOS.util.gVersions                     import Gversions
00045 from LICOS.scriptEngine.HwCfgSelectorImpl     import HwCfgSelectorImpl
00046 from LICOS.lib.LATconstants                   import *
00047 
00048 from ISOC.TlmUtils.TlmRdbInterface import TlmRdbDb
00049 import VSC
00050 
00051 
00052 class GDBN(dict):
00053   """!\brief Database node record.
00054 
00055      The database node contains session level variables in addition
00056      to preferences and entries used for diagnostics purposes.
00057   """
00058   def __init__(self):
00059     """!\brief GDBN constructor.
00060 
00061     Initialize the dictionary.
00062 
00063     """
00064     dict.__init__(self)
00065 
00066 
00067 class ScriptEngineSocketHandler(logging.handlers.SocketHandler):
00068   """!\brief Socket handler for logging.
00069 
00070   """
00071   def __init__(self, *args):
00072     """!\brief ScriptEngineSocketHandler constructor.
00073 
00074     \param args Positional arguments
00075     """
00076     apply(logging.handlers.SocketHandler.__init__, (self,) + args)
00077 
00078   def handleError(self, record):
00079     """!\brief Handle error.
00080 
00081     \param record Log record
00082     """
00083     if self.closeOnError and self.sock:
00084       self.sock.shutdown(2)
00085       self.sock.close()
00086       self.sock = None        #try to reconnect next time
00087     else:
00088       raise IOError, sys.exc_info()[1]
00089 
00090 class ErrorLogCounterHandler(logging.Handler):
00091   """!\brief Log handler to check if any ERROR logs are produced during the run.
00092 
00093   """
00094   def __init__(self, common):
00095     """!\brief ErrorLogCounterHandler constructor.
00096 
00097     """
00098     logging.Handler.__init__(self)
00099     self.__common = common
00100 
00101   def emit(self, record):
00102     """!\brief Log handler callback.
00103 
00104     Increment the error log count.
00105 
00106     \param record Log record
00107     """
00108     self.__common.incrementErrorLogCount()
00109 
00110 class ScriptEngineFileHandler(log.FileHandler):
00111   """!\brief FileHandler class for handling multiple line log entries
00112 
00113   If a log entry contains multiple lines, such as the case for
00114   tracebacks or exceptions a begin and end delimiter is added
00115   to the log entry so that it can be parsed by the MessageLogger
00116   """
00117   def __init__(self, filename, mode):
00118     """!\brief ScriptEngineFileHandler constructor.
00119 
00120     """
00121     log.FileHandler.__init__(self, filename, mode)
00122 
00123   def emit(self, record):
00124     """!\brief Log handler callback.
00125 
00126     Format the log message. If it is a multiline message
00127     (like in exceptions), delimit the beginning and ending
00128     of the message.
00129 
00130     \param record Log record
00131     """
00132     try:
00133       msg = self.format(record)
00134       (msg1, msg2) = msg.split(' - ',1)
00135       if msg2.find('\n') > 0:
00136         msg = msg1 + " - <//" + msg2+"//>"
00137       if not hasattr(types, "UnicodeType"): #if no unicode support...
00138         self.stream.write("%s\n" % msg)
00139       else:
00140         try:
00141           self.stream.write("%s\n" % msg)
00142         except UnicodeError:
00143           self.stream.write("%s\n" % msg.encode("UTF-8"))
00144       self.flush()
00145     except:
00146       self.handleError(record)
00147 
00148 class ScriptEngineCommon(object):
00149   """!\brief Common class for providing a run control helper functions.
00150 
00151   """
00152   def __init__(self):
00153     """!\brief ScriptEngineCommon constructor.
00154 
00155     """
00156     self.MSGLogger = None
00157     self.__startGMT = time.gmtime()
00158     self.__options  = Options(['config', 'server', 'vscConfig'],
00159                               ['noreload', 'securedir',
00160                                'app', 'appdir',
00161                                'cvtHost', 'cvtPort', 'scriptOpts',
00162                                'diagHost', 'telemHost'],
00163                               ['cmdDebug', 'endRunDlg', 'norcoverride',
00164                                'paramverify'])
00165     if len(sys.argv) > 1 and sys.argv[1] == '--help':
00166       self.__options.usage()
00167       print self.__usage()
00168       sys.exit(0)
00169     self.__dds = None
00170     self.__server = None
00171     try:
00172       self.__options.parse()
00173     except Exception, msg:
00174       self.__options.usage(self.__usage())
00175       raise Exception, msg
00176 
00177     self.__evtCli = None
00178     self.__securityMan = None
00179     self.__dbn = GDBN()
00180     self.__dbn['_common'] = self
00181     self.__prefMan = None
00182     self.__prefGUI = None
00183     self.__errLogCnt = 0
00184     self.__hwVersions = None
00185     self.__gui = None
00186     self.__diagHandler = None
00187     self.__tlmDb = None
00188     self.__lcat = None
00189     self.__lcatTlm = None
00190 
00191     try:
00192       import qt
00193       self.__qApp = qt.QApplication([])
00194       self.__qApp.addLibraryPath(os.path.join(ONLINE_ROOT, 'LICOS/ext/plugins'))
00195     except ImportError:
00196       self.__qApp = None
00197 
00198     # Arrange for logging to be properly shutdown at program exit
00199     atexit.register(log.shutdown)
00200 
00201   def connectVSC(self):
00202     """!\brief Connect to the Script Engine Proxy.
00203 
00204     """
00205     configFile = os.path.abspath(self.__options.vscConfig)
00206     config = ConfigParser()
00207     config.readfp(file(configFile))
00208 
00209     try:
00210       archive_path = config.get('paths','archive_path')
00211       granularity  = config.getint('ccsds_archivers',
00212                                     'granularity')
00213       if len(archive_path) != 0:
00214         from LICOS.tools.proxy.VscArchivers import VscArchiver
00215         archiver = VscArchiver("CMD", archive_path, granularity)
00216       else:
00217         print "Archiving disabled due to null archive_path or ingest_path"
00218         archiver = None
00219     except NoOptionError, e:
00220       print "Archiving disabled: ", e
00221       archiver = None
00222 
00223     ## Read hardware configuration options
00224     #hwConfig = {}
00225     #try:
00226     #  hwConfig['siuSelect'] = config.get('lat','siuSelect')
00227     #  hwConfig['daqSelect'] = config.get('lat','daqSelect')
00228     #  hwConfig['siuIdPhysical'] = config.get('lat','siuIdPhysical')
00229     #  hwConfig['siuIdLogical'] = config.get('lat','siuIdLogical')
00230     #  hwConfig['pduId'] = config.get('lat','pduId')
00231     #  hwConfig['primaryFeed'] = config.get('lat','primaryFeed')
00232     #  hwConfig['primaryGasu'] = config.get('lat','primaryGasu')
00233     #  hwConfig['firstEpuId'] = config.get('lat','firstEpuId')
00234     #  hwConfig['secondEpuId'] = config.get('lat','secondEpuId')
00235     #  hwConfig['acdSupply'] = config.get('lat','acdSupply')
00236     #  hwConfig['hvbs'] = config.get('lat','hvbs')
00237     #except NoOptionError, e:
00238     #  log.warn("One or more hardware configuration options not found, some scripts may fail.")
00239     #  log.exception(e)
00240     #self.__prefMan.setPref('hwConfig', hwConfig)
00241 
00242     diagHost = self.__options.diagHost
00243     if diagHost is None: diagHost = 'localhost'
00244     telemHost = self.__options.telemHost
00245     if telemHost is None: telemHost = 'localhost'
00246     portBase = config.getint('vsc', 'proxyPortBase')
00247     vsc = ScriptEngineConnector( vscHost=self.__options.server,
00248                                  diagHost=diagHost,
00249                                  telemHost=telemHost,
00250                                  archiver=archiver,
00251                                  cmdDebug=self.__options.cmdDebug,
00252                                  portBase = portBase)
00253     self.__lcatTlm = LCATtlmDb()
00254     vsc.setTlmDb(self.__lcatTlm)
00255     vsc.initCmdCountMon()
00256     vsc.start()
00257     vsc.m7default()
00258     #vsc.monitor(VSC.VscProxy.Primary)   # {Primary, Redundant, None}
00259     self.__vsc = vsc
00260     self.__dbn['_vsc'] = vsc
00261     self.__lcat = LCATcmdDb(vsc)
00262     self.__lcat.LIM.startStateMonitor()
00263 
00264     # TODO: Move this to a plugin class in the future
00265     self.addLatWatchItems()
00266 
00267   def getLCATcmd(self):
00268     """!\brief Retrieve the LCAT command database wrapper instance.
00269 
00270     \return LCATcmdDb instance
00271     """
00272     return self.__lcat
00273 
00274   def getLCATtlm(self):
00275     """!\brief Retrieve the LCAT telemetry database wrapper instance.
00276 
00277     \return LCATtlmDb instance
00278     """
00279     return self.__lcatTlm
00280 
00281   def addLatWatchItems(self):
00282     """!\brief Add LAT related watch items to the status panel.
00283 
00284     """
00285     statMon = self.__gui.statusMonitor()
00286     statMon.addWatchItem('LAT Configuration', self.getLatConfigId)
00287     lim = self.getLCATcmd().LIM
00288     statMon.addWatchItem('LIM Operating Mode', lim.getOperatingModeStr,
00289                          isStale=lim.isLimStateStale)
00290     statMon.addWatchItem('LIM Action', lim.getActionStr,
00291                          isStale=lim.isLimStateStale)
00292     statMon.addWatchItem('LIM Status', lim.getStatusStr,
00293                          isStale=lim.isLimStateStale)
00294     self.__gui.statusMonitor().saveWatch()
00295 
00296 
00297   def connectCVT(self):
00298     """!\brief Connect to the current value table.
00299 
00300     """
00301     try:
00302       self.cvt = ScriptClient(self.__options.cvtHost, int(self.__options.cvtPort))
00303     except:
00304       log.info("Connection to CVT failed.  User scripts that call the CVT may fail")
00305       self.cvt = None
00306       pass
00307 
00308   def populateTlmDb(self):
00309     try:
00310       import psycopg
00311     except ImportError:
00312       log.warn("Unable to import the Postgres Python package, EGU conversions will not be available")
00313       return
00314     try:
00315       #DSN = "user=panetta dbname=panetta host=gitow1 password=panetta"
00316       configFile = self.__options.vscConfig
00317       config = ConfigParser()
00318       config.read(configFile)
00319       DSN = config.get('postgres', 'dsn')
00320       db = psycopg.connect( DSN )
00321       dbc = db.cursor()
00322       self.__tlmDb = TlmRdbDb(dbc)
00323       src = config.get('tlmdb', 'source')
00324       bld = config.get('tlmdb', 'build')
00325       self.__tlmDb.populate(source=src, build=bld)
00326     except Exception, e:
00327       log.exception("Unable to populate the telemetry database")
00328       self.__tlmDb = None
00329 
00330   def initialize(self, startup=False):
00331     """!\brief Initialization.
00332 
00333     \param startup Are we initializing for the first time?
00334     """
00335     self.__prefMan = rcPreferencesManager(self.__options.config)
00336     if (self.__prefMan.loadConfig()):
00337 
00338       self.startLogger(startup)
00339 
00340       #if self.__options.schema is not None:
00341       #  try:
00342       #    self.readSchema(os.path.abspath(self.__options.schema))
00343       #  except Exception, e:
00344       #    log.exception("Exception in readSchema:")
00345       #    raise e
00346 
00347       if self.__options.securedir is not None:
00348         self.__securityMan = rcSecurityMan(os.path.abspath(self.__options.securedir),
00349                                            self.preferences()["users"])
00350         self.__securityMan.readPermissions()
00351         self.__dbn['_securityMan'] = self.__securityMan
00352       if self.__options.noreload is not None:
00353         import string
00354         self.__dbn["_dontReload"] = map(string.strip, file(self.__options.noreload).readlines())
00355       if self.__options.scriptOpts is not None:
00356         scrOptsFile = os.path.abspath(self.__options.scriptOpts)
00357         self.__scriptOpts = self.readScriptOpts(scrOptsFile)
00358       else:
00359         self.__scriptOpts = {}
00360 
00361     else:
00362       raise RuntimeError, "Can not find configuration file: %s" % self.__options.config
00363 
00364   def readScriptOpts(self, scrOptsFile):
00365     """!\brief Read the script options file.
00366 
00367     The script options file is used to debug a script without
00368     issuing a LICOS release. It should not be used in 'for credit'
00369     runs since it may change the behavior of the script.
00370 
00371     The script options file is a configuration file parsable by
00372     ConfigParser. Each section contains the script name. Under
00373     each section the options for that script and their values
00374     are listed.
00375 
00376     The options used for a given script are recorded in the run
00377     report.
00378 
00379     \param scrOptsFile File containing the script options
00380 
00381     \return Dictionary containing the script options
00382     """
00383     config = ConfigParser()
00384     config.readfp(file(scrOptsFile))
00385     scriptOpts = {}
00386     for section in config.sections():
00387       scriptOpts[section] = {}
00388       for option in config.options(section):
00389         scriptOpts[section][option] = config.get(section, option)
00390     return scriptOpts
00391 
00392   def getScriptOpts(self, scriptName):
00393     """!\brief Retrieve the options for script \a scriptName.
00394 
00395     \param scriptName Name of the script
00396 
00397     \return Dictionary of options for the script or None.
00398     """
00399     if scriptName in self.__scriptOpts:
00400       return self.__scriptOpts[scriptName]
00401     else:
00402       return {}
00403 
00404   def __usage(self):
00405     """!\brief Usage.
00406 
00407     """
00408     return """
00409 
00410 Detailed explanation:
00411 
00412 Mandatory options:
00413 --config to specify the run control configuration file to use
00414 --server to specify the hostname or the IP address of the teststand crate
00415    to connect to.
00416 --vscConfig to specify the configuration of the VSC and related quantities
00417 
00418 Optional options:
00419 --app Specify the standalone application or suite to run.
00420    Typically used by test or suite runners.
00421 --appdir Specify the application directory
00422 --cmdDebug Specify command debugging.
00423 --cvtHost Current value table host.
00424 --cvtPort Current value table port.
00425 --diagHost Diagnostic proxy host. If omitted, defaults to localhost.
00426 --endRunDlg Force the end run dialog to come up even in non-secure mode.
00427 --norcoverride Prevents the run conditions to be overridden with NOT-DEFINED.
00428 --noreload Specify a file that contains prefixes of modules
00429    which should not be reloaded when a user script is selected.
00430    This list gets appended to the default list which currently contains
00431    the following prefixes 'scipy', 'weave', 'qwt', 'xml', 'pyexpat', 'win32'.
00432    The file should contain one prefix per line.
00433 --paramverify Force the parameter verifier to come up even if running in non-secure mode
00434 --scriptOpts Specify a configuration file containing script specific options.
00435    The script name is specified as a section and all options can be specified
00436    under that section.
00437 --securedir The full path to the secure directory where the password file
00438    ("passwords") and the user permissions file ("security.cfg") is stored.
00439    If this switch is specified then ScriptEngine is started in secure mode.
00440 --telemHost Telemetry proxy host. If omitted, defaults to localhost.
00441   """
00442 
00443 
00444   def connect(self):
00445     """!\brief Connect to the servers.
00446 
00447     """
00448     #self.__cmdCli.connect(self.__options.server)
00449     #self.__evtCli.connect(self.__options.server, force)
00450     #self.__evtCli.purge()
00451     self.connectCVT()
00452     self.populateTlmDb()
00453     self.connectVSC()
00454 
00455   def disconnect(self):
00456     """!\brief Disconnect from the servers.
00457 
00458     """
00459     # TODO: Do we need to send any commands here to disconnect from the VSC?
00460     pass
00461 
00462   def elogWebsite(self):
00463     """!\brief Launch the web browser and point it to the E-Logbook site.
00464 
00465     """
00466     import webbrowser
00467     webbrowser.open(url=self.preferences()["elogurl"], new=1)
00468 
00469   def EBFdistribution(self):
00470     """!\brief Initialize the data distribution server.
00471 
00472     """
00473     if int(self.preferences()["servernbl"]) == 0:
00474       if self.__dds is not None:
00475         self.__dds.disconnect()
00476         log.info("Disconnected from the data distribution server since it was disabled in preferences.")
00477         self.__dds = None
00478       return
00479     dataType   = 'LAT_EBFdata'
00480     server     = self.preferences()["server"].strip()
00481     if server != '':
00482       try:
00483         import LICOS.core.distributor.DataDistributor as DD
00484       except:
00485         log.error("Can't find DataDistributor module, is it in PYTHONPATH?")
00486       else:
00487         if self.__server is None:
00488           self.__dds = DD.DataDistributorServer(dataType)
00489           try:
00490             self.__dds.connect(server)
00491             log.info("Connected to the data distribution server at %s." % server)
00492             #atexit.register(self.__dds.disconnect)  # Already done somewhere?
00493           except:
00494             log.warn("Unable to connect to data distribution server %s: serving of %s disabled" % (self.preferences()["server"], dataType))
00495             self.__dds = None
00496         elif server != self.__server:
00497           if self.__dds is not None:
00498             self.__dds.disconnect()
00499             log.info("Disconnected from the data distribution server.")
00500           self.__dds = DD.DataDistributorServer(dataType)
00501           try:
00502             self.__dds.connect(server)
00503             log.info("Reconnected to the data distribution server since the server changed in preferences.")
00504             #atexit.register(self.__dds.disconnect)  # Already done somewhere?
00505           except:
00506             log.warn("Unable to connect to data distribution server %s: serving of %s disabled" % (self.preferences()["server"], dataType))
00507             self.__dds = None
00508       self.__server = self.preferences()["server"].strip()
00509 
00510   def setLoggingLevel(self, logLevel=None):
00511     """!\brief Set the logging level.
00512 
00513     \param logLevel Log level.
00514                     Can be one of "DEBUG","INFO","WARN","ERROR","CRITICAL"
00515     """
00516     if logLevel is None: logLevel = self.preferences()["loglevel"]
00517     # Set the log levels at the handler level so that
00518     # file based handlers can still record DEBUG logs.
00519     log.getLogger("").setLevel(0)
00520     # First handler is always the default stdout handler
00521     log.getLogger("").handlers[0].setLevel(eval("log."+logLevel))
00522     for hdlr in log.getLogger("").handlers[1:]:
00523       if hdlr.__class__.__name__ == 'ScriptEngineSocketHandler':
00524         hdlr.setLevel(eval("log."+logLevel))
00525       elif hdlr.__class__.__name__ == 'ErrorLogCounterHandler':
00526         hdlr.setLevel(eval("log.ERROR"))
00527 
00528   def startLogger(self, startup=True):
00529     """!\brief Start the logger.
00530 
00531     \param startup Are we calling startLogger from startup?
00532     """
00533     # Start up the message logger
00534     log.basicConfig()
00535     loghost = self.preferences()["loghost"]
00536     logport = self.preferences()["logport"]
00537     local = socket.gethostname().lower() == loghost.lower() or socket.gethostbyname(loghost) == '127.0.0.1'
00538     if int(self.preferences()["lognbl"]) == 1:
00539       if local and startup:
00540         if self.MSGLogger is not None:
00541           return
00542         self.MSGLogger = MSGLogGUIImpl(logport)
00543         self.MSGLogger.startListenerThread()
00544       msgPath = self.preferences()["logdir"]
00545       # Note that if the file already exists, it will be appended to
00546       ts   = time.strftime('%y%m%d%H%M%S', self.__startGMT)
00547       fileName = "msg" + ts + ".log"
00548       # Hack until the log handler goes in its own class -ST # revisit
00549       self.preferences()["logfilename"] = fileName
00550       fmt = log.Formatter("%(asctime)s %(filename)s:%(lineno)d %(levelname)-5s - %(message)s")
00551       self.fileHdlr = ScriptEngineFileHandler(os.path.join(msgPath, fileName), "a")
00552       self.fileHdlr.setFormatter(fmt)
00553       log.getLogger("").addHandler(self.fileHdlr)
00554       self.sockHdlr = ScriptEngineSocketHandler(loghost, logport)
00555       self.sockHdlr.setFormatter(fmt)
00556       log.getLogger("").addHandler(self.sockHdlr)
00557       self.errLogCounter = ErrorLogCounterHandler(self)
00558       log.getLogger("").addHandler(self.errLogCounter)
00559       self.setLoggingLevel()
00560       try:
00561         log.info('Trying to connect to the message logger')
00562       except:
00563         log.getLogger("").removeHandler(self.sockHdlr)
00564         log.exception("Can't connect to the message logger, disabling logging to socket")
00565       else:
00566         log.info('Successfully connected to the message logger')
00567     elif self.MSGLogger is not None:
00568       log.info('Disconnecting from the message logger')
00569       if local:
00570         self.MSGLogger.close()
00571         self.MSGLogger = None
00572       log.getLogger("").removeHandler(self.errLogCounter)
00573       log.getLogger("").removeHandler(self.sockHdlr)
00574       log.getLogger("").removeHandler(self.fileHdlr)
00575       log.shutdown()
00576     else:
00577       # Make sure error log counter handler is added
00578       # even when logs are disabled
00579       self.errLogCounter = ErrorLogCounterHandler(self)
00580       log.getLogger("").addHandler(self.errLogCounter)
00581       self.setLoggingLevel()
00582 
00583 
00584   def stopRunLog(self, fileHdlr):
00585     """!\brief Stop the file log.
00586 
00587     \brief fileHdlr Log file handler.
00588     """
00589     # Acquire the I/O thread lock so that we don't accept any more logs
00590     # for this handler while the log is being closed.
00591     fileHdlr.acquire()
00592     log.getLogger("").removeHandler(fileHdlr)
00593     fileHdlr.release()
00594     fileHdlr.close()
00595 
00596   def startRunLog(self, fileName):
00597     """!\brief Start the file log.
00598 
00599     \brief fileName File name for the log file.
00600     """
00601     fileHdlr = ScriptEngineFileHandler(fileName, "w")
00602     fmt = log.Formatter("%(asctime)s %(filename)s:%(lineno)d %(levelname)-5s - %(message)s")
00603     fileHdlr.setFormatter(fmt)
00604     log.getLogger("").addHandler(fileHdlr)
00605     return fileHdlr
00606 
00607   def startLcmLog(self, filename):
00608     self.__lcmFile = file(filename, "w")
00609     self.__vsc.getDiagHandler().register(self.__lcatTlm.getApidsFromNames(['LCMMSGOUTC']), self.__processMsgOut)
00610 
00611     # Lock object used to coordinate the closing of the LCM log
00612     # with the callback __processMsgOut that handles the writing
00613     self.__lcmLock = threading.Lock()
00614 
00615   def stopLcmLog(self):
00616     self.__vsc.getDiagHandler().unregister(self.__lcatTlm.getApidsFromNames(['LCMMSGOUTC']),
00617                                          self.__processMsgOut)
00618     self.__lcmLock.acquire()
00619     self.__lcmFile.close()
00620     self.__lcmLock.release()
00621 
00622   def __processMsgOut(self, telem):
00623     self.__lcmLock.acquire()
00624     if not self.__lcmFile.closed:
00625       pkt = self.__lcatTlm.decodeTelemetry(telem)
00626       msg = self.__lcatTlm.msgOutToText(pkt)
00627       log.debug(msg)
00628       self.__lcmFile.write(msg + '\n')
00629       self.__lcmFile.flush()
00630     self.__lcmLock.release()
00631 
00632   def options(self):
00633     """!\brief Retrieve the command line options.
00634 
00635     \return Command line options.
00636     """
00637     return self.__options
00638 
00639   def prefMan(self):
00640     """!\brief Retrieve the preferences manager.
00641 
00642     \return rcPreferencesManager instance
00643     """
00644     return self.__prefMan
00645 
00646   def preferences(self):
00647     """!\brief Retrieve the preferences.
00648 
00649     \return Preferences instance
00650     """
00651     return self.__prefMan.preferences()
00652 
00653   def prefGUI(self):
00654     """!\brief Retrieve the preferences GUI.
00655 
00656     \return rcPreferencesGUIImpl instance
00657     """
00658     if self.__prefGUI is None:
00659       self.__prefGUI = rcPreferencesGUIImpl(self)
00660     return self.__prefGUI
00661 
00662   def getMSGLogger(self):
00663     """!\brief Retrieve the message logger GUI.
00664 
00665     \return MSGLogGUIImpl instance
00666     """
00667     return self.MSGLogger
00668 
00669   def getDDS(self):
00670     """!\brief Retrieve the data distributor.
00671 
00672     \return DataDistributorServer instance
00673     """
00674     return self.__dds
00675 
00676   def getCmdCli(self):
00677     """!\brief Retrieve the Script Engine proxy.
00678 
00679     \return seProxy instance
00680     """
00681     # TODO: Should the VSC connection come from the script?
00682     #return self.__cmdCli
00683     return self.__vsc
00684 
00685   def getTlmDb(self):
00686     """!\brief Retrieve the telemetry database object.
00687 
00688     This object contains EGU conversions for LAT housekeeping telemetry.
00689 
00690     \return An ISOC.TlmUtils.TlmRdbInterface.TlmRdbDb instance
00691     """
00692     return self.__tlmDb
00693 
00694   def getDBN(self):
00695     """!\brief Retrieve the DBN node.
00696 
00697     \return GDBN instance.
00698     """
00699     return self.__dbn
00700 
00701   def getSecurityMan(self):
00702     """!\brief Retrieve the security manager.
00703 
00704     \return rcSecurityMan instance
00705     """
00706     return self.__securityMan
00707 
00708   def getQtApp(self):
00709     """!\brief Retrieve the Qt app.
00710 
00711     \return QApplication instance
00712     """
00713     return self.__qApp
00714 
00715   def setGUI(self, gui):
00716     """!\brief Set the GUI.
00717 
00718     \param gui The GUI widget
00719     """
00720     self.__gui = gui
00721 
00722   def getGUI(self):
00723     """!\brief Retrieve the GUI.
00724 
00725     \return The GUI widget
00726     """
00727     return self.__gui
00728 
00729   def getLoginId(self):
00730     """!\brief Returns the login id for the last successful login
00731 
00732     \return User's login id
00733     """
00734     return self.__loginId
00735 
00736   def getErrorLogCount(self):
00737     """!\brief Retrueve the error log count for the current run.
00738 
00739     \return Error log count
00740     """
00741     return self.__errLogCnt
00742 
00743   def incrementErrorLogCount(self):
00744     """!\brief Increment the error log count.
00745 
00746     """
00747     self.__errLogCnt += 1
00748 
00749   def resetErrorLogCount(self):
00750     """!\brief Reset the error log count.
00751 
00752     """
00753     self.__errLogCnt = 0
00754 
00755   def showLogin(self, parent):
00756     """!\brief Handle login.
00757 
00758     \param parent Parent GUI
00759 
00760     \return Authentication result, 0=Successful login,
00761                                   -1=Authentication failed,
00762                                   else password database is not accessible.
00763     """
00764     login = rcLoginImpl(parent=parent)
00765     status = login.exec_loop()
00766     if status == login.Accepted:
00767       loginId = str(login.txtLoginId.text()).strip()
00768       password = str(login.txtPassword.text()).strip()
00769       authResult = self.__securityMan.authenticateUser(loginId, password)
00770       if authResult == 0:
00771         self.__loginId = loginId
00772         log.info("User %s successfully logged in" % loginId)
00773         return 1
00774       elif authResult == -1:
00775         log.error("User authentication failed, loginId=%s" % loginId)
00776         return authResult
00777       else:
00778         log.error("Password database is not accessible.")
00779         return authResult
00780     else:
00781       return None
00782 
00783   def configureHardware(self):
00784     """!\brief Configure the hardware based on the user selection.
00785 
00786     \return Whether the user cancelled or confirmed the selection
00787     """
00788     hwCfgGUI = HwCfgSelectorImpl(self, self.getGUI())
00789     hwCfgGUI.setCaption("Hardware Configuration Selector")
00790     result = hwCfgGUI.exec_loop()
00791     if result:
00792       hwConfig = self.preferences()["hwConfig"]
00793       self.__vsc.siuSelect(getattr(self.__vsc, hwConfig['siuSelect']))
00794       self.__vsc.daqSelect(getattr(self.__vsc, hwConfig['daqSelect']))
00795       if hwConfig['primaryFeed'] == 1:
00796         self.__vsc.monitor(VSC.VscProxy.Primary)   # {Primary, Redundant, None}
00797       else:
00798         self.__vsc.monitor(VSC.VscProxy.Redundant)   # {Primary, Redundant, None}
00799     return result
00800 
00801   def getLatConfigId(self):
00802     if "hwConfig" in self.preferences():
00803       preset = self.preferences()["hwConfig"]["preset"]
00804       if preset == -1:
00805         return "NON STANDARD"
00806       else:
00807         return preset
00808 
00809   def getDiagHandler(self):
00810     """!\brief Retrieve the LAT/VSC diagnostic telemetry handler.
00811 
00812     \return seTelemetryHandler instance
00813     """
00814     return self.__vsc.getDiagHandler()
00815 
00816   def getTelemHandler(self):
00817     """!\brief Retrieve the LAT/VSC telemetry handler.
00818 
00819     \return seTelemetryHandler instance
00820     """
00821     return self.__vsc.getTelemHandler()
00822 
00823   def getPidsHandler(self):
00824     """!\brief Retrieve the pids telemetry handler.
00825 
00826     \return sePidsHandler instance
00827     """
00828     return self.__vsc.getPidsHandler()

Generated on Thu Apr 27 20:52:43 2006 for LICOS L02-01-00 by doxygen 1.4.6-NO