FMX.py

Go to the documentation of this file.
00001 #!/usr/local/bin/python
00002 #
00003 #                               Copyright 2006
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__ = "FMX interface library"
00012 __author__   = "J. Panetta <panetta@SLAC.Stanford.edu> SLAC - GLAST LAT I&T/Online"
00013 __date__     = "2006/03/31 00:00:00"
00014 __updated__  = "$Date: 2006/04/13 02:20:15 $"
00015 __version__  = "$Revision: 1.4 $"
00016 __release__  = "$Name: HEAD $"
00017 __credits__  = "SLAC"
00018 
00019 import LICOS.copyright_SLAC
00020 
00021 import logging as log
00022 import os
00023 import re
00024 import subprocess
00025 
00026 # This is a simple python wrapper to the perl interface around FMX
00027 #
00028 # It shall only support certain subsets of FMX, namely those dealing with
00029 #   the LAT filesystems
00030 #
00031 # add, upload, commit, corrupt, delete
00032 #
00033 #
00034 # Main functions:
00035 #  fmx_upload( filetype, ... )
00036 #    polymorphic upload method.  Due to some features of FMX, the arguments
00037 #    for different filetypes 
00038 #
00039 #
00040 #
00041 #
00042 
00043 
00044 # Notes for Jim to put into confluence at some point
00045 # Important FMX trickery for setup:
00046 #   FMX_C_FDB:  environment var defining where physical files live.
00047 #               --> Also contains softlink: fmx.host --> fmx database instance
00048 #               /nfs/slac/g/glast/fmx000  -->  lat-hobbit1  (060405)
00049 #               /afs/slac/g/glast/fmx     -->  glastlnx06
00050 #
00051 #   mysql --host <> -P 8206 --pass 
00052 #
00053 #
00054 
00055 
00056 ## FMX database location environment variable
00057 FMX_DB_ENV = "FMX_C_FDB"
00058 
00059 ## FMX file types
00060 FMX_TYPES = ['cdm', 'fof', 'hsk', 'latc', 'lci', 'pbc', 'rel', 'sbm', 'sbs', 'vxw']
00061 
00062 ## FMX devices
00063 FMX_DEVICES = ['ee0', 'ee1', 'mm0', 'mm1', 'ram', 'rom', 'mem']
00064 
00065 ## FMX allowed architectures
00066 FMX_ARCHS = ['rad-750', 'mv2304', 'mcp750', 'linux-gcc', 'sun-gcc']
00067 
00068 ## FMX allowed node names  ** Note:  Distinct from FSW_UNIT_NAMES in LATconstants.  There are *two* SIUs in this scheme.
00069 FMX_NODES = ['siu0', 'siu1', 'epu0', 'epu1', 'epu2']
00070 
00071 ## FMX base location, fully justified
00072 FMX_BASE  = os.path.expandvars("$%s" % FMX_DB_ENV)
00073 
00074 ## FMX logical name for the LAT
00075 FMX_LAT_NAME = 'mordor'
00076 
00077 ## FMX path parsing regexp
00078 FMX_PATH_REGEXP = ' *(?P<filetype>.*)/(?P<package>.*)/(?P<version>.*)/(?P<constituent>.*)'
00079 
00080 ## FMX upload success regexp
00081 FMX_UPGOOD_REGEXP = 'FMX: Upload physical=(?P<physical>.*) file=(?P<path>.*)$'
00082 
00083 class FMX_command(subprocess.Popen):
00084   """ Subclass subprocess.Popen to change the defaults for use with FMX
00085   """
00086   def __init__(self, args):
00087     subprocess.Popen.__init__(self, args,
00088                               shell     = True,
00089                               stdin     = subprocess.PIPE,
00090                               stdout    = subprocess.PIPE,
00091                               stderr    = subprocess.PIPE,
00092                               close_fds = True)
00093     self.args = args
00094 #    print "\nDEBUG: %s\n" % args[0]
00095   
00096 
00097 def fmx_delete( filetype, **argv ):
00098   """!\brief Interface to fmx delete <blatz>
00099 
00100   \param filetype   Type of package you are working with
00101   
00102   filetype is broken into three main types:
00103     CODE:     cdm, rel, sbm, vxw   --  Code (compiled) modules
00104     CONFIG:   hsk, latc, lci       --  Configuration files
00105     FOF:      fof, sbs             --  files of Files
00106   
00107   Required arguments, all keyword required:
00108     node    = Destination of file (siu0, epu2, etc.)
00109     device  = Storage location of file (ee0, ee1, ram, etc)
00110   Partially optional arguments, all keyword required:
00111     package      = source package.         Required for CODE filetypes
00112     constituent  = package constituent.    Required for CODE filetypes 
00113     version      = package version.        Required for CODE filetypes
00114     relname      = relative upload path.   Required for CONFIG and FOF filetypes
00115     instrument   = Instrument name.        Optional.  If not set, instrument name for LAT is used.  (mordor)
00116 
00117   """
00118   CMD_BASE = "fmx delete %s"
00119 
00120   def _handleDelete( fmx ):
00121     """ Private function to handle common semantics of deleting a file
00122         from the LAT (or anywhere else...)
00123 
00124         Returns True or False, depending on the errors encountered inside fmx
00125     """
00126     if fmx.returncode == 0:    # commit passed
00127       return True
00128     else:
00129       lines = fmx.stdout.readlines()
00130       # first error line can be a sort-of success
00131       notExtantString = "FMX: Cannot delete a non-existent file"
00132       l = lines[0].strip()
00133       if l == notExtantString:   # deleting a nonexistant file should succeed.
00134         return True
00135       else:
00136         msg = "%s : original cmd = %s" % (l.strip(), cmd)
00137         log.error(msg)
00138 
00139       # and continue printing errors
00140       for l in lines[1:]: # and if no stdout??? **revisit
00141         msg = "%s" % (l.strip())
00142         log.error(msg)
00143       return False
00144 
00145   defaultInstrument( argv )
00146   node        = checkNode(str(argv['node']))
00147   device      = checkDevice(str(argv['device']))
00148   if device is None:
00149     raise RuntimeError ("Supplied FMX device %s is not in list of allowed devices" % argv['device'] )
00150   else:
00151     argv['device'] = device
00152   if node is None:
00153     raise RuntimeError ("Supplied FMX node %s is not in list of allowed nodes" % argv['node'] )
00154   else:
00155     argv['node'] = node
00156     
00157   # cdm, rel, sbm, vxw  are homomorphic
00158   # hsk, latc, lci are homomorphic
00159   # fof, sbs are homomorphic
00160   # pbc is not implemented in FMX
00161   if filetype in ['cdm', 'rel', 'sbm', 'vxw']:
00162     cmd = __fmx_code_command( CMD_BASE, filetype, argv['package'], argv['version'],  argv['constituent'],  argv['instrument'],  argv['node'],  argv['device'] )
00163   elif filetype in ['hsk', 'latc', 'lci']:
00164     cmd = __fmx_config_command( CMD_BASE, filetype, argv['relname'], argv['instrument'],  argv['node'],  argv['device'] )
00165   elif filetype in ['fof', 'sbs']:
00166     cmd = __fmx_config_command( CMD_BASE, filetype, argv['relname'], argv['instrument'],  argv['node'],  argv['device'] )
00167   else:
00168     raise RuntimeError( "Filetype %s is not supported by fmx_commit" % filetype)
00169   
00170   fmx = FMX_command( [cmd] )
00171   fmx.wait()
00172   return _handleDelete( fmx )
00173 
00174 def fmx_commit( filetype, **argv ):
00175   """!\brief Interface to fmx commit <blatz>
00176 
00177   \param filetype   Type of package you are working with
00178   
00179   filetype is broken into three main types:
00180     CODE:     cdm, rel, sbm, vxw   --  Code (compiled) modules
00181     CONFIG:   hsk, latc, lci       --  Configuration files
00182     FOF:      fof, sbs             --  files of Files
00183   
00184   Required arguments, all keyword required:
00185     node    = Destination of file (siu0, epu2, etc.)
00186     device  = Storage location of file (ee0, ee1, ram, etc)
00187   Partially optional arguments, all keyword required:
00188     package      = source package.         Required for CODE filetypes
00189     constituent  = package constituent.    Required for CODE filetypes 
00190     version      = package version.        Required for CODE filetypes
00191     relname      = relative upload path.   Required for CONFIG and FOF filetypes
00192     instrument   = Instrument name.        Optional.  If not set, instrument name for LAT is used.  (mordor)
00193 
00194   """
00195   CMD_BASE = "fmx commit %s"
00196 
00197   def _fmx_commit_code( filetype , **argv ):
00198     """ Private commit function for uploading single code type modules.
00199 
00200     return True or False
00201     """
00202     cmd = __fmx_code_command( CMD_BASE, filetype, argv['package'], argv['version'],  argv['constituent'],  argv['instrument'],  argv['node'],  argv['device'] )
00203     fmx = FMX_command( [cmd] )
00204     fmx.wait()
00205 
00206     if fmx.returncode == 0:    # commit passed
00207       return True
00208     else:
00209       lines = fmx.stdout.readlines()
00210       for l in lines: # and if no stdout??? **revisit
00211         msg = "%s : original cmd = %s" % (l.strip(), cmd)
00212         log.error(msg)
00213       return False
00214 
00215     pass
00216 
00217   def _fmx_commit_fof( filetype , **argv ):
00218     """ Private commit function for uploading single code type modules.
00219 
00220     return True or False
00221     """
00222 
00223     cmd = __fmx_fof_command( CMD_BASE, filetype, argv['relname'], argv['instrument'],  argv['node'],  argv['device'] )
00224     fmx = FMX_command( [cmd] )
00225     fmx.wait()
00226 
00227     if fmx.returncode == 0:    # commit passed
00228       return True
00229     else:
00230       lines = fmx.stdout.readlines()
00231       for l in lines: # and if no stdout??? **revisit
00232         msg = "%s : original cmd = %s" % (l.strip(), cmd)
00233         log.error(msg)
00234       return False
00235 
00236 
00237   def _fmx_commit_config( filetype , **argv ):
00238     """ Private commit function for uploading single code type modules.
00239 
00240     return True or False
00241     """
00242 
00243     cmd = __fmx_config_command( CMD_BASE, filetype, argv['relname'], argv['instrument'],  argv['node'],  argv['device'] )
00244     fmx = FMX_command( [cmd] )
00245     fmx.wait()
00246 
00247     if fmx.returncode == 0:    # commit passed
00248       return True
00249     else:
00250       lines = fmx.stdout.readlines()
00251       for l in lines: # and if no stdout??? **revisit
00252         msg = "%s : original cmd = %s" % (l.strip(), cmd)
00253         log.error(msg)
00254       return False
00255 
00256   defaultInstrument( argv )
00257   node        = checkNode(str(argv['node']))
00258   device      = checkDevice(str(argv['device']))
00259   if device is None:
00260     raise RuntimeError ("Supplied FMX device %s is not in list of allowed devices" % argv['device'] )
00261   else:
00262     argv['device'] = device
00263   if node is None:
00264     raise RuntimeError ("Supplied FMX node %s is not in list of allowed nodes" % argv['node'] )
00265   else:
00266     argv['node'] = node
00267     
00268   # cdm, rel, sbm, vxw  are homomorphic
00269   # hsk, latc, lci are homomorphic
00270   # fof, sbs are homomorphic
00271   # pbc is not implemented in FMX
00272   if filetype in ['cdm', 'rel', 'sbm', 'vxw']:
00273     return _fmx_commit_code( filetype, **argv )
00274   elif filetype in ['hsk', 'latc', 'lci']:
00275     return _fmx_commit_config( filetype, **argv )
00276   elif filetype in ['fof', 'sbs']:
00277     return _fmx_commit_fof( filetype, **argv )
00278   else:
00279     raise RuntimeError( "Filetype %s is not supported by fmx_commit" % filetype)
00280   
00281 
00282   pass
00283 
00284 
00285 def fmx_upload( filetype, **argv ):
00286   """ upload a file to the system
00287 
00288   \param filetype   Type of file to upload.
00289 
00290   filetype is broken into three main types:
00291     CODE:     cdm, rel, sbm, vxw   --  Code (compiled) modules
00292     CONFIG:   hsk, latc, lci       --  Configuration files
00293     FOF:      fof, sbs             --  files of Files
00294   
00295   Required arguments, all keyword required:
00296     node    = Destination of file (siu0, epu2, etc.)
00297     device  = Storage location of file (ee0, ee1, ram, etc)
00298   Partially optional arguments, all keyword required:
00299     package      = source package.         Required for CODE filetypes
00300     constituent  = package constituent.    Required for CODE filetypes 
00301     version      = package version.        Required for CODE filetypes
00302     relname      = relative upload path.   Required for CONFIG and FOF filetypes
00303     instrument   = Instrument name.        Optional.  If not set, instrument name for LAT is used.  (mordor)
00304     
00305   """
00306   CMD_BASE = "fmx upload %s"
00307   upload_allowed_args = [ 'package', 'version', 'constituent', 'node',
00308                           'device', 'relname', 'instrument' ]
00309   
00310   def _fmx_upload_code( filetype, **argv ):
00311     """ Private upload function for uploading single code type modules.
00312 
00313     return Either: (physical ID, path to disk file)
00314     return Or:     (None, None) and an error message is logged
00315     """
00316 
00317     cmd = __fmx_code_command( CMD_BASE, filetype, argv['package'], argv['version'],  argv['constituent'],  argv['instrument'],  argv['node'],  argv['device'] )
00318     fmx = FMX_command( [cmd] )
00319     fmx.wait()
00320 
00321 
00322     if fmx.returncode == 0:    # Safe to upload, return the physical ID and path
00323       return physPath(fmx.stdout.readline())
00324     else:                      # Not safe to upload.  Raise something???  ***REVISIT
00325       msg = "FMX upload failed: %s" % cmd
00326       log.error(msg)
00327       lines = fmx.stdout.readlines()
00328       for l in lines: # and if no stdout??? **revisit
00329         msg = "%s " % (l.strip())
00330         log.error(msg)
00331 
00332       return (None, None)
00333 
00334   def _fmx_upload_fof( filetype, **argv ):
00335     """ Private function for uploading Files of Files.
00336 
00337     \return Either: (physical ID, path to disk file)
00338     \return Or:     [list of upload requirements]
00339     """
00340 
00341     cmd = __fmx_fof_command( CMD_BASE, filetype, argv['relname'], argv['instrument'],  argv['node'],  argv['device'] )
00342     # special code for resolving a FOF/SBS object on upload:
00343     if 'create' in argv and argv['create']:
00344       cmd += ' --create'
00345     fmx = FMX_command( [cmd] )
00346     fmx.wait()
00347 
00348     if fmx.returncode == 0:    # Safe to upload, return the physical ID and path
00349       return physPath(fmx.stdout.readline())
00350     else:                      # Not safe to upload.  return prereqs
00351       notAvString = "FMX: Files not available on"
00352       prereqs = []
00353       lines = fmx.stdout.readlines()
00354 
00355       l = lines[0].strip()   # fmx fof error returns summary line, followed by list of files
00356       if len(l) < len(notAvString) or l[0:len(notAvString)] != notAvString:
00357         log.error("Fmx upload of %s failed: Original command: %s" % ( filetype, fmx.args) )
00358         raise RuntimeError("Error, unexpected return string from FMX: %s" % l)
00359       
00360       for l in lines[1:]: # and if no stdout??? **revisit
00361         if filetype == 'fof':
00362           prereqs.append(l.strip().split('/',1))  # split into filetype, relpath
00363         else:  # sbs
00364           prereqs.append(fmxPathSplit(l.strip()))  # split into filetype, relpath
00365           
00366 
00367       return prereqs
00368 
00369   def _fmx_upload_config( filetype, **argv ):
00370     """ Private function for uploading configuration files (lhk, lci, latc)
00371 
00372     \return Either: (physical ID, path to disk file)
00373     \return Or:     ???
00374     """
00375 
00376     cmd = __fmx_config_command( CMD_BASE, filetype, argv['relname'], argv['instrument'],  argv['node'],  argv['device'] )
00377     fmx = FMX_command( [cmd] )
00378     fmx.wait()
00379 
00380     if fmx.returncode == 0:    # Safe to upload, return the physical ID and path
00381       return physPath(fmx.stdout.readline())
00382     else:                      # Not safe to upload.  return (none, none)
00383       lines = fmx.stdout.readlines()
00384       for l in lines:
00385         msg = "%s : original cmd = %s" % (l.strip(), cmd)
00386         log.error(msg)
00387 
00388       return (None, None)
00389       
00390 
00391   # LAT instrument is default  **REVISIT**
00392   defaultInstrument( argv )
00393   
00394   node        = checkNode(str(argv['node']))
00395   device      = checkDevice(str(argv['device']))
00396   if device is None:
00397     raise RuntimeError ("Supplied FMX device %s is not in list of allowed devices" % argv['device'] )
00398   else:
00399     argv['device'] = device
00400   if node is None:
00401     raise RuntimeError ("Supplied FMX node %s is not in list of allowed nodes" % argv['node'] )
00402   else:
00403     argv['node'] = node
00404     
00405   
00406   # cdm, rel, sbm, vxw  are homomorphic
00407   # hsk, latc, lci are homomorphic
00408   # fof, sbs are homomorphic
00409   # pbc is not implemented in FMX
00410   if filetype in ['cdm', 'rel', 'sbm', 'vxw']:
00411     return _fmx_upload_code( filetype, **argv )
00412   elif filetype in ['hsk', 'latc', 'lci']:
00413     return _fmx_upload_config( filetype, **argv )
00414   elif filetype in ['fof', 'sbs']:
00415     return _fmx_upload_fof( filetype, **argv )
00416   else:
00417     raise RuntimeError( "Filetype %s is not supported by fmx_upload" % filetype)
00418 
00419 
00420 def __fmx_code_command( command, filetype, package, version, constituent, instrument, node, device ):
00421   ## Private call constructing commands for code use
00422 
00423   # Need strings.  Coerce everything just in case
00424   package     = str(package).upper()
00425   version     = str(version).upper()
00426   constituent = str(constituent)
00427   instrument  = str(instrument)
00428   node        = str(node)
00429   device      = str(device)
00430 
00431   cmd  = "".join( [command % filetype,
00432                    " %s %s " % (package, constituent),
00433                    " --version=%s" % version,
00434                    " --instrument=%s" % instrument,
00435                    " --device=/%s" % device,
00436                    " --node=%s" % node,] )
00437   return cmd
00438 
00439 def __fmx_fof_command( command, filetype, relname, instrument, node, device ):
00440   ## Private call for constructing fof type commands
00441 
00442   relname     = str(relname)
00443   instrument  = str(instrument)
00444   node        = str(node)
00445   device      = str(device)
00446 
00447   cmd = "".join( [ command % filetype,
00448                    " %s" % relname,
00449                    " --instrument=%s" % instrument,
00450                    " --device=/%s" % device,
00451                    " --node=%s" % node,] )
00452   return cmd
00453                    
00454 def __fmx_config_command( command, filetype, relname, instrument, node, device ):
00455   ## Private call for constructing config type commands
00456 
00457   relname     = str(relname)
00458   instrument  = str(instrument)
00459   node        = str(node)
00460   device      = str(device)
00461 
00462   cmd = "".join( [ command % filetype,
00463                    " %s" % relname,
00464                    " --instrument=%s" % instrument,
00465                    " --device=/%s" % device,
00466                    " --node=%s" % node,] )
00467   return cmd
00468                    
00469   
00470 
00471 ## helper functions
00472 
00473 def defaultInstrument( argv ):
00474   # Dumb function, if instrument isn't set, set it to standard name.  else, make sure it is lowercase
00475   if 'instrument' not in argv:
00476     argv['instrument'] = FMX_LAT_NAME
00477   else:
00478     argv['instrument'] = str(argv['instrument']).lower()
00479 
00480   
00481 
00482 def physPath( line ):
00483   m = re.match(FMX_UPGOOD_REGEXP, line)
00484   if m:
00485     physical, filepath = m.groups()
00486     physical = int(physical, 16)
00487   else:
00488     physical, filepath = None, ""
00489   return physical, filepath.strip()
00490   
00491   
00492 def fmxPathSplit( fmxPath ):
00493   # split the FMX path into filetype, package, version, constituent
00494   # and return a list in the above order
00495   m = re.match(FMX_PATH_REGEXP, fmxPath)
00496   return m.groups()
00497 
00498 def checkDevice( device ):
00499   # Check if the device is in the allowed list of devices
00500   # Returns the device passed, or None
00501   if device in FMX_DEVICES:
00502     return device
00503   return None
00504 
00505 def checkNode( node ):
00506   # Check if the unit is in the allowed list of units
00507   # Returns the unit passed, or None
00508   if node in FMX_NODES:
00509     return node
00510   return None
00511 
00512 
00513 
00514 
00515 
00516 if __name__ == "__main__":
00517   import unittest
00518   import time
00519 
00520   class FmxInterfaceTestCase(unittest.TestCase):
00521     sbsp = []
00522     latc = [      ]
00523     
00524     def __init__(self, arg):
00525       unittest.TestCase.__init__(self, arg)
00526 
00527     def checkPathSplit(self):
00528       """ Check if fmxPathSplit function works correctly"""
00529       filetype, package, version, constituent = fmxPathSplit('cdm/CGB_DB/V0-0-2/cal_db_gains')
00530 
00531       self.failUnlessEqual(filetype, 'cdm')
00532       self.failUnlessEqual(package, 'CGB_DB')
00533       self.failUnlessEqual(version, 'V0-0-2')
00534       self.failUnlessEqual(constituent, 'cal_db_gains')
00535 
00536     def checkUploadCode(self):
00537       """ Check if code files upload correctly"""
00538       filetype, package, version, constituent = 'cdm','CGB_DB','V0-0-2','cal_db_gains'
00539 
00540       result = fmx_upload( filetype = filetype, package = package,
00541                            version = version, constituent = constituent, 
00542                            instrument = 'mordor', node ="siu0", device = 'ee0' )
00543 
00544       self.failUnless( result[0] )
00545       self.failUnless( result[1] )
00546 
00547     def checkCommitCode(self):
00548       """ Check if code files commit correctly"""
00549       filetype, package, version, constituent = 'cdm','CGB_DB','V0-0-2','cal_db_gains'
00550 
00551       result = fmx_commit( filetype = filetype, package = package,
00552                            version = version, constituent = constituent, 
00553                            instrument = 'mordor', node ="siu0", device = 'ee0' )
00554       self.failUnless( result )
00555 
00556     def checkDeleteCode(self):
00557       """ Check if code files delete correctly"""
00558       filetype, package, version, constituent = 'cdm','CGB_DB','V0-0-2','cal_db_gains'
00559 
00560       result = fmx_delete( filetype = filetype, package = package,
00561                            version = version, constituent = constituent, 
00562                            instrument = 'mordor', node ="siu0", device = 'ee0' )
00563       self.failUnless( result )
00564 
00565     def checkUploadConfig(self):
00566       """ Check if configuration files db upload correctly"""
00567 
00568       result = fmx_upload( filetype = 'latc', relname='panetta/test1/latc.a',
00569                            instrument = 'mordor', node ="siu0", device = 'ee0' )
00570 
00571       self.failUnless( result[0] )
00572       self.failUnless( result[1] )
00573 
00574     def checkCommitConfig(self):
00575       """ Check if configuration db files commit correctly"""
00576 
00577       result = fmx_commit( filetype = 'latc', relname='panetta/test1/latc.a',
00578                            instrument = 'mordor', node ="siu0", device = 'ee0' )
00579 
00580       self.failUnless( result )
00581 
00582     def checkDeleteConfig(self):
00583       """ Check if configuration db files delete correctly"""
00584 
00585       result = fmx_delete( filetype = 'latc', relname='panetta/test1/latc.a',
00586                            instrument = 'mordor', node ="siu0", device = 'ee0' )
00587 
00588       self.failUnless( result )
00589     
00590 
00591     def checkUploadBadVersion(self):
00592       """ Check if uploading a file with a bad version *fails*"""
00593       # note bad version string...
00594       log.disable(log.ERROR)
00595       filetype, package, version, constituent = 'cdm','CGB_DB','V99999','cal_db_gains'
00596 
00597       result = fmx_upload( filetype = filetype, package = package,
00598                            version = version, constituent = constituent, 
00599                            instrument = 'mordor', node ="siu0", device = 'ee0' )
00600 
00601       # result should now be (None, None), and an error message is printed
00602       self.failIf( result[0] )
00603       self.failIf( result[1] )
00604       # turn logging back on
00605       log.disable(log.NOTSET)
00606 
00607     def checkNoInstrument(self):
00608       """ Check if uploading without specifying instrument works"""
00609       # same as checkUploadConfig but instrument isn't set.
00610       #   only one test needed as code is common
00611 
00612       # Note:  assumes checkDeleteConfig has been run
00613       result = fmx_upload( filetype = 'latc', relname='panetta/test1/latc.a',
00614                            node ="siu0", device = 'ee0' )
00615 
00616       self.failUnless( result[0] )
00617       self.failUnless( result[1] )      
00618 
00619     def checkUploadSBSunresolved(self):
00620       """ Check returning of unresolved files from an unresolved SBS"""
00621       
00622       result = fmx_upload( filetype = 'sbs', relname = 'FTS/V0-1-4/B0-6-5/siu.fmx.template',
00623                            device = 'mm0', node = 'siu0' )
00624 
00625       self.failUnless( len(result) )
00626 
00627     def checkUploadedAlready(self):
00628       """ Check if attempting to upload an already uploaded file fails"""
00629       # File has been uploaded already
00630       log.disable(log.ERROR)
00631       result = fmx_upload( filetype = 'hsk', relname = 'LHK/V6-4-8/LHKCFLIM/LHKCFLIM',
00632                            device = 'ee0', node = 'siu0' )
00633       # result should be (None, None) and an error message should be printed
00634       self.failIf( result[0] )
00635       self.failIf( result[1] )
00636       log.disable(log.NOTSET)
00637 
00638     def checkResolveSBS(self):
00639       """ Check logic for resolving an SBS"""
00640       # test of actually doing a resolve on an SBS script.
00641       # 0) Set up variables to clean up afterwards
00642       dev = 'ee0'
00643       node = 'siu0'
00644 
00645       # 1) Attempt an upload of SBS.  Note requirements for upload
00646       prereqs = fmx_upload( filetype = 'sbs', relname = 'FTS/V0-1-4/B0-6-5/siu.fmx.template',
00647                             device = 'mm0', node = 'siu0' )
00648       self.failUnless( len(prereqs) )
00649 
00650       # 2) Loop over the prereqs, uploading and committing
00651       for f in prereqs:
00652         self.sbsp.append(f)  # for cleanup later
00653         ft, pac, ver, con = f
00654         result = fmx_upload( ft, package=pac, version=ver, constituent=con,
00655                              device=dev, node=node )
00656         self.failUnless( result[0] )
00657         self.failUnless( result[1] )
00658         if result is not (None, None):
00659           passed = fmx_commit( ft, package=pac, version=ver, constituent=con,
00660                                device=dev, node=node )
00661           self.failUnless( passed )
00662 
00663       final = fmx_upload( filetype = 'sbs', relname = 'FTS/V0-1-4/B0-6-5/siu.fmx.template',
00664                           device = 'mm0', node = 'siu0', create = True )
00665       self.failUnless( final[0] )
00666       self.failUnless( final[1] )
00667       self.failIf( len(final) > 2 )
00668 
00669       passed = fmx_commit( filetype = 'sbs', relname = 'FTS/V0-1-4/B0-6-5/siu.fmx.template',
00670                            device = 'mm0', node = 'siu0' )
00671 
00672       self.failUnless( passed )
00673 
00674     def checkUnResolveSBS(self):
00675       """ Check logic for removing an SBS from the system"""
00676       # Must be run *after* checkResolveSBS
00677       dev = 'ee0'
00678       node = 'siu0'
00679 
00680       # empirical knowledge:  One must delete the sbs *before* one deletes the components
00681       final = fmx_delete( filetype = 'sbs', relname = 'FTS/V0-1-4/B0-6-5/siu.fmx.template',
00682                            device = 'mm0', node = 'siu0' )
00683       self.failUnless( final )
00684       
00685       for f in self.sbsp:
00686         ft, pac, ver, con = f
00687         result = fmx_delete( ft, package=pac, version=ver, constituent=con,
00688                              device=dev, node=node )
00689         self.failUnless( result )
00690 
00691     def deleteList(self):
00692       """ Only used in testing.  DO NOT USE"""
00693       pkgs = [ ('rel','LTC','V3-0-4','ltc'),
00694                ('rel','LATC','V7-5-4','latc'),
00695                ('rel','LATC','V7-5-4','latc_cmn'),
00696                ('rel','LCI','V3-1-1','lci'),
00697                ('rel','LPA','V3-0-0','lpa_siu'),
00698                ('rel','LIM','V1-10-0','lim'),
00699                ('cdm','LIM_DB','V0-4-0','lim_data'),
00700             ]
00701       dev = 'ee0'
00702       node = 'siu0'
00703       for f in pkgs:
00704         ft, pac, ver, con = f
00705         result = fmx_delete( ft, package=pac, version=ver, constituent=con,
00706                              device=dev, node=node )
00707         self.failUnless( result )
00708 
00709       latc = [('latc','panetta/test1/latc_DFT.lcb'),
00710               ('latc','panetta/test1/latc_AEM.lcb'),
00711               ('latc','panetta/test1/latc_AFE.lcb'),
00712               ('latc','panetta/test1/latc_ARC.lcb'),
00713               ('latc','panetta/test1/latc_CCC.lcb'),
00714               ('latc','panetta/test1/latc_CFE.lcb'),
00715               ('latc','panetta/test1/latc_GEM.lcb'),
00716               ('latc','panetta/test1/latc_TCC.lcb'),
00717               ('latc','panetta/test1/latc_TDC.lcb'),
00718               ('latc','panetta/test1/latc_TEM.lcb'),
00719               ('latc','panetta/test1/latc_TFE.lcb'),]
00720         
00721 
00722     def checkUploadLATC(self):
00723       """ Test resolving and uploading a LATC fof."""
00724       dev = 'ee0'
00725       node= 'siu0'
00726 
00727       # 1) Attempt an upload of SBS.  Note requirements for upload
00728       prereqs = fmx_upload( filetype = 'fof', relname = 'panetta/test1/latc.lcm',
00729                             device = 'ee0', node = 'siu0' )
00730       self.failUnless( len(prereqs) )
00731 
00732       for f in prereqs:
00733         self.latc.append(f)
00734         ft, rp = f
00735         result = fmx_upload( ft, relname=rp,
00736                              device=dev, node=node )
00737         self.failUnless( result[0] )
00738         self.failUnless( result[1] )
00739         if result is not (None, None):
00740           passed = fmx_commit( ft, relname=rp,
00741                                device=dev, node=node )
00742           self.failUnless( passed )
00743 
00744       final = fmx_upload( filetype = 'fof', relname = 'panetta/test1/latc.lcm',
00745                           device = 'ee0', node = 'siu0', create = True )
00746       self.failUnless( final[0] )
00747       self.failUnless( final[1] )
00748       self.failIf( len(final) > 2 )
00749 
00750       passed = fmx_commit( filetype = 'fof', relname = 'panetta/test1/latc.lcm',
00751                            device = 'ee0', node = 'siu0' )
00752 
00753       self.failUnless( passed )
00754       
00755 
00756     def checkUnloadLATC(self):
00757       """ Test removal of a LATC FOF from the system (with its files)"""
00758       #import time
00759       #print "sleeping..."
00760       #time.sleep(60)
00761       dev = 'ee0'
00762       node= 'siu0'
00763       final = fmx_delete( filetype = 'fof', relname = 'panetta/test1/latc.lcm',
00764                            device = 'ee0', node = 'siu0' )
00765       self.failUnless( final )
00766       
00767       for f in self.latc:
00768         ft, rp = f
00769         result = fmx_delete( ft, relname=rp,
00770                              device=dev, node=node )
00771         self.failUnless( result )
00772       
00773       
00774 
00775   def suite():
00776     loader = unittest.TestLoader()
00777     testSuite = loader.loadTestsFromNames(
00778       ['checkPathSplit',
00779        'checkNoInstrument',
00780        'checkUploadCode',
00781        'checkCommitCode',
00782        'checkDeleteCode',
00783        'checkDeleteCode',     # twice to check for success when deleting nonexistent file
00784        'checkUploadConfig',
00785        'checkCommitConfig',
00786        'checkDeleteConfig',
00787        'checkUploadBadVersion',
00788        'checkUploadSBSunresolved',
00789        'checkResolveSBS',
00790        'checkUnResolveSBS',
00791        'checkUploadedAlready',
00792        'checkUploadLATC',
00793        'checkUnloadLATC',
00794        #'deleteList',          # only used during script debugging.  DO NOT USE for normal unit test
00795        ],
00796       FmxInterfaceTestCase )
00797     return testSuite
00798       
00799 
00800   def test():
00801 
00802     # Initialize logging
00803     log.basicConfig()
00804     #log.disable(log.ERROR)
00805 
00806     runner =  unittest.TextTestRunner(verbosity=2)
00807     runner.run(suite())
00808 
00809     # Shut down the logger
00810     log.shutdown()
00811 
00812   # Now run the tests
00813   test()
00814 
00815 
00816 #EOF

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