#!/usr/bin/python2 import argparse, glob, operator, os, random, shutil, subprocess, sys, signal shouldQuit = False def getFreeSpaceForDir(dir): stats = os.statvfs(dir) return (stats.f_bavail * stats.f_frsize) def getFreePercentForDir(dir): stats = os.statvfs(dir) total = (stats.f_blocks) avail = (stats.f_bavail) return (total - avail) / float(total) def getFileSize(fullPath): return os.path.getsize(fullPath) def sizeof_fmt(num, suffix='B'): for unit in ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']: if abs(num) < 1024.0: return "%3.1f %s%s" % (num, unit, suffix) num /= 1024.0 return "%.1f %s%s" % (num, 'Yi', suffix) def signal_handler(signal, frame): print "\nWill quit when file has been moved.\nMoving File..." global shouldQuit shouldQuit = True if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('-c', '--checkonly', action='store_true', help="Check only, don't move any files.") cmdargs = parser.parse_args() SGs = [] SGDIRS = [] SGgrp = "Default" SGselectdata = [] signal.signal(signal.SIGINT, signal_handler) print "\nEmpty a MythTV Storage Group Directory\nPress Ctrl+C to quit" # Get Storage Groups from MythDB try: from MythTV import MythDB mythDB = MythDB() records = mythDB.getStorageGroup() recs = mythDB.getStorageGroup() except: print "Couldn't connect to MythTV database." sys.exit(1) # get list of non duplicate SGs for record in records: SGs.append(record.groupname) SGs=list(set(SGs)) # Move Default to top of list if "Default" in SGs: SGs.remove("Default") SGs.insert(0,"Default") # ask user which SG to use print "\n------------------------------------------------" print "Storage Groups:" for i,sg in enumerate(SGs): print str(i+1) + ": " + sg try: SGselect=raw_input("\nEnter the number of the storage group to use (default 1): ") or 1 SGselect=int(SGselect) if SGselect > len(SGs) or SGselect < 1: SGselect=int("e") except ValueError: print "You must enter a number between 1 and " + str(len(SGs)) + ". Exiting." sys.exit(0) SGgrp=SGs[SGselect-1] # Get Storage Group directories for record in recs: if record.groupname == SGgrp: dirname = record.dirname SGDIRS.append(dirname) # If there are less than 2 directories defined bail as we can't move anything if len(SGDIRS) < 2: print "There are less than 2 directories defined. Exiting." sys.exit(0) while not shouldQuit: SGDIRSdata = [] print "\n------------------------------------------------" print "'" + SGgrp + "' Storage Group Directories - Percent Used:" SGcnt=0 # Get percent free and size free for directory in SGDIRS: # Check if SG path exists if not os.path.exists(directory): print " " + directory + " - Not Mounted" continue # Check if SG has data files to move if len(glob.glob1(directory,"*.ts")) or len(glob.glob1(directory,"*.mpg")) or len(glob.glob1(directory,"*.nuv")) or len(glob.glob1(directory,"*.jpg")): freePcent = getFreePercentForDir(directory) freeSize = getFreeSpaceForDir(directory) SGDIRSdata.append([directory, freePcent, freeSize]) SGcnt=SGcnt+1 print "%s: %s - %.2f%%" % (SGcnt, directory, freePcent * 100) else: # Check if the selected SG dir has no data files exit if SGselectdata and SGselectdata[0] == directory: print "\n'" + SGgrp + "' Storage Group directories have no files to move. Exiting" sys.exit(0) # Exit if no SGs with data found if SGcnt is 0: print "\n'" + SGgrp + "' Storage Group directories have no files to move. Exiting." sys.exit(0) # Ask user to select which SG to empty if not already selected if not SGselectdata: try: SGDIRselect=int(raw_input("\nEnter the number of the storage group directory to empty: ")) if SGDIRselect > SGcnt or SGDIRselect < 1: SGDIRselect=int("e") except ValueError: print "You must enter a number between 1 and %s. Exiting." %SGcnt sys.exit(0) SGselectdata=SGDIRSdata[SGDIRselect-1] # Sort data on percent free SGDIRSdata = sorted(SGDIRSdata, reverse=True, key=operator.itemgetter(1)) leastFull = SGDIRSdata[-1] # Make sure leastFull and SGselectdata are not the same dir if leastFull[0] == SGselectdata[0]: leastFull = SGDIRSdata[-2] # Get random file from user selected dir fileToMove = random.choice([f for f in os.listdir(SGselectdata[0]) if f.endswith(".ts") or f.endswith(".mpg") or f.endswith(".nuv") or f.endswith(".jpg")]) filePathToMove = SGselectdata[0] + "/" + fileToMove # Check that the file isn't too big for least used dir fileSize = getFileSize(filePathToMove) if (fileSize > getFreeSpaceForDir(leastFull[0])): # Too big to move print filePathToMove + " is too big to move to " + leastFull[0] sys.exit() print "------------------------------------------------" print "Move File:" print " " + filePathToMove print " Size: " + sizeof_fmt(os.path.getsize(filePathToMove)) print "To:" print " " + leastFull[0] print " Available: " + sizeof_fmt(getFreeSpaceForDir(leastFull[0])) # Move file if cmdargs.checkonly: print "------------------------------------------------" print"Check Only option was used. No files were moved." shouldQuit = True else: print "------------------------------------------------" print "Checking System Status..." if subprocess.call(["/usr/bin/python2", "/usr/LH/bin/idle.py", "-s"]): print " System is busy. The file will not be moved." sys.exit() print "Moving File..." try: shutil.move(filePathToMove, leastFull[0]) # eg. src and dest are the same file except shutil.Error as e: a=raw_input("\n%s. Overwrite destination (y/n)? " % e) if a == "y" or a == "Y": os.remove(leastFull[0] + "/" + fileToMove) shutil.move(filePathToMove, leastFull[0]) else: b=raw_input("\nRemove %s (y/n)? " % filePathToMove) if b == "y" or b == "Y": os.remove(filePathToMove) # eg. source or destination doesn't exist except IOError as e: print('Error: %s' % e.strerror) # Remove png files for Default & LiveTV SGs if SGgrp == "Default" or SGgrp == "LiveTV": print "------------------------------------------------" print "Removing png Files:" pngFiles = glob.glob(filePathToMove + "*.png") for p in pngFiles: os.remove(p) print " " + p