summaryrefslogtreecommitdiffstats
path: root/linhes/linhes-system/empty_storage_groups.py
blob: 4b5aff8c4950a3cefb37e18444e8f5cce5d2e626 (plain)
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#!/usr/bin/python

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=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(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=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=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)