diff options
author | Matt Hart <matthew.hart@linaro.org> | 2014-04-18 17:43:41 +0100 |
---|---|---|
committer | Matt Hart <matthew.hart@linaro.org> | 2014-04-18 17:43:41 +0100 |
commit | ffb5edd271230606407c5ebe4c708cd637ea7436 (patch) | |
tree | 4183ac39b7e348a660fcae2ce7e134e1a3889f03 /lavaproxy | |
parent | bc8b057384ebc289f6f708818c78690b4c4d36d4 (diff) |
Renamed folder and cut down socketserver.py to remove the lavapdu specific stuff
Diffstat (limited to 'lavaproxy')
-rw-r--r-- | lavaproxy/__init__.py | 22 | ||||
-rw-r--r-- | lavaproxy/apcdrivers.py | 168 | ||||
-rw-r--r-- | lavaproxy/driver.py | 27 | ||||
-rw-r--r-- | lavaproxy/engine.py | 111 | ||||
-rw-r--r-- | lavaproxy/pdurunner.py | 85 | ||||
-rw-r--r-- | lavaproxy/proxyexample.py | 98 | ||||
-rw-r--r-- | lavaproxy/socketserver.py | 80 |
7 files changed, 591 insertions, 0 deletions
diff --git a/lavaproxy/__init__.py b/lavaproxy/__init__.py new file mode 100644 index 0000000..9b73b54 --- /dev/null +++ b/lavaproxy/__init__.py @@ -0,0 +1,22 @@ +#! /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 pdurunner +import socketserver diff --git a/lavaproxy/apcdrivers.py b/lavaproxy/apcdrivers.py new file mode 100644 index 0000000..0dad9b6 --- /dev/null +++ b/lavaproxy/apcdrivers.py @@ -0,0 +1,168 @@ +#! /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 logging + +from driver import PDUDriver + + +class apc7952(PDUDriver): + def _pdu_logout(self): + self._back_to_main() + logging.debug("Logging out") + self.connection.send("4\r") + + def _back_to_main(self): + logging.debug("Returning to main menu") + self.connection.expect('>') + for i in range(1, 20): + #print("Sending escape character") + self.connection.send("\x1B") + self.connection.send("\r") + res = self.connection.expect(["4- Logout", "> "]) + if res == 0: + logging.debug("Back at main menu") + break + #self.connection.send("\r") + #self.connection.expect("4- Logout") + #self.connection.expect("> ") + + def _enter_outlet(self, outlet, enter_needed=True): + outlet = "%s" % outlet + logging.debug("Attempting to enter outlet %s", outlet) + if (enter_needed): + self.connection.expect("Press <ENTER> to continue...") + logging.debug("Sending enter") + self.connection.send("\r") + self.connection.expect("> ") + logging.debug("Sending outlet number") + self.connection.send(outlet) + self.connection.send("\r") + logging.debug("Finished entering outlet") + + def _port_interaction(self, command, port_number): + print("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") + self.connection.send("1\r") + res = self.connection.expect(["3- Outlet Control/Configuration", "2- Outlet Control", "2- Outlet Management", "------- Device Manager"]) + logging.debug("Matched pattern %s", res) + if res == 0: + self.connection.send("3\r") + self._enter_outlet(port_number) + elif res == 1: + self.connection.send("2\r") + self._enter_outlet(port_number) + elif res == 2: + self.connection.send("2\r") + elif res == 3: + logging.debug("Matched ------- Device Manager") + self._enter_outlet(port_number, False) + res = self.connection.expect(["1- Control Outlet", "1- Outlet Control/Configuration"]) + self.connection.expect("> ") + self.connection.send("1\r") + res = self.connection.expect(["> ", "Press <ENTER> to continue..."]) + if res == 1: + logging.debug("Stupid paging thingmy detected, pressing enter") + self.connection.send("\r") + self.connection.send("\r") + res = self.connection.expect(["Control Outlet %s" % port_number, "Control Outlet"]) + if res == 0: + logging.debug("Already at the right port") + else: + self.connection.send("%s\r" % port_number) + self.connection.send("1\r") + self.connection.expect("3- Immediate Reboot") + self.connection.expect("> ") + if command == "reboot": + self.connection.send("3\r") + self.connection.expect("Immediate Reboot") + self._do_it() + elif command == "delayed": + self.connection.send("6\r") + self.connection.expect("Delayed Reboot") + self._do_it() + elif command == "on": + self.connection.send("1\r") + self.connection.expect("Immediate On") + self._do_it() + elif command == "off": + self.connection.send("2\r") + self.connection.expect("Immediate Off") + self._do_it() + else: + logging.debug("Unknown command!") + + def _do_it(self): + self.connection.expect("Enter 'YES' to continue or <ENTER> to cancel :") + self.connection.send("YES\r") + self.connection.expect("Press <ENTER> to continue...") + self.connection.send("\r") + + def port_delayed(self, port_number): + self._port_interaction("delayed", port_number) + + def port_on(self, port_number): + self._port_interaction("on", port_number) + + def port_off(self, port_number): + self._port_interaction("off", port_number) + + def port_reboot(self, port_number): + self._port_interaction("reboot", port_number) + + +class apc8959(PDUDriver): + connection = None + pdu_commands = {"off": "olOff", "on": "olOn", "reboot": "olReboot", "delayed": "olDlyReboot"} + + def _pdu_logout(self): + logging.debug("logging out") + self.connection.send("\r") + self.connection.send("exit") + self.connection.send("\r") + logging.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)) + self._pdu_get_to_prompt() + self.connection.sendline(self.pdu_commands[command] + (" %i" % port_number)) + self.connection.expect("E000: Success") + logging.debug("done") + + def port_delayed(self, port_number): + self._port_interaction("delayed", port_number) + + def port_on(self, port_number): + self._port_interaction("on", port_number) + + def port_off(self, port_number): + self._port_interaction("off", port_number) + + def port_reboot(self, port_number): + self._port_interaction("reboot", port_number) diff --git a/lavaproxy/driver.py b/lavaproxy/driver.py new file mode 100644 index 0000000..bd36c18 --- /dev/null +++ b/lavaproxy/driver.py @@ -0,0 +1,27 @@ +#! /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. + + +class PDUDriver(): + connection = None + pdu_commands = {"off": "olOff", "on": "olOn", "reboot": "olReboot", "delayed": "olDlyReboot"} + + def __init__(self, connection): + self.connection = connection diff --git a/lavaproxy/engine.py b/lavaproxy/engine.py new file mode 100644 index 0000000..beb954f --- /dev/null +++ b/lavaproxy/engine.py @@ -0,0 +1,111 @@ +#! /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 pexpect +import os +import logging +import sys + +from apcdrivers import apc8959 +from apcdrivers import apc7952 + + +class PDUEngine(): + connection = None + prompt = 0 + driver = None + + def __init__(self, pdu_hostname, pdu_telnetport=23): + self.exec_string = "/usr/bin/telnet %s %d" % (pdu_hostname, pdu_telnetport) + logging.debug("Created new PDUEngine: %s" % self.exec_string) + #self.connection.logfile_read = sys.stdout + prompt = self._pdu_login("apc", "apc") + if prompt == 0: + logging.debug("Found a v5 prompt") + self.driver = apc8959(self.connection) + elif prompt == 1: + logging.debug("Found a v3 prompt") + self.driver = apc7952(self.connection) + else: + logging.debug("Unknown prompt!") + + def pduconnect(self): + self.connection = self.get_connection(self.exec_string) + + def pduclose(self): + self.connection.close(True) + + def pdureconnect(self): + self.pduclose() + self.pduconnect() + + def get_connection(self, exec_string): + connection = pexpect.spawn(exec_string) + connection.logfile = sys.stdout + return connection + + def is_busy(self): + if os.path.exists("/proc/%i" % self.connection.pid): + return True + return False + + def close(self): + self.driver._pdu_logout() + self.connection.close(True) + + def _pdu_login(self, username, password): + logging.debug("attempting login with username %s, password %s" % (username, password)) + self.pduconnect() + self.connection.send("\r") + self.connection.expect("User Name :") + self.connection.send("apc\r") + self.connection.expect("Password :") + self.connection.send("apc\r") + return self.connection.expect(["apc>", ">"]) + + +if __name__ == "__main__": + #pe1 = PDUEngine("pdu15") + #pe1.driver.port_off(22) + #pe1.driver.port_on(22) + #pe1.close() + #pe2 = PDUEngine("pdu14") + #pe2.driver.port_off(6) + #pe2.driver.port_on(6) + #pe2.close() + #pe3 = PDUEngine("pdu01") + #pe3.driver.port_reboot(1) + #pe3.driver.port_off(1) + #pe3.driver.port_on(1) + #pe3.close() + logging.basicConfig(level=logging.DEBUG) + logging.getLogger().setLevel(logging.DEBUG) + pe4 = PDUEngine("192.168.1.153") + pe4.driver.port_reboot(1) + pe4.driver.port_reboot(2) + pe4.driver.port_reboot(3) + pe4.driver.port_reboot(4) + pe4.driver.port_reboot(5) + pe4.driver.port_reboot(6) + pe4.driver.port_reboot(7) + pe4.driver.port_reboot(8) + #pe4.driver.port_off(8) + #pe4.driver.port_on(8) + pe4.close() diff --git a/lavaproxy/pdurunner.py b/lavaproxy/pdurunner.py new file mode 100644 index 0000000..cc2b19d --- /dev/null +++ b/lavaproxy/pdurunner.py @@ -0,0 +1,85 @@ +#! /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 logging +import time +from engine import PDUEngine +from socketserver import DBHandler + + +class PDURunner(): + + def __init__(self, config): + logging.basicConfig(level=config["logging_level"]) + logging.getLogger().setLevel(config["logging_level"]) + logging.getLogger().name = "PDURunner" + self.config = config + + def get_one(self, db): + job = db.get_next_job() + if job: + job_id, hostname, port, request = job + logging.info("Processing queue item: (%s %s) on hostname: %s" % (request, port, hostname)) + #logging.debug(id, hostname, request, port) + res = self.do_job(hostname, port, request) + db.delete_row(job_id) + else: + logging.debug("Found nothing to do in database") + + def do_job(self, hostname, port, request): + retries = 5 + while retries > 0: + try: + pe = PDUEngine(hostname, 23) + if request == "reboot": + pe.driver.port_reboot(port) + elif request == "on": + pe.driver.port_on(port) + elif request == "off": + pe.driver.port_off(port) + elif request == "delayed": + pe.driver.port_delayed(port) + else: + logging.debug("Unknown request type: %s" % request) + pe.pduclose() + retries = 0 + except: + logging.warn("Failed to execute job: %s %s %s (attempts left %i)" % (hostname, port, request, retries)) + #logging.warn(e) + time.sleep(5) + retries -= 1 + + def run_me(self): + logging.info("Starting up the PDURunner") + while 1: + db = DBHandler(self.config) + self.get_one(db) + db.close() + del(db) + time.sleep(2) + +if __name__ == "__main__": + starter = {"dbhost": "127.0.0.1", + "dbuser": "pdudaemon", + "dbpass": "pdudaemon", + "dbname": "lavapdu", + "logging_level": logging.DEBUG} + p = PDURunner(starter) + p.run_me() diff --git a/lavaproxy/proxyexample.py b/lavaproxy/proxyexample.py new file mode 100644 index 0000000..e11a4a0 --- /dev/null +++ b/lavaproxy/proxyexample.py @@ -0,0 +1,98 @@ +__author__ = 'matt' + +#!/usr/bin/python +# This is a simple port-forward / proxy, written using only the default python +# library. If you want to make a suggestion or fix something you can contact-me +# at voorloop_at_gmail.com +# Distributed over IDC(I Don't Care) license +import socket +import select +import time +import sys + +# Changing the buffer_size and delay, you can improve the speed and bandwidth. +# But when buffer get to high or delay go too down, you can broke things +buffer_size = 4096 +delay = 0.0001 +forward_to = ('smtp.zaz.ufsk.br', 25) + +class Forward: + def __init__(self): + self.forward = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + + def start(self, host, port): + try: + self.forward.connect((host, port)) + return self.forward + except Exception, e: + print e + return False + +class TheServer: + input_list = [] + channel = {} + + def __init__(self, host, port): + self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.server.bind((host, port)) + self.server.listen(200) + + def main_loop(self): + self.input_list.append(self.server) + while 1: + time.sleep(delay) + ss = select.select + inputready, outputready, exceptready = ss(self.input_list, [], []) + for self.s in inputready: + if self.s == self.server: + self.on_accept() + break + + self.data = self.s.recv(buffer_size) + if len(self.data) == 0: + self.on_close() + else: + self.on_recv() + + def on_accept(self): + forward = Forward().start(forward_to[0], forward_to[1]) + clientsock, clientaddr = self.server.accept() + if forward: + print clientaddr, "has connected" + self.input_list.append(clientsock) + self.input_list.append(forward) + self.channel[clientsock] = forward + self.channel[forward] = clientsock + else: + print "Can't establish connection with remote server.", + print "Closing connection with client side", clientaddr + clientsock.close() + + def on_close(self): + print self.s.getpeername(), "has disconnected" + #remove objects from input_list + self.input_list.remove(self.s) + self.input_list.remove(self.channel[self.s]) + out = self.channel[self.s] + # close the connection with client + self.channel[out].close() # equivalent to do self.s.close() + # close the connection with remote server + self.channel[self.s].close() + # delete both objects from channel dict + del self.channel[out] + del self.channel[self.s] + + def on_recv(self): + data = self.data + # here we can parse and/or modify the data before send forward + print data + self.channel[self.s].send(data) + +if __name__ == '__main__': + server = TheServer('', 9090) + try: + server.main_loop() + except KeyboardInterrupt: + print "Ctrl C - Stopping server" + sys.exit(1)
\ No newline at end of file diff --git a/lavaproxy/socketserver.py b/lavaproxy/socketserver.py new file mode 100644 index 0000000..a678207 --- /dev/null +++ b/lavaproxy/socketserver.py @@ -0,0 +1,80 @@ +#! /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 SocketServer +import logging +import socket + +class ListenerServer(object): + servers = [] + + def __init__(self, config): + logging.getLogger().name = "ManagementServer" + logging.getLogger().setLevel(config["logging_level"]) + self.management_server = TCPServer((config["hostname"], config["mgmt-port"]), TCPRequestHandler) +# for portnum in range(config["port-start"], config["port-end"]): +# self.servers.append(TCPServer((config["hostname"], portnum), TCPRequestHandler)) +# logging.info("listening on %s:%s" % (config["hostname"], portnum)) + + def start(self): + logging.info("Starting the Management Server") + self.management_server.serve_forever() + # for server in self.servers: + # server.serve_forever() + + +class TCPRequestHandler(SocketServer.BaseRequestHandler): + #"One instance per connection. Override handle(self) to customize action." + def handle(self): + logging.getLogger().name = "TCPRequestHandler" + ip = self.client_address[0] + logging.debug(self.client_address) + try: + data = self.request.recv(4096).strip() + socket.setdefaulttimeout(2) + try: + request_host = socket.gethostbyaddr(ip)[0] + except socket.herror as e: + logging.debug("Unable to resolve: %s error: %s" % (ip, e)) + request_host = ip + logging.info("Received a request from %s: '%s'" % (request_host, data)) + self.request.sendall("ack\n") + except Exception as e: + logging.debug(e) + self.request.sendall("nack\n") + self.request.close() + + +class TCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): + allow_reuse_address = True + daemon_threads = True + pass + +if __name__ == "__main__": + logging.basicConfig(level=logging.DEBUG) + logging.getLogger().setLevel(logging.DEBUG) + logging.debug("Executing from __main__") + starter = {"hostname": "0.0.0.0", + "port-start": 40001, + "port-end": 41000, + "mgmt-port": 40000, + "logging_level": logging.DEBUG} + ss = ListenerServer(starter) + ss.start() |