X-Git-Url: https://git.ucc.asn.au/?p=uccvend-vendserver.git;a=blobdiff_plain;f=VendServer%2FLATClient.py;fp=VendServer%2FLATClient.py;h=638d20b05bc1f3a136a93f2c5fd415f964c1048e;hp=0000000000000000000000000000000000000000;hb=6c130dc942392ccc8b7ffa0ec2ede5f9327f99e6;hpb=e423f11f190d685156cb557319b169d2b79b752f diff --git a/VendServer/LATClient.py b/VendServer/LATClient.py new file mode 100644 index 0000000..638d20b --- /dev/null +++ b/VendServer/LATClient.py @@ -0,0 +1,157 @@ +from socket import * +from select import select +from os import popen4 +from time import sleep +import logging + +LATCP_SOCKET = '/var/run/latlogin' + +LAT_VERSION = '1.22' +LAT_VERSION = '1.24' # for running on Mermaid. [DAA] 20071107 +LATCP_CMD_VERSION = 8 +LATCP_CMD_TERMINALSESSION = 26 +LATCP_CMD_ERRORMSG = 99 + +class LATClientException(Exception): pass + +def read_for_a_bit(rfh): + message = '' + while 1: + r = select([rfh], [], [], 5.0)[0] + if r: + try: + ch = rfh.read(1) + except socket.error: + ch = '' + if ch == '': + break + message = message + ch + else: + break + logging.debug("Received message: ", repr(message)) + return message + +def write_and_get_response(rfh, wfh, message, expect_echo=True): + logging.debug("Writing message:", repr(message)) + wfh.write(message+'\r\n') + wfh.flush() + logging.debug(" --> Sent") + response = read_for_a_bit(rfh) + if response.find(message) == -1 and expect_echo: + raise LATClientException("Talking to DEC server, expected to find original message in echo but didn't") + return response + +class LATClient: + def __init__(self, service = None, node = None, port = None, + localport = None, password = None, is_queued = False, + server_name = '', connect_password='', priv_password=''): + + self.server_name = server_name + self.connect_password = connect_password + self.priv_password = priv_password + + self.sock = socket(AF_UNIX, SOCK_STREAM, 0); + self.sock.connect(LATCP_SOCKET) + self.send_msg(LATCP_CMD_VERSION, LAT_VERSION+'\000') + (cmd, msg) = self.read_reply() + if service == None: service = '' + if node == None: node = '' + if port == None: port = '' + if localport == None: localport = '' + if password == None: password = '' + if is_queued == True: + is_queued = 1 + else: + is_queued = 0 + self.send_msg(LATCP_CMD_TERMINALSESSION, '%c%c%s%c%s%c%s%c%s%c%s' % \ + (is_queued, + len(service), service, + len(node), node, + len(port), port, + len(localport), localport, + len(password), password + )) + (cmd, msg) = self.read_reply() + if ord(cmd) == LATCP_CMD_ERRORMSG: + raise LATClientException(msg) + + self.rfh = self.sock.makefile('r') + self.wfh = self.sock.makefile('w') + + r = select([self.rfh], [], [], 2.0)[0] + if r: + l = self.rfh.readline() + if l.find('Service in use') >= 0: + logging.warning("Service in use, apparently: restarting DEC server") + self.reboot_server() + + def __del__(self): + try: + self.sock.close() + self.sock.shutdown(2) + except: + pass + del self.sock + + def send_msg(self, cmd, msg): + self.sock.send('%c%c%c%s'%(cmd, len(msg)/256, len(msg)%256, msg)) + + def reboot_server(self): + self.sock.shutdown(2) + self.sock.close() + + logging.info('Logging into DEC server') + mopw, mopr = popen4('/usr/sbin/moprc '+self.server_name) + write_and_get_response(mopr, mopw, '') + + logging.info('Sending password') + r = write_and_get_response(mopr, mopw, self.connect_password, False) + if r.find('Enter username> ') == -1: + logging.warning("Expected username prompt, got " + repr(r)) + raise LATClientException('failed to reboot server') + + logging.info('Sending username') + r = write_and_get_response(mopr, mopw, 'grim reaper') + if r.find('Local> ') == -1: + logging.warning("Expected DEC server prompt, got " + repr(r)) + raise LATClientException('failed to reboot server') + + logging.info('Requesting privileges') + r = write_and_get_response(mopr, mopw, 'set priv') + if r.find('Password> ') == -1: + logging.warning("Expected priv password prompt, got " + repr(r)) + raise LATClientException('failed to reboot server') + + logging.info('Sending password') + r = write_and_get_response(mopr, mopw, self.priv_password, False) + if r.find('Local> ') == -1: + logging.warning("Expected DEC server prompt, got " + repr(r)) + raise LATClientException('failed to reboot server') + + logging.info('Sending reboot request') + r = write_and_get_response(mopr, mopw, 'init del 0') + if r.find('Target does not respond') == -1: + logging.warning("Expected DEC server to die, got " + repr(r)) + raise LATClientException('failed to reboot server') + + logging.info('Closed connection to server') + mopr.close() + mopw.close() + logging.info("Waiting 10 seconds for DEC server to come back to life...") + sleep(10) + logging.info("Rightyo, back to vending!") + raise LATClientException('needed to reboot server') + + def read_reply(self): + head = self.sock.recv(3) + if len(head) != 3: + raise LATClientException('Short LAT packet') + cmd = head[0] + length = ord(head[1])*256 + ord(head[2]) + msg = self.sock.recv(length) + if cmd == LATCP_CMD_ERRORMSG: + raise LATClientException('Received LAT error: %s'%msg) + return (cmd, msg) + + def get_fh(self): + return (self.rfh, self.wfh)