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

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