def addCrash(self, bSerial=None, sTraceback='', fLocal=None, sUser=''): """ Add new crash log for dvs """ try: try: bSerial = int(bSerial) except ValueError: return False # Verify the Serial is known oServer = self._dbServerList.getServer(bSerial=bSerial) if oServer is None: return False # Bail if we want to skip this bug if self._checkSkipList(fLocal, sTraceback): return False self._openBug(bSerial, oServer.getCompany(), oServer.getName(), fLocal, sUser, sTraceback) return True except Exception, e: errMsg('error adding crash') errMsg(e) return False
def verifySession(self, sSess): """ Validate session and return authenticated username. """ try: self._oLock.acquire() try: self._expireSessions() sQuery = 'SELECT U.sName FROM CustUser U, CustSession S WHERE ' + \ 'U.bID = S.bUserID AND S.sSessID=%s' rgoResult = self._libDB.query(sQuery, sSess) if len(rgoResult) == 0: return 'noauth' oRow = rgoResult[0] return oRow[0] except Exception, e: errMsg('error while attempting to verify session [%s]' % e) raise Exception, "System error while verifying session." finally: self._oLock.release()
def getItems( self ): """ Return a list of all items on our pricelist. """ try: rgoItem = [] rgoResult = self._libDB.query( 'SELECT i.bID, i.bCategory, i.sName, i.sDescription, i.bCost, i.bRetail, i.bDiscount FROM PLItem i, PLCategory c WHERE i.bCategory=c.bID ORDER BY c.sName, i.sName' ) for oResult in rgoResult: oItem = ItemEntry( oResult[ 0 ], oResult[ 1 ], oResult[ 2 ], oResult[ 3 ], float( oResult[ 4 ] ), float( oResult[ 5 ] ), float( oResult[ 6 ] ) ) rgoItem.append( oItem ) return rgoItem except Exception, e: errMsg( 'error getting item list' ) errMsg( e ) return []
def _getBugzillaSerialsAndCameras(self, sQuery): """ Return a list of Serial/Camera numbers that already have tickets opened that match sQuery in Bugzilla. sQuery should return a version and short_desc to parse for the camera number. """ try: rgoSerial = [] rgoResult = self._libDBbug.query(sQuery) if rgoResult is None: return rgoSerial for oRow in rgoResult: try: bSerial = int(oRow[0]) rgs = oRow[1].split(' - ') bCamera = int(rgs[2]) rgoSerial.append([bSerial, bCamera]) except Exception, e: errMsg('error converting serial/camera [%s]-[%s]' % (oRow[0], oRow[1])) return rgoSerial
def getKeyDVS( self, bSeed ): """ Decompose Seed and check credentials. If they match, then return Product Key. """ try: bSeed = long( bSeed ) ( bSerial, sVersion, bNumcam, sMac ) = self.decomposeSeed( bSeed ) # Skip reporting on devel serials if bSerial >= 4000: return ( False, 'Unknown Server' ) dbgMsg( 'getting key for seed-[%d] serial-[%d] version-[%s] numcam-[%d] mac-[%s]' % ( bSeed, bSerial, sVersion, bNumcam, sMac ) ) # Make sure this server exists oServer = self._dbServerList.getServer( bSerial=bSerial ) if oServer is None: dbgMsg( 'server [%d] does not exists?' % bSerial ) return ( False, 'Unknown Server' ) # If Numcam and/or Mac are blank for this Server object # then we will allow this system to auto-key this time if oServer.getNumcam() == 0: dbgMsg( 'automatically setting numcam [%d] from seed' % bNumcam ) oServer.setNumcam( bNumcam ) oServer.setKey( '' ) if oServer.getMac() == '': dbgMsg( 'automatically setting mac [%s] from seed' % sMac ) oServer.setMac( sMac ) oServer.setKey( '' ) # Now, check all key items if sVersion != oServer.getVersion(): dbgMsg( 'key check failed [version mismatch] [%s != %s]' % ( sVersion, oServer.getVersion() ) ) return ( False, 'version mismatch' ) if bNumcam != oServer.getNumcam(): dbgMsg( 'key check failed [numcam mismatch] [%d != %d]' % ( bNumcam, oServer.getNumcam() ) ) return ( False, 'numcam mismatch' ) if sMac != oServer.getMac(): dbgMsg( 'key check failed [mac mismatch] [%s != %s]' % ( sMac, oServer.getMac() ) ) return ( False, 'mac mismatch' ) # We passed! Make new key if we do not have one if oServer.getKey() == '': sKey = self.makeKey( bSerial, sVersion, bNumcam, sMac ) dbgMsg( 'making new key serial-[%d] key-[%s]' % ( bSerial, sKey ) ) oServer.setKey( sKey ) # Save server information back to database in case we changed something self._dbServerList.setServer( oServer ) dbgMsg( 'serial-[%d] has valid key' % bSerial ) return ( True, oServer.getKey() ) except Exception, e: errMsg( 'error while getting product key' ) errMsg( e ) raise Exception, "System error during keying process."
def getTickets(self, bSerial): """ Return a list of the 5 most recent open tickets for this serial """ try: # Get most recent 5 tickets for this serial sQuery = "SELECT B.bug_id, P.realname, B.bug_status, B.short_desc, UNIX_TIMESTAMP( B.lastdiffed ) " + \ "FROM bugs B, components C, profiles P " + \ "WHERE " + \ "( B.component_id = C.id AND B.assigned_to = P.userid ) AND " + \ "( C.name = 'Fort Worth' OR C.name = 'Odessa' OR C.name = 'Contractor' ) AND " + \ "B.version = " + str( bSerial ) + " " + \ "ORDER BY B.bug_id DESC LIMIT 5" rgoResult = self._libDBbug.query(sQuery) if rgoResult is None: return [] return rgoResult except Exception, e: errMsg('error while getting open tickets for serial [%d]' % bSerial) errMsg(e) raise Exception, "System error while getting tickets."
def _processFailedCameras(self): """ Open a ticket for any camera that has been marked failed more than 1 day. """ try: dbgMsg('processing camera failure tickets') oMatchTest = re.compile( '.*test.*') # Regex to skip any "test" systems # Get Serials from Bugzilla that already have tickets open sQuery = "SELECT version, short_desc FROM bugs WHERE " + \ "product_id=7 AND " + \ "short_desc LIKE 'Camera Down - %' AND " + \ "((bug_status<>'RESOLVED') OR (bug_status='RESOLVED' AND (resolution='REMIND' OR resolution='LATER' OR resolution='WONTFIX')))" rgoSerial = self._getBugzillaSerialsAndCameras(sQuery) bCount = 0 bNow = int(time.time()) for oCamera in self._dbCameraList.getList(): oServer = self._dbServerList.getServer( bSerial=oCamera.getSerial()) if oServer is None: continue if oCamera.checkHasSkip(): continue if oMatchTest.match(oServer.getCategories()): continue if oServer.getMaintenance() == 'no': continue if oCamera.getTimestamp() is not None and ( bNow - oCamera.getTimestamp()) <= CAMERA_FAIL_LIMIT: continue # Make sure we do not already have a ticket open bSerial = oServer.getSerial() bCamera = oCamera.getCamera() fFound = False for o in rgoSerial: if bSerial == o[0] and bCamera == o[1]: fFound = True break if fFound: continue if self._openBug("Camera Down", oServer.getSerial(), oServer.getCompany(), oServer.getName(), bCamera=oCamera.getCamera()): bCount += 1 dbgMsg('opened [%d] camera failure tickets' % bCount) except Exception, e: errMsg('error occurred while processing camera failure tickets') errMsg(e)
def run(self): try: self._fRunning = True # sleep a bit and let everything initialize first time.sleep(10) self._postInit() while not self._fStop: try: rgoArg = self._q.get(True, 5) try: bRequest = int(rgoArg[0]) except ValueError: raise Exception, 'invalid request [%s]' % bRequest if bRequest == PC_OPEN_TICKET: bArg1, bArg2, bArg3 = self._getArgs( bRequest, rgoArg[1:]) self._openTicket(bArg1, bArg2, bArg3) else: raise Exception, 'unknown request [%d]' % bRequest except Queue.Empty: pass except Exception, e: errMsg('error processing request [%s]' % e) self._fRunning = False
def _getNewFeatures( self, sFeatures ): """ Get feature and pos type list. """ try: rgsFeature = [] rgsPosType = [] for s in sFeatures.split( ',' ): if s == 'jws': rgsFeature.append( 'pos' ) rgsPosType.append( 'jws_apex' ) if s == 'lpr': rgsFeature.append( 'lpr' ) rgsPosType.append( 'license_plate_recognition' ) if ( s == 'valve' or s == 'scale' ) and ('jws_anti_theft' not in rgsFeature): rgsFeature.append( 'jws_anti_theft' ) if s == 'vscale': rgsFeature.append( 'jws_cloud' ) if s == 'pos': for sPos in [ 'aloha','subway','debug','retail_pro','polewatcher','verifone','micros','drb','restaurant_manager','cap_retail','focus_pos','positouch','hme_zoom_drive_timer','tanklogix','ecrs' ]: rgsPosType.append( sPos ) return ( ",".join( rgsFeature ), ",".join( rgsPosType ) ) except Exception, e: errMsg( 'error while mapping old features to new features' ) errMsg( e ) return ( '', '' )
def getAllCameras(self): """ Get all registered cameras """ try: rgoResult = [] rgoCamera = self._dbCameraList.getList() for oCamera in rgoCamera: # Filter out non-maintenance and test servers oServer = self._dbServerList.getServer( bSerial=oCamera.getSerial()) if oServer is None or \ oServer.getMaintenance() == 'no' or \ oServer.getPreferred() == 'test': continue rgsCamera = self._freezeCamera(oCamera) # Get Server Name for this camera rgsCamera['sServer'] = oServer.getName() rgoResult.append(rgsCamera) return rgoResult except Exception, e: errMsg('error getting camera list [%s]' % e) raise Exception, 'error getting camera list'
def getSupportedFeaturesV2( self ): """ Return a JSON object of features and pos_types we support. """ try: rgs = [ '/usr/local/bin/make-key', '-J' ] oCMD = subprocess.Popen( rgs, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False, close_fds=True ) sOutput = oCMD.communicate()[ 0 ] bStatus = oCMD.returncode if bStatus != 1: raise Exception( 'make-key returned bad exit status' ) return sOutput.strip() except Exception, e: errMsg( 'error while getting supported features V2' ) errMsg( e ) raise Exception, "System error while querying for supported features."
def setServer(self, rgsServer): """ Set server in database. """ try: oServerNew = self._thawServer(rgsServer) bVersion = float(oServerNew.getVersion()) if bVersion >= 4.0: # Handle new Product Keys oServer = self._dbServerList.getServer( bSerial=oServerNew.getSerial()) if oServer.getVersion() != oServerNew.getVersion() or \ oServer.getNumcam() != oServerNew.getNumcam() or \ oServer.getPosLock() != oServerNew.getPosLock() or \ oServer.getLprLock() != oServerNew.getLprLock() or \ oServer.getFeatures() != oServerNew.getFeatures() or \ oServer.getPosTypes() != oServerNew.getPosTypes() or \ oServer.getSeed() != oServerNew.getSeed(): try: oServerNew.setKey( self._modKey.makeKeyV2(oServerNew.getSeed(), oServerNew.getSerial(), oServerNew.getVersion(), oServerNew.getNumcam(), oServerNew.getPosLock(), oServerNew.getLprLock(), oServerNew.getFeatures(), oServerNew.getPosTypes())) except Exception, e: errMsg('error creating new key [%s]' % e) oServerNew.setKey('') else:
def getSyncHash(self, bSerial): """ Return a binary has of our sync data. Used to test if we should sync (data changed). """ try: oServer = self._dbServerList.getServer(bSerial=bSerial) if oServer is None: dbgMsg('unknown serial') return {} if not oServer.checkHasAuth(): dbgMsg('auth not supported for this serial') return {} rgsType = ['rgsUser'] rgs = {} for sType in rgsType: rgsData = self._getSyncData(sType, bSerial) # return an md5 hash of the object serialized as a string try: import hashlib m = hashlib.md5() except ImportError: import md5 m = md5.new() m.update(pickle.dumps(rgsData)) rgs[sType] = m.hexdigest() return rgs except Exception, e: errMsg( 'error while getting sync hash user list for serial-[%s] [%s]' % (bSerial, e)) return {}
def _authUserInternal(self, oUser, sPass): try: # See if we are using the old Mysql hash fUseOldHash = False if len(oUser.getPassword()) == 16: fUseOldHash = True (fSuccess, sHash) = self._libUtil.hashPassword(sPass, fUseOldHash=fUseOldHash) if not fSuccess: return False if oUser.getPassword() == sHash: # If using old password hash, upgrade password hash stored in db on the fly if fUseOldHash: if self._libUtil.upgradePasswordHash(oUser.getID(), sPass): dbgMsg('upgrade password hash for user [%s]' % oUser.getName()) return True return False except Exception, e: errMsg('error while authenticating user [%s]' % e) return False
def _getSkipList(self): """ Read exception skip list from file. """ try: # Clear cache self._rgoSkip = [] if not os.access(IMPORT_FILE, 'r'): return # Slurp the file Yummy! oFile = open(IMPORT_FILE, 'r') rgsLine = oFile.readlines() oFile.close() # Build regex cache for sLine in rgsLine: # Skip blank lines and comments if not sLine.strip() or sLine.startswith('#'): continue self._rgoSkip.append(re.compile(sLine.strip())) except Exception, e: errMsg('error reading skip list') errMsg(e)
def _processOfflineServers(self): """ Open a ticket for any server that has been offline more than 1 day. If we are going to open more than 30 tickets at a time, then send a warning email and delay since this means our Internet may be down. """ try: dbgMsg('processing offline servers') oMatchTest = re.compile( '.*test.*') # Regex to skip any "test" systems rgoServer = [] # Array to hold Servers we want to open tickets for # Get Serials from Bugzilla that already have tickets open sQuery = "SELECT version FROM bugs WHERE " + \ "product_id=7 AND " + \ "short_desc LIKE 'Offline - %' AND " + \ "((bug_status<>'RESOLVED') OR (bug_status='RESOLVED' AND (resolution='REMIND' OR resolution='LATER')))" rgbSerial = self._getBugzillaSerials(sQuery) bNow = int(time.time()) for oServer in self._dbServerList.getList(): if oServer.checkHasSkip(): continue if oMatchTest.match(oServer.getCategories()): continue if oServer.getMaintenance() == 'no': continue if oServer.getTimestamp() is not None and ( bNow - oServer.getTimestamp()) <= DVS_OFFLINE_LIMIT: continue # Make sure we do not already have a ticket open if oServer.getSerial() in rgbSerial: continue # Delay opening ticket here, just save it for later. # This way we can check if we have more than 10 systems # reporting down at a time to send an alert email instead rgoServer.append(oServer) # Internet down? if len(rgoServer) > 30: self._sendEmail("Internet Down") rgoServer = [] bCount = 0 for oServer in rgoServer: if self._openBug("Offline", oServer.getSerial(), oServer.getCompany(), oServer.getName()): bCount += 1 dbgMsg('opened [%d] offline server tickets' % bCount) except Exception, e: errMsg('error occurred while processing offline server tickets') errMsg(e)
def _openBug(self, bSerial, sCompany, sName, fLocal, sUser, sTraceback): """ Open new bug in bugzilla. """ try: sType = 'Crash Report' dbgMsg( 'Opening Bug [%s] serial-[%d] company-[%s] name-[%s]' % \ ( sType, bSerial, sCompany, sName ) ) if self._fOfflineDebug: dbgMsg('Skipping since we are in offline debug mode') return True sFileIn = BASE + 'templates/dvs-crash.bug' sFileOut = '/tmp/dvs-crash.bug' sAssignee = '*****@*****.**' # Sanitize input for perl replacements sCompany = sCompany.replace('"', "_") sName = sName.replace('"', "_") sAssignee = sAssignee.replace('"', "_") os.system('cp %s %s' % (sFileIn, sFileOut)) os.system("perl -pi -e \"s/\@\@SERIAL\@\@/%03d/g\" %s" % (bSerial, sFileOut)) os.system("perl -pi -e \"s/\@\@COMPANY\@\@/%s/g\" %s" % (re.escape(sCompany), sFileOut)) os.system("perl -pi -e \"s/\@\@NAME\@\@/%s/g\" %s" % (re.escape(sName), sFileOut)) os.system("perl -pi -e \"s/\@\@LOCAL\@\@/%s/g\" %s" % (re.escape(fLocal), sFileOut)) os.system("perl -pi -e \"s/\@\@USER\@\@/%s/g\" %s" % (re.escape(sUser), sFileOut)) os.system("perl -pi -e \"s/\@\@ASSIGNEE\@\@/%s/g\" %s" % (re.escape(sAssignee), sFileOut)) os.system("perl -pi -e \"s/\@\@TRACEBACK\@\@/%s/g\" %s" % (sTraceback, sFileOut)) os.system("perl -pi -e \"s/@/\\\\\\@/g\" %s" % sFileOut) bStatus = os.system( '/usr/local/bin/bz_webservice_demo.pl --uri http://tickets.dividia.net/xmlrpc.cgi --rememberlogin --login bugzilla --password \'dt!8734\' --create %s 2>/dev/null' % sFileOut) os.unlink(sFileOut) if not os.WIFEXITED(bStatus): return False if os.WEXITSTATUS(bStatus) != 0: return False return True except Exception, e: errMsg('error opening new bug in bugzilla') errMsg(e) return False
def isAlive( self, bSerial ): """ Let clients test whether they are alive by calling us. """ try: return True except Exception, e: errMsg( 'error serving alive call [%s]' % e ) raise Exception, "System error serving alive call."
def _processWeeklyChecks(self): """ Certain maintenance plans include our techs looks at the cameras once a week. This should automatically open tickets for those systems to help us track if the techs are looking at this information. Also, if they notice a bad camera (focus) they should contact to see if we should go onsite. Included in plan2, plan3, plan4, and plan5. """ try: # Only run this check if it is Monday rgoTime = time.localtime() if rgoTime.tm_wday != 0: return dbgMsg('processing weekly maintenance checks') # List of plans that support weekly checks rgsPlans = ['plan2', 'plan3', 'plan4', 'plan5'] # Get Serials from Bugzilla that already have tickets open sQuery = "SELECT version FROM bugs WHERE " + \ "product_id=7 AND " + \ "short_desc LIKE 'Weekly Check - %' AND " + \ "((bug_status<>'RESOLVED') OR (bug_status='RESOLVED' AND (resolution='REMIND' OR resolution='LATER' OR resolution='WONTFIX')))" rgbSerialOpen = self._getBugzillaSerials(sQuery) # Get Serials from Bugzilla that have tickets opened/closed for today sQuery = "SELECT version FROM bugs WHERE " + \ "product_id=7 AND " + \ "short_desc LIKE 'Weekly Check - %' AND " + \ "DATE(delta_ts)='" + time.strftime( '%Y-%m-%d' ) + "'" rgbSerialToday = self._getBugzillaSerials(sQuery) bCount = 0 for oServer in self._dbServerList.getList(): # See if maintenance plan includes weekly checks if not oServer.getMaintenance() in rgsPlans: continue # Is there an existing ticket open for this server already? if oServer.getSerial() in rgbSerialOpen: continue # Was there a ticket opened for this location already today? # It may be closed, but just skip since we already logged it if oServer.getSerial() in rgbSerialToday: continue if self._openBug("Weekly Check", oServer.getSerial(), oServer.getCompany(), oServer.getName()): bCount += 1 dbgMsg('opened [%d] weekly maintenance check tickets' % bCount) except Exception, e: errMsg( 'error occurred while processing weekly maintenance check tickets' ) errMsg(e)
def _saveLastTime( self, sWhich ): """ Save last check time to database """ bNow = int( time.time() ) try: # Save our last run time self._dbMisc.set( 'checksick', sWhich, time.strftime( '%Y-%m-%d %H:%M:%S' ) ) except: errMsg( 'error saving last check %s time' % sWhich ) return bNow
def addServer(self, bSerial): """ Set server in database. """ try: oServer = self._dbServerList.addServer(bSerial=bSerial) return self._freezeServer(oServer) except Exception, e: errMsg('error adding server [%s]' % e) raise Exception, 'error adding server'
def delCamera(self, rgsCamera): """ Delete camera from database. """ try: oCamera = self._thawCamera(rgsCamera) return self._dbCameraList.delCamera(oCamera) except Exception, e: errMsg('error deleting camera [%s]' % e) raise Exception, 'error deleting camera'
def addServerV2(self, sSeed): """ Add new server in database with Seed. """ try: oServer = self._dbServerList.addServer(sSeed=sSeed) return self._freezeServer(oServer) except Exception, e: errMsg('error adding server [%s]' % e) raise Exception, 'error adding server'
def enterDaemonMode(sIn='/dev/null', sOut='/dev/null', sError='/dev/null'): # Do first fork. try: bPid = os.fork() if bPid > 0: # Exit first parent sys.exit(0) except OSError, (bError, sError): errMsg('first fork failed: (%d) %s' % (bError, sError)) return 1
def _dispatch(self, sRequest, rgoParam, sRemoteIP): # Okay, let's check our subclasses try: libCache = lib.cache.Cache() # Parse Request sModule, sMethod = self._parseRequest(sRequest) oModule = libCache.get(sModule) if oModule is None: raise AttributeError # Make sure this method isn't private if sMethod[0:1] == '_': stdMsg('cannot call private method "%s"' % sRequest) raise Exception, 'cannot call private method "%s"' % sRequest # If this is not a function that can be called by Everyone, check session and proceed if not self._checkEverybody(sModule, sMethod): # Discard any attempt to proceed further without a session or magic if len(rgoParam) == 0: return (True, 'noauth') sSessID, rgoParam = self._getSession(rgoParam) if self._checkPrivate(sModule, sMethod): return (True, 'noauth') elif sSessID == MAGIC and self._checkMagic(sModule, sMethod): pass # Okay, just check the session elif not libCache.get('dbSessionList').checkExists( sSessID=sSessID): return (True, 'noauth') # Inject Remote IP into UpdateIP call if sModule == 'modStats' and (sMethod == 'updateIP' or sMethod == 'newserver'): rgoParam = list(rgoParam) rgoParam.insert(1, sRemoteIP) rgoParam = tuple(rgoParam) # Alright, let's call it oFunc = getattr(oModule, sMethod) # Skip logging these functions since they are chatty rgsSkipLog = [ 'stats.updateIP', 'stats.cameraFail', 'stats.isAlive' ] except AttributeError, e: errMsg(e) # Oops it wasn't found, throw an error sMsg = 'method "%s" is not supported' % sRequest stdMsg(sMsg) return (False, 'method "%s" is not supported' % sRequest)
def getDiscount( self ): """ Get default discount percentage. """ try: oResult = self._libDB.query( 'SELECT sValue FROM PLMisc WHERE sName=%s', 'discount' ) return float( oResult[ 0 ][ 0 ] ) except Exception, e: errMsg( 'error getting default discount' ) errMsg( e ) return 0.0
def setUser(self, rgsUser): """ Set user from hash """ try: oUser = self._thawUser(rgsUser) self._dbUserList.setUser(oUser) return True except Exception, e: errMsg('error setting user [%s]' % e) raise Exception, 'error setting user'
def hdlrSignal(signum, frame): global oXmlRpc, fReady if signum == signal.SIGINT or signum == signal.SIGTERM: raise KeyboardInterrupt elif signum == signal.SIGHUP: try: if not fReady: return oXmlRpc.reloadConfig() except Exception, e: errMsg('error reloading config [%s]' % e)
def checkExists(self, sSessID): """ Check if session has authenticated. """ try: if self._dbSessionList.checkExists(sSessID=sSessID): return True return False except Exception, e: errMsg('error while checking if session is valid [%s]' % e) raise Exception, "System error while checking session."
def runReport(self, bReport, sDateFrom='2016-01-01', sDateTo='2016-01-01'): """ Run report and return HTML result page """ try: oReport = self._getReport(bReport) if oReport is None: return 'Could not find report' if oReport.getPath() == 'inventory_by_location': import modules.tpreports.inventory_by_location oApp = modules.tpreports.inventory_by_location.App() return oApp.run() elif oReport.getPath() == 'inventory_by_vendor': import modules.tpreports.inventory_by_vendor oApp = modules.tpreports.inventory_by_vendor.App() return oApp.run() elif oReport.getPath() == 'commission_sales': import modules.tpreports.commission_sales oApp = modules.tpreports.commission_sales.App() return oApp.run(sDateFrom, sDateTo) elif oReport.getPath() == 'commission_tech': import modules.tpreports.commission_tech oApp = modules.tpreports.commission_tech.App() return oApp.run(sDateFrom, sDateTo) elif oReport.getPath() == 'employee_time_off': import modules.tpreports.employee_time_off oApp = modules.tpreports.employee_time_off.App() return oApp.run(sDateFrom, sDateTo) elif oReport.getPath() == 'time_slips': import modules.tpreports.time_slips oApp = modules.tpreports.time_slips.App() return oApp.run(sDateFrom, sDateTo) elif oReport.getPath() == 'items_to_purchase': import modules.tpreports.items_to_purchase oApp = modules.tpreports.items_to_purchase.App() return oApp.run() elif oReport.getPath() == 'command_price_book': import modules.tpreports.command_price_book oApp = modules.tpreports.command_price_book.App() return oApp.run() return 'Could not run report [%s]' % oReport.getName() except Exception, e: errMsg('error running tigerpaw report [%s]' % e) raise Exception, 'error running tigerpaw report'