~awstools-dev/ubuntu/maverick/ec2-ami-tools/maverick

« back to all changes in this revision

Viewing changes to lib/ec2/amitools/util.rb

  • Committer: Bazaar Package Importer
  • Author(s): Chuck Short
  • Date: 2008-10-14 08:35:25 UTC
  • Revision ID: james.westby@ubuntu.com-20081014083525-c0n69wr7r7aqfb8w
Tags: 1.3-26357-0ubuntu2
* New upstream version.
* Update the debian copyright file.
* Added quilt patch system to make it easier to maintain. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright 2008 Amazon.com, Inc. or its affiliates.  All Rights
 
2
# Reserved.  Licensed under the Amazon Software License (the
 
3
# "License").  You may not use this file except in compliance with the
 
4
# License. A copy of the License is located at
 
5
# http://aws.amazon.com/asl or in the "license" file accompanying this
 
6
# file.  This file is distributed on an "AS IS" BASIS, WITHOUT
 
7
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
 
8
# the License for the specific language governing permissions and
 
9
# limitations under the License.
 
10
 
 
11
require 'monitor'
 
12
require 'thread'
 
13
require 'syslog'
 
14
 
 
15
##
 
16
# generate a unique identifier used for filenames
 
17
#
 
18
def gen_ident()
 
19
  (0..19).inject("") {|ident, n| ident+(?A + Kernel.rand(26)).chr}
 
20
end
 
21
 
 
22
#------------------------------------------------------------------------------#
 
23
 
 
24
# A thread local buffer manager. Provide's each thread with a single
 
25
# pre-allocated IO buffer. IMPORTANT: as these buffers are indexed in a 
 
26
# hashtable they will not be freed until the application closes. If a thread
 
27
# needs to free the memory its buffer is using, it must call
 
28
# <code>delete_buffer</code> and ensure it has no references to the buffer.
 
29
class ThreadLocalBuffer
 
30
  POWER = 12      # Log SIZE base 2
 
31
  SIZE = 2**POWER # Size of the buffer.
 
32
  @@buffers = {}
 
33
  @@buffers.extend( MonitorMixin )
 
34
  
 
35
  #----------------------------------------------------------------------------#
 
36
  
 
37
  # Return the thread's buffer.
 
38
  def ThreadLocalBuffer.get_buffer
 
39
    @@buffers.synchronize do
 
40
      @@buffers[Thread.current] = new_buffer unless @@buffers.has_key?( Thread.current )
 
41
      @@buffers[Thread.current]
 
42
    end
 
43
  end
 
44
  
 
45
  #----------------------------------------------------------------------------#
 
46
  
 
47
  # Delete the threads buffer.
 
48
  def delete_buffer buffer
 
49
    @@buffers.delete buffer
 
50
  end
 
51
  
 
52
  #----------------------------------------------------------------------------#
 
53
  
 
54
  def ThreadLocalBuffer.new_buffer
 
55
    buffer = String.new
 
56
    buffer = Format::hex2bin( '00' )
 
57
    POWER.times { buffer << buffer }
 
58
    buffer
 
59
  end
 
60
  
 
61
  private_class_method :new_buffer
 
62
end
 
63
 
 
64
#------------------------------------------------------------------------------#
 
65
 
 
66
##
 
67
# Base class for XML-RPC structures. Stores key and values pairs. Key names are
 
68
# mapped to method names by converting '-' to '_' characters.
 
69
#
 
70
class XMLRPCStruct < Hash
 
71
  # _members_ A list of the structure's key names or nil if any key names
 
72
  # are allowed.
 
73
  def initialize members
 
74
    unless members.kind_of? Array or members.nil?
 
75
      raise ArgumentError.new( "invalid members argument" )
 
76
    end
 
77
    @members = members
 
78
  end
 
79
  
 
80
  # Provide direct access to individual instance elements by methods named after
 
81
  # the element's key.
 
82
  def method_missing( method_symbol, argument=nil )
 
83
    # Here kid, play with this loaded gun...
 
84
    method = method_symbol.to_s
 
85
    
 
86
    # Determine if setter or getter call and remove '=' if setter.
 
