#!/usr/bin/python2 import argparse, os, re, subprocess, sys, time from datetime import datetime, date, timedelta def msg(cmdargs,msg): if cmdargs.silent is False: print "%s" %msg def mythshutdownlock_check(cmdargs,cursor): if (cmdargs.lock): msg(cmdargs," Checking mythshutdown for lock...") try: cursor.execute("select data from settings where value = 'MythShutdownLock'") results=cursor.fetchone() except: return True lock=results[0] if int(lock) == 0 : msg(cmdargs," mythshutdown is NOT locked.") return True else: msg(cmdargs," mythshutdown is locked.") return False else: return True def dailywake_check(cmdargs,cursor): if (cmdargs.daily): msg(cmdargs," Checking if in a daily wake period...") dailyWake=False today = date.today() now = datetime.now() try: cursor.execute("select data from settings where value = 'DailyWakeupStartPeriod1'") results=cursor.fetchone() p1Start=datetime.strptime(' '.join([str(today), results[0]]), "%Y-%m-%d %H:%M") cursor.execute("select data from settings where value = 'DailyWakeupEndPeriod1'") results=cursor.fetchone() p1End=datetime.strptime(' '.join([str(today), results[0]]), "%Y-%m-%d %H:%M") cursor.execute("select data from settings where value = 'DailyWakeupStartPeriod2'") results=cursor.fetchone() p2Start=datetime.strptime(' '.join([str(today), results[0]]), "%Y-%m-%d %H:%M") cursor.execute("select data from settings where value = 'DailyWakeupEndPeriod2'") results=cursor.fetchone() p2End=datetime.strptime(' '.join([str(today), results[0]]), "%Y-%m-%d %H:%M") except: print "error" return True # Check for time periods that cross midnight if (p1End < p1Start): if (now > p1End): p1End = p1End + timedelta(days=1) else: p1Start = p1Start + timedelta(days=-1) if (p2End < p2Start): if (now > p2End): p2End = p2End + timedelta(days=1) else: p2Start = p2Start + timedelta(days=-1) #Check for one of the daily wakeup periods if (p1Start != p1End): if (now >= p1Start and now <= p1End): msg(cmdargs," Currently in daily wake period 1.") return False if (p2Start != p2End): if (now >= p2Start and now <= p2End): msg(cmdargs," Currently in daily wake period 2.") return False #Are we about to start a daily wakeup period using the -t TIME var if (p1Start != p1End): delta=p1Start-now if (delta.seconds >= 0 and delta.seconds <= cmdargs.time * 60): msg(cmdargs," Daily wake period 1 will start in less than %s minutes." %cmdargs.time) return False if (p2Start != p2End): delta=p2Start-now if (delta.seconds >= 0 and delta.seconds <= cmdargs.time * 60): msg(cmdargs," Daily wake period 2 will start in less than %s minutes." %cmdargs.time) return False msg(cmdargs," Currently NOT in a daily wake period.") return True else: return True def schemalock_check(cmdargs,cursor): msg(cmdargs," Checking if the schema is locked...") try: cursor.execute("select count(*) from schemalock") results=cursor.fetchone() except: return True schemalock=results[0] if schemalock == 0: msg(cmdargs," The schema is NOT locked.") return True else: msg(cmdargs," The schema is locked.") return False def in_use(cmdargs,cursor): msg(cmdargs," Checking if programs are in use...") try: cursor.execute("select count(*) from inuseprograms") results=cursor.fetchone() except: return True prginuse=results[0] if prginuse == 0 : msg(cmdargs," Programs are NOT in use.") return True else: msg(cmdargs," Programs are in use.") return False def job_check(cmdargs,cursor): msg(cmdargs," Checking jobqueue for active jobs...") try: cursor.execute("select count(*) from jobqueue where status between 2 and 5") results=cursor.fetchone() except: return True jobs=results[0] if jobs == 0 : msg(cmdargs," No jobs are active.") return True else: msg(cmdargs," Jobs are active.") return False def upcoming_check(cmdargs,mythBE): msg(cmdargs," Checking for recordings in the next %s minutes..." %cmdargs.time) try: upcoming = mythBE.getUpcomingRecordings() except: msg(cmdargs," Could not get upcoming recordings.") return True time_diff=10000 r=0 for i in upcoming: r += 1 if r > 1: break show=str(i) show=show.strip() showtime=re.split("[-+]\d\d:\d\d",str(i.starttime))[0] now=time.time() rec_time=time.strptime( showtime ,"%Y-%m-%d %H:%M:%S" ) r=time.mktime(rec_time) time_diff = ( r - now ) / 60 if ( time_diff > cmdargs.time) : msg(cmdargs," No recordings starting in %s minutes." %cmdargs.time) return True else: msg(cmdargs," A recording is starting in %s minutes." %int(time_diff)) return False def mfd_check(cmdargs): msg(cmdargs," Checking if mythfilldatabase is running...") with open(os.devnull, "w") as fnull: mythfilldatabase_ret = subprocess.call(["pidof", "mythfilldatabase"], stdout=fnull) if mythfilldatabase_ret == 0 : msg(cmdargs," mythfilldatabase is running.") return False else: msg(cmdargs," mythfilldatabase is NOT running.") return True def mythtvsetup_check(cmdargs): msg(cmdargs," Checking if mythtv-setup is running...") with open(os.devnull, "w") as fnull: mythsetup_ret = subprocess.call(["pidof", "mythtv-setup"], stdout=fnull) if mythsetup_ret == 0 : msg(cmdargs," mythtv-setup is running.") return False else: msg(cmdargs," mythtv-setup is NOT running.") return True def userlogins_check(cmdargs): if (cmdargs.logins): u=False msg(cmdargs," Checking for users logged in...") users=subprocess.check_output("who") names=([x.split() for x in users.splitlines()]) for i in names: if (i[0] == "mythtv" and i[4] == "(:0)"): msg(cmdargs," Ignoring %s %s" %(i[0],i[4])) else: msg(cmdargs," User logged in: %s %s" %(i[0],i[4])) u=True if u: return False else: return True else: return True def sambafiles_check(cmdargs): if (cmdargs.sambafiles): msg(cmdargs," Checking if Samba files are in use...") try: smbstatus=subprocess.check_output(["smbstatus", "-L"]) except: smbstatus="No locked files" if "No locked files" in smbstatus: msg(cmdargs," Samba files are NOT in use.") return True else: msg(cmdargs," Samba files are in use.") return False else: return True def mythfe_check(cmdargs,cursor,mythDB): #checks to see if a frontend is considered idle # True means FE is idle if ( cmdargs.runningfe ): msg(cmdargs," Checking for running and playing mythfrontends...") else: msg(cmdargs," Checking for playing mythfrontends...") try: cursor.execute("select distinct hostname from settings where hostname is not null;") frontends=cursor.fetchall() except: return True for i in frontends: try: msg(cmdargs," Checking %s's mythfrontend status..." %i) frontend = mythDB.getFrontend(''.join(i)) if ( cmdargs.runningfe ): msg(cmdargs," %s's mythfrontend is RUNNING." %i) return False location = frontend.sendQuery('Location') if location == "standbymode": msg(cmdargs," %s's mythfrontend is in Standby Mode." %i) continue if ( location.startswith('Playback ') ): msg(cmdargs," %s's mythfrontend is PLAYING." %i) return False else: msg(cmdargs," %s's mythfrontend is NOT playing." %i) if '.xml' in location or 'mainmenu' in location: msg(cmdargs," %s's mythfrontend is in MENUS." %i) else: #FE is not in menus, so it must be active in a plugin msg(cmdargs," %s's mythfrontend is NOT in menus." %i) return False except: msg(cmdargs," Could not connect to %s's mythfrontend." %i) if ( cmdargs.runningfe ): msg(cmdargs," mythfrontends are not running or playing or are in menus.") else: msg(cmdargs," mythfrontends are not playing or are in menus.") return True def usage(): line = ''' idle.py checks if the system is idle. Use idle.py -h to see options. idle.py checks these parts of the system in this order to determine if it is idle: - (option -g) users are logged in return busy ignores mythtv (:0) for busy - (option -f) Samba files are in use return busy - (option -l) mythshutdown is locked return busy - (option -d) in a daily wake period or about to start a daily wake period return busy checks the next 15 minutes. -t TIME changes time - schema is locked return busy - there are in use programs return busy - there are active jobs in the job queue return busy - mythfilldatabase is running return busy - mythtv-setup is running return busy - there are upcoming recordings return busy checks the next 15 minutes. -t TIME changes time - (option -r) mythfrontends running return busy - mythfrontends playing back a recording or video return busy - mythfrontends not in menus return busy idle.py stops checking and returns false (busy) when the first busy is found. ''' print line sys.exit(0) def main(args=[False]): parser = argparse.ArgumentParser() parser.add_argument('-d', '--daily', action='store_true', help='Include daily wake & about to start wake in system busy. (default: daily wake & about to start wake is system idle)') parser.add_argument('-g', '--logins', action='store_true', help='Include user logins in system busy. Ignores mythtv (:0) in system busy.') parser.add_argument('-f', '--sambafiles', action='store_true', help='Include Samba files in use in system busy.') parser.add_argument('-l', '--lock', action='store_true', help='Include mythshutdown lock in system busy. (default: mythshutdown lock is system idle)') parser.add_argument('-r', '--runningfe', action='store_true', help='Include running mythfrontends in system busy. (default: running mythfrontends are system idle)') parser.add_argument('-s', '--silent', action='store_true', help='Run without printing output. Recommended for use in cron jobs or scripts.') parser.add_argument('-t', '--time', type=int, default=15, help='Minutes of idle time needed to return idle for upcoming recordings and daily wake.') parser.add_argument('-u', '--usage', action='store_true', help='Print usage instructions.') if args[0] is False: cmdargs = parser.parse_args() else: cmdargs = parser.parse_args(args) if cmdargs.usage: usage() idle=True msg(cmdargs,"Checking system idle...") if (userlogins_check(cmdargs)): idle = True else: idle = False if (idle and sambafiles_check(cmdargs)): idle = True else: idle = False try: from MythTV import MythDB mythDB = MythDB() cursor = mythDB.cursor() db_conn=True except: msg(cmdargs,"Couldn't connect to MythTV database.") db_conn=False try: from MythTV import MythBE mythBE = MythBE() be_conn=True except: msg(cmdargs,"Couldn't connect to MythTV backend.") be_conn=False if ( db_conn and idle ): if (mythshutdownlock_check(cmdargs,cursor) and dailywake_check(cmdargs,cursor) and schemalock_check(cmdargs,cursor) and in_use(cmdargs,cursor) and job_check(cmdargs,cursor)): idle=True else: idle=False if ( be_conn and idle ): if (mfd_check(cmdargs) and mythtvsetup_check(cmdargs) and upcoming_check(cmdargs,mythBE)): idle=True else: idle=False if ( db_conn and idle ): if (mythfe_check(cmdargs,cursor,mythDB)): idle=True else: idle=False if ( idle ): msg(cmdargs,"System is idle.") else: msg(cmdargs,"System is busy.") return idle if __name__ == "__main__": idle=main() if ( idle ): exit(0) else: exit(1)