From 3642e67013e05e526870d8ab504f9c283a3dd5ba Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 25 Oct 2013 04:22:09 +0200 Subject: [PATCH] added main thread for background scheduling; version set to 0.11 --- bin/jsonrpc-client | 4 +-- bin/linspector | 59 ++++++++++++++------------------- linspector/frontends/lish.py | 4 ++- linspector/linspector.py | 64 ++++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 38 deletions(-) create mode 100644 linspector/linspector.py diff --git a/bin/jsonrpc-client b/bin/jsonrpc-client index e6479ce..131a421 100755 --- a/bin/jsonrpc-client +++ b/bin/jsonrpc-client @@ -25,7 +25,7 @@ from bjsonrpc import connect c = connect() -#print c.call.get_job_list() +print c.call.get_job_list() #print c.call.get_job_info_by_id("3950d44b") @@ -39,4 +39,4 @@ c = connect() #print c.call.get_job_list_by_host("d") -#print c.call.get_job_count_by_host("d") \ No newline at end of file +#print c.call.get_job_count_by_host("d") diff --git a/bin/linspector b/bin/linspector index ead64b0..fe96394 100755 --- a/bin/linspector +++ b/bin/linspector @@ -1,7 +1,7 @@ #!/usr/bin/python2.7 -tt """ -Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" +Copyright (c) 2011-2013 by Johannes Findeisen and Rafael Timmerberg This file is part of Linspector (http://linspector.org). @@ -20,7 +20,7 @@ along with this program. If not, see . """ -__version__ = "0.10" +__version__ = "0.11" __default_config__ = "./examples/minimal.json" import argparse @@ -28,11 +28,12 @@ import logging import logging.handlers import os import os.path as path +import Queue import time +from linspector.linspector import Linspector from linspector.core.interface import LinspectorInterface from linspector.config.parser import FullConfigParser -from linspector.core.job import Job from linspector.core.scheduler import Scheduler from linspector.backends.jsonrpc import JsonrpcBackend from linspector.frontends.lish import LishFrontend @@ -67,13 +68,14 @@ def parse_args(): def setup_logging(logfile="./log/linspector.log", logLevel=logging.ERROR, logfileLevel=logging.DEBUG): + #TODO: catch all log messages (apscheduler etc.); make logging more generic to support libraries logging logfile = path.expanduser(logfile) if not path.exists(path.dirname(logfile)): os.makedirs(path.dirname(logfile)) - logging.basicConfig(level=logging.WARNING) + #logging.basicConfig(level=logging.WARNING) log = logging.getLogger(__name__) - #log.setLevel(logging.DEBUG) + log.setLevel(logging.DEBUG) consoleHandler = logging.StreamHandler() consoleHandler.setLevel(logLevel) @@ -93,13 +95,9 @@ def setup_logging(logfile="./log/linspector.log", logLevel=logging.ERROR, logfil return log -def handle_job(jobInfo): - jobInfo.handle_call() - - def main(): args = parse_args() - #TODO: catch all log messages (apscheduler etc.); make logging more generic to support libraries logging + log = setup_logging(args.logfile, args.loglevel) log.info("parsed arguments") @@ -108,33 +106,20 @@ def main(): linConf, core = configParser.parse_config(args.config) scheduler = Scheduler() - - ''' - The next lines should go over to a thread class into background (thread queue) - ''' scheduler.start() - jobs = [] - for layout in linConf.get_enabled_layouts(): - for hostgroup in layout.get_hostgroups(): - #time.sleep(1) - for service in hostgroup.get_services(): - for host in hostgroup.get_hosts(): - #time.sleep(0.5) - for period in service.get_periods(): - #time.sleep(0.1) - job = Job(service, host, hostgroup.get_members(), hostgroup.get_processors(), core, hostgroup) - schedulerJob = period.createJob(scheduler, job, handle_job) - if schedulerJob is not None: - job.set_job(schedulerJob) - job.set_logger(log) - jobs.append(job) + q = Queue.Queue() + linspector = Linspector(linConf, core, scheduler, log, q) + linspector.daemon = True + linspector.start() - ''' - the next stuff could stay here but needs access to the "jobs" list from above - ''' + while True: + if q.qsize() < 1: + time.sleep(1) + else: + break - interface = LinspectorInterface(jobs, scheduler, linConf) + interface = LinspectorInterface(q.get(), scheduler, linConf) if "jsonrpc_backend" in core and core["jsonrpc_backend"]: jsonrpc = JsonrpcBackend(interface, core) @@ -144,8 +129,12 @@ def main(): LishFrontend(interface) log.debug("shutting down scheduler") - #TODO: make "wait" configurable because when it is True a shutdown can take long time - scheduler.shutdown(wait=False) + + shutdown_wait = True + if "shutdown_wait" in core: + shutdown_wait = core["shutdown_wait"] + + scheduler.shutdown(wait=shutdown_wait) logging.shutdown() diff --git a/linspector/frontends/lish.py b/linspector/frontends/lish.py index f334f04..e549323 100644 --- a/linspector/frontends/lish.py +++ b/linspector/frontends/lish.py @@ -4,7 +4,7 @@ Lish is the Linspector Interactive Shell. This will become a commandline interface to Linspector. Think of a network switch or router like those from Cisco. -Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" +Copyright (c) 2011-2013 by Johannes Findeisen and Rafael Timmerberg This file is part of Linspector (http://linspector.org). @@ -175,6 +175,8 @@ class LishCommander(Exit): PURPLE + " Host" + END + ": " + job_dict["Host"] + \ PURPLE + " Service" + END + ": " + job_dict["Service"] + \ PURPLE + " Next run" + END + ": " + job_dict["Next run"] + \ + PURPLE + " Runs" + END + ": " + job_dict["Runs"] + \ + PURPLE + " Fails" + END + ": " + job_dict["Fails"] + \ PURPLE + " Enabled" + END + ": " + job_dict["Enabled"] elif text == "count": print GREEN + "Job Count" + END + ":\t" + str(self.interface.get_job_count()) diff --git a/linspector/linspector.py b/linspector/linspector.py new file mode 100644 index 0000000..7650c7a --- /dev/null +++ b/linspector/linspector.py @@ -0,0 +1,64 @@ +""" +The Linspector main thread. Here all scheduling is done so backends and +frontends can start before all jobs are scheduled. + +Copyright (c) 2011-2013 by Johannes Findeisen and Rafael Timmerberg + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +""" + +import threading +import time + +from core.job import Job + + +def handle_job(jobInfo): + jobInfo.handle_call() + + +class Linspector(threading.Thread): + def __init__(self, linConf, core, scheduler, log, q): + self.linConf = linConf + self.core = core + self.scheduler = scheduler + self.log = log + self.q = q + threading.Thread.__init__(self) + + def handle_job(self, jobInfo): + jobInfo.handle_call() + + def run(self): + jobs = [] + for layout in self.linConf.get_enabled_layouts(): + for hostgroup in layout.get_hostgroups(): + for service in hostgroup.get_services(): + for host in hostgroup.get_hosts(): + for period in service.get_periods(): + time.sleep(3) + job = Job(service, + host, + hostgroup.get_members(), + hostgroup.get_processors(), + self.core, + hostgroup) + schedulerJob = period.createJob(self.scheduler, job, handle_job) + if schedulerJob is not None: + job.set_job(schedulerJob) + job.set_logger(self.log) + jobs.append(job) + self.q.put(jobs) \ No newline at end of file