Statistics
| Branch: | Tag: | Revision:

root / lib / logger.py @ 17dfc522

History | View | Annotate | Download (5.8 kB)

1
#
2
#
3

    
4
# Copyright (C) 2006, 2007 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

    
21

    
22
"""Logging for Ganeti
23

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

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

    
30
import sys
31
import logging
32
import os, os.path
33

    
34
from ganeti import constants
35

    
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

    
79

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

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'):
113
  """Setup logging for ganeti
114

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

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

122
  Parameter:
123
    twisted_workaround: passed to `_GenericSetup()`
124

125
  """
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.
154

155
  Parameters:
156
    - log: the destination log
157
    - txt: the message
158

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
165

    
166
  lines = txt.split('\n')
167

    
168
  spaces = ' ' * len(_program) + '| '
169

    
170
  lines = ([ _program + ': ' + lines[0] ] +
171
           map(lambda a: spaces + a, lines[1:]))
172

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

    
176

    
177
def ToStdout(txt):
178
  """Write a message to stdout only, bypassing the logging system
179

180
  Parameters:
181
    - txt: the message
182

183
  """
184
  sys.stdout.write(txt + '\n')
185
  sys.stdout.flush()
186

    
187

    
188
def ToStderr(txt):
189
  """Write a message to stderr only, bypassing the logging system
190

191
  Parameters:
192
    - txt: the message
193

194
  """
195
  sys.stderr.write(txt + '\n')
196
  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)