Revision 75ec29e4
b/snf-django-lib/snf_django/management/commands/__init__.py | ||
---|---|---|
31 | 31 |
# interpreted as representing official policies, either expressed |
32 | 32 |
# or implied, of GRNET S.A. |
33 | 33 |
|
34 |
import os |
|
35 |
import datetime |
|
36 |
import logging |
|
34 | 37 |
from optparse import (make_option, OptionParser, OptionGroup, |
35 | 38 |
TitledHelpFormatter) |
36 | 39 |
|
... | ... | |
45 | 48 |
USER_EMAIL_FIELD = "user.email" |
46 | 49 |
|
47 | 50 |
|
51 |
class SynnefoOutputWrapper(object): |
|
52 |
"""Wrapper around stdout/stderr |
|
53 |
|
|
54 |
This class replaces Django's 'OutputWrapper' which doesn't handle |
|
55 |
logging to file. |
|
56 |
|
|
57 |
Since 'BaseCommand' doesn't initialize the 'stdout' and 'stderr' |
|
58 |
attributes at '__init__' but sets them only when it needs to, |
|
59 |
this class has to be a descriptor. |
|
60 |
|
|
61 |
We will use the old 'OutputWrapper' class for print to the screen and |
|
62 |
a logger for logging to the file. |
|
63 |
|
|
64 |
""" |
|
65 |
def __init__(self): |
|
66 |
self.django_wrapper = None |
|
67 |
self.logger = None |
|
68 |
|
|
69 |
def __set__(self, obj, value): |
|
70 |
self.django_wrapper = value |
|
71 |
|
|
72 |
def __getattr__(self, name): |
|
73 |
return getattr(self.django_wrapper, name) |
|
74 |
|
|
75 |
def init_argv(self, argv): |
|
76 |
"""Initialize this class using the command line |
|
77 |
|
|
78 |
Takes the command arguments, generate the filename where |
|
79 |
we are going to log, initialize our logger and return the |
|
80 |
generated filename. |
|
81 |
|
|
82 |
""" |
|
83 |
curr_time = datetime.datetime.now() |
|
84 |
curr_time = datetime.datetime.strftime(curr_time, "%y%m%d%H%M%S") |
|
85 |
command = argv[1] |
|
86 |
pid = os.getpid() |
|
87 |
basename = "%s_%s_%s.log" % (curr_time, command, pid) |
|
88 |
filename = os.path.join("/var/log/synnefo/", basename) |
|
89 |
self.init_file(filename) |
|
90 |
self.logger.info(" ".join(map(str, argv)) + "\n\n") |
|
91 |
return filename |
|
92 |
|
|
93 |
def init_file(self, filename): |
|
94 |
"""Create a logger for the filename""" |
|
95 |
|
|
96 |
basename = os.path.splitext(os.path.basename(filename))[0] |
|
97 |
self.logger = logging.getLogger(basename) |
|
98 |
self.logger.setLevel(logging.DEBUG) |
|
99 |
self.logger.propagate = False |
|
100 |
|
|
101 |
if not self.logger.handlers: |
|
102 |
handler = logging.FileHandler(filename) |
|
103 |
self.logger.addHandler(handler) |
|
104 |
# Also set all other logger to log to this file |
|
105 |
logging.getLogger().addHandler(handler) |
|
106 |
|
|
107 |
def write(self, msg, *args, **kwargs): |
|
108 |
if self.logger is not None: |
|
109 |
self.logger.info(msg) |
|
110 |
if self.django_wrapper is not None: |
|
111 |
self.django_wrapper.write(msg, *args, **kwargs) |
|
112 |
|
|
113 |
|
|
48 | 114 |
class SynnefoCommandFormatter(TitledHelpFormatter): |
49 | 115 |
def format_heading(self, heading): |
50 | 116 |
if heading == "Options": |
... | ... | |
64 | 130 |
"csv [comma-separated output]"), |
65 | 131 |
) |
66 | 132 |
|
133 |
stdout = SynnefoOutputWrapper() |
|
134 |
stderr = SynnefoOutputWrapper() |
|
135 |
|
|
136 |
def run_from_argv(self, argv): |
|
137 |
"""Initialize 'SynnefoOutputWrapper' and call super |
|
138 |
|
|
139 |
The two wrappers have to write to the same filename, so we cannot |
|
140 |
initialze both of them (each will create a new filename). Furthermore |
|
141 |
we cannot have only one wrapper (BaseCommand has both 'stdout' and |
|
142 |
'stderr'). So call 'init_argv' for the first wrapper and give the |
|
143 |
resulting filename to the second. |
|
144 |
|
|
145 |
XXX: Find a better way to do the above. |
|
146 |
|
|
147 |
""" |
|
148 |
filename = self.stdout.init_argv(argv) |
|
149 |
self.stderr.init_file(filename) |
|
150 |
super(SynnefoCommand, self).run_from_argv(argv) |
|
151 |
|
|
67 | 152 |
def create_parser(self, prog_name, subcommand): |
68 | 153 |
parser = OptionParser(prog=prog_name, add_help_option=False, |
69 | 154 |
formatter=SynnefoCommandFormatter()) |
... | ... | |
295 | 380 |
objects = objects.prefetch_related(*prefetch_related) |
296 | 381 |
objects = objects.filter(**self.filters) |
297 | 382 |
for key, value in self.excludes.iteritems(): |
298 |
objects = objects.exclude(**{key:value}) |
|
383 |
objects = objects.exclude(**{key: value})
|
|
299 | 384 |
except FieldError as e: |
300 | 385 |
raise CommandError(e) |
301 | 386 |
except Exception as e: |
Also available in: Unified diff