blob: 410188eae78e493ea471651994741bed87327002 [file] [log] [blame]
matthew.hart@linaro.org5e4fce92013-08-22 11:29:21 +01001#! /usr/bin/python
2
3# Copyright 2013 Linaro Limited
4# Author Matt Hart <matthew.hart@linaro.org>
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19# MA 02110-1301, USA.
20
Matt Hart1306d822013-08-09 12:08:22 +010021import SocketServer
Matt Hart1306d822013-08-09 12:08:22 +010022import logging
matthew.hart@linaro.org6e15b5e2013-08-28 19:48:51 +010023import socket
Matt Hart76fb2542014-06-01 14:24:56 +010024import time
Matt Hart132d43c2015-02-25 18:19:53 +000025import json
Matt Hartfc646822015-02-27 14:51:16 +000026from lavapdu.dbhandler import DBHandler
Matt Harte7bddc02015-07-08 18:05:08 +010027from lavapdu.shared import drivername_from_hostname
Matt Hart1499bd42013-08-20 11:35:46 +010028
Matt Hart1499bd42013-08-20 11:35:46 +010029class ListenerServer(object):
Matt Hart1499bd42013-08-20 11:35:46 +010030
Matt Harte7bddc02015-07-08 18:05:08 +010031 def __init__(self, config):
32 self.config = config
33 settings = config["daemon"]
Matt Hart132d43c2015-02-25 18:19:53 +000034 listen_host = settings["hostname"]
35 listen_port = settings["port"]
36
Matt Hart40d6c312013-08-20 14:47:31 +010037 logging.getLogger().name = "ListenerServer"
Matt Hart132d43c2015-02-25 18:19:53 +000038 logging.getLogger().setLevel(settings["logging_level"])
39 logging.debug("ListenerServer __init__")
Matt Hartfc646822015-02-27 14:51:16 +000040 logging.info("listening on %s:%s", listen_host, listen_port)
Matt Hart132d43c2015-02-25 18:19:53 +000041
42 self.server = TCPServer((listen_host, listen_port), TCPRequestHandler)
43 self.server.settings = settings
Matt Harte7bddc02015-07-08 18:05:08 +010044 self.server.config = config
Matt Hartfc646822015-02-27 14:51:16 +000045 dbh = DBHandler(settings)
46 dbh.create_db()
47 dbh.close()
48 del dbh
Matt Hart1306d822013-08-09 12:08:22 +010049
50 def start(self):
Matt Hart1499bd42013-08-20 11:35:46 +010051 logging.info("Starting the ListenerServer")
Matt Hart1306d822013-08-09 12:08:22 +010052 self.server.serve_forever()
53
Matt Hart1499bd42013-08-20 11:35:46 +010054
Matt Hart1306d822013-08-09 12:08:22 +010055class TCPRequestHandler(SocketServer.BaseRequestHandler):
Matt Hart1499bd42013-08-20 11:35:46 +010056 #"One instance per connection. Override handle(self) to customize action."
Matt Hart1306d822013-08-09 12:08:22 +010057 def insert_request(self, data):
matthew.hart@linaro.org1d632392013-08-27 14:40:11 +010058 logging.getLogger().name = "TCPRequestHandler"
Matt Hart132d43c2015-02-25 18:19:53 +000059 logging.getLogger().setLevel(self.server.settings["logging_level"])
Matt Hart1306d822013-08-09 12:08:22 +010060 array = data.split(" ")
Matt Hart76fb2542014-06-01 14:24:56 +010061 delay = 10
62 custom_delay = False
63 now = int(time.time())
Matt Hart132d43c2015-02-25 18:19:53 +000064 if (len(array) < 3) or (len(array) > 4):
matthew.hart@linaro.org1d632392013-08-27 14:40:11 +010065 logging.info("Wrong data size")
66 raise Exception("Unexpected data")
Matt Hart76fb2542014-06-01 14:24:56 +010067 if len(array) == 4:
68 delay = int(array[3])
69 custom_delay = True
Matt Hart1306d822013-08-09 12:08:22 +010070 hostname = array[0]
71 port = int(array[1])
72 request = array[2]
Matt Harte7bddc02015-07-08 18:05:08 +010073 drivername_from_hostname(hostname, self.server.config["pdus"])
Matt Hartfc646822015-02-27 14:51:16 +000074 if not (request in ["reboot", "on", "off"]):
Matt Hart76584172015-03-02 10:25:51 +000075 logging.info("Unknown request: %s", request)
76 raise Exception("Unknown request: %s", request)
Matt Hart76fb2542014-06-01 14:24:56 +010077 if request == "reboot":
78 logging.debug("reboot requested, submitting off/on")
Matt Hartfc646822015-02-27 14:51:16 +000079 self.queue_request(hostname, port, "off", now)
80 self.queue_request(hostname, port, "on", now+delay)
Matt Hart76fb2542014-06-01 14:24:56 +010081 else:
82 if custom_delay:
83 logging.debug("using delay as requested")
Matt Hartfc646822015-02-27 14:51:16 +000084 self.queue_request(hostname, port, request, now+delay)
Matt Hart76fb2542014-06-01 14:24:56 +010085 else:
Matt Hartfc646822015-02-27 14:51:16 +000086 self.queue_request(hostname, port, request, now)
Matt Hart76fb2542014-06-01 14:24:56 +010087
88 def queue_request(self, hostname, port, request, exectime):
Matt Hart76584172015-03-02 10:25:51 +000089 dbhandler = DBHandler(self.server.settings)
Matt Hart132d43c2015-02-25 18:19:53 +000090 sql = "insert into pdu_queue (hostname,port,request,exectime) " \
Matt Hartfc646822015-02-27 14:51:16 +000091 "values ('%s',%i,'%s',%i)" % (hostname, port, request, exectime)
Matt Hart76584172015-03-02 10:25:51 +000092 dbhandler.do_sql(sql)
93 dbhandler.close()
94 del dbhandler
Matt Hart1306d822013-08-09 12:08:22 +010095
Matt Hart76fb2542014-06-01 14:24:56 +010096
Matt Hart1306d822013-08-09 12:08:22 +010097 def handle(self):
Matt Hart40d6c312013-08-20 14:47:31 +010098 logging.getLogger().name = "TCPRequestHandler"
Matt Hart76584172015-03-02 10:25:51 +000099 request_ip = self.client_address[0]
Matt Hart40d6c312013-08-20 14:47:31 +0100100 try:
101 data = self.request.recv(4096).strip()
matthew.hart@linaro.org6e15b5e2013-08-28 19:48:51 +0100102 socket.setdefaulttimeout(2)
matthew.hart@linaro.org00612962014-02-13 15:49:27 +0000103 try:
Matt Hart76584172015-03-02 10:25:51 +0000104 request_host = socket.gethostbyaddr(request_ip)[0]
105 except socket.herror as e: #pylint: disable=invalid-name
Matt Hart132d43c2015-02-25 18:19:53 +0000106 #logging.debug("Unable to resolve: %s error: %s" % (ip,e))
Matt Hart76584172015-03-02 10:25:51 +0000107 request_host = request_ip
108 logging.info("Received a request from %s: '%s'", request_host, data)
Matt Hart40d6c312013-08-20 14:47:31 +0100109 self.insert_request(data)
110 self.request.sendall("ack\n")
Matt Hart76584172015-03-02 10:25:51 +0000111 except Exception as e: #pylint: disable=invalid-name
Matt Hart2af71142014-07-22 10:40:41 +0100112 logging.debug(e.__class__)
113 logging.debug(e.message)
Matt Harte7bddc02015-07-08 18:05:08 +0100114 self.request.sendall(e.message)
Matt Hart1306d822013-08-09 12:08:22 +0100115 self.request.close()
116
Matt Hart76584172015-03-02 10:25:51 +0000117
Matt Hart1306d822013-08-09 12:08:22 +0100118class TCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
119 allow_reuse_address = True
120 daemon_threads = True
Matt Hart76584172015-03-02 10:25:51 +0000121 #pass
Matt Hart1306d822013-08-09 12:08:22 +0100122
123if __name__ == "__main__":
Matt Hart1499bd42013-08-20 11:35:46 +0100124 logging.basicConfig(level=logging.DEBUG)
Matt Hart63ed9112013-08-20 13:31:50 +0100125 logging.getLogger().setLevel(logging.DEBUG)
Matt Hart1499bd42013-08-20 11:35:46 +0100126 logging.debug("Executing from __main__")
Matt Hart132d43c2015-02-25 18:19:53 +0000127 filename = "/etc/lavapdu/lavapdu.conf"
128 print("Reading settings from %s" % filename)
129 with open(filename) as stream:
130 jobdata = stream.read()
131 json_data = json.loads(jobdata)
Matt Harte7bddc02015-07-08 18:05:08 +0100132 ss = ListenerServer(json_data)
Matt Hart21dc0372015-02-25 21:15:21 +0000133 ss.start()