bin/pvl.irker-syslog
changeset 224 ed410776effd
parent 223 6842794c20e8
child 225 3c2d0dd42045
equal deleted inserted replaced
223:6842794c20e8 224:ed410776effd
     1 #!/usr/bin/env python
       
     2 
       
     3 """
       
     4     Syslog -> Irk
       
     5 """
       
     6 
       
     7 __version__ = '0.0'
       
     8 
       
     9 import pvl.args
       
    10 import pvl.syslog.args
       
    11 import pvl.syslog.rule
       
    12 import pvl.irk
       
    13 
       
    14 import logging, optparse
       
    15 
       
    16 log = logging.getLogger('main')
       
    17 
       
    18 def parse_options (argv) :
       
    19     """
       
    20         Parse command-line arguments.
       
    21     """
       
    22 
       
    23     prog = argv[0]
       
    24 
       
    25     parser = optparse.OptionParser(
       
    26             prog        = prog,
       
    27             usage       = '%prog: [options]',
       
    28             version     = __version__,
       
    29 
       
    30             # module docstring
       
    31             description = __doc__,
       
    32     )
       
    33     
       
    34     # options
       
    35     parser.add_option_group(pvl.args.parser(parser))
       
    36 
       
    37     # input
       
    38     parser.add_option_group(pvl.syslog.args.parser(parser))
       
    39     parser.add_option_group(pvl.syslog.rule.parser(parser))
       
    40     parser.add_option_group(pvl.irk.parser(parser, connect=None))
       
    41 
       
    42     parser.add_option('--irker-target', metavar='IRC',
       
    43             help="Irker target URL")
       
    44 
       
    45     # parse
       
    46     options, args = parser.parse_args(argv[1:])
       
    47     
       
    48     # apply
       
    49     pvl.args.apply(options, prog, rootok=False)
       
    50 
       
    51     return options, args
       
    52 
       
    53 def apply_irker (irker) :
       
    54     """
       
    55         Handle irker activity.
       
    56     """
       
    57 
       
    58     for msg in irker.irk :
       
    59         log.info("irk: %s", msg)
       
    60  
       
    61 def apply_syslog (options, syslog, rules, irker) :
       
    62     """
       
    63         Handle syslog activity.
       
    64     """
       
    65 
       
    66     # syslogs
       
    67     for item in syslog :
       
    68         match, rulepath, apply = rules.apply(item)
       
    69         
       
    70         log.debug("%s: %s: %s", item, rulepath, apply)
       
    71         
       
    72         target = apply.get('irk', options.irker_target)
       
    73         
       
    74         tag = '/'.join(str(rule) for rule in reversed(rulepath[:-1]))
       
    75         text = apply.get('text')
       
    76         
       
    77         log.info("%s: %s: %s", target, tag, text)
       
    78 
       
    79         if not text :
       
    80             # XXX: plain irk = ... in rule is broken, as it always applies, and skips any further rules
       
    81             continue
       
    82         
       
    83         if irker and target :
       
    84             irker[target]('[' + tag + '] ' + text)
       
    85         else :
       
    86             print tag, text
       
    87 
       
    88 def close_irker (irker) :
       
    89     """
       
    90         Shutdown irker before quitting.
       
    91 
       
    92         XXX: irker.close() to disconnect?
       
    93     """
       
    94     
       
    95     log.info("Shutting down IRK...")
       
    96 
       
    97     for target in list(irker) :
       
    98         log.warn("%s", target)
       
    99         del irker[target]
       
   100 
       
   101 def close_syslog (syslog) :
       
   102     """
       
   103         Shutdown syslog before quitting
       
   104     """
       
   105     
       
   106     # XXX: do all sources support close()?
       
   107     log.warn("%s", syslog)
       
   108     syslog.close()
       
   109 
       
   110 def main (argv) :
       
   111     options, args = parse_options(argv)
       
   112     
       
   113     # no args
       
   114     if args :
       
   115         log.error("Usage: pvl.irker-syslog [options]")
       
   116         return 2
       
   117     
       
   118     # setup
       
   119     log.info("Open syslog...")
       
   120     syslog = pvl.syslog.args.apply(options)
       
   121     
       
   122     log.info("Load rules...")
       
   123     rules = pvl.syslog.rule.apply(options)
       
   124 
       
   125     log.info("Connect IRK..")
       
   126     irker = pvl.irk.apply(options)
       
   127     
       
   128     if options.irker_target :
       
   129         # pre-join target
       
   130         irker[options.irker_target]
       
   131 
       
   132     log.info("Process syslog messages...")
       
   133 
       
   134     # customized mainloop that supports irker.irk
       
   135     while True :
       
   136         try :
       
   137             # TODO: seprate IrkError, to not confuse irk write vs syslog read eof
       
   138             apply_syslog(options, syslog, rules, irker)
       
   139 
       
   140         except EOFError as ex :
       
   141             log.error("syslog: EOF")
       
   142 
       
   143             close_irker(irker)
       
   144             
       
   145             # 0 is controlled exit
       
   146             return 0
       
   147 
       
   148         except pvl.irk.IrkError as ex :
       
   149             log.error("irker: %s", ex)
       
   150 
       
   151             # XXX: copy-pasta
       
   152             close_syslog(syslog)
       
   153             return 0
       
   154 
       
   155         # quit unless we have something to poll
       
   156         if not syslog.poll :
       
   157             break
       
   158 
       
   159         # is irk pollable?
       
   160         if irker.irk.recv :
       
   161             reading = (irker.irk, )
       
   162         else :
       
   163             reading = ()
       
   164         
       
   165         poll = syslog.select(syslog.poll, reading=reading) or () # timeout -> ()
       
   166         
       
   167         if irker.irk in poll :
       
   168             # irks?
       
   169             try :
       
   170                 apply_irker(irker)
       
   171 
       
   172             except EOFError :
       
   173                 log.error("irk: EOF")
       
   174                 
       
   175                 close_syslog(syslog)
       
   176 
       
   177                 # exit 0, so as to restart sooner
       
   178                 # XXX: maybe use a special exit code instead?
       
   179                 return 0
       
   180      
       
   181     # done
       
   182     log.info("Exiting...")
       
   183     return 0
       
   184 
       
   185 if __name__ == '__main__':
       
   186     import sys
       
   187 
       
   188     sys.exit(main(sys.argv))