87
    setter = /[\S]+=/.match(method)
 
88
    member = (setter ? method.slice(0, method.size - 1) : method)
 
89
    
 
90
    # Map method name to member name.
 
91
    member = member.gsub('_', '-')
 
92
   
 
93
    # If valid attribute set or get accordingly. If the member list is nil then
 
94
    # any members are allowed.
 
95
    if @members.nil? or @members.include?( member )
 
96
      if setter
 
97
        raise ArgumentError, "value for key #{member} may not be nil" if argument.nil?
 
98
        self[member] = argument
 
99
      else
 
100
        self[member]
 
101
      end
 
102
    else
 
103
      raise NoMethodError.new( method )
 
104
    end
 
105
  end
 
106
end
 
107
 
 
108
#------------------------------------------------------------------------------#
 
109
 
 
110
##
 
111
# Note to self - use log4r next time ;)
 
112
#
 
113
class Log
 
114
  #----------------------------------------------------------------------------#
 
115
 
 
116
  # @deprecated use Priority instead
 
117
  class Verbosity
 
118
    private_class_method :new
 
119
    @@levels = Hash.new
 
120
    
 
121
    def initialize value
 
122
      @value = value
 
123
      @@levels[value] = self
 
124
    end
 
125
 
 
126
    V0 = new 0  # Unhandled exceptions only.
 
127
    V1 = new 1  # As for 0 but with error messages.
 
128
    V2 = new 2  # As for 1 but with informational messages.
 
129
    V3 = new 3  # As for 2 but with XML-RPC logging.
 
130
    V4 = new 4  # As for 3 but with Xen logging.
 
131
    V5 = new 5  # As for 4 but with debugging messages.
 
132
    
 
133
    attr_accessor :value
 
134
        
 
135
    def >= operand
 
136
      @value >= operand.value
 
137
    end
 
138
    
 
139
    def Verbosity.from_string s
 
140
      level = s.to_i
 
141
      if not @@levels[level]
 
142
        raise ArgumentError.new("invalid logging verbosity level #{level}")
 
143
      else
 
144
        @@levels[level]
 
145
      end
 
146
    end
 
147
    
 
148
    def to_priority
 
149
      case self
 
150
      when V0
 
151
        return Priority::ALERT
 
152
      when V1
 
153
        return Priority::ERR
 
154
      when V2
 
155
        return Priority::WARNING
 
156
      when V3
 
157
        return Priority::NOTICE
 
158
      when V4
 
159
        return Priority::INFO
 
160
      else
 
161
        return Priority::DEBUG
 
162
      end
 
163
    end
 
164
  end
 
165
 
 
166
  #----------------------------------------------------------------------------#
 
167
 
 
168
  class Facility
 
169
    private_class_method :new
 
170
 
 
171
    def initialize(name)
 
172
      @name = name
 
173
      @value = (name == "AES")?(12<<3):eval("Syslog::LOG_#{name}")
 
174
    end
 
175
 
 
176
    AUTHPRIV  = new "AUTHPRIV"
 
177
    CRON      = new "CRON"
 
178
    DAEMON    = new "DAEMON"
 
179
    FTP       = new "FTP"
 
180
    KERN      = new "KERN"
 
181
    LOCAL0    = new "LOCAL0"
 
182
    LOCAL1    = new "LOCAL1"
 
183
    LOCAL2    = new "LOCAL2"
 
184
    LOCAL3    = new "LOCAL3"
 
185
    LOCAL4    = new "LOCAL4"
 
186
    LOCAL5    = new "LOCAL5"
 
187
    LOCAL6    = new "LOCAL6"
 
188
    LOCAL7    = new "LOCAL7"
 
189
    LPR       = new "LPR"
 
190
    MAIL      = new "MAIL"
 
191
    NEWS      = new "NEWS"
 
192
    SYSLOG    = new "SYSLOG"
 
193
    USER      = new "USER"
 
194
    UUCP      = new "UUCP"
 
195
    AES       = new "AES"
 
196
 
 
197
    attr_accessor :value
 
198
    attr_accessor :name
 
199
    
 
200
    def to_s
 
