Esempio n. 1
0
    def _getNZDS(self, sql, bv=[], po='SEL'):
        self.log.debug('qry = %s' % sql)
        cs = getDSConnStr('NZODBC', self.ib.user, self.ib.pwd, self.ib.dbserver, self.ib.db)
        dbh = NZODBC(cs, self.log)
        rc  = dbh.connToDB () 
        if rc != 0 : 
            self.log.error('Could not connect to the DB rc = %s ' % rc)
            return None
        
        if po == 'SEL': r = dbh.runQry(sql)
        else          : r = dbh.exeQry(sql,bv)

        dbh.closeDBConn()
        return r
Esempio n. 2
0
 def connToDB(self):
     r = 1
     sql = 'select current_timestamp'
     self.logger.debug('qry = %s' % sql)
     cs = getDSConnStr('NZODBC',self.ib.db_user,self.ib.db_pwd,self.ib.db_server,self.ib.db_name)
     self.logger.debug('ConnStr %s' % cs)
     dbh = NZODBC(cs,self.logger)
     if dbh.connToDB() != 0 : return r
     
     rs = dbh.runQry(sql)
     if rs is not None and len(rs) > 0 :  
         r = 0
         self.logger.debug("rs = %s" % rs[0][0])
     
     dbh.closeDBConn()
     return r
Esempio n. 3
0
class _InfaBaseApp(object):
    '''
    classdocs
    '''
    # Set of diagnostics commands to run
    hostname = socket.gethostname()
    exitOnError = False   # default.
    
    def __init__(self):
        self.appName = self.__class__.__name__.lower()
        self.log = log4py.Logger().get_instance()       
        self.suf = 'cfg'
        self.ib           = InfaBaseAppBean
