1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
#!/usr/bin/python
import argparse, glob, operator, os, random, shutil, subprocess, sys, signal, time
shouldQuit = False
movingFiles = 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):
if movingFiles:
print("\nWill quit when file has been moved.\nMoving File...")
global shouldQuit
shouldQuit = True
else:
sys.exit(0)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-c', '--checkonly', action='store_true', help="Check only, don't move any files.")
parser.add_argument('-p', '--percent', type=int, default=7, help="The percentage difference between the most full dir and least full dir that will stop balancing.")
cmdargs = parser.parse_args()
SGDIRS = []
SGgrp = "Default"
signal.signal(signal.SIGINT, signal_handler)
print("\nBalance MythTV Storage Group Directories\nPress Ctrl+C to quit")
# Get Storage Groups from MythDB
try:
from MythTV import MythDB
mythDB = MythDB()
records = mythDB.getStorageGroup()
except:
print("Couldn't connect to MythTV database.")
sys.exit(1)
# Get Storage Group directories
for record in records:
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:")
# 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
freePcent = getFreePercentForDir(directory)
freeSize = getFreeSpaceForDir(directory)
SGDIRSdata.append([directory, freePcent, freeSize])
print(" %s - %.2f%%" % (directory, freePcent * 100))
# Sort data on percent free
SGDIRSdata = sorted(SGDIRSdata, reverse=True, key=operator.itemgetter(1))
#print SGDIRSdata
# Check if SG has any ts, mpg or nuv files
i=0
for dir in SGDIRSdata:
mostFull = SGDIRSdata[i]
i=i+1
if len(glob.glob1(mostFull[0],"*.ts")) or len(glob.glob1(mostFull[0],"*.mpg")) or len(glob.glob1(mostFull[0],"*.nuv")):
break
else:
if i == 1:
print("------------------------------------------------")
print(" " + mostFull[0] + " - NO files to move")
leastFull = SGDIRSdata[-1]
print("------------------------------------------------")
print("Most Used Storage Group Directory with files to move: ")
print(" %s - %.2f%%" % (mostFull[0], mostFull[1] * 100))
print("Least Used Storage Group Directory: ")
print(" %s - %.2f%%" % (leastFull[0], leastFull[1] * 100))
# Check if mostFull and leastFull are within the percent var of each other
if mostFull[1] - (float(cmdargs.percent) / 100) < leastFull[1]:
print("\nThe most used and least used storage group directories are\nwithin " + str(cmdargs.percent) + "% used of each other. No files will be moved.")
sys.exit()
# Get random file from most used dir
fileToMove = random.choice([f for f in os.listdir(mostFull[0]) if f.endswith(".ts") or f.endswith(".mpg") or f.endswith(".nuv")])
filePathToMove = mostFull[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()
# Move file
if cmdargs.checkonly:
print("------------------------------------------------")
print("Check Only option was used. No files were moved.")
shouldQuit = True
else:
isBusy = True
while isBusy:
if shouldQuit:
sys.exit(0)
print("------------------------------------------------")
print("Checking System Status...")
if subprocess.call(["/usr/bin/python", "/usr/bin/idle.py", "-s"]):
print(" System is busy. The file will not be moved.")
print(" Waiting 5 minutes before trying again.")
time.sleep(300)
else:
isBusy = False
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])))
print("Moving File...")
movingFiles = True
try:
shutil.move(filePathToMove, leastFull[0])
# eg. src and dest are the same file
except shutil.Error as e:
print(('Error: %s' % e))
except IOError as e:
print(('Error: %s' % e.strerror))
# Remove png files
print("------------------------------------------------")
print("Removing png Files:")
pngFiles = glob.glob(filePathToMove + "*.png")
for p in pngFiles:
os.remove(p)
print(" " + p)
movingFiles = False
|