201
      "Facility[LOG_#{@name}]"
 
202
    end
 
203
  end
 
204
 
 
205
  #----------------------------------------------------------------------------#
 
206
 
 
207
  class Priority
 
208
    include Comparable
 
209
    
 
210
    private_class_method :new
 
211
 
 
212
    def initialize(name)
 
213
      @name = name
 
214
      @value = eval("Syslog::LOG_#{name}")
 
215
    end
 
216
    
 
217
    EMERG   = new "EMERG"     # 0
 
218
    ALERT   = new "ALERT"     # 1
 
219
    CRIT    = new "CRIT"      # 2
 
220
    ERR     = new "ERR"       # 3
 
221
    WARNING = new "WARNING"   # 4
 
222
    NOTICE  = new "NOTICE"    # 5
 
223
    INFO    = new "INFO"      # 6
 
224
    DEBUG   = new "DEBUG"     # 7
 
225
 
 
226
    attr_accessor :value
 
227
    attr_accessor :name
 
228
 
 
229
    def <=>(priority)
 
230
      @value <=> priority.value
 
231
    end
 
232
    
 
233
    def to_s
 
234
      "Priority[LOG_#{@name}]"
 
235
    end
 
236
  end
 
237
 
 
238
  #----------------------------------------------------------------------------#
 
239
 
 
240
  @@facility = Facility::AES
 
241
  @@priority = Priority::INFO
 
242
  @@identity = nil
 
243
  @@streams_mutex = Mutex.new
 
244
  @@streams = []
 
245
 
 
246
  #----------------------------------------------------------------------------#
 
247
 
 
248
  ##
 
249
  # Set the verbosity of the logging.
 
250
  # @deprecated use set_priority
 
251
  def Log.set_verbosity(verbosity)
 
252
    set_priority(verbosity.to_priority)
 
253
  end
 
254
  
 
255
  #----------------------------------------------------------------------------#
 
256
 
 
257
  ##
 
258
  # Set the IO instance to log to.
 
259
  # @deprecated use add_stream
 
260
  def Log.set_io(io)
 
261
    add_stream(io)
 
262
  end
 
263
 
 
264
  #----------------------------------------------------------------------------#
 
265
 
 
266
  ##
 
267
  # Log a debug message.
 
268
  def Log.debug(msg=nil)
 
269
    if block_given?
 
270
      write(Priority::DEBUG) {yield}
 
271
    else
 
272
      write(Priority::DEBUG) {msg}
 
273
    end
 
274
  end
 
275
 
 
276
  #----------------------------------------------------------------------------#
 
277
 
 
278
  ##
 
279
  # Log a warning message.
 
280
  def Log.warn(msg=nil)
 
281
    if block_given?
 
282
      write(Priority::WARNING) {yield}
 
283
    else
 
284
      write(Priority::WARNING) {msg}
 
285
    end
 
286
  end
 
287
 
 
288
  #----------------------------------------------------------------------------#
 
289
 
 
290
  ##
 
291
  # Log an informational message.
 
292
  def Log.info(msg=nil)
 
293
    if block_given?
 
294
      write(Priority::INFO) {yield}
 
295
    else
 
296
      write(Priority::INFO) {msg}
 
297
    end
 
298
  end
 
299
 
 
300
  #----------------------------------------------------------------------------#
 
301
 
 
302
  ##
 
303
  # Log an error message.
 
304
  def Log.err(msg=nil)
 
305
    if block_given?
 
306
      write(Priority::ERR) {yield}
 
307
    else
 
308
      write(Priority::ERR) {msg}
 
309
    end
 
310
  end
 
311
 
 
312
  #----------------------------------------------------------------------------#
 
313
 
 
314
  ##
 
315
  # Log a warning message.
 
316
  def Log.warn(msg=nil)
 
317
    if block_given?
 
318
      write(Priority::WARNING) {yield}
 
319
    else
 
320
      write(Priority::WARNING) {msg}
 
321
    end
 
322
  end
 
323
 
 
324
  #----------------------------------------------------------------------------#
 
325
 
 
326
  ##
 
327
  # Log an unhandled exception.
 
