added pizza
[uccvend-vendserver.git] / sql-edition / servers / LATClient.py
1 from socket import *
2 from select import select
3 from os import popen4
4 from time import sleep
5 import logging
6
7 LATCP_SOCKET = '/var/run/latlogin'
8
9 LAT_VERSION = '1.22'
10 LATCP_CMD_VERSION = 8
11 LATCP_CMD_TERMINALSESSION = 26
12 LATCP_CMD_ERRORMSG = 99
13
14 class LATClientException(Exception): pass
15
16 def read_for_a_bit(rfh):
17         message = ''
18         while 1:
19                 r = select([rfh], [], [], 5.0)[0]
20                 if r:
21                         try:
22                                 ch = rfh.read(1)
23                         except socket.error:
24                                 ch = ''
25                         if ch == '':
26                                 break
27                         message = message + ch
28                 else:
29                         break
30         logging.debug("Received message: ", repr(message))
31         return message
32
33 def write_and_get_response(rfh, wfh, message, expect_echo=True):
34         logging.debug("Writing message:", repr(message))
35         wfh.write(message+'\r\n')
36         wfh.flush()
37         logging.debug("  --> Sent")
38         response = read_for_a_bit(rfh)
39         if response.find(message) == -1 and expect_echo:
40                 raise LATClientException("Talking to DEC server, expected to find original message in echo but didn't")
41         return response
42
43 class LATClient:
44         def __init__(self, service = None, node = None, port = None,
45                      localport = None, password = None, is_queued = False,
46                      server_name = '', connect_password='', priv_password=''):
47
48                 self.server_name = server_name
49                 self.connect_password = connect_password
50                 self.priv_password = priv_password
51                 
52                 self.sock = socket(AF_UNIX, SOCK_STREAM, 0);
53                 self.sock.connect(LATCP_SOCKET)
54                 self.send_msg(LATCP_CMD_VERSION, LAT_VERSION+'\000')
55                 (cmd, msg) = self.read_reply()
56                 if service == None: service = ''
57                 if node == None: node = ''
58                 if port == None: port = ''
59                 if localport == None: localport = ''
60                 if password == None: password = ''
61                 if is_queued == True:
62                         is_queued = 1
63                 else:
64                         is_queued = 0
65                 self.send_msg(LATCP_CMD_TERMINALSESSION, '%c%c%s%c%s%c%s%c%s%c%s' % \
66                         (is_queued,
67                          len(service), service,
68                          len(node), node,
69                          len(port), port,
70                          len(localport), localport,
71                          len(password), password
72                          ))
73                 (cmd, msg) = self.read_reply()
74                 if ord(cmd) == LATCP_CMD_ERRORMSG:
75                         raise LATClientException(msg)
76
77                 self.rfh = self.sock.makefile('r')
78                 self.wfh = self.sock.makefile('w')
79
80                 r = select([self.rfh], [], [], 2.0)[0]
81                 if r:
82                         l = self.rfh.readline()
83                         if l.find('Service in use') >= 0:
84                                 logging.warning("Service in use, apparently: restarting DEC server")
85                                 self.reboot_server()
86
87         def __del__(self):
88                 try:
89                         self.sock.close()
90                         self.sock.shutdown(2)
91                 except:
92                         pass
93                 del self.sock
94
95         def send_msg(self, cmd, msg):
96                 self.sock.send('%c%c%c%s'%(cmd, len(msg)/256, len(msg)%256, msg))
97
98         def reboot_server(self):
99                 self.sock.shutdown(2)
100                 self.sock.close()
101                 
102                 logging.info('Logging into DEC server')
103                 mopw, mopr = popen4('/usr/sbin/moprc '+self.server_name)
104                 write_and_get_response(mopr, mopw, '')
105
106                 logging.info('Sending password')
107                 r = write_and_get_response(mopr, mopw, self.connect_password, False)
108                 if r.find('Enter username> ') == -1:
109                         logging.warning("Expected username prompt, got " + repr(r))
110                         raise LATClientException('failed to reboot server')
111
112                 logging.info('Sending username')
113                 r = write_and_get_response(mopr, mopw, 'grim reaper')
114                 if r.find('Local> ') == -1:
115                         logging.warning("Expected DEC server prompt, got " + repr(r))
116                         raise LATClientException('failed to reboot server')
117
118                 logging.info('Requesting privileges')
119                 r = write_and_get_response(mopr, mopw, 'set priv')
120                 if r.find('Password> ') == -1:
121                         logging.warning("Expected priv password prompt, got " + repr(r))
122                         raise LATClientException('failed to reboot server')
123
124                 logging.info('Sending password')
125                 r = write_and_get_response(mopr, mopw, self.priv_password, False)
126                 if r.find('Local> ') == -1:
127                         logging.warning("Expected DEC server prompt, got " + repr(r))
128                         raise LATClientException('failed to reboot server')
129
130                 logging.info('Sending reboot request')
131                 r = write_and_get_response(mopr, mopw, 'init del 0')
132                 if r.find('Target does not respond') == -1:
133                         logging.warning("Expected DEC server to die, got " + repr(r))
134                         raise LATClientException('failed to reboot server')
135
136                 logging.info('Closed connection to server')
137                 mopr.close()
138                 mopw.close()
139                 logging.info("Waiting 10 seconds for DEC server to come back to life...")
140                 sleep(10)
141                 logging.info("Rightyo, back to vending!")
142                 raise LATClientException('needed to reboot server')
143
144         def read_reply(self):
145                 head = self.sock.recv(3)
146                 if len(head) != 3:
147                         raise LATClientException('Short LAT packet')
148                 cmd = head[0]
149                 length = ord(head[1])*256 + ord(head[2])
150                 msg = self.sock.recv(length)
151                 if cmd == LATCP_CMD_ERRORMSG:
152                         raise LATClientException('Received LAT error: %s'%msg)
153                 return (cmd, msg)
154         
155         def get_fh(self):
156                 return (self.rfh, self.wfh)

UCC git Repository :: git.ucc.asn.au