source: vanHelsing/trunk/bconsole.py@ 866

Last change on this file since 866 was 810, checked in by hmueller, on Jan 8, 2010 at 11:02:22 AM

bacula_repo removed

  • Property svn:executable set to *
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-python
File size: 5.5 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# simple illustration client/server pair; client program sends a string
5# to server, which echoes it back to the client (in multiple copies),
6# and the latter prints to the screen
7# this is the client
8import socket
9import sys
10import struct
11import re
12import time
13import md5
14
15PORT = 9101
16BUFSIZE = 1048576
17
18# BNET signals
19BNET_SIGNALS = {
20 'BNET_EOD' : -1, # End of data stream, new data may follow
21 'BNET_EOD_POLL' : -2, # End of data and poll all in one
22 'BNET_STATUS' : -3, # Send full status
23 'BNET_TERMINATE' : -4, # Conversation terminated, doing close()
24 'BNET_POLL' : -5, # Poll request, I'm hanging on a read
25 'BNET_HEARTBEAT' : -6, # Heartbeat Response requested
26 'BNET_HB_RESPONSE' : -7, # Only response permited to HB
27 'BNET_PROMPT' : -8, # Prompt for subcommand
28 'BNET_BTIME' : -9, # Send UTC btime
29 'BNET_BREAK' : -10, # Stop current command -- ctl-c
30 'BNET_START_SELECT' : -11, # Start of a selection list
31 'BNET_END_SELECT' : -12, # End of a select list
32 'BNET_INVALID_CMD' : -13, # Invalid command sent
33 'BNET_CMD_FAILED' : -14, # Command failed
34 'BNET_CMD_OK' : -15, # Command succeeded
35 'BNET_CMD_BEGIN' : -16, # Start command execution
36 'BNET_MSGS_PENDING' : -17, # Messages pending
37 'BNET_MAIN_PROMPT' : -18, # Server ready and waiting
38 'BNET_SELECT_INPUT' : -19, # Return selection input
39 'BNET_WARNING_MSG' : -20, # Warning message
40 'BNET_ERROR_MSG' : -21, # Error message -- command failed
41 'BNET_INFO_MSG' : -22, # Info message -- status line
42 'BNET_RUN_CMD' : -23, # Run command follows
43 'BNET_YESNO' : -24, # Request yes no response
44 'BNET_START_RTREE' : -25, # Start restore tree mode
45 'BNET_END_RTREE' : -26, # End restore tree mode
46}
47
48import clibbac
49
50class ConsoleError(IOError):
51 pass
52
53class Console:
54 """Class to connect with the bacula director as a console client
55 """
56
57 HELLO = r"Hello %s calling"
58 HELLO_OK = "1000 OK"
59 RXP_RESP = re.compile(
60 """^auth\scram-md5(?P<compatible>c?)\s
61 (?P<challenge>\S+)\s
62 ssl=(?P<tls>\d)""",
63 re.VERBOSE)
64
65 def __init__(self, host="bacula", port=PORT):
66 self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
67 self.socket.connect((host, port))
68 self.last_state = 0
69
70 def __del__(self):
71 """Destructor closes the network socket"""
72 self.socket.close()
73
74 def _send(self, data):
75 """Prepend size of data before the data string
76 and send it trough the socket"""
77 size = struct.pack("!i", len(data))
78 self.socket.send(size + data)
79
80 def _recv(self, bufsize=BUFSIZE):
81 """Recieve data from socket and strip the prepended
82 data size"""
83 r = self.socket.recv(4)
84 size = struct.unpack("!i", r)[0]
85 if size < 0:
86 self.last_state = size
87 r = ""
88 elif size + 4 > BUFSIZE:
89 raise ConsoleError("Buffer to small: %i" %size)
90 else:
91 r = self.socket.recv(size)
92 return r
93
94 def _recv_all(self):
95 """Gets all lines of a request"""
96 r = ""
97 s = self._recv()
98 while s:
99 r += s
100 s = self._recv()
101 return r
102
103 def login(self, username, password):
104 pw = md5.md5(password).hexdigest()
105
106 self._send(self.HELLO % username + "\n")
107 response = self._recv()
108
109 # Challenge from director
110 m = self.RXP_RESP.search(response)
111 challenge = clibbac.hmac_md5(m.group("challenge"), pw)
112 self._send(clibbac.bin_to_base64(challenge[:16], False))
113 resp = self._recv()
114 if not resp.startswith(self.HELLO_OK):
115 raise ConsoleError("Challenge: %s" % resp)
116
117 # now from client site
118 now = time.time()
119 respond = clibbac.bin_to_base64(
120 clibbac.hmac_md5("<%10.10f@bconsole>" % now, pw)[:16],
121 False)
122 self._send("auth cram-md5 <%10.10f@bconsole> ssl=0\n" % now)
123 resp = self._recv().rstrip("\x000")
124 if resp != respond:
125 print len(resp)
126 print len(respond)
127 raise ConsoleError("Respond: %s expected: %s" % (resp, respond))
128 self._send("1000 OK auth\n")
129
130 return self._recv()
131
132 def version(self):
133 """Returns the bacula director version string"""
134 self._send("version")
135 return self._recv_all().split("\n")[0]
136
137 def dotstatus(self):
138 self._send(".status dir current")
139 return self._recv_all()
140
141if __name__ == "__main__":
142 try:
143 host = sys.argv[1]
144 port = int(sys.argv[2])
145 except:
146 host = "bacula-devel"
147 port = 9101
148
149# print sys.path
150
151 console = Console(host, port)
152 console.login("python", "dass-it")
153
154 print console.version()
155 print console.dotstatus()
156
157
158#....Hello python calling
159#...7auth cram-md5 <1938954300.1244114680@bacula-dir> ssl=0
160#....XRx1dCJU36/UJD/l7TBZZC....
161#1000 OK auth
162#...4auth cram-md5 <238682207.1244114679@bconsole> ssl=0
163#....klIi6CczoW89Bl/wCA04wA....
164#1000 OK auth
165#...31000 OK: bacula-dir Version: 3.0.1 (30 April 2009)
Note: See TracBrowser for help on using the repository browser.