| author | ymh <ymh.work@gmail.com> |
| Wed, 20 Jan 2010 12:37:40 +0100 | |
| changeset 3 | 526ebd3988b0 |
| permissions | -rw-r--r-- |
|
3
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
1 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
2 |
Sync Media to S3 |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
3 |
================ |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
4 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
5 |
Django command that scans all files in your settings.MEDIA_ROOT folder and |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
6 |
uploads them to S3 with the same directory structure. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
7 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
8 |
This command can optionally do the following but it is off by default: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
9 |
* gzip compress any CSS and Javascript files it finds and adds the appropriate |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
10 |
'Content-Encoding' header. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
11 |
* set a far future 'Expires' header for optimal caching. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
12 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
13 |
Note: This script requires the Python boto library and valid Amazon Web |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
14 |
Services API keys. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
15 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
16 |
Required settings.py variables: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
17 |
AWS_ACCESS_KEY_ID = '' |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
18 |
AWS_SECRET_ACCESS_KEY = '' |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
19 |
AWS_BUCKET_NAME = '' |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
20 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
21 |
Command options are: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
22 |
-p PREFIX, --prefix=PREFIX |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
23 |
The prefix to prepend to the path on S3. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
24 |
--gzip Enables gzipping CSS and Javascript files. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
25 |
--expires Enables setting a far future expires header. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
26 |
--force Skip the file mtime check to force upload of all |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
27 |
files. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
28 |
--filter-list Override default directory and file exclusion |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
29 |
filters. (enter as comma seperated line) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
30 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
31 |
TODO: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
32 |
* Use fnmatch (or regex) to allow more complex FILTER_LIST rules. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
33 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
34 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
35 |
import datetime |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
36 |
import email |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
37 |
import mimetypes |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
38 |
import optparse |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
39 |
import os |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
40 |
import sys |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
41 |
import time |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
42 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
43 |
from django.conf import settings |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
44 |
from django.core.management.base import BaseCommand, CommandError |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
45 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
46 |
# Make sure boto is available |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
47 |
try: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
48 |
import boto |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
49 |
import boto.exception |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
50 |
except ImportError: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
51 |
raise ImportError, "The boto Python library is not installed." |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
52 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
53 |
class Command(BaseCommand): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
54 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
55 |
# Extra variables to avoid passing these around |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
56 |
AWS_ACCESS_KEY_ID = '' |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
57 |
AWS_SECRET_ACCESS_KEY = '' |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
58 |
AWS_BUCKET_NAME = '' |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
59 |
DIRECTORY = '' |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
60 |
FILTER_LIST = ['.DS_Store', '.svn', '.hg', '.git', 'Thumbs.db'] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
61 |
GZIP_CONTENT_TYPES = ( |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
62 |
'text/css', |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
63 |
'application/javascript', |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
64 |
'application/x-javascript' |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
65 |
) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
66 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
67 |
upload_count = 0 |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
68 |
skip_count = 0 |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
69 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
70 |
option_list = BaseCommand.option_list + ( |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
71 |
optparse.make_option('-p', '--prefix', |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
72 |
dest='prefix', default='', |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
73 |
help="The prefix to prepend to the path on S3."), |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
74 |
optparse.make_option('-d', '--dir', |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
75 |
dest='dir', default=settings.MEDIA_ROOT, |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
76 |
help="The root directory to use instead of your MEDIA_ROOT"), |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
77 |
optparse.make_option('--gzip', |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
78 |
action='store_true', dest='gzip', default=False, |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
79 |
help="Enables gzipping CSS and Javascript files."), |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
80 |
optparse.make_option('--expires', |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
81 |
action='store_true', dest='expires', default=False, |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
82 |
help="Enables setting a far future expires header."), |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
83 |
optparse.make_option('--force', |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
84 |
action='store_true', dest='force', default=False, |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
85 |
help="Skip the file mtime check to force upload of all files."), |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
86 |
optparse.make_option('--filter-list', dest='filter_list', |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
87 |
action='store', default='', |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
88 |
help="Override default directory and file exclusion filters. (enter as comma seperated line)"), |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
89 |
) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
90 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
91 |
help = 'Syncs the complete MEDIA_ROOT structure and files to S3 into the given bucket name.' |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
92 |
args = 'bucket_name' |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
93 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
94 |
can_import_settings = True |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
95 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
96 |
def handle(self, *args, **options): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
97 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
98 |
# Check for AWS keys in settings |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
99 |
if not hasattr(settings, 'AWS_ACCESS_KEY_ID') or \ |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
100 |
not hasattr(settings, 'AWS_SECRET_ACCESS_KEY'): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
101 |
raise CommandError('Missing AWS keys from settings file. Please' + |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
102 |
'supply both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.') |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
103 |
else: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
104 |
self.AWS_ACCESS_KEY_ID = settings.AWS_ACCESS_KEY_ID |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
105 |
self.AWS_SECRET_ACCESS_KEY = settings.AWS_SECRET_ACCESS_KEY |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
106 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
107 |
if not hasattr(settings, 'AWS_BUCKET_NAME'): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
108 |
raise CommandError('Missing bucket name from settings file. Please' + |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
109 |
' add the AWS_BUCKET_NAME to your settings file.') |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
110 |
else: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
111 |
if not settings.AWS_BUCKET_NAME: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
112 |
raise CommandError('AWS_BUCKET_NAME cannot be empty.') |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
113 |
self.AWS_BUCKET_NAME = settings.AWS_BUCKET_NAME |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
114 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
115 |
if not hasattr(settings, 'MEDIA_ROOT'): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
116 |
raise CommandError('MEDIA_ROOT must be set in your settings.') |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
117 |
else: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
118 |
if not settings.MEDIA_ROOT: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
119 |
raise CommandError('MEDIA_ROOT must be set in your settings.') |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
120 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
121 |
self.verbosity = int(options.get('verbosity')) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
122 |
self.prefix = options.get('prefix') |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
123 |
self.do_gzip = options.get('gzip') |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
124 |
self.do_expires = options.get('expires') |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
125 |
self.do_force = options.get('force') |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
126 |
self.DIRECTORY = options.get('dir') |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
127 |
self.FILTER_LIST = getattr(settings, 'FILTER_LIST', self.FILTER_LIST) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
128 |
filter_list = options.get('filter_list').split(',') |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
129 |
if filter_list: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
130 |
# command line option overrides default filter_list and |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
131 |
# settings.filter_list |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
132 |
self.FILTER_LIST = filter_list |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
133 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
134 |
# Now call the syncing method to walk the MEDIA_ROOT directory and |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
135 |
# upload all files found. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
136 |
self.sync_s3() |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
137 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
138 |
print |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
139 |
print "%d files uploaded." % (self.upload_count) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
140 |
print "%d files skipped." % (self.skip_count) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
141 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
142 |
def sync_s3(self): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
143 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
144 |
Walks the media directory and syncs files to S3 |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
145 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
146 |
bucket, key = self.open_s3() |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
147 |
os.path.walk(self.DIRECTORY, self.upload_s3, |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
148 |
(bucket, key, self.AWS_BUCKET_NAME, self.DIRECTORY)) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
149 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
150 |
def compress_string(self, s): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
151 |
"""Gzip a given string.""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
152 |
import cStringIO, gzip |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
153 |
zbuf = cStringIO.StringIO() |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
154 |
zfile = gzip.GzipFile(mode='wb', compresslevel=6, fileobj=zbuf) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
155 |
zfile.write(s) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
156 |
zfile.close() |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
157 |
return zbuf.getvalue() |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
158 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
159 |
def open_s3(self): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
160 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
161 |
Opens connection to S3 returning bucket and key |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
162 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
163 |
conn = boto.connect_s3(self.AWS_ACCESS_KEY_ID, self.AWS_SECRET_ACCESS_KEY) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
164 |
try: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
165 |
bucket = conn.get_bucket(self.AWS_BUCKET_NAME) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
166 |
except boto.exception.S3ResponseError: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
167 |
bucket = conn.create_bucket(self.AWS_BUCKET_NAME) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
168 |
return bucket, boto.s3.key.Key(bucket) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
169 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
170 |
def upload_s3(self, arg, dirname, names): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
171 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
172 |
This is the callback to os.path.walk and where much of the work happens |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
173 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
174 |
bucket, key, bucket_name, root_dir = arg # expand arg tuple |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
175 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
176 |
# Skip directories we don't want to sync |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
177 |
if os.path.basename(dirname) in self.FILTER_LIST: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
178 |
# prevent walk from processing subfiles/subdirs below the ignored one |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
179 |
del names[:] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
180 |
return |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
181 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
182 |
# Later we assume the MEDIA_ROOT ends with a trailing slash |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
183 |
if not root_dir.endswith(os.path.sep): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
184 |
root_dir = root_dir + os.path.sep |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
185 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
186 |
for file in names: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
187 |
headers = {} |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
188 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
189 |
if file in self.FILTER_LIST: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
190 |
continue # Skip files we don't want to sync |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
191 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
192 |
filename = os.path.join(dirname, file) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
193 |
if os.path.isdir(filename): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
194 |
continue # Don't try to upload directories |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
195 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
196 |
file_key = filename[len(root_dir):] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
197 |
if self.prefix: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
198 |
file_key = '%s/%s' % (self.prefix, file_key) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
199 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
200 |
# Check if file on S3 is older than local file, if so, upload |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
201 |
if not self.do_force: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
202 |
s3_key = bucket.get_key(file_key) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
203 |
if s3_key: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
204 |
s3_datetime = datetime.datetime(*time.strptime( |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
205 |
s3_key.last_modified, '%a, %d %b %Y %H:%M:%S %Z')[0:6]) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
206 |
local_datetime = datetime.datetime.utcfromtimestamp( |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
207 |
os.stat(filename).st_mtime) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
208 |
if local_datetime < s3_datetime: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
209 |
self.skip_count += 1 |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
210 |
if self.verbosity > 1: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
211 |
print "File %s hasn't been modified since last " \ |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
212 |
"being uploaded" % (file_key) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
213 |
continue |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
214 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
215 |
# File is newer, let's process and upload |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
216 |
if self.verbosity > 0: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
217 |
print "Uploading %s..." % (file_key) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
218 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
219 |
content_type = mimetypes.guess_type(filename)[0] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
220 |
if content_type: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
221 |
headers['Content-Type'] = content_type |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
222 |
file_obj = open(filename, 'rb') |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
223 |
file_size = os.fstat(file_obj.fileno()).st_size |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
224 |
filedata = file_obj.read() |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
225 |
if self.do_gzip: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
226 |
# Gzipping only if file is large enough (>1K is recommended) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
227 |
# and only if file is a common text type (not a binary file) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
228 |
if file_size > 1024 and content_type in self.GZIP_CONTENT_TYPES: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
229 |
filedata = self.compress_string(filedata) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
230 |
headers['Content-Encoding'] = 'gzip' |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
231 |
if self.verbosity > 1: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
232 |
print "\tgzipped: %dk to %dk" % \ |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
233 |
(file_size/1024, len(filedata)/1024) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
234 |
if self.do_expires: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
235 |
# HTTP/1.0 |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
236 |
headers['Expires'] = '%s GMT' % (email.Utils.formatdate( |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
237 |
time.mktime((datetime.datetime.now() + |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
238 |
datetime.timedelta(days=365*2)).timetuple()))) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
239 |
# HTTP/1.1 |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
240 |
headers['Cache-Control'] = 'max-age %d' % (3600 * 24 * 365 * 2) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
241 |
if self.verbosity > 1: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
242 |
print "\texpires: %s" % (headers['Expires']) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
243 |
print "\tcache-control: %s" % (headers['Cache-Control']) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
244 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
245 |
try: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
246 |
key.name = file_key |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
247 |
key.set_contents_from_string(filedata, headers, replace=True) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
248 |
key.set_acl('public-read') |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
249 |
except boto.s3.connection.S3CreateError, e: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
250 |
print "Failed: %s" % e |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
251 |
except Exception, e: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
252 |
print e |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
253 |
raise |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
254 |
else: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
255 |
self.upload_count += 1 |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
256 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
257 |
file_obj.close() |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
258 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
259 |
# Backwards compatibility for Django r9110 |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
260 |
if not [opt for opt in Command.option_list if opt.dest=='verbosity']: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
261 |
Command.option_list += ( |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
262 |
optparse.make_option('-v', '--verbosity', |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
263 |
dest='verbosity', default=1, action='count', |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
264 |
help="Verbose mode. Multiple -v options increase the verbosity."), |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
265 |
) |