#       self.cmdStep    = {}                         # Empty for base class
        self.infaEnvVar   = {}                       # Empty for base class
        self.pLock        = None
        self.ib.fu        = '*****@*****.**'
        self.ib.touser    = None
        self.ib.pager     = None
        self.ib.pgOnErr   = 'False'                  # Need to be string by contract 
        self.ib.mailOnErr = 'False'                  # Need to be string by contract

        self.ib.xpwd_dbg   = False
        # pwd palceholders
        self.ib.rep_xpwd   = None
        self.ib.xpwd       = None
        self.ib.db_xpwd    = None
        self.ib.rep_dbxpwd = None
        self.ib.dom_dbxpwd = None
              
        self.runSeq = None 
        
        self.ib.FileColCnt = {}                     # Column verification
   
        # Flags
        self.checkNextRunFlg   = False
        self.runWkfFlowFlg     = False
        self.checkFileColsFlag = False
        self.checkFileRowsFlg  = False
        
        # Db handler
        self.dbh = None

    # Create Lock File for processes that could not have more than one instances running concurrently.   
    # Command Step.
    def getLock(self):
        self.lockFn = '%s/%s.lck' % (self.ib.lckDir, self.appName) 
        self.pLock = lck.LockFile(self.lockFn, self.log)
        rc = self.pLock.getLock()
        self.log.debug('Creating Lock: %s\t:rc = %s ' % (self.lockFn, rc))
        if rc is True : return 0
        else          : return 1
    
    #---------------------- File Operations (high level)  --------------------------------------
        
    # This method will create 0 bytes file(s). 
    # self.ib.crtFiles list w/Full path for files that need to be created.
    def _touchFiles(self):
        
        if len(self.ib.crtFiles) < 1 : 
            self.log.error('List to create files is empty !')
            return 1
        
        rc = 0
        for fn in self.ib.crtFiles:
            r = fu.crtEmpFile(fn)    
            if r == False :  
                self.log.error('Could not create file %s' % fn)
                rc += 1
            else          : self.log.info('Created file %s ' % fn)
        return rc
    
    # Check if the file is not growing !
    def _isFileStable(self, fn):
        # We know that file exist
        r = fu.chkFileModTime(fn)
        rc = (float(r) > float(self.ib.stableFile))
        self.log.debug('chkFileModTime r = %s > %s \trc=%s' % (r, self.ib.stableFile, rc))
        if rc is True: self.log.info('File %s is stable ' % (fn))
        else         : self.log.warn('File %s is Not stable.\n\tWill Sleep for %s secs' % (fn, self.ib.stableFile))

        if rc is False:
            i = 1
            wi = int(self.ib.stbFileIter)
            while (i <= wi):
                time.sleep(float(self.ib.stableFile))
                r = fu.chkFileModTime(fn)
                rc = (float(r) > float(self.ib.stableFile))
                self.log.debug('chkFileModTime r = %s > %s \trc=%s' % (r, self.ib.stableFile, rc))
                self.log.info('Iteration %d out of %d' % (i, wi))
                if rc is True: self.log.info('File %s is stable ' % (fn))
                else         : self.log.warn('File %s is Not stable.\n\tWill Sleep for %s secs' % (fn, self.ib.stableFile))

                if rc is True : break
                else          : i += 1
        
        self.log.info('rc = ', rc)
        if rc is False: return 1 
    
        return rc 
    
    def _chkInfaRdyDly(self,job):
        rs = self._chkInfaRdy(job)
        if rs is None or len(rs) != 1 : return -1
        dt = rs[0][0]

        todm  = su.getTodayDtStr('%Y%m%d')
        self.log.debug('dt = %s todm = %s' % (dt,todm))
        if  dt == todm : return 0
        return 1

    def _chkInfaRdyMthly(self,job):
        rs = self._chkInfaRdy(job)
        if rs is None or len(rs) != 1 : return -1
        d = rs[0][0]; dt = d[:-2]
        todm  = su.getTodayDtStr('%Y%m')
        self.log.debug('d = %s dt = %s todm = %s' % (d,dt,todm))
        if  dt == todm : return 0
        return 1
    
    # Check for Predecessor. Invoke this method only if child class overwrites chkPred Method.
    # Query is the table to query.
    # Job = 'SCH - 8th Workday - Tech Ratio Data Load'
    def _chkInfaRdy(self,job):
        self.ib.user = self.ib.ora_user; self.ib.pwd = self.ib.ora_pwd; self.ib.db = self.ib.ora_db; 
        qryStr = ds.selInfPredDlyQry % job
        self.log.debug('qryStr = %s' % qryStr)        
        rs = self._getOracleDS(qryStr)
        self.log.debug("rs = ",rs)
        return rs
     
    # Invoking Method : qryStr = ds.selMssqlPredDlyQry % job
    # Use this to get status from MS SQL Metadata  msdb.dbo.sysjobhistory    
    def chkMssqlRdyDly(self,job):
        qryStr = ds.selMssqlPredQry % job
        self.log.debug('qryStr = %s' % qryStr)
        rs = self._chkMssqlRdy(qryStr)
        if rs is None or len(rs) != 1 : return -1
        dt = rs[0][0]
        todm  = su.getTodayDtStr('%Y%m%d')
        self.log.debug('dt = %s todm = %s' % (dt,todm))
        if  dt == todm : return 0
        return 1
    # Invoking Method qryStr = ds.selMssqlPredDlyQry % job
    #Use this to get status from MS SQL Metadata  msdb.dbo.sysjobhistory 
    def chkMssqlRdyMthly(self,job):
        qryStr = ds.selMssqlPredQry % job
        self.log.debug('qryStr = %s' % qryStr)
        rs = self._chkMssqlRdy(qryStr)
        if rs is None or len(rs) != 1  : return -1
        d = rs[0][0]; dt = d[:-2]
        
        todm  = su.getTodayDtStr('%Y%m')
        self.log.debug('dt = %s todm = %s' % (dt,todm))
        if  dt == todm : return 0
        return 1
    
    
    def _chkMssqlRdy(self,qryStr):
        self.ib.user = self.ib.ms_user; self.ib.pwd = self.ib.ms_pwd;  self.ib.dbserver = self.ib.ms_dbserver ; self.ib.db = self.ib.ms_db   
        rs = self._getMSSQLNatDS(qryStr)
        self.log.debug('rs = ', rs)
        return rs
   
    # This method checks specifically for workflows that run daily.
    # prdLst = self.ib.infadlypred contains list 
    # prdLst workflowList . self.ib.infaFREQpred where FREQ = Dly, Wkly or Mthly
    # freq. Run freq : Dly, Wkly or Mthly
    def _chkWkfPred(self, prdLst, freq):  
        if len(prdLst) < 1 : 
            self.log.error("No predecessors to execute !")
            return 1        
        
        wnl  = prdLst.split(',')
        meth = 'self._chkInfaRdy%s(wkf)' % freq
        self.log.debug('Method = ',  meth, '\tPredecessor list : ', prdLst, "\tsplit : ", wnl)
        for w in wnl:
            wkf = w.strip()
            if len(wkf)  < 1 : continue
            #rc = self.chkInfaRdyDly(wkf)
            rc = eval(meth)
            if rc == 0 :
                self.log.info('Predecessor %s done.' % wkf)
                continue
            else :
                i = 1
                wi = int(self.ib.waitPredIter)
                while (i <= wi):
                    self.log.info('Iteration %d out of %d. Will wait for %s secs' % (i, wi,self.ib.waitPred))
                    time.sleep(float(self.ib.waitPred))
                    #rc = self.chkInfaRdyDly(wkf)
                    rc = eval(meth)
                    if rc == 0 : 
                        self.log.info('Predecessor %s done.' % wkf)
                        break
                    else      : i += 1  
                
                if rc != 0 : 
                    self.log.error("Predecessor %s was not met." % wkf)
                    return rc                     
        return rc
           
    def chkPred(self,pmet):
        
        if len(pmet) < 1 : 
            self.log.error("No predecessors to execute !")
            return 1
            
        self.log.debug('Predecessor list', pmet)
        for p in pmet:
            
            rc = eval('self.%s' % p)
            self.log.debug("%s rc = %s" % (p,rc))
            if rc == 0: 
                self.log.info('Predecessor %s completed.' % p)
                continue
            
            else:
                i = 1
                wi = int(self.ib.waitPredIter)
                while (i <= wi):
                    self.log.info('Iteration %d out of %d. Will wait for %s secs' % (i, wi,self.ib.waitPred))
                    time.sleep(float(self.ib.waitPred))
                    rc = eval('self.%s' % p)
                    self.log.debug(' %s\trc=%s' % (p,rc))
                    if rc == 0 : 
                        self.log.info('Predecessor %s completed.' % p)
                        break
                    else      : i += 1          
                
                if rc != 0 : 
                    self.log.error("Predecessor %s was not met." %  p)
                    return rc 
        return 0
    
    # File list needs to include the absolute path.
    # For this Use a list of files
    # fls List of files w/full path.
    # If all files are not present it returns a 1, otherwise a 0.
    def _chkFiles(self, fls):
        rc = 0
        
        if len(fls) < 1 : return 1
        
        for fnp in fls:
            if fu.fileExists(fnp):
                if fu.isDir(fnp):
                    self.log.error('%s is a directory' % fnp)
                    rc += 1
                else:
                    self.log.info('%s exists' % fnp)
            else : 
                self.log.error('%s does not exist' % fnp)
                rc += 1
                
        return rc

    # Use to check set file completion ! 
    # Command Step.
    def chkFiles(self):
        rc = self._chkFiles(self.ib.chkFiles)
        self.log.debug('file list ', self.ib.chkFiles, 'rc = ' , rc)  
        return rc
    
    # Command Step.
    # Check incoming trigger(s) file. This method does not check for file stability.
    # Use if trigger file is 0 bytes, otherwise consider to use checkIncFiles.
    # Fl is a string of the form 'fil1,file2, ...filen' w filenames.
    def chkTrigFiles(self, fls):
        filesInc = []
        
        # Check if complete
        if len(fls) < 1 : 
            self.log.error('Trigger File list to verify is empty !')
            return filesInc
        
        # Create the full path to send for check.
        fns = fls.split(',')
        for fn in fns:
            f = '%s/%s' % (self.ib.landDir, fn)
            filesInc.append(f)
        
        self.log.debug('Trigger Files to check', filesInc)
            
        i = 1
        wi = int(self.ib.waitFileIter)
                
        while (i <= wi):           
            rc = self._chkFiles(filesInc)
            if rc != 0 :
                self.log.info('Will check for trigger files in ', self.ib.waitFile, ' secs.')
                time.sleep(float(self.ib.waitFile))
                self.log.info('Iteration %d out of %d ' % (i, wi))
                i += 1
                
            elif rc == 0 :      # All Files are present.
                self.log.debug('Trigger Files: ' , filesInc)
                return filesInc
                 
        return []
    
    # This method checks if all trigger files are present and modified on runtime date. Otherwise might be an older trigger file !
    # Should iterate and wait just in case the new trigger file arrives !
    def chkTrigFilesDate(self,fls):
        filesInc = []

        # Check if complete
        if len(fls) < 1 : 
            self.log.error('Trigger File list to verify is empty !')
            return filesInc
        
        # Create the full path to send for check.
        fns = fls.split(',')
        for fn in fns:
            f = '%s/%s' % (self.ib.landDir, fn)
            filesInc.append(f)
        
        self.log.debug('Trigger Files to check', filesInc)
            
        i = 1
        wi = int(self.ib.waitFileIter)
                
        while (i <= wi):           
            rc = self._chkFiles(filesInc)
            if rc != 0 :
                self.log.info('Will check for trigger files in ', self.ib.waitFile, ' secs.')
            
            elif rc == 0 :   # All Files are present. Check for date.
                ct = 0
                self.log.debug('Trigger Files: ' , self.trigFiles)
                for fn in filesInc:
                    dt = fu.chkFileModDate(fn,fmt='%Y%m%d')
                    self.log.debug('fn = %s dt = %s RUN_DATE = %s' % (fn,dt,RUN_DATE))
                    if dt != RUN_DATE :       # Check File Process date.
                        self.log.info("Filename %s has been modified on %s. Will Continue to Iterate " % (fn,dt))
                        ct = 0
                        continue
                    else:
                        ct+=1
                        if ct == len(filesInc) :
                            self.log.debug('ct = %d total files = %d' % (ct,len(self.trigFiles)))
                            return filesInc
                  
            time.sleep(float(self.ib.waitFile))
            self.log.info('Iteration %d out of %d ' % (i, wi))
            i += 1
                     
        return []

    # Note Need to ensure that getTrigFilesDate had been invoked first !
    def verTrigFileDate(self):
        global RUN_DATE
        rc = 0
        
        rdayoffset = su.toInt(self.ib.rdayoffset)
        if rdayoffset is None or rdayoffset < 0:
            self.log.error('rdayoffset needs to be a number => 0. Current Value = %s' % self.ib.rdayoffset)
            
        if rdayoffset != 0 :
            RUN_DATE = su.getDayMinusStr(rdayoffset, RUN_DATE, '%Y%m%d')

        for fn in self.trigFiles:
            fdt = fu.readFile(fn).strip(' \t\n\r')
            self.log.debug('fn = %s fdt = %s RUN_DATE=%s rdayoffset = %s ' % (fn,fdt,RUN_DATE, rdayoffset))
            if fdt != RUN_DATE:
                self.log.error("%s date field %s does not match the process RUN_DATE %s." % (fn,fdt,RUN_DATE))
                rc = 1
            else :
                self.log.info("%s date field %s matches the process RUN_DATE %s." % (fn,fdt,RUN_DATE))
        return rc

    # check incoming file(s)
    # values need to be in config file.
    # return a list of stable files to process. 
    # Use only for data files. For Trigger File(s) use chkTrigFiles
    # This method  will find  one or more files at a given time based on filename wildcards 
    # e.g.  Ap_scusrctl_*[0-9]_*[1-9].txt -> Ap_scusrctl_20120812_1.txt,Ap_scusrctl_20120812_2.txt, etc
    # If you need TO ENFORCE a set of files need to do a chkFiles first ! 
    # This method will look for any file name in a pattern ( fu.getFileName ) and will capture 0 or more to process.
    def checkIncFiles(self, fn):
        filesInc = [] # Incoming file
        fl = fu.getFileName(self.ib.landDir, fn)
       
        if len(fl) == 0:
            i = 1
            self.log.info('File %s/%s does not exists. Will start in %s sec' % (self.ib.landDir, fn, self.ib.waitFile))
            wi = int(self.ib.waitFileIter)
            while (i <= wi):       
                time.sleep(float(self.ib.waitFile))
                fl = fu.getFileName(self.ib.landDir, fn)
                self.log.info('Iteration %d out of %d ' % (i, wi))
                
                if len(fl) > 0 : break
                else           : i += 1
                
        if len(fl) == 0 : return filesInc
        
        self.log.info('File(s) found ', fl)
        
        for f in fl: 
             
            rc = self._isFileStable(f)
            if rc is True : filesInc.append(f)
         
        return filesInc

    # This is a wrapper function so if file is not found will not send ERROR email
    def chkIncFilesWarn(self):
        rc = self.getIncFiles()
        if rc != 0 : return RET_WARN
        else       : return rc

    # Check if approval file has arrive in order to continue with load.
    # Command Step.
    def checkApprovFile(self):
        fl = fu.getFileName(self.ib.landDir, self.ib.fileName)
        
        if len(fl) == 0:
            i = 1
            self.log.info('Approval File %s/%s does not exists. Will start in %s sec' % (self.ib.landDir, self.ib.fileName, self.ib.waitAppFile))
            wi = int(self.ib.waitFileAppIter)
            while (i <= wi):       
                time.sleep(float(self.ib.waitAppFile))
                fl = fu.getFileName(self.ib.landDir, self.ib.fileName)
                self.log.info('Iteration %d out of %d ' % (i, wi))
                
                if len(fl) > 0 : break
                else           : i += 1
                
        if len(fl) == 0 : return 1
        else: 
            rc = fu.delFile(fl[0])
            self.log.info('Removing %s , rc = %s ' % (fl[0], rc))
            return 0
        
    # flst file path list to verify.
    # Returns 0 if success, otherwise numbr of bad files. 
    def checkFileCols(self,flst,FLD_SEP,strp=' \t\n\r'):
        rc = 0
        for fnp in flst:
            bfnm   = fu.getFileBaseName(fnp)  
            colc   = self.ib.FileColCnt.get(bfnm)
            self.log.debug('fkey = %s colc= %s fp = %s ' %(bfnm,colc,fnp))
            if colc is not None:
                    x,b = fu.readCSV(fnp,colc,FLD_SEP,strp)
                    if len(b) < 1 : 
                        self.log.debug('Columns number [%d] match on file %s ' % (colc,fnp)) 
                    else :
                        rc += 1         
                        badf = '%s/%s%s.bad' % (self.ib.badDir,bfnm,su.getTimeSTamp())
                        f = fu.createFile(badf,b)
                        if f == 0 : self.log.error('Columns number (%d) did not match on %s.\nPlease see Bad file %s .' % (colc,fnp,badf))
                        else      :
                            self.log.error('Columns number (%d) did not match on %s.\n.COULD NOT  create file  %s .' % (colc,fnp,badf))
                            self.log.error('BAD Rows===========\n', b)     
            else:
                rc += 1
                self.log.error("Did not find Column Count for %s. Unable to verify Column Numbers !" % bfnm)   

        return rc
    
    # Get Trigger File.    
    # S.E. Sets self.trigFiles
    # Command Step.   
    def getTrigFiles(self):
        self.trigFiles = self.chkTrigFiles(self.ib.trigFiles)
        if len(self.trigFiles) == 0 : return 1
        return 0
    
    # Get Trigger File Date. Use this method if the trigger file have been created/modifed on the day the process run.
    # This method should be used e.g. a daily process create a trigger file, but you need to wait that daily process before 
    # triggering.(a trigger file for a previous day will exist)   
    # S.E. Sets self.trigFiles
    # Command Step.  
    def getTrigFilesDate(self):
        self.trigFiles = self.chkTrigFilesDate(self.ib.trigFiles)
        if len(self.trigFiles) == 0 : return 1
        return 0   
           
    # Get Incoming Files to Process.    
    # S.E. Sets self.incFiles
    # Command Step.   
    def getIncFiles(self):
        self.incFiles = self.checkIncFiles(self.ib.fileName)
        if len(self.incFiles) == 0 : return 1
        return 0
    
    # Get Incoming File set. All files need to be present to load.
    # This method will return all qualifying files for a given set.
    # A set should have at least 2 file patterns, otherwise use the getIncFiles method. # 
    # self.fileSet is a 2 dim array. It sorts the filename for processing.
    #  
    #  self.incFileSet [['$LANDING/Ap_scusrctl_20120914_1.txt', '$LANDING/Ap_scusrctl_20121015_3.txt', '$LANDING/Ap_scusrctl_20121016_3.txt'],
    #                   ['$LANDING/Ap_scg4000_20120914_1.txt', '$LANDING/Ap_scg4000_20121016_3.txt'],
    #                   ['$LANDING/Ap_scg4100_20120914_1.txt', '$LANDING/Ap_scg4100_20121016_3.txt'],
    #                   ['$LANDING/Ap_scudrldn_20120914_1.txt', '$LANDING/Ap_scudrldn_20121016_3.txt'],
    #                   ['$LANDING/Ap_scg520e_20120914_1.txt'],
    #                   ['$LANDING/Ap_sce5100_20120914_1.txt','$LANDING/Ap_sce5100_20121016_3.txt']] len = 6
    #
    # S.E. self.fileSet is a 2 dim array.
    # Command Step. 
    def getIncSetFiles(self):
        # File sets
        fnl = self.ib.fileName.split(',')
        self.log.info('filename Size= %d List = %s ' % (len(fnl), fnl))
        for fn in fnl:
            fs = self.checkIncFiles(fn)
            if len(fs) == 0 : return 1
            self.log.debug('fs = ', fs)
            self.incFileSet.append(sorted(fs))
        
        return 0
                   
    # Copy files that are ready to process.
    # Other method should mv the files.
    # Command Step. 
    def cpFileToWorkDir(self):
        self.workFiles  = []
        for src in self.incFiles:
            fn = fu.getFileBaseName(src)
            d = '%s/%s' % (self.ib.workDir, fn) 
            rc = fu.copyFile(src, d)
            if rc == 0 : self.workFiles.append(d)
            self.log.info('Copying file %s to %s rc= %s' % (src, d, rc))
        
        if len(self.workFiles) < 1 : return 1
        else                       : return 0
    
    # Copy files that are ready to process.
    # srcFile and incFiles need to be in the same order !
    # Command Step. self.srcFile
    def cpSrcToTgtFiles(self):
        self.workFiles  = []
        srcLen = len(self.srcFile)
        incLen = len(self.incFiles)
        if srcLen != incLen:
            self.log.error('srcFiles len = %d Does not match IncFiles len  %d' % (srcLen,incLen))
            self.log.debug('srcFiles = ',self.srcFile, '\tincFiles = ', self.incFiles)
            return 1 
        
        for i in range (srcLen):
            #fn = self.incFiles[i]
            d = '%s/%s' % (self.ib.workDir, self.srcFile[i]) 
            rc = fu.copyFile(self.incFiles[i], d)
            if rc == 0 : self.workFiles.append(d)
            self.log.info('Copying file %s to %s rc= %s' % (self.incFiles[i], d, rc))
        
        if len(self.workFiles) < 1 : return 2
        else                       : return 0
           
    # Move files that are ready to process.
    # Command Step. 
    def mvFileToWorkDir(self):
        self.workFiles  = []
        for src in self.incFiles:
            fn = fu.getFileBaseName(src)
            d = '%s/%s' % (self.ib.workDir, fn) 
            rc = fu.moveFile(src, d)
            if rc == 0 : self.workFiles.append(d)
            self.log.info('Moving file %s to %s rc= %s' % (src, d, rc))
        
        if len(self.workFiles) < 1 : return 1
        else                       : return 0
        
    # This moves triggerFile and append timestamp to keep time history
    # There shoud only be one trigger file.
    # Command Step. 
    def mvTrigFileToArchDir(self):
        rc = 0 
        for src in self.trigFiles:
            fn = fu.getFileBaseName(src)
            d = '%s/%s.%s' % (self.ib.archDir, fn, su.getTimeSTamp()) 
            r = fu.moveFile(src, d)
            if r != 0 : 
                rc += 1
                self.log.error ("Error moving trigger file  %s r = %s. " % (src, r))
            
            else      : self.log.info('Moving Trigger file %s to %s rc= %s' % (src, d, r))
            
        return rc    # Only reach this line if trigger file had been removed externa to the program !

    # List of files to archive.
    # Command Step. 
    # EO TODO Change to archIncFiles
    def archFiles(self)    : 
        rc = 0
        for src in self.incFiles:
            fn = fu.getFileBaseName(src)
            d = '%s/%s' % (self.ib.archDir, fn)
            r = fu.moveFile(src, d)
            if r != 0 : rc += 1
            self.log.info('Moving file %s to %s rc= %s' % (src, d, rc))
            zf = '%s/%s.%s' % (self.ib.archDir , fn, self.ib.archSuff)
            r = fu.compressFile(zf, d)
            if r != 0 : self.log.warn ("Cannot compresss %s r = %s. " % (zf, r))
            else      : self.log.info ("Compressed %s r = %s " % (zf, r))
        return rc
    
    # This method renames control files with a timestamp and archives control files.
    # fls : List with full path for files to be archived.
    # ts Timestamp
    # cf compress flag.
    def archGenFiles(self,fls,ts,cf=False)    : 
        rc = 0
        for src in fls:
            fn = fu.getFileBaseName(src)
            if ts == '' : d = '%s/%s' % (self.ib.archDir, fn) 
            else        : d = '%s/%s.%s' % (self.ib.archDir,ts, fn)
            r = fu.moveFile(src, d)
            if r != 0 : rc += 1
            self.log.info('Moving file %s to %s rc= %s' % (src, d, rc))
            
            if cf is True:
                zf = '%s/%s.%s' % (self.ib.archDir , fn, self.ib.archSuff)
                r = fu.compressFile(zf, d)
                if r != 0 : self.log.warn ("Cannot compresss %s r = %s. " % (zf, r))
                else      : self.log.info ("Compressed %s r = %s " % (zf, r))
        return rc
    
    def _remFiles(self, flp):
        rc = 0
   
        if len(flp) < 1 : 
            self.log.warn('File list to delete is empty !')
            return 1
        
        #fns = fl.split(',')
        for fnp in flp:
            r = fu.delFile(fnp)
            if r != 0 : 
                rc += 1
                self.log.error ("Could not delete  %s r = %s " % (fnp, r))
            else      :
                self.log.info ("Removed  %s r = %d " % (fnp, r))
        return rc
    
    # Remove Incoming Files (Use for watch files)
    # Command Step. 
    def remIncFiles(self):
        rc = self._remFiles(self.incFiles)
        self.log.debug('Removing ', self.incFiles, 'rc = ', rc)
        return rc
    
    # Command Step. 
    def remChkFiles(self):
        rc = self._remFiles(self.ib.chkFiles)
        self.log.debug('Removing ', self.ib.chkFiles, 'rc = ', rc)
        return rc
    
    # Command Step. 
    def remTrigFiles(self):
        rc = self._remFiles(self.trigFiles)
        self.log.debug('Removing ', self.trigFiles, 'rc = ', rc)
        return rc
    
    # Command Step. 
    def remWorkFiles(self):
        rc = self._remFiles(self.workFiles)
        self.log.debug('Removing ', self.workFiles, 'rc = ', rc)
        return rc  
    
    # To remove Files from self.ib.landDir directory.
    def remFiles(self):
        fl = fu.getFileName(self.ib.landDir, self.ib.fileName)
        
        if len(fl) < 1 :
            self.log.warn('Nothing to remove %s/%s' % (self.ib.landDir, self.ib.fileName))
            return 0
        
        fls = ','.join(fl)
        self.log.debug('fls = %s ' % fls)
        rc = self._remFiles(fls)
        return rc
 
    # Flag Setters
    def rWkfFlowFlg(self) : 
        self.runWkfFlowFlg  = True
        return 0
    
    #Set flags to verify number of columns.
    def chkFileColsFlg(self):
        self.checkFileColsFlag = True
        return 0

    # Verify line counts.
    def chkFileRowsFlg(self):
        self.checkFileRowsFlg = True
        return
         
           
    # Sets a flag, to check for next run.
    def chkNextRunFlg(self) : 
        self.checkNextRunFlg = True
        return 0    
    
    def crtTrigFile(self):
        fn = '%s/%s' % (self.ib.landDir ,self.ib.trigfile)
        rc = fu.crtEmpFile(fn)    
        if rc == False :  
            self.log.error('Could not create file %s' % fn)
            return 1
        else          : 
            self.log.info('Created file %s ' % fn)
        return 0
    
    # Command Step
    # Use this method to Pivot self.incFileSet and copy elements to self.incFile
    # It will get the first element [0] of the bucket and will copy to  self.incFile
    # SE re-initializes  self.incFile

    def setIncFilePvt(self):
        rc = 1; 
        self.incFiles = []; i = 0
        while i < len(self.incFileSet):
            self.incFiles.append(self.incFileSet[i][0])
            i += 1
        
        if len(self.incFiles) > 0 : rc = 0
   
        return rc       
          
    # Workday specific.    
    def getWorkDay(self):
        self.log.debug('qry = %s ' % ds.workDay)
        rs   = self._getNZDS(ds.workDay)
        self.log.debug('rs ' , rs)
        if rs is None      : return -5
        if len(rs)    != 1 : return -1
        if len(rs[0]) != 4 : return -4
        return rs[0][03] 
    
    # Use this method to get workdays count from end of month.    
    # rs[(datetime.date(2014, 8, 25), )]
    def getLastWorkDay(self,lwd):
        mtyr = su.getTodayDtStr(fmt='%m%Y')
        m = mtyr[:2] ; y = mtyr[2:]  
        qry = ds.lastworkDay % (m,y,m,y,lwd)
        self.log.debug('qry = %s ' % qry)
        rs   = self._getNZDS(qry)
        self.log.debug('rs' , rs)
        if rs is None      : return None
        if len(rs)    != 1 : return -1
        if len(rs[0]) != 1 : return -4
        return rs[0][0] 
    
    def isWorkDay(self):
        rc = -2
        w = self.getWorkDay() 
        if w < 1 :
            self.log.error(' wkday = %s : Please check DB connectivity table' % w)
            return w
        rwd =  self.ib.workday.split(',')
        self.log.debug('self.ib.workday = %s dbWkday = %s len rdw = %d' % (self.ib.workday,w,len(rwd)))
        for wd in rwd:
            if w == su.toIntPos(wd) : return 0
        return rc
    
    def isWorkDayWarn(self):
        rc  = -2
        w   = self.getWorkDay()
        if w < 1 :
            self.log.error(' wkday = %s : Please check DB connectivity or Table' % w)
            return w
        rwd =  self.ib.workday.split(',')
        self.log.debug('self.ib.workday = %s dbWkday = %s len rdw = %d' % (self.ib.workday,w,len(rwd)))
        for wd in rwd:
            if w == su.toIntPos(wd) : return  0
            else                    : rc = RET_WARN
        return rc
     
    def isLastWorkDayWarn(self):
        rc = -2
        w  = self.getLastWorkDay(self.ib.lastworkday)
        if w is None :
            self.log.error(' wkday = %s : Please check DB connectivity table' % w)
            return -5 

        wd = su.getDtStr(w,'%Y-%m-%d')
        d=su.getTodayDtStr('%Y-%m-%d')
        self.log.debug('self.ib.lastworkday = %s date_day = %s today = %s' % (self.ib.lastworkday,w,d))
        if d == wd : rc = 0
        else       : rc = RET_WARN
        return rc

    #---------------------- Database Operations (high level)  --------------------------------------
   
    # Sets self.dbh 
    # dbEng : Database Engine connect Strings
    # CAUTION : Cannot have 2 open connections. Use this method for 1 open connection otherwise override in child class.
    def _connToDB(self, dbEng):
        cs = getDSConnStr(dbEng, self.ib.user, self.ib.pwd, self.ib.dbserver, self.ib.db)
        self.dbh = NZODBC(cs, self.log)
        rc = self.dbh.connToDB () 
        if rc != 0 : 
            self.log.error('Could not connect to the DB rc = %s ' % rc)
            return 1
        return rc
    
    
        # Disconnects from DB 
    def _disFromDB(self): self.dbh.closeDBConn()
    
    #  This method is used for DB Connections. 
    #  sql statement to execute.
    #  bv bind variables
    #  po sql operation. SEL otherwise INS, UPD, DEL
    #  This method returns 
    #     SUCCESS : a list (runQry) or a positive number (exeQry)
    #     ERROR   : None . 
    def _getNZDS(self, sql, bv=[], po='SEL'):
        self.log.debug('qry = %s' % sql)
        cs = getDSConnStr('NZODBC', self.ib.user, self.ib.pwd, self.ib.dbserver, self.ib.db)
        dbh = NZODBC(cs, self.log)
        rc  = dbh.connToDB () 
        if rc != 0 : 
            self.log.error('Could not connect to the DB rc = %s ' % rc)
            return None
        
        if po == 'SEL': r = dbh.runQry(sql)
        else          : r = dbh.exeQry(sql,bv)

        dbh.closeDBConn()
        return r
     
    def _getMSSQLDS(self, sql,bv=[], po='SEL'): 
        self.log.debug('qry = %s' % sql)
        cs = getDSConnStr('MSSQLODBC', self.ib.user, self.ib.pwd, self.ib.dbserver, self.ib.db)
        dbh = MSSQLODBC(cs, self.log)
        rc  = dbh.connToDB ()
        if rc != 0 :
            self.log.error('Could not connect to the DB rc = %s ' % rc)
            return None
         
        if po == 'SEL': r = dbh.runQry(sql)
        else          : r = dbh.exeQry(sql,bv)
        dbh.closeDBConn()
        return r
    
    def _getMSSQLNatDS(self, sql,bv=[], po='SEL'):
        self.log.debug('qry = %s' % sql)
        cs = getDSConnStr('MSSQLNAT', self.ib.user, self.ib.pwd, self.ib.dbserver, self.ib.db)
        dbh = MSSQLNat(cs, self.log)
        rc  = dbh.connToDB ()
        if rc != 0 :
            self.log.error('Could not connect to the DB rc = %s ' % rc)
            return None
         
        if po == 'SEL': r = dbh.runQry(sql)
        else          : r = dbh.exeQry(sql,bv)
        dbh.closeDBConn()
        return r
    
    def _getOracleDS(self, sql,bv=[], po='SEL'):
        self.log.debug('qry = %s' % sql)
        cs = getDSConnStr('ORADB', self.ib.user, self.ib.pwd, self.ib.db)
        dbh = DBOracle(cs, self.log)
        rc  = dbh.connToDB ()
        if rc != 0 :
            self.log.error('Could not connect to the DB rc = %s ' % rc)
            return None
         
        if po == 'SEL': r = dbh.runQry(sql)
        else          : r = dbh.exeQry(sql,bv)
        dbh.closeDBConn()
        return r
    
    def _getDB2CliDS(self, sql,bv=[], po='SEL'):
        self.log.debug('qry = %s' % sql)
        cs = getDSConnStr('DB2CLI', self.ib.user, self.ib.pwd, self.ib.dsn, self.ib.db)
        dbh = DBOracle(cs, self.log)
        rc  = dbh.connToDB ()
        if rc != 0 :
            self.log.error('Could not connect to the DB rc = %s ' % rc)
            return None
         
        if po == 'SEL': r = dbh.runQry(sql)
        else          : r = dbh.exeQry(sql,bv)
        dbh.closeDBConn()
        return r        
    #---------------------- App Config File / Environment variables settings  --------------------------------------
    # Process App config file.
    # by convention file will be className with .cfg
    def _getConfigFile(self):
        fn = '%s/%s.%s' % (self.ib.cfgDir, self.appName,self.suf)
        self.log.info('Loading config file:%s' % fn)
        return fu.loadConfigFile(fn, self.ib, self.log)
    
    def _setDataDir(self):
        self.ib.landDir = '%s/%s' % (self.ib.shareDir, self.landDir)
        self.ib.archDir = '%s/%s/%s' % (self.ib.shareDir, self.landDir, self.ib.archDirName)
        self.ib.workDir = '%s/%s/%s' % (self.ib.shareDir, self.landDir, self.ib.workDirName)
        self.ib.badDir  = '%s/%s/%s' % (self.ib.shareDir, self.landDir, self.ib.badDirName)
        return 0
        
    def printEnvBean(self):
        ibr = vars(self.ib)
        for k, v in ibr.items():
            self.log.debug("k = %s\tv = %s" % (k, v))
          
    # Form host:pwd. returns h,pwd
    def _dPWX(self,x,ev):
        st = su.dec64(x)
        if self.ib.xpwd_dbg is True : self.log.debug('st = ' , st)
        if len(st) < 2            : 
            self.log.error('%s rc=%s. 1-Invalid, 2 Corrupted' % (ev,st[0]))
            if self.ib.xpwd_dbg is True : self.log.debug('%s : Pwd 1) Invalid was not generated using h:p pattern !\n 2) pwd was tampered string is not complete. Regen' % ev)
            return None
        if self.hostname != st[0] : 
            self.log.error('%s check host %s' % (ev,st[0]))
            if self.ib.xpwd_dbg is True : self.log.debug('%s : Current host %s does not match pattern h:p. Wronly generated or copied form another host' % (ev,self.hostname))
            return None 
        return st[1]
   
    def _initEnvVar(self):     
        xpwd_dbg      = os.environ['XPWD_DBG'] if os.environ.has_key('XPWD_DBG')  else 'False'
        if xpwd_dbg == 'True' : self.ib.xpwd_dbg = True
        
        if self.ib.rep_xpwd   is not None: self.ib.rep_pwd   = self._dPWX(self.ib.rep_xpwd   ,'REP_XPWD')
        if self.ib.xpwd       is not None: self.ib.pwd       = self._dPWX(self.ib.xpwd       ,'XPWD')    
        if self.ib.db_xpwd    is not None: self.ib.db_pwd    = self._dPWX(self.ib.db_xpwd    ,'DB_XPWD')    
        if self.ib.rep_dbxpwd is not None: self.ib.rep_dbpwd = self._dPWX(self.ib.rep_dbxpwd ,'REP_DBXPWD')
        if self.ib.dom_dbxpwd is not None: self.ib.dom_dbpwd = self._dPWX(self.ib.dom_dbxpwd ,'DOM_DBXPWD')   
    
    # Environment Variables that need to be set. Key is the ENV and ELE the name of var.
    # Below are global variables. Env variables should be set based on env settings.    
    def _getEnvVars(self):
        ret = 0   
        for ev, v in  self.infaEnvVar.items():
            self.log.debug("ev =%s v = %s" % (ev, v))
            
        try:     
            for ev, v in  self.infaEnvVar.items():
                x = os.environ[ev]
                exec  "%s='%s'" % (v, x) 
                self.log.debug("%s='%s'" % (v, x))  
                
            self._initEnvVar()                 
             
        except:
                ret = 2
                self.log.error("ENV var not set %s %s\n" % (sys.exc_type, sys.exc_info()[1]))
    
        finally : return ret
    
    # Use this method to set an environemnt variable from another. E.g. when you have more than one ftp site per program.
    # envVars : dict {ENV_TO_SET:ENV_SRC, }
    def setEnvVars(self,envVars):
        ret = 0   
        try:
            for ev,v in envVars.items():
                os.environ[ev] = os.environ[v]
                self.log.debug("os.environ[%s] = os.environ[%s] " % (ev,v))
        
        except:
                ret = 2
                self.log.error("ENV var not set %s %s\n" % (sys.exc_type, sys.exc_info()[1]))      
    
        finally : return ret 

    #---------------------- Miscellaneous utility methods  --------------------------------------
    # Process App ctl file.
    # by convention file will be className with .ctl
    # Control file is use to store previous load run.
    def _getCtlFile(self):
        fn = '%s/%s.ctl' % (self.ib.ctlDir, self.appName)
        if fu.fileExists(fn) is False:
            self.log.error('Control File:%s does not exist' % fn)
            return None
        
        self.log.info('Loading Control File:%s' % fn)
        return fu.readFile(fn).strip()
    
    # This method will get State Files and return the string.
    def getStateFile(self):
        fn = '%s/%s.state' % (self.ib.ctlDir, self.appName)
        if fu.fileExists(fn) is False:
            self.log.error('State File:%s does not exist' % fn)
            return None
        
        self.log.info('Reading State File :%s' % fn)
        return fu.readFile(fn).strip()
              
    # Use this notification for application specific notifications. Do not use for admin users, as you should use the 
    # sm.sendNotif which get it values from ENV VAR.  
    # This method gets it mail list from app user, out of the configuration file.
    def _notifyAppUsers(self, rd='plain'):

        if self.ib.touser is None and self.ib.pager is None:
            self.log.info ('No notification is set mail_list or/and pager_list is/are not set')
            return 0
        
        # Implicit boolean casting. 
        try: 
            m = -1 ; p = -1
            m = eval(self.ib.mailOnErr) ; p = eval(self.ib.pgOnErr)
        except:
            self.log.error('Error with configuration value(s) self.ib.mailOnErr = %s self.ib.pgOnErr = %s' % (m,p) )
        
        finally:  
            self.ib.mailOnErr = m
            self.ib.pgOnErr   = p
            
        rc = sm.notify(self.rc, self.ib.touser, self.ib.pager, self.subj, self.text, self.ib.mailOnErr, self.ib.pgOnErr, self.ib.fu, self.log, self.files, rd)
        self.log.info('Sending notification rc = %s == to mail = %s\tpager = %s\tsubj=%s\trender %s' % (rc, self.ib.touser, self.ib.pager, self.subj, rd))
        return rc
          
    #---------------------- Main / Command execution.  --------------------------------------
    
    def _execSteps(self, runStep):
        
        self.log.debug('runStep = %s' % runStep)
        for s in runStep:
            if (not self.cmdStep.has_key(s)):
                self.log.error('Invalid step %s' % s)
                return 1
            
            rv = 1
            try:
                rv = self.cmdStep[s]()
                if rv != 0 and self.exitOnError : 
                    self.log.error('[%s]:%s()\trc\t= %d' % (s, self.cmdStep[s].__name__, rv))
                    return rv
                
                #self.log.debug('[%s]:%s()\trc\t= %s' % (s,self.cmdStep[s].__name__,rv))
                self.log.info('[%s]:%s()\trc\t= %d' % (s, self.cmdStep[s].__name__, rv))
            
            except AttributeError:
                self.log.error('[%s]:%s()' % (s, self.cmdStep[s].__name__))
                self.log.error(' %s ' % (sys.exc_info()[1]))
                if (self.exitOnError) : return rv
                
            except SyntaxError:
                self.log.error('[%s]:%s()' % (s, self.cmdStep[s].__name__))
                self.log.error(' %s ' % (sys.exc_info()[1]))
                if (self.exitOnError) : return rv
            
        return rv

    #Set Incoming arguments 
    def setArgs(self,Argv):
        
        if len(Argv) != 2 :
            self.log.error("USAGE : <%s> fx [runSeq] Incorrect Number of arguments (%d)" % (Argv[0], len(Argv)))
            return 1  
        self.runSeq = Argv[1] 
        
        return 0
    # Argv is a list of runnable commands, defined per class basis
    # 'C:\\Users\\eocampo\\workspace\\rydinfap\\src\\apps\\infbaseapp.py'    
    def main(self, Argv):
        rc = 1  # Failed
        logFile = getLogHandler(self.appName, self.log)
        self.log.info('logFile= %s' % logFile)
        
        # should NEVER get this programmatic error !!!!
        if self.cmdStep is None or len(self.cmdStep) == 0 :
            self.log.error("Program Error:self.cmdStep is ", self.cmdStep)
            return rc
        
        rc = self.setArgs(Argv)
        if rc != 0 : return rc
        
        rc = self._getEnvVars()
        if rc != 0 :
            self.log.error("Need to set all env vars:\n %s" % self.infaEnvVar.keys())
            return rc
        
        rc = self._getConfigFile()
        if rc != 0 :
            self.log.error("Error Loading Config File:\n")
            return rc
        
        self._setDataDir()
           
        if self.runSeq is not None and len(self.runSeq) > 0 : 
            rc = self._execSteps(self.runSeq)
            if rc == 0 : self.log.info ('Completed running execSteps rc = %s' % rc)
            else       : self.log.error('execSteps rc = %s' % rc)
        
        
        if rc != RET_WARN:
            text = 'Please see logFile %s' % logFile
            subj = "SUCCESS running %s on %s " % (self.appName, self.hostname) if rc == 0 else "ERROR running %s on %s" % (self.appName, self.hostname)
            r, msg = sm.sendNotif(rc, self.log, subj, text, [logFile, ])
            self.log.info('Sending Notification\t%s rc = %s' % (msg, r))    
        
        else:
            self.log.info('Notification Overrided. Not sending message (RET_WARN) rc = %s ' % rc)
            
        self.printEnvBean()
        sys.exit(rc)
    
    def __del___(self):
        self.log.debug('Base class cleaning')
