Revision 2a2060ff

b/daemons/ganeti-noded
592 592
  if options.fork:
593 593
    utils.Daemonize(logfile=constants.LOG_NODESERVER)
594 594

  
595
  logger.SetupLogging(twisted_workaround=True, debug=options.debug,
596
                      program="ganeti-noded")
595
  logger.SetupLogging(program="ganeti-noded", debug=options.debug)
597 596

  
598 597
  httpd = BaseHTTPServer.HTTPServer(('', port), ServerObject)
599 598
  httpd.serve_forever()
b/lib/cli.py
506 506
    for key, val in override.iteritems():
507 507
      setattr(options, key, val)
508 508

  
509
  logger.SetupLogging(debug=options.debug, program=binary)
509
  logger.SetupLogging(program=binary, debug=options.debug)
510 510

  
511 511
  utils.debug = options.debug
512 512

  
b/lib/logger.py
23 23

  
24 24
This module abstracts the logging handling away from the rest of the
25 25
Ganeti code. It offers some utility functions for easy logging.
26

  
26 27
"""
27 28

  
28 29
# pylint: disable-msg=W0603,C0103
......
33 34

  
34 35
from ganeti import constants
35 36

  
36
_program = '(unknown)'
37
_errlog = None
38
_inflog = None
39
_dbglog = None
40
_stdout = None
41
_stderr = None
42
_debug = False
43

  
44

  
45
def _SetDestination(name, filename, stream=None):
46
  """Configure the destination for a given logger
47

  
48
  This function configures the logging destination for a given loger.
49
  Parameters:
50
    - name: the logger name
51
    - filename: if not empty, log messages will be written (also) to this file
52
    - stream: if not none, log messages will be output (also) to this stream
53

  
54
  Returns:
55
    - the logger identified by the `name` argument
56
  """
57
  ret = logging.getLogger(name)
58

  
59
  if filename:
60
    fmtr = logging.Formatter('%(asctime)s %(message)s')
61

  
62
    hdlr = logging.FileHandler(filename)
63
    hdlr.setFormatter(fmtr)
64
    ret.addHandler(hdlr)
65

  
66
  if stream:
67
    if name in ('error', 'info', 'debug'):
68
      fmtr = logging.Formatter('%(asctime)s %(message)s')
69
    else:
70
      fmtr = logging.Formatter('%(message)s')
71
    hdlr = logging.StreamHandler(stream)
72
    hdlr.setFormatter(fmtr)
73
    ret.addHandler(hdlr)
74

  
75
  ret.setLevel(logging.INFO)
76

  
77
  return ret
78 37

  
38
def _CreateFileHandler(name):
39
  return logging.FileHandler(os.path.join(constants.LOG_DIR, name))
79 40

  
80
def _GenericSetup(program, errfile, inffile, dbgfile,
81
                  twisted_workaround=False):
82
  """Configure logging based on arguments
83 41

  
84
  Arguments:
85
    - name of program
86
    - error log filename
87
    - info log filename
88
    - debug log filename
89
    - twisted_workaround: if true, emit all messages to stderr
90
  """
91
  global _program
92
  global _errlog
93
  global _inflog
94
  global _dbglog
95
  global _stdout
96
  global _stderr
97

  
98
  _program = program
99
  if twisted_workaround:
100
    _errlog = _SetDestination('error', None, sys.stderr)
101
    _inflog = _SetDestination('info', None, sys.stderr)
102
    _dbglog = _SetDestination('debug', None, sys.stderr)
103
  else:
104
    _errlog = _SetDestination('error', errfile)
105
    _inflog = _SetDestination('info', inffile)
106
    _dbglog = _SetDestination('debug', dbgfile)
107

  
108
  _stdout = _SetDestination('user', None, sys.stdout)
109
  _stderr = _SetDestination('stderr', None, sys.stderr)
110

  
111

  
112
def SetupLogging(twisted_workaround=False, debug=False, program='ganeti'):
42
def SetupLogging(program='ganeti', debug=False):
113 43
  """Setup logging for ganeti
114 44

  
115 45
  On failure, a check is made whether process is run by root or not,
116 46
  and an appropriate error message is printed on stderr, then process
117 47
  exits.
118 48

  
119
  This function is just a wraper over `_GenericSetup()` using specific
120
  arguments.
121

  
122
  Parameter:
123
    twisted_workaround: passed to `_GenericSetup()`
49
  Args:
50
    debug: Whether to enable verbose logging
51
    program: Program name
