blob: c1b8c27c6e60be54344d8bb6c7f64de92c8ef0d1 [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 Hart1499bd42013-08-20 11:35:46 +010027
Matt Hart1499bd42013-08-20 11:35:46 +010028class ListenerServer(object):
Matt Hart1499bd42013-08-20 11:35:46 +010029
Matt Hart132d43c2015-02-25 18:19:53 +000030 def __init__(self, settings):
31 listen_host = settings["hostname"]
32 listen_port = settings["port"]
33
Matt Hart40d6c312013-08-20 14:47:31 +010034 logging.getLogger().name = "ListenerServer"
Matt Hart132d43c2015-02-25 18:19:53 +000035 logging.getLogger().setLevel(settings["logging_level"])
36 logging.debug("ListenerServer __init__")
Matt Hartfc646822015-02-27 14:51:16 +000037 logging.info("listening on %s:%s", listen_host, listen_port)
Matt Hart132d43c2015-02-25 18:19:53 +000038
39 self.server = TCPServer((listen_host, listen_port), TCPRequestHandler)
40 self.server.settings = settings
Matt Hartfc646822015-02-27 14:51:16 +000041 dbh = DBHandler(settings)
42 dbh.create_db()
43 dbh.close()
44 del dbh
Matt Hart1306d822013-08-09 12:08:22 +010045
46 def start(self):
Matt Hart1499bd42013-08-20 11:35:46 +010047 logging.info("Starting the ListenerServer")
Matt Hart1306d822013-08-09 12:08:22 +010048 self.server.serve_forever()
49
Matt Hart1499bd42013-08-20 11:35:46 +010050
Matt Hart1306d822013-08-09 12:08:22 +010051class TCPRequestHandler(SocketServer.BaseRequestHandler):
Matt Hart1499bd42013-08-20 11:35:46 +010052 #"One instance per connection. Override handle(self) to customize action."
Matt Hart1306d822013-08-09 12:08:22 +010053 def insert_request(self, data):
matthew.hart@linaro.org1d632392013-08-27 14:40:11 +010054 logging.getLogger().name = "TCPRequestHandler"
Matt Hart132d43c2015-02-25 18:19:53 +000055 logging.getLogger().setLevel(self.server.settings["logging_level"])
Matt Hart1306d822013-08-09 12:08:22 +010056 array = data.split(" ")
Matt Hart76fb2542014-06-01 14:24:56 +010057 delay = 10
58 custom_delay = False
59 now = int(time.time())
Matt Hart132d43c2015-02-25 18:19:53 +000060 if (len(array) < 3) or (len(array) > 4):
matthew.hart@linaro.org1d632392013-08-27 14:40:11 +010061 logging.info("Wrong data size")
62 raise Exception("Unexpected data")
Matt Hart76fb2542014-06-01 14:24:56 +010063 if len(array) == 4:
64 delay = int(array[3])
65 custom_delay = True
Matt Hart1306d822013-08-09 12:08:22 +010066 hostname = array[0]
67 port = int(array[1])
68 request = array[2]
Matt Hartfc646822015-02-27 14:51:16 +000069 if not (request in ["reboot", "on", "off"]):
matthew.hart@linaro.org1d632392013-08-27 14:40:11 +010070 logging.info("Unknown request: %s" % request)
71 raise Exception("Unknown request: %s" % request)
Matt Hart76fb2542014-06-01 14:24:56 +010072 if request == "reboot":
73 logging.debug("reboot requested, submitting off/on")
Matt Hartfc646822015-02-27 14:51:16 +000074 self.queue_request(hostname, port, "off", now)
75 self.queue_request(hostname, port, "on", now+delay)
Matt Hart76fb2542014-06-01 14:24:56 +010076 else:
77 if custom_delay:
78 logging.debug("using delay as requested")
Matt Hartfc646822015-02-27 14:51:16 +000079 self.queue_request(hostname, port, request, now+delay)
Matt Hart76fb2542014-06-01 14:24:56 +010080 else:
Matt Hartfc646822015-02-27 14:51:16 +000081 self.queue_request(hostname, port, request, now)
Matt Hart76fb2542014-06-01 14:24:56 +010082
83 def queue_request(self, hostname, port, request, exectime):
Matt Hart2af71142014-07-22 10:40:41 +010084 db = DBHandler(self.server.settings)
Matt Hart132d43c2015-02-25 18:19:53 +000085 sql = "insert into pdu_queue (hostname,port,request,exectime) " \
Matt Hartfc646822015-02-27 14:51:16 +000086 "values ('%s',%i,'%s',%i)" % (hostname, port, request, exectime)
Matt Hart1499bd42013-08-20 11:35:46 +010087 db.do_sql(sql)
matthew.hart@linaro.org6e15b5e2013-08-28 19:48:51 +010088 db.close()
Matt Hartfc646822015-02-27 14:51:16 +000089 del db
Matt Hart1306d822013-08-09 12:08:22 +010090
Matt Hart76fb2542014-06-01 14:24:56 +010091
Matt Hart1306d822013-08-09 12:08:22 +010092 def handle(self):
Matt Hart40d6c312013-08-20 14:47:31 +010093 logging.getLogger().name = "TCPRequestHandler"
matthew.hart@linaro.org00612962014-02-13 15:49:27 +000094 ip = self.client_address[0]
Matt Hart40d6c312013-08-20 14:47:31 +010095 try:
96 data = self.request.recv(4096).strip()
matthew.hart@linaro.org6e15b5e2013-08-28 19:48:51 +010097 socket.setdefaulttimeout(2)
matthew.hart@linaro.org00612962014-02-13 15:49:27 +000098 try:
99 request_host = socket.gethostbyaddr(ip)[0]
100 except socket.herror as e:
Matt Hart132d43c2015-02-25 18:19:53 +0000101 #logging.debug("Unable to resolve: %s error: %s" % (ip,e))
matthew.hart@linaro.org00612962014-02-13 15:49:27 +0000102 request_host = ip
Matt Hartfc646822015-02-27 14:51:16 +0000103 logging.info("Received a request from %s: '%s'"
104 % (request_host, data))
Matt Hart40d6c312013-08-20 14:47:31 +0100105 self.insert_request(data)
106 self.request.sendall("ack\n")
matthew.hart@linaro.org6e15b5e2013-08-28 19:48:51 +0100107 except Exception as e:
Matt Hart2af71142014-07-22 10:40:41 +0100108 logging.debug(e.__class__)
109 logging.debug(e.message)
Matt Hart40d6c312013-08-20 14:47:31 +0100110 self.request.sendall("nack\n")
Matt Hart1306d822013-08-09 12:08:22 +0100111 self.request.close()
112
113class TCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
114 allow_reuse_address = True
115 daemon_threads = True
116 pass
117
118if __name__ == "__main__":
Matt Hart1499bd42013-08-20 11:35:46 +0100119 logging.basicConfig(level=logging.DEBUG)
Matt Hart63ed9112013-08-20 13:31:50 +0100120 logging.getLogger().setLevel(logging.DEBUG)
Matt Hart1499bd42013-08-20 11:35:46 +0100121 logging.debug("Executing from __main__")
Matt Hart132d43c2015-02-25 18:19:53 +0000122 filename = "/etc/lavapdu/lavapdu.conf"
123 print("Reading settings from %s" % filename)
124 with open(filename) as stream:
125 jobdata = stream.read()
126 json_data = json.loads(jobdata)
127
128 #starter = {"daemon": {"dbhost":"127.0.0.1",
129 # "dbuser":"pdudaemon",
130 # "dbpass":"pdudaemon",
131 # "dbname":"lavapdu",
132 # "logging_level": logging.DEBUG,
133 # "hostname": "0.0.0.0", "port": 16421}}
134 #ss = ListenerServer(starter)
Matt Hart21dc0372015-02-25 21:15:21 +0000135 ss = ListenerServer(json_data["daemon"])
136 ss.start()