Esempio n. 4
0
class _QueryBaseDB(object):
    '''
    classdocs
    '''
    # Set of diagnostics commands to run
    hostname = socket.gethostname()
    exitOnError = False   # default.
    
    def __init__(self):
        self.appName = self.__class__.__name__.lower()
        self.log = log4py.Logger().get_instance()       
        self.infaEnvVar   = {}                       # Empty for base class

        # Db handler
        self.dbh = None   
        
        self.infaEnvVar   = {
                'DB_USER'        : 'self.ib.user'      ,
                'DB_PWD'         : 'self.ib.pwd'       ,
                'DB_SERVER'      : 'self.ib.dbserver'  ,
                'DB_NAME'        : 'self.ib.db'        ,
                'DB_ENG '        : 'self.ib.dbeng'     ,             
               }  
   
    # Sets self.dbh 
    # dbEng : Database Engine connect Strings
    # CAUTION : Cannot have 2 open connections. Use this method for 1 open connection otherwise override in child class.
    # Valid DB Engines:
    #      'ORADB'     
    #      'SQLLITE'   
    #      'NZODBC'    
    #      'MSSQLODBC' 
    #      'MSSQLNAT'  
    
    def _connToDB(self):
        cs = getDSConnStr(self.ib.dbeng, self.ib.user, self.ib.pwd, self.ib.dbserver, self.ib.db)
        self.dbh = NZODBC(cs, self.log)
        rc = self.dbh.connToDB () 
        if rc != 0 : 
            self.log.error('Could not connect to the DB rc = %s ' % rc)
            return 1
        return rc
    
    
        # Disconnects from DB 
    def _disFromDB(self): self.dbh.closeDBConn()
    
    #  This method is used for DB Connections. 
    #  sql statement to execute.
    #  bv bind variables
    #  po sql operation. SEL otherwise INS, UPD, DEL
    #  This method returns 
    #     SUCCESS : a list (runQry) or a positive number (exeQry)
    #     ERROR   : None . 
    def _getNZDS(self, sql, bv=[], po='SEL'):
        self.log.debug('qry = %s' % sql)
        cs = getDSConnStr('NZODBC', self.ib.user, self.ib.pwd, self.ib.dbserver, self.ib.db)
        dbh = NZODBC(cs, self.log)
        rc  = dbh.connToDB () 
        if rc != 0 : 
            self.log.error('Could not connect to the DB rc = %s ' % rc)
            return None
        
        if po == 'SEL': r = dbh.runQry(sql)
        else          : r = dbh.exeQry(sql,bv)

        dbh.closeDBConn()
        return r
     
    def _getMSSQLDS(self, sql,bv=[], po='SEL'): 
        self.log.debug('qry = %s' % sql)
        cs = getDSConnStr('MSSQLODBC', self.ib.user, self.ib.pwd, self.ib.dbserver, self.ib.db)
        dbh = MSSQLODBC(cs, self.log)
        rc  = dbh.connToDB ()
        if rc != 0 :
            self.log.error('Could not connect to the DB rc = %s ' % rc)
            return None
         
        if po == 'SEL': r = dbh.runQry(sql)
        else          : r = dbh.exeQry(sql,bv)
        dbh.closeDBConn()
        return r
    
    def _getMSSQLNatDS(self, sql,bv=[], po='SEL'):
        self.log.debug('qry = %s' % sql)
        cs = getDSConnStr('MSSQLNAT', self.ib.user, self.ib.pwd, self.ib.dbserver, self.ib.db)
        dbh = MSSQLNat(cs, self.log)
        rc  = dbh.connToDB ()
        if rc != 0 :
            self.log.error('Could not connect to the DB rc = %s ' % rc)
            return None
         
        if po == 'SEL': r = dbh.runQry(sql)
        else          : r = dbh.exeQry(sql,bv)
        dbh.closeDBConn()
        return r
    
    def _getOracleDS(self, sql,bv=[], po='SEL'):
        self.log.debug('qry = %s' % sql)
        cs = getDSConnStr('ORADB', self.ib.user, self.ib.pwd, self.ib.db)
        dbh = DBOracle(cs, self.log)
        rc  = dbh.connToDB ()
        if rc != 0 :
            self.log.error('Could not connect to the DB rc = %s ' % rc)
            return None
         
        if po == 'SEL': r = dbh.runQry(sql)
        else          : r = dbh.exeQry(sql,bv)
        dbh.closeDBConn()
        return r
    
        # Environment Variables that need to be set. Key is the ENV and ELE the name of var.
    # Below are global variables. Env variables should be set based on env settings.    
    def _getEnvVars(self):
        ret = 0   
        for ev, v in  self.infaEnvVar.items():
            self.log.debug("ev =%s v = %s" % (ev, v))
            
        try:     
            for ev, v in  self.infaEnvVar.items():
                x = os.environ[ev]
                exec  "%s='%s'" % (v, x) 
                self.log.debug("%s='%s'" % (v, x))  
                     
        except:
                ret = 2
                self.log.error("ENV var not set %s %s\n" % (sys.exc_type, sys.exc_info()[1]))
    
        finally : return ret
    
    # If arguments define  in child class.
    def setArgs(self,Argv): return 0 
        
    def main(self, Argv):
        rc = 1  # Failed
        logFile = getLogHandler(self.appName, self.log)
        self.log.info('logFile= %s' % logFile)
        
        # should NEVER get this programmatic error !!!!
        rc = self.setArgs(Argv)    
        if rc != 0 : return rc
        
        rc = self._getEnvVars()
        if rc != 0 :
            self.log.error("Need to set all env vars:\n %s" % self.infaEnvVar.keys())
            return rc
        
        sys.exit(rc)
    
    def __del___(self):
        self.log.debug('Base class cleaning')