124 52

  
125 53
  """
126
  try:
127
    _GenericSetup(program,
128
                  os.path.join(constants.LOG_DIR, "errors"),
129
                  os.path.join(constants.LOG_DIR, "info"),
130
                  os.path.join(constants.LOG_DIR, "debug"),
131
                  twisted_workaround)
132
  except IOError:
133
    # The major reason to end up here is that we're being run as a
134
    # non-root user.  We might also get here if xen has not been
135
    # installed properly.  This is not the correct place to enforce
136
    # being run by root; nevertheless, here makes sense because here
137
    # is where we first notice it.
138
    if os.getuid() != 0:
139
      sys.stderr.write('This program must be run by the superuser.\n')
140
    else:
141
      sys.stderr.write('Unable to open log files.  Incomplete system?\n')
142

  
143
    sys.exit(2)
144

  
145
  global _debug
146
  _debug = debug
147

  
148

  
149
def _WriteEntry(log, txt):
150
  """
151
  Write a message to a given log.
152
  Splits multi-line messages up into a series of log writes, to
153
  keep consistent format on lines in file.
54
  fmt = "%(asctime)s " + program + ": %(message)s"
55
  formatter = logging.Formatter(fmt)
154 56

  
155
  Parameters:
156
    - log: the destination log
157
    - txt: the message
57
  info_file = _CreateFileHandler("info")
58
  info_file.setLevel(logging.INFO)
59
  info_file.setFormatter(formatter)
158 60

  
159
  """
160
  if log is None:
161
    sys.stderr.write("Logging system not initialized while processing"
162
                     " message:\n")
163
    sys.stderr.write("%s\n" % txt)
164
    return
61
  errors_file = _CreateFileHandler("errors")
62
  errors_file.setLevel(logging.ERROR)
63
  errors_file.setFormatter(formatter)
165 64

  
166
  lines = txt.split('\n')
65
  debug_file = _CreateFileHandler("debug")
66
  debug_file.setLevel(logging.DEBUG)
67
  debug_file.setFormatter(formatter)
167 68

  
168
  spaces = ' ' * len(_program) + '| '
69
  stderr_file = logging.StreamHandler()
70
  if debug:
71
    stderr_file.setLevel(logging.NOTSET)
72
  else:
73
    stderr_file.setLevel(logging.ERROR)
169 74

  
170
  lines = ([ _program + ': ' + lines[0] ] +
171
           map(lambda a: spaces + a, lines[1:]))
75
  root_logger = logging.getLogger("")
76
  root_logger.setLevel(logging.NOTSET)
77
  root_logger.addHandler(info_file)
78
  root_logger.addHandler(errors_file)
79
  root_logger.addHandler(debug_file)
80
  root_logger.addHandler(stderr_file)
172 81

  
173
  for line in lines:
174
    log.log(logging.INFO, line)
82

  
83
# Backwards compatibility
84
Error = logging.error
85
Info = logging.info
86
Debug = logging.debug
175 87

  
176 88

  
177 89
def ToStdout(txt):
......
194 106
  """
195 107
  sys.stderr.write(txt + '\n')
196 108
  sys.stderr.flush()
197

  
198

  
199
def Error(txt):
200
  """Write a message to our error log
201

  
202
  Parameters:
203
    - dbg: if true, the message will also be output to stderr
204
    - txt: the log message
205

  
206
  """
207
  _WriteEntry(_errlog, txt)
208
  sys.stderr.write(txt + '\n')
209

  
210

  
211
def Info(txt):
212
  """Write a message to our general messages log
213

  
214
  If the global debug flag is true, the log message will also be
215
  output to stderr.
216

  
217
  Parameters:
218
    - txt: the log message
219

  
220
  """
221
  _WriteEntry(_inflog, txt)
222
  if _debug:
223
    _WriteEntry(_stderr, txt)
224

  
225

  
226
def Debug(txt):
227
  """Write a message to the debug log
228

  
229
  If the global debug flag is true, the log message will also be
230
  output to stderr.
231

  
232
  Parameters:
233
    - txt: the log message
234

  
235
  """
236
  _WriteEntry(_dbglog, txt)
237
  if _debug:
238
    _WriteEntry(_stderr, txt)
b/tools/burnin
62 62

  
63 63
  def __init__(self):
64 64
    """Constructor."""
65
    logger.SetupLogging(debug=False, program="ganeti/burnin")
65
    logger.SetupLogging(program="ganeti/burnin", debug=False)
66 66
    self._feed_buf = StringIO()
67 67
    self.proc = mcpu.Processor(feedback=self.Feedback)
68 68
    self.nodes = []

Also available in: Unified diff