328
  # @deprecated use write
 
329
  def Log.exception(e)
 
330
    if block_given?
 
331
      write(Priority::ALERT) {yield}
 
332
    else
 
333
      write(Priority::ALERT) {Log.exception_str(e)}
 
334
    end
 
335
  end
 
336
 
 
337
  #----------------------------------------------------------------------------#
 
338
 
 
339
  ##
 
340
  # Log an informational message.
 
341
  # @deprecated use write
 
342
  def Log.msg(msg)
 
343
    write(Verbosity::V2.to_priority) {msg}
 
344
  end
 
345
 
 
346
  #----------------------------------------------------------------------------#
 
347
 
 
348
  # @deprecated use write
 
349
  def Log.xen_msg(msg)
 
350
    write(Verbosity::V4.to_priority) {msg}
 
351
  end
 
352
 
 
353
  #----------------------------------------------------------------------------#
 
354
 
 
355
  # @deprecated use write
 
356
  def Log.xmlrpcmethod_call(name, *paramstructs)
 
357
    write(Verbosity::V3.to_priority) {Log.xmlrpcmethod_call_str(name, paramstructs)}
 
358
  end
 
359
 
 
360
  #----------------------------------------------------------------------------#
 
361
 
 
362
  # @deprecated use write
 
363
  def Log.xmlrpcmethod_return(name, value)
 
364
    write(Verbosity::V3.to_priority) {Log.xmlrpcmethod_return_str(name, value)}
 
365
  end
 
366
  
 
367
  #----------------------------------------------------------------------------#
 
368
 
 
369
  # @deprecated use write
 
370
  def Log.xmlrpcfault(xmlrpc_method, fault)
 
371
    write(Verbosity::V3.to_priority) {Log.xmlrpcfault_str(xmlrpc_method, fault)}
 
372
  end
 
373
  
 
374
  #----------------------------------------------------------------------------#
 
375
 
 
376
  ##
 
377
  # Add an additional stream (like a file, or $stdout) to send
 
378
  # log output to.
 
379
  #
 
380
  def Log.add_stream(stream)
 
381
    @@streams_mutex.synchronize do
 
382
      @@streams.push(stream)
 
383
      @@streams.delete_if { |io| io.closed? }
 
384
    end
 
385
  end
 
386
 
 
387
  #----------------------------------------------------------------------------#
 
388
 
 
389
  def Log.exception_str(e)
 
390
    e.message + "\n" + e.backtrace.to_s
 
391
  end
 
392
 
 
393
  #----------------------------------------------------------------------------#
 
394
 
 
395
  def Log.xmlrpcfault_str(xmlrpc_method, fault)
 
396
    "XML-RPC method fault\nmethod: #{xmlrpc_method}\nfault code: #{fault.faultCode}\nfault string: #{fault.faultString}"
 
397
  end
 
398
  
 
399
  #----------------------------------------------------------------------------#
 
400
 
 
401
  def Log.xmlrpcmethod_call_str(name, *paramstructs)
 
402
    msg = "name: #{name}\n"
 
403
    paramstructs.each_index { |i| msg += "parameter #{i + 1}: #{paramstructs[i].inspect}\n" }
 
404
    "XML-RPC method call\n#{msg}"
 
405
  end
 
406
 
 
407
  #----------------------------------------------------------------------------#
 
408
 
 
409
  def Log.xmlrpcmethod_return_str(name, value)
 
410
    msg = "name: #{name}\nvalue: #{value.inspect}"
 
411
    "XML-RPC method return\n#{msg}"
 
412
  end
 
413
  
 
414
  #----------------------------------------------------------------------------#
 
415
 
 
416
  ##
 
417
  # Set the minimum priority of the logging. Messages logged with a
 
418
  # lower (less urgent) priority will be ignored.
 
419
  #
 
420
  def Log.set_priority(priority)
 
421
    @@priority = priority
 
422
  end
 
423
 
 
424
  #----------------------------------------------------------------------------#
 
425
 
 
426
  ##
 
427
  # Set the facility to log messages against when no explicit facility is
 
428
  # provided.
 
429
  #
 
