diff --git a/lib/config/hostgroups.py b/lib/config/hostgroups.py index 87d03cb..6614a91 100644 --- a/lib/config/hostgroups.py +++ b/lib/config/hostgroups.py @@ -1,13 +1,37 @@ +class HostGroupException(Exception): + def __init__(self, msg): + self.msg = msg + + def __str__(self): + return repr(self.msg) + +class HostGroupMissingArgumentException(HostGroupException): + def __init__(self, missingArgument, hostgroupName): + super(HostGroupMissingArgumentException, self).__init__("no " + missingArgument + " defined for Hostgroup " + hostgroupName) + class HostGroup: - def __init__(self, name, members="", hosts="", services="", threshold="", parent="", comment=""): + def __init__(self, name, **kwargs): self.name = name - self.interval = 0 - self.members = members - self.hosts = hosts - self.services = services - self.threshold = threshold - self.parent = parent - self.comment = comment + + tmp = "members" + if not tmp in kwargs: + raise HostGroupMissingArgumentException(tmp, name) + self.members = kwargs[tmp] + + tmp = "hosts" + if not tmp in kwargs: + raise HostGroupMissingArgumentException(tmp, name) + self.hosts = kwargs[tmp] + + tmp = "services" + if not tmp in kwargs: + raise HostGroupMissingArgumentException(tmp, name) + self.services = kwargs[tmp] + + + def get_members(self): + return self.members + def __str__(self): ret = "HostGroup: " + self.name + " threshold: " + str(self.threshold) + " parent: " + self.parent + "\n" diff --git a/lib/config/layouts.py b/lib/config/layouts.py index d8a6822..df47d30 100644 --- a/lib/config/layouts.py +++ b/lib/config/layouts.py @@ -1,8 +1,28 @@ +class LayouException(Exception): + def __init__(self, msg): + self.msg = msg + + def __str__(self): + return repr(self.msg) + class Layout: - def __init__(self, myLayout): - self.name = myLayout - self.enabled = False - self.hostgroups = [] + def __init__(self, name, enabled = False , hostgroups=None): + self._name = name + self._enabled = enabled + + if hostgroups is None or len(hostgroups) <= 0: + raise Exception("Layout: " + name + " without hostgroups is useless") + else: + self._hostgroups = hostgroups + + def get_name(self): + return self._name + + def is_enabled(self): + return self._enabled + + def get_hostgroups(self): + return self._hostgroups def __str__(self): ret = "Layout: 'Name:" + str(self.name) + "', 'Enabled: " + str(self.enabled) + " " @@ -38,6 +58,7 @@ class LayoutList: else: # TODO: replace next line with new logging #logger.logWarningConfig(file="hostgroups", missing=group) + pass self.layouts.append(l) def __str__(self): diff --git a/lib/config/parser.py b/lib/config/parser.py new file mode 100644 index 0000000..72e893f --- /dev/null +++ b/lib/config/parser.py @@ -0,0 +1,153 @@ +''' +Created on Jun 9, 2013 + +@author: Rafael Timmerberg(raffn1+linspector@gmail.com) +''' + +import os, os.path as path +import json +from layouts import Layout +from hostgroups import HostGroup + +class ConfigurationException(Exception): + def __init__(self, msg, log): + log.e(msg) + self.msg = msg + + def __str__(self): + return repr(self.msg) + + +KEY_LAYOUTS = "layouts" +KEY_HOSTGROUPS = "hostgroups" +KEY_MEMBERS = "members" +KEY_PERIODS = "periods" +KEY_CORE = "core" + + + +class ConfigParser: + def __init__(self, log): + ''' + initializes a new ConfigParser Object + + params: + log: pre configured logger Object to post messages while parsing" + ''' + self.log = log + self.hostgroups = {} + self.members = {} + self.periods = {} + + + def _read_json_config(self, configFilename): + ''' + reads the config File and returns a dictionary, while lowering the first keys + + params: + configFilename: the path under which the configuration file should be found + ''' + if not path.isfile(configFilename): + msg = "config file not found at " + str(configFilename) + raise ConfigurationException(msg, self.log) + + self.configfilename = configFilename + + with open(configFilename) as cfgFile: + config = cfgFile.read() + + self.log.i("reading Config: " + configFilename) + return json.loads(config) + + + + def _get_as_list(self, configValue): + ''' + In some cases the config permits to define a list or a single value. + + returns the value as list + ''' + return configValue if isinstance(configValue, list) else [configValue] + + + def create_layouts_from_json(self, jsonLayouts): + layouts = [] + for lName, lValues in jsonLayouts.items(): + try: + layout = Layout(lName, **lValues) + layouts.append(layout) + except Exception: + self.log.w("ignoring Layout " + lName + "! reason:") + self.log.w(str(Exception)) + return layouts + + + def create_hostgroups_from_json(self, jsonHostGroups): + ''' + creates Hostgroups from the jsonConfig + ''' + hostgroups = [] + for hgName, hgValues in jsonHostGroups.items(): + try: + hostgroup = HostGroup(hgName, **hgValues) + hostgroups.append(hostgroup) + except Exception: + self.log.w("ignoring hostgroup: " + hgName + "!") + self.log.w("reason: " + str(Exception)) + return hostgroups + + + + + def parse_config(self, configFilename): + ''' + parses the json configuration and returns a list of layouts, + which contains all nessesary information of the config file. + Parsing will be done in 3 steps: + 1. get raw Config Objects by just passing the values defined inside the config + 2. replace references by objects + 3. do sanity checks + + params: + configFilename: indicates which configuration file to parse + ''' + + self.jsonDict = self._read_json_config(configFilename) + + jsonLayouts = self.jsonDict[KEY_LAYOUTS] + layouts = self.create_layouts_from_json(jsonLayouts) + + hostgroupNames = set() + for layout in layouts: + for hgName in layout.get_hostgroups(): + hostgroupNames.add(hgName) + + + jsonHostgroups = {} + for hgName in hostgroupNames: + if not hgName in self.jsonDict[KEY_HOSTGROUPS]: + self.log.w("Hostgroup " + hgName + " not found!") + for layout in layouts: + if hgName in layout.hostgroups: + del layout.hostgroups[layout.hostgroups.index(hgName)] + jsonHostgroups[hgName] = self.jsonDict[KEY_HOSTGROUPS][hgName] + + self.hostgroups = self.create_hostgroups_from_json(jsonHostgroups) + + memberNames = set() + for hostgroup in self.hostgroups: + for memberName in layout.get_mebers(): + memberNames.add(memberName) + + + jsonMembernames = {} + for memberName in hostgroupNames: + if not memberName in self.jsonDict[KEY_MEMBERS]: + self.log.w("Member " + memberName + " not found!") + for hostgroup in self.hostgroups: + if memberName in hostgroup.members: + del hostgroup.members[hostgroup.members.index(hgName)] + jsonHostgroups[hgName] = self.jsonDict[KEY_HOSTGROUPS][hgName] + + self.hostgroups = self.create_hostgroups_from_json(jsonHostgroups) + \ No newline at end of file diff --git a/linspector b/linspector index 4a9d4f9..6009a4b 100755 --- a/linspector +++ b/linspector @@ -9,7 +9,7 @@ import logging import subprocess as sp from lib.core.job import JobInfo from lib.core.logger import Logger -from lib.config.config import Config +from lib.config.parser import ConfigParser from apscheduler.scheduler import Scheduler @@ -58,19 +58,9 @@ def main(): scheduler.start() log.i("starting linspector: reading config... (" + args.config + ")") - config = Config(args.config, log) + config_parser = ConfigParser(log) + config = config_parser.parse_config(args.config) log.d("parsed config: " + str(config)) - for hg in config.hostgroups: - - for hostGroupService in hg.services: - log.d(hostGroupService) - jobInfo = JobInfo(hg.name, hg.members, hg.hosts, hostGroupService.services, hg.threshold, hg.parent) - jobInfo.setLogger(log) - for period in hostGroupService.periods: - log.d(period) - jobs.append(period.createJob(scheduler, jobInfo, handleJob)) - for job in jobs: - log.d(str(job)) while True: time.sleep(10)