blob: 43972e23c091669674a87c243b78d8dd46719d1d [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 Hartfe042212015-07-09 14:13:29 +010029
Matt Hart1499bd42013-08-20 11:35:46 +010030class ListenerServer(object):
Matt Hart1499bd42013-08-20 11:35:46 +010031
Matt Harte7bddc02015-07-08 18:05:08 +010032 def __init__(self, config):
33 self.config = config
34 settings = config["daemon"]
Matt Hart132d43c2015-02-25 18:19:53 +000035 listen_host = settings["hostname"]
36 listen_port = settings["port"]
37
Matt Hart40d6c312013-08-20 14:47:31 +010038 logging.getLogger().name = "ListenerServer"
Matt Hart132d43c2015-02-25 18:19:53 +000039 logging.getLogger().setLevel(settings["logging_level"])
40 logging.debug("ListenerServer __init__")
Matt Hartfc646822015-02-27 14:51:16 +000041 logging.info("listening on %s:%s", listen_host, listen_port)
Matt Hart132d43c2015-02-25 18:19:53 +000042
43 self.server = TCPServer((listen_host, listen_port), TCPRequestHandler)
44 self.server.settings = settings
Matt Harte7bddc02015-07-08 18:05:08 +010045 self.server.config = config
Matt Hartfc646822015-02-27 14:51:16 +000046 dbh = DBHandler(settings)
47 dbh.create_db()
48 dbh.close()
49 del dbh
Matt Hart1306d822013-08-09 12:08:22 +010050
51 def start(self):
Matt Hart1499bd42013-08-20 11:35:46 +010052 logging.info("Starting the ListenerServer")
Matt Hart1306d822013-08-09 12:08:22 +010053 self.server.serve_forever()
54
Matt Hart1499bd42013-08-20 11:35:46 +010055
Matt Hart1306d822013-08-09 12:08:22 +010056class TCPRequestHandler(SocketServer.BaseRequestHandler):
Matt Hartfe042212015-07-09 14:13:29 +010057 # "One instance per connection. Override handle(self) to customize
58 # action."
Matt Hart1306d822013-08-09 12:08:22 +010059 def insert_request(self, data):
matthew.hart@linaro.org1d632392013-08-27 14:40:11 +010060 logging.getLogger().name = "TCPRequestHandler"
Matt Hart132d43c2015-02-25 18:19:53 +000061 logging.getLogger().setLevel(self.server.settings["logging_level"])
Matt Hart1306d822013-08-09 12:08:22 +010062 array = data.split(" ")
Matt Hart76fb2542014-06-01 14:24:56 +010063 delay = 10
64 custom_delay = False
65 now = int(time.time())
Matt Hart132d43c2015-02-25 18:19:53 +000066 if (len(array) < 3) or (len(array) > 4):
matthew.hart@linaro.org1d632392013-08-27 14:40:11 +010067 logging.info("Wrong data size")
68 raise Exception("Unexpected data")
Matt Hart76fb2542014-06-01 14:24:56 +010069 if len(array) == 4:
70 delay = int(array[3])
71 custom_delay = True
Matt Hart1306d822013-08-09 12:08:22 +010072 hostname = array[0]
73 port = int(array[1])
74 request = array[2]
Matt Harte7bddc02015-07-08 18:05:08 +010075 drivername_from_hostname(hostname, self.server.config["pdus"])
Matt Hartfc646822015-02-27 14:51:16 +000076 if not (request in ["reboot", "on", "off"]):
Matt Hart76584172015-03-02 10:25:51 +000077 logging.info("Unknown request: %s", request)
78 raise Exception("Unknown request: %s", request)
Matt Hart76fb2542014-06-01 14:24:56 +010079 if request == "reboot":
80 logging.debug("reboot requested, submitting off/on")
Matt Hartfc646822015-02-27 14:51:16 +000081 self.queue_request(hostname, port, "off", now)
Matt Hartfe042212015-07-09 14:13:29 +010082 self.queue_request(hostname, port, "on", now + delay)
Matt Hart76fb2542014-06-01 14:24:56 +010083 else:
84 if custom_delay:
85 logging.debug("using delay as requested")
Matt Hartfe042212015-07-09 14:13:29 +010086 self.queue_request(hostname, port, request, now + delay)
Matt Hart76fb2542014-06-01 14:24:56 +010087 else:
Matt Hartfc646822015-02-27 14:51:16 +000088 self.queue_request(hostname, port, request, now)
Matt Hart76fb2542014-06-01 14:24:56 +010089
90 def queue_request(self, hostname, port, request, exectime):
Matt Hart76584172015-03-02 10:25:51 +000091 dbhandler = DBHandler(self.server.settings)
Matt Hart132d43c2015-02-25 18:19:53 +000092 sql = "insert into pdu_queue (hostname,port,request,exectime) " \
Matt Hartfc646822015-02-27 14:51:16 +000093 "values ('%s',%i,'%s',%i)" % (hostname, port, request, exectime)
Matt Hart76584172015-03-02 10:25:51 +000094 dbhandler.do_sql(sql)
95 dbhandler.close()
96 del dbhandler
Matt Hart1306d822013-08-09 12:08:22 +010097
98 def handle(self):
Matt Hart40d6c312013-08-20 14:47:31 +010099 logging.getLogger().name = "TCPRequestHandler"
Matt Hart76584172015-03-02 10:25:51 +0000100 request_ip = self.client_address[0]
Matt Hart40d6c312013-08-20 14:47:31 +0100101 try:
102 data = self.request.recv(4096).strip()
matthew.hart@linaro.org6e15b5e2013-08-28 19:48:51 +0100103 socket.setdefaulttimeout(2)
matthew.hart@linaro.org00612962014-02-13 15:49:27 +0000104 try:
Matt Hart76584172015-03-02 10:25:51 +0000105 request_host = socket.gethostbyaddr(request_ip)[0]
Matt Hartfe042212015-07-09 14:13:29 +0100106 except socket.herror:
Matt Hart76584172015-03-02 10:25:51 +0000107 request_host = request_ip
Matt Hartfe042212015-07-09 14:13:29 +0100108 logging.info("Received a request from %s: '%s'",
109 request_host,
110 data)
Matt Hart40d6c312013-08-20 14:47:31 +0100111 self.insert_request(data)
112 self.request.sendall("ack\n")
Matt Hartfe042212015-07-09 14:13:29 +0100113 except Exception as global_error: # pylint: disable=broad-except
114 logging.debug(global_error.__class__)
115 logging.debug(global_error.message)
116 self.request.sendall(global_error.message)
Matt Hart1306d822013-08-09 12:08:22 +0100117 self.request.close()
118
Matt Hart76584172015-03-02 10:25:51 +0000119
Matt Hart1306d822013-08-09 12:08:22 +0100120class TCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
121 allow_reuse_address = True
122 daemon_threads = True
Matt Hart1306d822013-08-09 12:08:22 +0100123
124if __name__ == "__main__":
Matt Hart1499bd42013-08-20 11:35:46 +0100125 logging.basicConfig(level=logging.DEBUG)
Matt Hart63ed9112013-08-20 13:31:50 +0100126 logging.getLogger().setLevel(logging.DEBUG)
Matt Hart1499bd42013-08-20 11:35:46 +0100127 logging.debug("Executing from __main__")
Matt Hart132d43c2015-02-25 18:19:53 +0000128 filename = "/etc/lavapdu/lavapdu.conf"
Matt Hartfe042212015-07-09 14:13:29 +0100129 logging.debug("Reading settings from %s", filename)
Matt Hart132d43c2015-02-25 18:19:53 +0000130 with open(filename) as stream:
131 jobdata = stream.read()
132 json_data = json.loads(jobdata)
Matt Harte7bddc02015-07-08 18:05:08 +0100133 ss = ListenerServer(json_data)
Matt Hart21dc0372015-02-25 21:15:21 +0000134 ss.start()