430
  def Log.set_facility(facility)
 
431
    @@facility = facility
 
432
  end
 
433
 
 
434
  #----------------------------------------------------------------------------#
 
435
 
 
436
  ##
 
437
  # Set the identity to log messages against when no explicit identity is
 
438
  # provided. If no identity is provided (either using this method or explicitly
 
439
  # when logging) the system will use the application name as the identity.
 
440
  #
 
441
  def Log.set_identity(identity)
 
442
    @@identity = identity
 
443
  end
 
444
 
 
445
  #----------------------------------------------------------------------------#
 
446
 
 
447
  SYSLOG_OPTS = (Syslog::LOG_PID | Syslog::LOG_CONS)
 
448
 
 
449
  #----------------------------------------------------------------------------#
 
450
  
 
451
  def Log.time
 
452
    Time.new.to_s
 
453
  end
 
454
  
 
455
  private_class_method :time
 
456
 
 
457
  #----------------------------------------------------------------------------#
 
458
  
 
459
  def Log.write(priority=Priority::DEBUG, facility=nil, identity=nil)
 
460
    # If the priority of this message is below the defined priority
 
461
    # for logging then we don't want to do this at all. NOTE: Priorities
 
462
    # for syslog are defined in ascending order (so lower priorities
 
463
    # are more urgent).
 
464
    return unless priority <= @@priority
 
465
    return unless block_given?
 
466
    
 
467
    begin
 
468
      facility = (facility == nil)?(@@facility):(facility)
 
469
      fac_int = facility.value
 
470
      ident = (identity == nil)?(@@identity):(identity)
 
471
      msg = yield
 
472
      Syslog.open(ident, SYSLOG_OPTS, fac_int) do |log|
 
473
        log.log(priority.value, '%s', msg)
 
474
      end
 
475
 
 
476
      # Now pass the message onto each registered stream
 
477
      # Access to our list of streams is synchronized so that it can be changed
 
478
      # at runtime.
 
479
      @@streams_mutex.synchronize do
 
480
        @@streams.each do |stream|
 
481
          begin
 
482
            stream.puts "#{time}: #{ident}: #{priority.value}: #{msg}"
 
483
            stream.flush
 
484
          rescue Exception => e
 
485
            $stderr.puts 'error writing to stream [#{stream}], logging to stdout'
 
486
          end
 
487
        end
 
488
      end
 
489
    rescue Exception => e
 
490
      $stderr.puts "error loggin to syslog, logging to stdout: #{e}"
 
491
      if block_given?
 
492
        begin
 
493
          $stdout.puts "Msg: #{msg}"
 
494
        rescue Exception => e
 
495
          $stderr.puts "Block raised error: #{e}"
 
496
        end
 
497
          end
 
498
    end
 
499
  end
 
500
end
 
501
 
 
502
#------------------------------------------------------------------------------#
 
503
 
 
504
##
 
505
# Utilities used for logging (in order for compatability between AESLogger and the previous Log class)
 
506
 
 
507
class LogUtils
 
508
 
 
509
##
 
510
# Prevent instantiation
 
511
private_class_method :new
 
512
 
 
513
 def LogUtils.exception_str(e)
 
514
   e.message + "\n" + e.backtrace.to_s
 
515
 end
 
516
 
 
517
 def LogUtils.xmlrpcfault_str(xmlrpc_method, fault)
 
518
   "XML-RPC method fault : method: #{xmlrpc_method} : fault code: #{fault.faultCode} : fault string: #{fault.faultString}"
 
519
 end
 
520
  
 
521
 def LogUtils.xmlrpcmethod_call_str(name, *paramstructs)
 
522
   msg = "name: #{name} : "
 
523
   paramstructs.each_index { |i| msg += "parameter #{i + 1}: #{paramstructs[i].inspect} : " }
 
524
   "XML-RPC method call\n#{msg}"
 
525
 end
 
526
 
 
527
 def LogUtils.xmlrpcmethod_return_str(name, value)
 
528
   msg = "name: #{name} : value: #{value.inspect}"
 
529
    "XML-RPC method return : #{msg}"
 
530
 end 
 
531
end
 
532