#!/usr/bin/python # Copyright (C) 2004, Christof Meerwald # http://cmeerw.org # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 dated June, 1991. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA import string class MonitoringTarget: def __init__(self, service_name, host, interval): self._service_name = service_name self._host = host self._interval = interval self._domain = None self._check_fn = None self._args = None def get_service_name(self): return self._service_name def get_host(self): return self._host def get_interval(self): return self._interval def get_domain(self): return self._domain def set_domain(self, domain): self._domain = domain def get_check_fn(self): return self._check_fn def set_check_fn(self, check_fn): self._check_fn = check_fn def get_args(self): return self._args def set_args(self, args): self._args = args def get_indent(l): l = l.expandtabs() i = 0 while i < len(l) and l[i] in string.whitespace: i += 1 if i >= len(l): return (None, None) return (i, string.rstrip(l[i:])) def tokenize(l): state = 0 tokens = [''] for i in xrange(0, len(l)): c = l[i] if state != 2 and state != 3: if c == '"': tokens.append(c) state = 2 continue elif state == 2: if c == '"': tokens[-1] += c state = 0 elif c == '\\': state = 3 else: tokens[-1] += c continue elif state == 3: tokens[-1] += c continue if state == 0 or state == 1: if c in ',()': tokens.append(c) state = 1 continue elif c == '#': break if state == 0: if c in string.whitespace: state = 1 else: tokens[-1] += c elif state == 1: if not c in string.whitespace: tokens.append(c) state = 0 while len(tokens) and tokens[-1] == '': del tokens[-1] return tokens def parse_interval(interval): if len(interval) == 2: val = string.atoi(interval[0]) unit = interval[1].lower() if unit == 's' or unit == 'sec' or unit == 'second' or unit == 'seconds': unit = 1 elif unit == 'min' or unit == 'minute' or unit == 'minutes': unit = 60 elif unit == 'hour' or unit == 'hours': unit = 60*60 elif unit == 'day' or unit == 'days': unit = 24*60*60 else: raise 'Unknow unit "%s"' % (unit,) val *= unit else: val = string.atoi(interval[0]) return val def parse_args(args): if args == None: return None result = [] for arg in args: if arg[0] == '"' and arg[-1] == '"': result.append(arg[1:-1]) else: result.append(string.atoi(arg)) return tuple(result) def process_context(context): #print 'processing', context if context[-1][1] == []: return None settings = {} for indent, ctx in context: for keyword, value in ctx: if settings.has_key(keyword): raise 'Redefining %s not allowed' % (keyword,) settings[keyword] = value try: service = settings['service'][0] del settings['service'] except KeyError: raise 'required "service" keyword missing' try: server = settings['server'][0] del settings['server'] except KeyError: raise 'required "server" keyword missing' try: interval = settings['interval'] del settings['interval'] except KeyError: raise 'required "interval" keyword missing' interval = parse_interval(interval) entry = MonitoringTarget(service, server, interval) try: domain = settings['domain'][0] entry.set_domain(domain) del settings['domain'] except KeyError: domain = '' try: args = settings['args'] del settings['args'] except KeyError: try: args = settings['arg'] del settings['arg'] except KeyError: args = None args = parse_args(args) entry.set_args(args) return entry def parse(filename): conf = [] context = [(0, [])] indent = 0 fd = open(filename, 'r') l = fd.readline() while l: newind, l = get_indent(l) if newind != None: if newind > indent: indent = newind context.append((indent, [])) elif newind <= indent: entry = process_context(context) if entry != None: conf.append(entry) while len(context) and context[-1][0] > newind: del context[-1] if len(context): if context[-1][0] != newind: raise 'Indentation error' context[-1] = (newind, []) indent = newind tokens = tokenize(l) state = 0 keyword = None value = [] for t in tokens: if state == 0: keyword = t state = 1 elif state == 1: if t == ',': context[-1][1].append((keyword, value)) state = 0 keyword = None value = [] elif t == '(': state = 2 else: value.append(t) elif state == 2: if t == ')': state == 1 elif t != ',': value.append(t) if keyword != None: context[-1][1].append((keyword, value)) l = fd.readline() entry = process_context(context) if entry != None: conf.append(entry) return conf if __name__ == '__main__': conf = parse('downtime.conf') for entry in conf: print entry._service_name, entry._domain, entry._host, entry._interval, entry._args