summaryrefslogtreecommitdiff
path: root/scripts/dailyimgupload.py
blob: 186614dbfe1bf61b34380ad2ad7eddcdf205b4c9 (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
import ctypes
import datetime
import os
import platform
import shutil
import sys
import traceback
import s3upload


def freespace(p):
     """
     FROM: http://atlee.ca/blog/2008/02/23/getting-free-diskspace-in-python/
           http://stackoverflow.com/questions/51658/cross-platform-space-remaining-on-volume-using-python
     Returns the number of free bytes on the drive that ``p`` is on
     """
     if platform.system() == 'Windows':
         free_bytes = ctypes.c_ulonglong(0)
         ctypes.windll.kernel32.GetDiskFreeSpaceExW(ctypes.c_wchar_p(p), None, None, ctypes.pointer(free_bytes))
         return free_bytes.value
     else:
         s = os.statvfs(p)
         return s.f_bsize * s.f_bavail

def directory_size(path):
    """
    FROM: http://stackoverflow.com/questions/1392413/calculating-a-directory-size-using-python
    """
    total_size = 0.0
    for dirpath, dirnames, filenames in os.walk(path):
        for f in filenames:
            fp = os.path.join(dirpath, f)
            total_size += os.path.getsize(fp)
    return total_size

def parse_date_dir(d, date_fmt):
    if not os.path.exists(d):
        raise ValueError('%s does not exist' % d)
    if not os.path.isdir(d):
        raise ValueError('%s is not a directory' % d)
    return datetime.datetime.strptime(os.path.basename(d), date_fmt)

def is_date_dir(d, date_fmt):
    try:
        parse_date_dir(d, date_fmt)
        return True
    except ValueError:
        return False

def get_directory_list(path, date_fmt='%Y%m%d'):
    parse_func = lambda d: parse_date_dir(d, date_fmt)
    subdirs = [os.path.join(path, child) for child in os.listdir(path)]
    datedirs = [d for d in subdirs if is_date_dir(d, date_fmt)]
    return sorted(datedirs, key=parse_func)
    

def upload_dirs_until_free(path, target_free_mbs, dryrun):
    starting_freespace = float(freespace(path))
    dirs_uploaded = 0
    files_uploaded = 0
    cur_freespace = starting_freespace
    reclaimed_space = 0.0
    error = False
    directory_list = get_directory_list(path)

    if not directory_list:
        print "Target directory %s has no subdirectories!" % path
        sys.exit(1)

    print "Target directory: %s" % path
    print "Starting freespace: %.02f MBs" % (starting_freespace / 1024 / 1024)
    print "Target freespace: %.02f MBs"  % target_free_mbs
    print "Image subdirectories: %s" % len(directory_list)

    if dryrun:
        print
        print '!!! Doing dryrun -- current free space will be estimated !!!'

    print
    try:
        for dir_to_upload in directory_list:
            if cur_freespace >= target_free_mbs * 1024 * 1024:
                break
        
            dir_size = directory_size(dir_to_upload)
            print 'Uploading %s (%.02f MBs)' % (dir_to_upload, dir_size / 1024 / 1024)

            res = s3upload.do_upload(dir_to_upload, verbose=False, dryrun=dryrun)
            files_uploaded += res['files_uploaded']
            print "%s files uploaded in %.02fs" % (res['files_uploaded'], res['sec_elapsed'])

            dirs_uploaded += 1
            reclaimed_space += dir_size

            if not dryrun:
                print "Deleting %s" % dir_to_upload
                shutil.rmtree(dir_to_upload)
                
            if dryrun:
                cur_freespace += dir_size 
            else:
                cur_freespace = float(freespace(path))
            print "%.02f MBs now free" % (cur_freespace / 1024 / 1024)
            print

    except Exception:
        print "An unexpected error occured!"
        error = True
        traceback.print_exc()

    print "---------------------------------------"
    if error:
        pass
    else:
        pass
    print "Finished successfully" if not error else "!!! Terminated abnormally !!!"
    print "Current free space: %.02f MBs" % (cur_freespace / 1024 / 1024)
    print "Reclaimed space: %.02f MBs" % (reclaimed_space / 1024 / 1024)
    print "Directories uploaded: %s" % dirs_uploaded
    print "Files uploaded: %s" % files_uploaded


if __name__ == '__main__':
    if not 4 <= len(sys.argv) <= 5:
        print "usage: dailyimgupload.py workingdir path megabytes [dryrun]"
        sys.exit(1)

    wd = sys.argv[1]
    if not os.path.isdir(wd):
        print "Invalid working directory: %s" % wd
        sys.exit(1)
    print "Switching working directory to %s" % wd
    os.chdir(wd)

    path = sys.argv[2]
    if not os.path.isdir(path):
        print "invalid image directory: %s" % path
        sys.exit(1)

    mbs = sys.argv[3]
    try:
        target_free_mbs = float(mbs)
    except ValueError:
        print "invalid number of megabytes: %s" % mbs
        sys.exit(1)

    if len(sys.argv) == 5:
        dryrun = sys.argv[4]
        if dryrun in ('true', 'false'):
            dryrun = dryrun == 'true'
        else:
            print "invalid dry run argument: %s (must be either 'true' or 'false')" % dryrun
            sys.exit(1)
    else:
        dryrun = True

    upload_dirs_until_free(path, target_free_mbs, dryrun)