Run a pdurunner process for each separate PDU
Software fix to hardware problem:
https://bugs.linaro.org/show_bug.cgi?id=1683
Software fix to config problem:
https://bugs.linaro.org/show_bug.cgi?id=1684
Run a separate "pdurunner" process for each configured PDU
so that one PDU failing does not affect the whole system.
Also, some code cleanup and database usage improvements
and init script fixes.
Change-Id: Ie3c3de8fb68012604626e9a4273a002308ba92b3
diff --git a/etc/lavapdu-listen.init b/etc/lavapdu-listen.init
old mode 100644
new mode 100755
diff --git a/etc/lavapdu-runner.init b/etc/lavapdu-runner.init
old mode 100644
new mode 100755
index 168bde0..befa0c7
--- a/etc/lavapdu-runner.init
+++ b/etc/lavapdu-runner.init
@@ -65,7 +65,7 @@
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
- start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
+ start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
# Wait for children to finish too if this is a daemon that forks
@@ -75,7 +75,10 @@
# needed by services started subsequently. A last resort is to
# sleep for some time.
# Many daemons don't delete their pidfiles when they exit.
- rm -f $PIDFILE
+ if [ $RETVAL -lt 2 ]
+ then
+ rm -f $PIDFILE
+ fi
return "$RETVAL"
}
@@ -83,6 +86,9 @@
start)
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC " "$NAME"
do_start
+ sleep 1
+ echo -n " "
+ cat $PIDFILE
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
diff --git a/etc/lavapdu/lavapdu.conf b/etc/lavapdu/lavapdu.conf
index c57ae01..fd9c428 100644
--- a/etc/lavapdu/lavapdu.conf
+++ b/etc/lavapdu/lavapdu.conf
@@ -21,9 +21,10 @@
"driver": "apc7952"
},
"192.168.10.5": {
- "driver": "apc8959",
- "this": "that",
- "something": "else"
+ "driver": "apc8959"
+ },
+ "192.168.10.6": {
+ "driver": "apc7952"
},
"192.168.25.52": {
"driver": "apc7952"
diff --git a/lavapdu-runner b/lavapdu-runner
index fea53e8..f32b217 100755
--- a/lavapdu-runner
+++ b/lavapdu-runner
@@ -24,6 +24,7 @@
import optparse
from lavapdu.shared import get_daemon_logger
from lavapdu.shared import read_settings
+import lavapdu.runnermaster as runnermaster
import daemon
try:
@@ -39,21 +40,6 @@
logfile = "/var/log/lavapdu-runner.log"
conffile = "/etc/lavapdu/lavapdu.conf"
settings = read_settings(conffile)
- usage = "Usage: %prog [--logfile] --[loglevel]"
- description = "LAVA PDU request listener server, " \
- "host and port are handled in %s" % conffile
- parser = optparse.OptionParser(usage=usage, description=description)
- parser.add_option("--logfile", dest="logfile", action="store",
- type="string", help="log file [%s]" % logfile)
- parser.add_option("--loglevel", dest="loglevel", action="store",
- type="string", help="logging level [INFO]")
- (options, args) = parser.parse_args()
- if options.logfile:
- if os.path.exists(os.path.dirname(options.logfile)):
- logfile = options.logfile
- else:
- print "No such directory for specified logfile '%s'" % logfile
- open(logfile, 'w').close()
level = logging.DEBUG
daemon_settings = settings["daemon"]
if daemon_settings["logging_level"] == "DEBUG":
@@ -71,20 +57,11 @@
if isinstance(client_logger, Exception):
print("Fatal error creating client_logger: " + str(client_logger))
sys.exit(os.EX_OSERR)
- # noinspection PyArgumentList
- lockfile = pidlockfile.PIDLockFile(pidfile)
- if lockfile.is_locked():
- logging.error("PIDFile %s already locked" % pidfile)
- sys.exit(os.EX_OSERR)
context = daemon.DaemonContext(
detach_process=True,
working_directory=os.getcwd(),
- pidfile=lockfile,
files_preserve=[watched_file_handler.stream],
stderr=watched_file_handler.stream,
stdout=watched_file_handler.stream)
with context:
- logging.info("Running LAVA PDU Runner %s dbhost: %s"
- % (logfile, settings["daemon"]["dbhost"]))
- p = PDURunner(settings)
- p.run_me()
+ runnermaster.start_em_up(settings, pidfile)
diff --git a/lavapdu/dbhandler.py b/lavapdu/dbhandler.py
index 7b0364b..5526e1b 100644
--- a/lavapdu/dbhandler.py
+++ b/lavapdu/dbhandler.py
@@ -21,12 +21,13 @@
import logging
import psycopg2
import time
+log = logging.getLogger(__name__)
class DBHandler(object):
def __init__(self, config):
- logging.debug("Creating new DBHandler: %s", config["dbhost"])
- logging.getLogger().name = "DBHandler"
+ log.debug("Creating new DBHandler: %s %s", config["dbhost"],
+ config["dbname"])
self.conn = psycopg2.connect(database=config["dbname"],
user=config["dbuser"],
password=config["dbpass"],
@@ -34,49 +35,55 @@
self.cursor = self.conn.cursor()
def do_sql(self, sql):
- logging.debug("executing sql: %s", sql)
+ log.debug("executing sql: %s", sql)
self.cursor.execute(sql)
self.conn.commit()
def do_sql_with_fetch(self, sql):
- logging.debug("executing sql: %s", sql)
+ log.debug("executing sql: %s", sql)
self.cursor.execute(sql)
row = self.cursor.fetchone()
self.conn.commit()
return row
def create_db(self):
- logging.info("Creating db table if it doesn't exist")
+ log.info("Creating db table if it doesn't exist")
sql = "create table if not exists pdu_queue (id serial, hostname " \
"text, port int, request text, exectime int)"
- self.cursor.execute(sql)
- self.conn.commit()
+ self.do_sql(sql)
sql = "select column_name from information_schema.columns where " \
"table_name='pdu_queue' and column_name='exectime'"
- self.cursor.execute(sql)
- res = self.cursor.fetchone()
+ res = self.do_sql_with_fetch(sql)
if not res:
- logging.info("Old db schema discovered, upgrading")
+ log.info("Old db schema discovered, upgrading")
sql = "alter table pdu_queue add column exectime int default 1"
- self.cursor.execute(sql)
- self.conn.commit()
+ self.do_sql(sql)
+
+ def insert_request(self, hostname, port, request, exectime):
+ sql = "insert into pdu_queue (hostname,port,request,exectime) " \
+ "values ('%s',%i,'%s',%i)" % (hostname, port, request, exectime)
+ self.do_sql(sql)
def delete_row(self, row_id):
- logging.debug("deleting row %i", row_id)
+ log.debug("deleting row %i", row_id)
self.do_sql("delete from pdu_queue where id=%i" % row_id)
def get_res(self, sql):
return self.cursor.execute(sql)
- def get_next_job(self):
+ def get_next_job(self, single_pdu=False):
now = int(time.time())
- row = self.do_sql_with_fetch("select id, hostname, port, "
- "request from pdu_queue where "
- "(exectime < %i or exectime is null)"
- "order by id asc limit 1" % now)
+ extra_sql = ""
+ if single_pdu:
+ log.debug("Looking for jobs for PDU: %s", single_pdu)
+ extra_sql = "and hostname='%s'" % single_pdu
+ row = self.do_sql_with_fetch("select id, hostname, port, request "
+ "from pdu_queue where ((exectime < %i "
+ "or exectime is null) %s) order by id asc"
+ " limit 1" % (now, extra_sql))
return row
def close(self):
- logging.debug("Closing DBHandler")
+ log.debug("Closing DBHandler")
self.cursor.close()
self.conn.close()
diff --git a/lavapdu/drivers/apc7952.py b/lavapdu/drivers/apc7952.py
index 79c2148..7140948 100644
--- a/lavapdu/drivers/apc7952.py
+++ b/lavapdu/drivers/apc7952.py
@@ -20,6 +20,7 @@
import logging
from lavapdu.drivers.apcbase import APCBase
+log = logging.getLogger(__name__)
class APC7952(APCBase):
@@ -32,11 +33,11 @@
def _pdu_logout(self):
self._back_to_main()
- logging.debug("Logging out")
+ log.debug("Logging out")
self.connection.send("4\r")
def _back_to_main(self):
- logging.debug("Returning to main menu")
+ log.debug("Returning to main menu")
self.connection.send("\r")
self.connection.expect('>')
for _ in range(1, 20):
@@ -44,31 +45,31 @@
self.connection.send("\r")
res = self.connection.expect(["4- Logout", "> "])
if res == 0:
- logging.debug("Back at main menu")
+ log.debug("Back at main menu")
break
def _enter_outlet(self, outlet, enter_needed=True):
outlet = "%s" % outlet
- logging.debug("Attempting to enter outlet %s", outlet)
+ log.debug("Attempting to enter outlet %s", outlet)
if enter_needed:
self.connection.expect("Press <ENTER> to continue...")
- logging.debug("Sending enter")
+ log.debug("Sending enter")
self.connection.send("\r")
self.connection.expect("> ")
- logging.debug("Sending outlet number")
+ log.debug("Sending outlet number")
self.connection.send(outlet)
self.connection.send("\r")
- logging.debug("Finished entering outlet")
+ log.debug("Finished entering outlet")
def _port_interaction(self, command, port_number):
- logging.debug("Attempting command: %s port: %i",
- command, port_number)
+ log.debug("Attempting command: %s port: %i",
+ command, port_number)
# make sure in main menu here
self._back_to_main()
self.connection.send("\r")
self.connection.expect("1- Device Manager")
self.connection.expect("> ")
- logging.debug("Entering Device Manager")
+ log.debug("Entering Device Manager")
self.connection.send("1\r")
self.connection.expect("------- Device Manager")
self.connection.send("2\r")
@@ -80,7 +81,7 @@
self.connection.send("1\r")
res = self.connection.expect(["> ", "Press <ENTER> to continue..."])
if res == 1:
- logging.debug("Stupid paging thingmy detected, pressing enter")
+ log.debug("Stupid paging thingmy detected, pressing enter")
self.connection.send("\r")
self.connection.send("\r")
if command == "on":
@@ -92,7 +93,7 @@
self.connection.expect("Immediate Off")
self._do_it()
else:
- logging.debug("Unknown command!")
+ log.debug("Unknown command!")
def _do_it(self):
self.connection.expect("Enter 'YES' to continue or "
diff --git a/lavapdu/drivers/apc8959.py b/lavapdu/drivers/apc8959.py
index e4bcf54..c699962 100644
--- a/lavapdu/drivers/apc8959.py
+++ b/lavapdu/drivers/apc8959.py
@@ -20,6 +20,7 @@
import logging
from lavapdu.drivers.apcbase import APCBase
+log = logging.getLogger(__name__)
class APC8959(APCBase):
@@ -32,21 +33,21 @@
return False
def _pdu_logout(self):
- logging.debug("logging out")
+ log.debug("logging out")
self.connection.send("\r")
self.connection.send("exit")
self.connection.send("\r")
- logging.debug("done")
+ log.debug("done")
def _pdu_get_to_prompt(self):
self.connection.send("\r")
self.connection.expect('apc>')
def _port_interaction(self, command, port_number):
- logging.debug("Attempting %s on port %i", command, port_number)
+ log.debug("Attempting %s on port %i", command, port_number)
self._pdu_get_to_prompt()
self.connection.sendline(self.pdu_commands[command] +
(" %i" % port_number))
self.connection.expect("E000: Success")
self._pdu_get_to_prompt()
- logging.debug("done")
+ log.debug("done")
diff --git a/lavapdu/drivers/apc9210.py b/lavapdu/drivers/apc9210.py
index a817842..7069820 100644
--- a/lavapdu/drivers/apc9210.py
+++ b/lavapdu/drivers/apc9210.py
@@ -20,6 +20,7 @@
import logging
from lavapdu.drivers.apc7952 import APC7952
+log = logging.getLogger(__name__)
class APC9210(APC7952):
@@ -31,16 +32,16 @@
return False
def _port_interaction(self, command, port_number):
- logging.debug("Attempting command: %s port: %i", command, port_number)
+ log.debug("Attempting command: %s port: %i", command, port_number)
# make sure in main menu here
self._back_to_main()
self.connection.send("\r")
self.connection.expect("1- Outlet Manager")
self.connection.expect("> ")
- logging.debug("Entering Outlet Manager")
+ log.debug("Entering Outlet Manager")
self.connection.send("1\r")
self.connection.expect("------- Outlet Manager")
- logging.debug("Got to Device Manager")
+ log.debug("Got to Device Manager")
self._enter_outlet(port_number, False)
self.connection.expect(["1- Control of Outlet",
"1- Outlet Control/Configuration"])
@@ -57,4 +58,4 @@
self.connection.expect("Turn Outlet Off")
self._do_it()
else:
- logging.debug("Unknown command!")
+ log.debug("Unknown command!")
diff --git a/lavapdu/drivers/apc9218.py b/lavapdu/drivers/apc9218.py
index 382bd7d..4189b29 100644
--- a/lavapdu/drivers/apc9218.py
+++ b/lavapdu/drivers/apc9218.py
@@ -20,6 +20,7 @@
import logging
from lavapdu.drivers.apc7952 import APC7952
+log = logging.getLogger(__name__)
class APC9218(APC7952):
@@ -37,10 +38,10 @@
self.connection.send("\r")
self.connection.expect("1- Device Manager")
self.connection.expect("> ")
- logging.debug("Entering Device Manager")
+ log.debug("Entering Device Manager")
self.connection.send("1\r")
self.connection.expect("------- Device Manager")
- logging.debug("Got to Device Manager")
+ log.debug("Got to Device Manager")
self._enter_outlet(port_number, False)
self.connection.expect(["1- Control Outlet",
"1- Outlet Control/Configuration"])
@@ -48,7 +49,7 @@
self.connection.send("1\r")
res = self.connection.expect(["> ", "Press <ENTER> to continue..."])
if res == 1:
- logging.debug("Stupid paging thingmy detected, pressing enter")
+ log.debug("Stupid paging thingmy detected, pressing enter")
self.connection.send("\r")
self.connection.send("\r")
self.connection.expect(["Control Outlet %s" % port_number,
@@ -64,4 +65,4 @@
self.connection.expect("Immediate Off")
self._do_it()
else:
- logging.debug("Unknown command!")
+ log.debug("Unknown command!")
diff --git a/lavapdu/drivers/apcbase.py b/lavapdu/drivers/apcbase.py
index 1946b62..5f16705 100644
--- a/lavapdu/drivers/apcbase.py
+++ b/lavapdu/drivers/apcbase.py
@@ -21,7 +21,7 @@
import logging
import pexpect
from lavapdu.drivers.driver import PDUDriver
-import sys
+log = logging.getLogger(__name__)
class APCBase(PDUDriver):
@@ -29,7 +29,7 @@
def __init__(self, hostname, settings):
self.hostname = hostname
- logging.debug(settings)
+ log.debug(settings)
self.settings = settings
telnetport = 23
if "telnetport" in settings:
@@ -40,34 +40,32 @@
@classmethod
def accepts(cls, drivername):
- logging.debug(drivername)
+ log.debug(drivername)
return False
def port_interaction(self, command, port_number):
- logging.debug("Running port_interaction from APCBase")
+ log.debug("Running port_interaction from APCBase")
self._port_interaction(command, # pylint: disable=no-member
port_number)
def get_connection(self):
- logging.debug("Connecting to APC PDU with: %s", self.exec_string)
- if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
- self.connection = pexpect.spawn(self.exec_string,
- logfile=sys.stdout)
- else:
- self.connection = pexpect.spawn(self.exec_string)
+ log.debug("Connecting to APC PDU with: %s", self.exec_string)
+ # only uncomment this line for FULL debug when developing
+ # self.connection = pexpect.spawn(self.exec_string, logfile=sys.stdout)
+ self.connection = pexpect.spawn(self.exec_string)
self._pdu_login("apc", "apc")
def _cleanup(self):
self._pdu_logout() # pylint: disable=no-member
def _bombout(self):
- logging.debug("Bombing out of driver: %s", self.connection)
+ log.debug("Bombing out of driver: %s", self.connection)
self.connection.close(force=True)
del self
def _pdu_login(self, username, password):
- logging.debug("attempting login with username %s, password %s",
- username, password)
+ log.debug("attempting login with username %s, password %s",
+ username, password)
self.connection.send("\r")
self.connection.expect("User Name :")
self.connection.send("%s\r" % username)
diff --git a/lavapdu/drivers/driver.py b/lavapdu/drivers/driver.py
index a56fea6..f0bdbe7 100644
--- a/lavapdu/drivers/driver.py
+++ b/lavapdu/drivers/driver.py
@@ -19,6 +19,7 @@
# MA 02110-1301, USA.
import logging
+log = logging.getLogger(__name__)
class PDUDriver(object):
@@ -30,18 +31,18 @@
@classmethod
def select(cls, drivername):
- logging.debug("adding PDUDriver subclasses: %s",
- cls.__subclasses__()) # pylint: disable=no-member
+ log.debug("adding PDUDriver subclasses: %s",
+ cls.__subclasses__()) # pylint: disable=no-member
candidates = cls.__subclasses__() # pylint: disable=no-member
for subc in cls.__subclasses__(): # pylint: disable=no-member
- logging.debug("adding %s subclasses: %s", subc,
- subc.__subclasses__())
+ log.debug("adding %s subclasses: %s", subc,
+ subc.__subclasses__())
candidates = candidates + (subc.__subclasses__())
for subsubc in subc.__subclasses__():
- logging.debug("adding %s subclasses: %s", subsubc,
- subsubc.__subclasses__())
+ log.debug("adding %s subclasses: %s", subsubc,
+ subsubc.__subclasses__())
candidates = candidates + (subsubc.__subclasses__())
- logging.debug(candidates)
+ log.debug(candidates)
willing = [c for c in candidates if c.accepts(drivername)]
if len(willing) == 0:
raise NotImplementedError(
@@ -49,19 +50,19 @@
"'%s' with the specified job parameters. %s" %
(drivername, cls)
)
- logging.debug("%s accepted the request", willing[0])
+ log.debug("%s accepted the request", willing[0])
return willing[0]
def handle(self, request, port_number, delay=0):
- logging.debug("Driving PDU hostname: %s "
- "PORT: %s REQUEST: %s (delay %s)",
- self.hostname, port_number, request, delay)
+ log.debug("Driving PDU hostname: %s "
+ "PORT: %s REQUEST: %s (delay %s)",
+ self.hostname, port_number, request, delay)
if request == "on":
self.port_on(port_number)
elif request == "off":
self.port_off(port_number)
else:
- logging.debug("Unknown request to handle - oops")
+ log.debug("Unknown request to handle - oops")
raise NotImplementedError(
"Driver doesn't know how to %s " % request
)
diff --git a/lavapdu/pdurunner.py b/lavapdu/pdurunner.py
index 843c6b2..95c6767 100644
--- a/lavapdu/pdurunner.py
+++ b/lavapdu/pdurunner.py
@@ -20,35 +20,36 @@
import logging
import time
-import json
import traceback
from lavapdu.dbhandler import DBHandler
from lavapdu.drivers.driver import PDUDriver
import lavapdu.drivers.strategies # pylint: disable=W0611
from lavapdu.shared import drivername_from_hostname
+from lavapdu.shared import pdus_from_config
assert lavapdu.drivers.strategies
+log = logging.getLogger(__name__)
class PDURunner(object):
- def __init__(self, config):
- self.pdus = config["pdus"]
+ def __init__(self, config, single_pdu=False):
self.settings = config["daemon"]
- logging.basicConfig(level=self.settings["logging_level"])
- logging.getLogger().setLevel(self.settings["logging_level"])
- logging.getLogger().name = "PDURunner"
+ self.pdus = config["pdus"]
+ if single_pdu:
+ if single_pdu not in pdus_from_config(config):
+ raise NotImplementedError
+ self.single_pdu = single_pdu
+ self.dbh = DBHandler(self.settings)
- def get_one(self, db):
- job = db.get_next_job()
+ def get_one(self):
+ job = self.dbh.get_next_job(self.single_pdu)
if job:
job_id, hostname, port, request = job
- logging.debug(job)
- logging.info("Processing queue item: (%s %s) on hostname: %s",
- request, port, hostname)
+ log.debug(job)
+ log.info("Processing queue item: (%s %s) on hostname: %s",
+ request, port, hostname)
self.do_job(hostname, port, request)
- db.delete_row(job_id)
- else:
- logging.debug("Found nothing to do in database")
+ self.dbh.delete_row(job_id)
def driver_from_hostname(self, hostname):
drivername = drivername_from_hostname(hostname, self.pdus)
@@ -63,32 +64,21 @@
driver = self.driver_from_hostname(hostname)
return driver.handle(request, port, delay)
except Exception as e: # pylint: disable=broad-except
- logging.warn(traceback.format_exc())
- logging.warn("Failed to execute job: %s %s %s "
- "(attempts left %i) error was %s",
- hostname, port, request, retries, e.message)
+ log.warn(traceback.format_exc())
+ log.warn("Failed to execute job: %s %s %s "
+ "(attempts left %i) error was %s",
+ hostname, port, request, retries, e.message)
if driver:
- driver._bombout() # pylint: disable=no-member,protected-access
+ driver._bombout() # pylint: disable=W0212,E1101
time.sleep(5)
retries -= 1
return False
def run_me(self):
- logging.info("Starting up the PDURunner")
+ if self.single_pdu:
+ log.info("Starting a PDURunner for PDU: %s", self.single_pdu)
+ else:
+ log.info("Starting a PDURunner for all PDUS")
while 1:
- db = DBHandler(self.settings)
- self.get_one(db)
- db.close()
- del db
+ self.get_one()
time.sleep(2)
-
-if __name__ == "__main__":
- settings = {}
- filename = "/etc/lavapdu/lavapdu.conf"
- print("Reading settings from %s", filename)
- with open(filename) as stream:
- jobdata = stream.read()
- json_data = json.loads(jobdata)
-
- p = PDURunner(json_data)
- p.run_me()
diff --git a/lavapdu/runnermaster.py b/lavapdu/runnermaster.py
new file mode 100644
index 0000000..fe979da
--- /dev/null
+++ b/lavapdu/runnermaster.py
@@ -0,0 +1,61 @@
+#! /usr/bin/python
+
+# Copyright 2013 Linaro Limited
+# Author Matt Hart <matthew.hart@linaro.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; either version 2 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 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., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+import lavapdu.pdurunner as pdurunner
+from multiprocessing import Process
+from setproctitle import setproctitle # pylint: disable=no-name-in-module
+from lavapdu.shared import pdus_from_config
+import signal
+import sys
+import os
+import logging
+processes = []
+log = logging.getLogger(__name__)
+
+
+def start_runner(config, pdu):
+ setproctitle("pdurunner for %s" % pdu)
+ p = pdurunner.PDURunner(config, pdu)
+ p.run_me()
+
+
+def start_em_up(config, pidfile):
+ pid = os.getpid()
+ if os.path.isfile(pidfile):
+ log.error("Pidfile already exists")
+ sys.exit(1)
+ f = open(pidfile, 'w')
+ f.write(str(pid))
+ f.close()
+ pdus = pdus_from_config(config)
+ for pdu in pdus:
+ p = Process(target=start_runner, args=(config, pdu))
+ p.start()
+ processes.append(p)
+ signal.signal(signal.SIGTERM, signal_term_handler)
+
+
+def signal_term_handler(a, b):
+ del a, b
+ print 'Sending sigterm to all children'
+ for proc in processes:
+ log.debug("Terminate %s", proc.pid)
+ proc.terminate()
+ sys.exit(0)
diff --git a/lavapdu/shared.py b/lavapdu/shared.py
index 39c281b..46af539 100644
--- a/lavapdu/shared.py
+++ b/lavapdu/shared.py
@@ -18,7 +18,6 @@
def read_settings(filename):
- logging.debug("Reading settings from %s", filename)
with open(filename) as stream:
jobdata = stream.read()
json_data = json.loads(jobdata)
@@ -33,3 +32,10 @@
"is there a section in the lavapdu.conf?" %
hostname)
return drivername
+
+
+def pdus_from_config(data):
+ output = []
+ for pdu in data["pdus"]:
+ output.append(pdu)
+ return output
diff --git a/lavapdu/socketserver.py b/lavapdu/socketserver.py
index 43972e2..2d93367 100644
--- a/lavapdu/socketserver.py
+++ b/lavapdu/socketserver.py
@@ -22,9 +22,9 @@
import logging
import socket
import time
-import json
from lavapdu.dbhandler import DBHandler
from lavapdu.shared import drivername_from_hostname
+log = logging.getLogger(__name__)
class ListenerServer(object):
@@ -34,22 +34,16 @@
settings = config["daemon"]
listen_host = settings["hostname"]
listen_port = settings["port"]
-
- logging.getLogger().name = "ListenerServer"
- logging.getLogger().setLevel(settings["logging_level"])
- logging.debug("ListenerServer __init__")
- logging.info("listening on %s:%s", listen_host, listen_port)
+ log.debug("ListenerServer __init__")
+ log.info("listening on %s:%s", listen_host, listen_port)
self.server = TCPServer((listen_host, listen_port), TCPRequestHandler)
self.server.settings = settings
self.server.config = config
- dbh = DBHandler(settings)
- dbh.create_db()
- dbh.close()
- del dbh
+ self.server.dbh = DBHandler(settings)
def start(self):
- logging.info("Starting the ListenerServer")
+ log.info("Starting the ListenerServer")
self.server.serve_forever()
@@ -57,14 +51,12 @@
# "One instance per connection. Override handle(self) to customize
# action."
def insert_request(self, data):
- logging.getLogger().name = "TCPRequestHandler"
- logging.getLogger().setLevel(self.server.settings["logging_level"])
array = data.split(" ")
delay = 10
custom_delay = False
now = int(time.time())
if (len(array) < 3) or (len(array) > 4):
- logging.info("Wrong data size")
+ log.info("Wrong data size")
raise Exception("Unexpected data")
if len(array) == 4:
delay = int(array[3])
@@ -72,31 +64,24 @@
hostname = array[0]
port = int(array[1])
request = array[2]
+ # this will throw if the pdu is not found
drivername_from_hostname(hostname, self.server.config["pdus"])
+ dbh = self.server.dbh
if not (request in ["reboot", "on", "off"]):
- logging.info("Unknown request: %s", request)
+ log.info("Unknown request: %s", request)
raise Exception("Unknown request: %s", request)
if request == "reboot":
- logging.debug("reboot requested, submitting off/on")
- self.queue_request(hostname, port, "off", now)
- self.queue_request(hostname, port, "on", now + delay)
+ log.debug("reboot requested, submitting off/on")
+ dbh.insert_request(hostname, port, "off", now)
+ dbh.insert_request(hostname, port, "on", now + delay)
else:
if custom_delay:
- logging.debug("using delay as requested")
- self.queue_request(hostname, port, request, now + delay)
+ log.debug("using delay as requested")
+ dbh.insert_request(hostname, port, request, now + delay)
else:
- self.queue_request(hostname, port, request, now)
-
- def queue_request(self, hostname, port, request, exectime):
- dbhandler = DBHandler(self.server.settings)
- sql = "insert into pdu_queue (hostname,port,request,exectime) " \
- "values ('%s',%i,'%s',%i)" % (hostname, port, request, exectime)
- dbhandler.do_sql(sql)
- dbhandler.close()
- del dbhandler
+ dbh.insert_request(hostname, port, request, now)
def handle(self):
- logging.getLogger().name = "TCPRequestHandler"
request_ip = self.client_address[0]
try:
data = self.request.recv(4096).strip()
@@ -105,14 +90,14 @@
request_host = socket.gethostbyaddr(request_ip)[0]
except socket.herror:
request_host = request_ip
- logging.info("Received a request from %s: '%s'",
- request_host,
- data)
+ log.info("Received a request from %s: '%s'",
+ request_host,
+ data)
self.insert_request(data)
self.request.sendall("ack\n")
except Exception as global_error: # pylint: disable=broad-except
- logging.debug(global_error.__class__)
- logging.debug(global_error.message)
+ log.debug(global_error.__class__)
+ log.debug(global_error.message)
self.request.sendall(global_error.message)
self.request.close()
@@ -120,15 +105,3 @@
class TCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
allow_reuse_address = True
daemon_threads = True
-
-if __name__ == "__main__":
- logging.basicConfig(level=logging.DEBUG)
- logging.getLogger().setLevel(logging.DEBUG)
- logging.debug("Executing from __main__")
- filename = "/etc/lavapdu/lavapdu.conf"
- logging.debug("Reading settings from %s", filename)
- with open(filename) as stream:
- jobdata = stream.read()
- json_data = json.loads(jobdata)
- ss = ListenerServer(json_data)
- ss.start()
diff --git a/setup.py b/setup.py
index dcf8a48..8e47cf5 100644
--- a/setup.py
+++ b/setup.py
@@ -33,7 +33,8 @@
"daemon",
"lockfile",
"pexpect",
- "psycopg2"
+ "psycopg2",
+ "setproctitle"
],
data_files=[
("/etc/init.d/", ["etc/lavapdu-runner.init"]),