annotate bitten/util/beep.py @ 93:b289e572bc7e

Improved logging; the build master can now optionally log to a file. Closes #13.
author cmlenz
date Fri, 15 Jul 2005 13:59:54 +0000
parents 2e090827c63a
children 1984b2e01998
rev   line source
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
1 # -*- coding: iso8859-1 -*-
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
2 #
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
3 # Copyright (C) 2005 Christopher Lenz <cmlenz@gmx.de>
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
4 #
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
5 # Bitten is free software; you can redistribute it and/or
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
6 # modify it under the terms of the GNU General Public License as
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
7 # published by the Free Software Foundation; either version 2 of the
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
8 # License, or (at your option) any later version.
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
9 #
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
10 # Trac is distributed in the hope that it will be useful,
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
13 # General Public License for more details.
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
14 #
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
15 # You should have received a copy of the GNU General Public License
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
16 # along with this program; if not, write to the Free Software
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
18 #
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
19 # Author: Christopher Lenz <cmlenz@gmx.de>
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
20
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
21 """Minimal implementation of the BEEP protocol (IETF RFC 3080) based on the
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
22 `asyncore` module.
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
23
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
24 Current limitations:
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
25 * No support for the TSL and SASL profiles.
33
d8d44216258a Exit the slave script when the master disconnects; and other minor fixes.
cmlenz
parents: 29
diff changeset
26 * No support for mapping frames (SEQ frames for TCP mapping).
d8d44216258a Exit the slave script when the master disconnects; and other minor fixes.
cmlenz
parents: 29
diff changeset
27 * No localization support (xml:lang attribute).
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
28 """
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
29
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
30 import asynchat
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
31 import asyncore
18
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
32 import bisect
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
33 import email
15
06207499c58c * Use logging in the BEEP core as well as in the master and slave scripts. Closes #4.
cmlenz
parents: 14
diff changeset
34 import logging
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
35 import socket
83
42970c14524a Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents: 80
diff changeset
36 try:
42970c14524a Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents: 80
diff changeset
37 set
42970c14524a Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents: 80
diff changeset
38 except NameError:
42970c14524a Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents: 80
diff changeset
39 from sets import Set as set
90
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
40 try:
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
41 from cStringIO import StringIO
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
42 except ImportError:
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
43 from StringIO import StringIO
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
44 import sys
14
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
45 import time
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
46
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
47 from bitten.util import xmlio
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
48
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
49 __all__ = ['Listener', 'Initiator', 'Payload', 'ProfileHandler',
80
dc1c7fc9b915 Record the output of build steps in the database. See #12. Still need to get better granularity in transmitting the log output from slave to master before #12 can be closed.
cmlenz
parents: 62
diff changeset
50 'ProtocolError']
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
51
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
52 BEEP_XML = 'application/beep+xml'
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
53
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
54 log = logging.getLogger('bitten.beep')
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
55
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
56
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
57 class ProtocolError(Exception):
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
58 """Generic root class for BEEP exceptions."""
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
59
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
60
13
21aa17f97522 Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents: 12
diff changeset
61 class TerminateSession(Exception):
21aa17f97522 Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents: 12
diff changeset
62 """Signal termination of a session."""
21aa17f97522 Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents: 12
diff changeset
63
21aa17f97522 Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents: 12
diff changeset
64
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
65 class Listener(asyncore.dispatcher):
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
66 """BEEP peer in the listener role.
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
67
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
68 This peer opens a socket for listening to incoming connections. For each
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
69 connection, it opens a new session: an instance of `Session` that handle
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
70 communication with the connected peer.
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
71 """
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
72 def __init__(self, ip, port):
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
73 asyncore.dispatcher.__init__(self)
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
74 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
75 self.set_reuse_addr()
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
76 self.bind((ip, port))
34
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
77 self.sessions = []
24
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
78 self.profiles = {} # Mapping from URIs to ProfileHandler sub-classes
18
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
79 self.eventqueue = []
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
80 log.debug('Listening to connections on %s:%d', ip, port)
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
81 self.listen(5)
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
82
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
83 def writable(self):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
84 """Called by asyncore to determine whether the channel is writable."""
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
85 return False
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
86
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
87 def handle_read(self):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
88 """Called by asyncore to signal data available for reading."""
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
89 pass
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
90
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
91 def readable(self):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
92 """Called by asyncore to determine whether the channel is readable."""
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
93 return True
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
94
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
95 def handle_accept(self):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
96 """Start a new BEEP session initiated by a peer."""
15
06207499c58c * Use logging in the BEEP core as well as in the master and slave scripts. Closes #4.
cmlenz
parents: 14
diff changeset
97 conn, (ip, port) = self.accept()
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
98 log.debug('Connected to %s:%d', ip, port)
34
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
99 self.sessions.append(Session(self, conn, (ip, port), self.profiles,
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
100 first_channelno=2))
18
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
101
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
102 def run(self, timeout=15.0, granularity=5):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
103 """Start listening to incoming connections."""
18
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
104 socket_map = asyncore.socket_map
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
105 last_event_check = 0
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
106 while socket_map:
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
107 now = int(time.time())
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
108 if (now - last_event_check) >= granularity:
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
109 last_event_check = now
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
110 fired = []
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
111 i = j = 0
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
112 while i < len(self.eventqueue):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
113 when, callback = self.eventqueue[i]
18
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
114 if now >= when:
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
115 fired.append(callback)
18
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
116 j = i + 1
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
117 else:
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
118 break
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
119 i = i + 1
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
120 if fired:
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
121 self.eventqueue = self.eventqueue[j:]
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
122 for callback in fired:
92
2e090827c63a Delete snapshots for builds that have been completed by all configured target platforms, and are thus no longer needed. Closes #20.
cmlenz
parents: 90
diff changeset
123 callback(now)
18
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
124 asyncore.poll(timeout)
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
125
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
126 def schedule(self, delta, callback):
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
127 """Schedule a function to be called.
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
128
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
129 @param delta: The number of seconds after which the callback should be
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
130 invoked
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
131 @param callback: The function to call
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
132 """
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
133 bisect.insort(self.eventqueue, (int(time.time()) + delta, callback))
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
134
34
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
135 def quit(self):
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
136 if not self.sessions:
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
137 self.close()
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
138 return
92
2e090827c63a Delete snapshots for builds that have been completed by all configured target platforms, and are thus no longer needed. Closes #20.
cmlenz
parents: 90
diff changeset
139 def terminate_next_session(when):
34
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
140 session = self.sessions[-1]
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
141 def handle_ok():
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
142 if self.sessions:
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
143 terminate_next_session()
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
144 else:
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
145 self.close()
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
146 def handle_error(channelno, code, message):
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
147 log.error('Failed to close channel %d', channelno)
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
148 log.debug('Closing session with %s', session.addr)
34
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
149 session.terminate(handle_ok=handle_ok)
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
150 self.schedule(0, terminate_next_session)
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
151 self.run(.5)
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
152
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
153
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
154 class Session(asynchat.async_chat):
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
155 """A BEEP session between two peers."""
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
156
18
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
157 def __init__(self, listener=None, conn=None, addr=None, profiles=None,
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
158 first_channelno=1):
24
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
159 """Create the BEEP session.
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
160
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
161 @param listener: The `Listener` this session belongs to, or `None` for
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
162 a session by the initiating peer
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
163 @param conn: The connection
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
164 @param addr: The address of the remote peer, a (IP-address, port) tuple
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
165 @param profiles: A dictionary of supported profiles; the keys are the
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
166 URIs of the profiles, the values are corresponding
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
167 sub-classes of `ProfileHandler`
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
168 @param first_channelno: The first channel number to request; 0 for the
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
169 peer in the listening role, 1 for initiators
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
170 """
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
171 asynchat.async_chat.__init__(self, conn)
18
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
172 self.listener = listener
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
173 self.addr = addr
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
174 self.set_terminator('\r\n')
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
175
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
176 self.profiles = profiles or {}
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
177 self.inbuf = []
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
178 self.header = self.payload = None
34
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
179
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
180 self.channelno = cycle_through(first_channelno, 2147483647, step=2)
24
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
181 self.channels = {0: Channel(self, 0, ManagementProfileHandler)}
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
182
34
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
183 def close(self):
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
184 if self.listener:
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
185 log.debug('Closing connection to %s:%s', self.addr[0], self.addr[1])
34
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
186 self.listener.sessions.remove(self)
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
187 else:
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
188 log.info('Session terminated')
34
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
189 asynchat.async_chat.close(self)
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
190
62
d108f780b76c Fixes to the BEEP implementation:
cmlenz
parents: 53
diff changeset
191 def handle_close(self):
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
192 log.warning('Peer %s:%s closed connection' % self.addr)
62
d108f780b76c Fixes to the BEEP implementation:
cmlenz
parents: 53
diff changeset
193 channels = self.channels.keys()
d108f780b76c Fixes to the BEEP implementation:
cmlenz
parents: 53
diff changeset
194 channels.reverse()
d108f780b76c Fixes to the BEEP implementation:
cmlenz
parents: 53
diff changeset
195 for channelno in channels:
d108f780b76c Fixes to the BEEP implementation:
cmlenz
parents: 53
diff changeset
196 self.channels[channelno].close()
d108f780b76c Fixes to the BEEP implementation:
cmlenz
parents: 53
diff changeset
197 asynchat.async_chat.handle_close(self)
d108f780b76c Fixes to the BEEP implementation:
cmlenz
parents: 53
diff changeset
198
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
199 def handle_error(self):
13
21aa17f97522 Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents: 12
diff changeset
200 """Called by asyncore when an exception is raised."""
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
201 cls, value = sys.exc_info()[:2]
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
202 if cls is TerminateSession:
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
203 raise cls, value
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
204 log.exception(value)
15
06207499c58c * Use logging in the BEEP core as well as in the master and slave scripts. Closes #4.
cmlenz
parents: 14
diff changeset
205 self.close()
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
206
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
207 def collect_incoming_data(self, data):
13
21aa17f97522 Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents: 12
diff changeset
208 """Called by async_chat when data is received.
21aa17f97522 Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents: 12
diff changeset
209
21aa17f97522 Initial code for build master and slave... these don't do a lot yet.
cmlenz
parents: 12
diff changeset
210 Buffer the data and wait until a terminator is found."""
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
211 self.inbuf.append(data)
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
212
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
213 def found_terminator(self):
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
214 """Called by async_chat when a terminator is found in the input
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
215 stream.
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
216
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
217 Parse the incoming data depending on whether it terminated on the frame
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
218 header, playload or trailer. For the header, extract the payload size
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
219 parameter and use it as terminator or the payload. When the trailer has
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
220 been received, delegate to `_handle_frame()`.
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
221 """
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
222 if self.header is None:
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
223 # Frame header received
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
224 self.header = ''.join(self.inbuf).split(' ')
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
225 self.inbuf = []
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
226 if self.header[0] == 'SEQ':
23
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
227 size = 0
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
228 else:
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
229 # Extract payload size to use as next terminator
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
230 try:
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
231 size = int(self.header[int(self.header[0] != 'ANS') - 2])
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
232 except ValueError:
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
233 # TODO: Malformed frame... should we terminate the session
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
234 # here?
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
235 log.error('Malformed frame header: [%s]',
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
236 ' '.join(self.header))
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
237 self.header = None
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
238 return
23
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
239 if size == 0:
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
240 self.payload = ''
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
241 self.set_terminator('END\r\n')
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
242 else:
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
243 self.set_terminator(size)
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
244 elif self.payload is None:
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
245 # Frame payload received
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
246 self.payload = ''.join(self.inbuf)
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
247 self.inbuf = []
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
248 self.set_terminator('END\r\n')
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
249 else:
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
250 # Frame trailer received
14
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
251 try:
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
252 self._handle_frame(self.header, self.payload)
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
253 finally:
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
254 self.header = self.payload = None
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
255 self.inbuf = []
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
256 self.set_terminator('\r\n')
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
257
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
258 def _handle_frame(self, header, payload):
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
259 """Handle an incoming frame.
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
260
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
261 This parses the frame header and decides which channel to pass it to.
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
262 """
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
263 log.debug('Handling frame [%s]', ' '.join(header))
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
264 msgno = None
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
265 channel = None
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
266 try:
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
267 cmd = header[0].upper()
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
268 channel = int(header[1])
23
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
269 if cmd == 'SEQ':
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
270 ackno = int(header[2])
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
271 window = int(header[3])
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
272 self.channels[channel].handle_seq_frame(ackno, window)
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
273 else:
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
274 msgno = int(header[2])
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
275 more = header[3] == '*'
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
276 seqno = int(header[4])
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
277 ansno = None
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
278 if cmd == 'ANS':
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
279 ansno = int(header[6])
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
280 self.channels[channel].handle_data_frame(cmd, msgno, more,
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
281 seqno, ansno, payload)
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
282 except (ValueError, TypeError, ProtocolError), e:
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
283 log.exception(e)
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
284 if channel == 0 and msgno is not None:
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
285 self.channels[0].profile.send_error(msgno, 550, e)
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
286
34
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
287 def terminate(self, handle_ok=None, handle_error=None):
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
288 """Terminate the session by closing all channels."""
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
289 def close_next_channel():
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
290 channelno = max(self.channels.keys())
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
291 def _handle_ok():
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
292 if channelno == 0:
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
293 if handle_ok is not None:
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
294 handle_ok()
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
295 else:
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
296 close_next_channel()
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
297 def _handle_error(code, message):
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
298 log.error('Peer refused to close channel %d: %s (%d)',
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
299 channelno, message, code)
34
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
300 if handle_error is not None:
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
301 handle_error(channelno, code, message)
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
302 else:
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
303 raise ProtocolError, '%s (%d)' % (message, code)
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
304 self.channels[0].profile.send_close(channelno, handle_ok=_handle_ok,
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
305 handle_error=_handle_error)
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
306 close_next_channel()
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
307
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
308
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
309 class Initiator(Session):
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
310 """Root class for BEEP peers in the initiating role."""
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
311
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
312 def __init__(self, ip, port, profiles=None):
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
313 """Create the BEEP session.
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
314
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
315 @param ip: The IP address to connect to
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
316 @param port: The port to connect to
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
317 @param profiles: A dictionary of the supported profiles, where the key
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
318 is the URI identifying the profile, and the value is a
34
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
319 `ProfileHandler` sub-class that will be instantiated to
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
320 handle the communication for that profile
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
321 """
18
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
322 Session.__init__(self, profiles=profiles or {})
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
323 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
324 log.debug('Connecting to %s:%s', ip, port)
34
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
325 self.addr = (ip, port)
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
326 self.connect(self.addr)
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
327
34
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
328 def handle_connect(self):
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
329 """Called by asyncore when the connection is established."""
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
330 log.debug('Connected to peer at %s:%s', self.addr[0], self.addr[1])
14
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
331
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
332 def greeting_received(self, profiles):
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
333 """Sub-classes should override this to start the channels they need.
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
334
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
335 @param profiles: A list of URIs of the profiles the peer claims to
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
336 support.
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
337 """
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
338 pass
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
339
14
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
340 def run(self):
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
341 """Start this peer, which will try to connect to the server and send a
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
342 greeting.
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
343 """
34
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
344 try:
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
345 asyncore.loop()
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
346 except TerminateSession, e:
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
347 log.info('Terminating session')
34
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
348 self.terminate()
14
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
349
34
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
350 def quit(self):
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
351 self.terminate()
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
352 asyncore.loop(timeout=10)
14
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
353
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
354
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
355 class Channel(object):
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
356 """A specific channel of a BEEP session."""
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
357
24
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
358 def __init__(self, session, channelno, profile_cls):
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
359 """Create the channel.
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
360
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
361 @param session The `Session` object that the channel belongs to
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
362 @param channelno The channel number
24
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
363 @param profile The associated `ProfileHandler` class
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
364 """
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
365 self.session = session
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
366 self.channelno = channelno
23
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
367 self.windowsize = 4096
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
368 self.inqueue = {}
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
369 self.reply_handlers = {}
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
370
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
371 self.msgno = cycle_through(0, 2147483647)
83
42970c14524a Perform slave/platform matching at slave registration. Use builtin {{{set}}} type on Python >= 2.4.
cmlenz
parents: 80
diff changeset
372 self.msgnos = set() # message numbers currently in use
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
373 self.ansnos = {} # answer numbers keyed by msgno, each 0-2147483647
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
374
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
375 # incoming, outgoing sequence numbers
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
376 self.seqno = [SerialNumber(), SerialNumber()]
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
377
27
a8e509f4d33b Added a couple of unit tests for the BEEP management profile. See #2. More to come.
cmlenz
parents: 24
diff changeset
378 self.profile = profile_cls(self)
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
379 self.profile.handle_connect()
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
380
24
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
381 def close(self):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
382 """Close the channel."""
24
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
383 self.profile.handle_disconnect()
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
384 del self.session.channels[self.channelno]
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
385
23
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
386 def handle_seq_frame(self, ackno, window):
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
387 """Process a TCP mapping frame (SEQ).
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
388
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
389 @param ackno: the value of the next sequence number that the sender is
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
390 expecting to receive on this channel
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
391 @param window: window size, the number of payload octets per frame that
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
392 the sender is expecting to receive on this channel
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
393 """
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
394 self.windowsize = window
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
395
1a7b9044b0a5 Basic TCP mapping and message fragmenting support. See #1.
cmlenz
parents: 18
diff changeset
396 def handle_data_frame(self, cmd, msgno, more, seqno, ansno, payload):
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
397 """Process a single data frame.
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
398
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
399 @param cmd: The frame keyword (MSG, RPY, ERR, ANS or NUL)
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
400 @param msgno: The message number
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
401 @param more: `True` if more frames are pending for this message
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
402 @param seqno: Sequence number of the frame
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
403 @param ansno: The answer number for 'ANS' messages, otherwise `None`
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
404 @param payload: The frame payload as a string
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
405 """
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
406 # Validate and update sequence number
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
407 if seqno != self.seqno[0]:
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
408 raise ProtocolError, 'Out of sync with peer' # TODO: Be nice
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
409 self.seqno[0] += len(payload)
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
410
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
411 if more:
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
412 # More of this message pending, so push it on the queue
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
413 self.inqueue.setdefault(msgno, []).append(payload)
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
414 return
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
415
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
416 # Complete message received, so handle it
27
a8e509f4d33b Added a couple of unit tests for the BEEP management profile. See #2. More to come.
cmlenz
parents: 24
diff changeset
417 if msgno in self.inqueue:
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
418 # Recombine queued messages
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
419 payload = ''.join(self.inqueue[msgno]) + payload
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
420 del self.inqueue[msgno]
62
d108f780b76c Fixes to the BEEP implementation:
cmlenz
parents: 53
diff changeset
421 if cmd in ('ERR', 'RPY', 'NUL') and msgno in self.msgnos:
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
422 # Final reply using this message number, so dealloc
46
f7bbf9d2bbe7 Use a set instead of a dictionary for keeping track of message numbers.
cmlenz
parents: 39
diff changeset
423 self.msgnos.remove(msgno)
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
424 if payload:
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
425 payload = Payload.parse(payload)
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
426 else:
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
427 payload = None
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
428
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
429 if cmd == 'MSG':
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
430 self.profile.handle_msg(msgno, payload)
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
431 else:
27
a8e509f4d33b Added a couple of unit tests for the BEEP management profile. See #2. More to come.
cmlenz
parents: 24
diff changeset
432 if msgno in self.reply_handlers:
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
433 try:
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
434 self.reply_handlers[msgno](cmd, msgno, ansno, payload)
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
435 finally:
53
f8a678d08296 Pass answer number to reply handlers
cmlenz
parents: 51
diff changeset
436 if cmd != 'ANS':
f8a678d08296 Pass answer number to reply handlers
cmlenz
parents: 51
diff changeset
437 del self.reply_handlers[msgno]
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
438 elif cmd == 'RPY':
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
439 self.profile.handle_rpy(msgno, payload)
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
440 elif cmd == 'ERR':
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
441 self.profile.handle_err(msgno, payload)
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
442 elif cmd == 'ANS':
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
443 self.profile.handle_ans(msgno, ansno, payload)
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
444 elif cmd == 'NUL':
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
445 self.profile.handle_nul(msgno)
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
446
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
447 def send_msg(self, payload, handle_reply=None):
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
448 """Send a MSG frame to the peer.
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
449
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
450 @param payload: The message payload (a `Payload` instance)
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
451 @param handle_reply: A function that is called when a reply to this
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
452 message is received
89
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
453 @return: the message number assigned to the message
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
454 """
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
455 while True: # Find a unique message number
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
456 msgno = self.msgno.next()
27
a8e509f4d33b Added a couple of unit tests for the BEEP management profile. See #2. More to come.
cmlenz
parents: 24
diff changeset
457 if msgno not in self.msgnos:
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
458 break
46
f7bbf9d2bbe7 Use a set instead of a dictionary for keeping track of message numbers.
cmlenz
parents: 39
diff changeset
459 self.msgnos.add(msgno) # Flag the chosen message number as in use
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
460 if handle_reply is not None:
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
461 self.reply_handlers[msgno] = handle_reply
89
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
462 self.session.push_with_producer(FrameProducer(self, 'MSG', msgno, None,
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
463 payload))
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
464 return msgno
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
465
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
466 def send_rpy(self, msgno, payload):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
467 """Send a RPY frame to the peer.
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
468
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
469 @param msgno: The number of the message this reply is in reference to
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
470 @param payload: The message payload (a `Payload` instance)
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
471 """
89
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
472 self.session.push_with_producer(FrameProducer(self, 'RPY', msgno, None,
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
473 payload))
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
474
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
475 def send_err(self, msgno, payload):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
476 """Send an ERR frame to the peer.
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
477
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
478 @param msgno: The number of the message this reply is in reference to
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
479 @param payload: The message payload (a `Payload` instance)
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
480 """
89
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
481 self.session.push_with_producer(FrameProducer(self, 'ERR', msgno, None,
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
482 payload))
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
483
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
484 def send_ans(self, msgno, payload):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
485 """Send an ANS frame to the peer.
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
486
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
487 @param msgno: The number of the message this reply is in reference to
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
488 @param payload: The message payload (a `Payload` instance)
89
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
489 @return: the answer number assigned to the answer
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
490 """
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
491 ansnos = self.ansnos.setdefault(msgno, cycle_through(0, 2147483647))
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
492 next_ansno = ansnos.next()
89
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
493 self.session.push_with_producer(FrameProducer(self, 'ANS', msgno,
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
494 next_ansno, payload))
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
495 return next_ansno
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
496
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
497 def send_nul(self, msgno):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
498 """Send a NUL frame to the peer.
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
499
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
500 @param msgno: The number of the message this reply is in reference to
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
501 """
89
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
502 self.session.push_with_producer(FrameProducer(self, 'NUL', msgno))
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
503 del self.ansnos[msgno] # dealloc answer numbers for the message
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
504
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
505
89
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
506 class FrameProducer(object):
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
507 """Internal class that emits the frames of a BEEP message, based on the
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
508 `asynchat` `push_with_producer()` protocol.
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
509 """
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
510
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
511 def __init__(self, channel, cmd, msgno, ansno=None, payload=None):
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
512 """Initialize the frame producer.
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
513
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
514 @param channel the channel the message is to be sent on
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
515 @param cmd the BEEP command/keyword (MSG, RPY, ERR, ANS or NUL)
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
516 @param msgno the message number
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
517 @param ansno the answer number (only for ANS messages)
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
518 @param payload the message payload (an instance of `Payload`)
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
519 """
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
520 self.session = channel.session
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
521 self.channel = channel
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
522 self.cmd = cmd
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
523 self.msgno = msgno
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
524 self.ansno = ansno
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
525
90
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
526 self.payload = payload
89
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
527 self.done = False
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
528
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
529 def more(self):
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
530 """Called by `async_chat` when the producer has been pushed on the
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
531 producer FIFO and the channel is about to write."""
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
532 if self.done:
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
533 return ''
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
534
90
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
535 if self.payload:
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
536 data = self.payload.read(self.channel.windowsize)
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
537 if len(data) < self.channel.windowsize:
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
538 self.done = True
89
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
539 else:
90
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
540 data = ''
89
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
541 self.done = True
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
542
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
543 headerbits = [self.cmd, self.channel.channelno, self.msgno,
90
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
544 self.done and '.' or '*', self.channel.seqno[1].value,
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
545 len(data)]
89
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
546 if self.cmd == 'ANS':
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
547 assert self.ansno is not None
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
548 headerbits.append(self.ansno)
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
549 header = ' '.join([str(bit) for bit in headerbits])
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
550 log.debug('Sending frame [%s]', header)
90
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
551 frame = '\r\n'.join((header, data, 'END', ''))
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
552 self.channel.seqno[1] += len(data)
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
553
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
554 return frame
89
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
555
7b10a8b2d0c4 Changed BEEP frame sending mechanism to use the `push_with_producer()` function provided by `asynchat`. In preparation for #17.
cmlenz
parents: 88
diff changeset
556
18
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
557 class ProfileHandler(object):
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
558 """Abstract base class for handlers of specific BEEP profiles.
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
559
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
560 Concrete subclasses need to at least implement the `handle_msg()` method,
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
561 and may override any of the others.
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
562 """
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
563
27
a8e509f4d33b Added a couple of unit tests for the BEEP management profile. See #2. More to come.
cmlenz
parents: 24
diff changeset
564 def __init__(self, channel):
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
565 """Create the profile."""
27
a8e509f4d33b Added a couple of unit tests for the BEEP management profile. See #2. More to come.
cmlenz
parents: 24
diff changeset
566 self.session = channel.session
a8e509f4d33b Added a couple of unit tests for the BEEP management profile. See #2. More to come.
cmlenz
parents: 24
diff changeset
567 self.channel = channel
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
568
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
569 def handle_connect(self):
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
570 """Called when the channel this profile is associated with is
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
571 initially started."""
24
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
572
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
573 def handle_disconnect(self):
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
574 """Called when the channel this profile is associated with is closed."""
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
575
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
576 def handle_msg(self, msgno, message):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
577 """Handle a MSG frame."""
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
578 raise NotImplementedError
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
579
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
580 def handle_rpy(self, msgno, message):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
581 """Handle a RPY frame."""
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
582 pass
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
583
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
584 def handle_err(self, msgno, message):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
585 """Handle an ERR frame."""
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
586 pass
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
587
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
588 def handle_ans(self, msgno, ansno, message):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
589 """Handle an ANS frame."""
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
590 pass
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
591
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
592 def handle_nul(self, msgno):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
593 """Handle a NUL frame."""
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
594 pass
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
595
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
596
18
591a5a836ecc * {{{beep.Listener}}} now has an event loop (based on code mostly from medusa)
cmlenz
parents: 15
diff changeset
597 class ManagementProfileHandler(ProfileHandler):
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
598 """Implementation of the BEEP management profile."""
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
599
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
600 def handle_connect(self):
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
601 """Send a greeting reply directly after connecting to the peer."""
15
06207499c58c * Use logging in the BEEP core as well as in the master and slave scripts. Closes #4.
cmlenz
parents: 14
diff changeset
602 profile_uris = self.session.profiles.keys()
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
603 log.debug('Send greeting with profiles: %s', profile_uris)
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
604 xml = xmlio.Element('greeting')[
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
605 [xmlio.Element('profile', uri=uri) for uri in profile_uris]
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
606 ]
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
607 self.channel.send_rpy(0, Payload(xml))
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
608
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
609 def handle_msg(self, msgno, message):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
610 """Handle an incoming message."""
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
611 assert message.content_type == BEEP_XML
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
612 elem = xmlio.parse(message.body)
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
613
51
5caccd7b247e Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents: 49
diff changeset
614 if elem.name == 'start':
5caccd7b247e Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents: 49
diff changeset
615 channelno = int(elem.attr['number'])
28
1e562dd56ec0 More management profile unit tests. Closes #2.
cmlenz
parents: 27
diff changeset
616 if channelno in self.session.channels:
1e562dd56ec0 More management profile unit tests. Closes #2.
cmlenz
parents: 27
diff changeset
617 self.send_error(msgno, 550, 'Channel already in use')
1e562dd56ec0 More management profile unit tests. Closes #2.
cmlenz
parents: 27
diff changeset
618 return
51
5caccd7b247e Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents: 49
diff changeset
619 for profile in elem.children('profile'):
5caccd7b247e Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents: 49
diff changeset
620 if profile.attr['uri'] in self.session.profiles:
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
621 log.debug('Start channel %s for profile <%s>',
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
622 elem.attr['number'], profile.attr['uri'])
28
1e562dd56ec0 More management profile unit tests. Closes #2.
cmlenz
parents: 27
diff changeset
623 channel = Channel(self.session, channelno,
51
5caccd7b247e Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents: 49
diff changeset
624 self.session.profiles[profile.attr['uri']])
28
1e562dd56ec0 More management profile unit tests. Closes #2.
cmlenz
parents: 27
diff changeset
625 self.session.channels[channelno] = channel
51
5caccd7b247e Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents: 49
diff changeset
626 xml = xmlio.Element('profile', uri=profile.attr['uri'])
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
627 self.channel.send_rpy(msgno, Payload(xml))
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
628 return
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
629 self.send_error(msgno, 550,
28
1e562dd56ec0 More management profile unit tests. Closes #2.
cmlenz
parents: 27
diff changeset
630 'None of the requested profiles is supported')
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
631
51
5caccd7b247e Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents: 49
diff changeset
632 elif elem.name == 'close':
5caccd7b247e Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents: 49
diff changeset
633 channelno = int(elem.attr['number'])
14
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
634 if not channelno in self.session.channels:
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
635 self.send_error(msgno, 550, 'Channel not open')
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
636 return
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
637 if channelno == 0:
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
638 if len(self.session.channels) > 1:
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
639 self.send_error(msgno, 550, 'Other channels still open')
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
640 return
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
641 if self.session.channels[channelno].msgnos:
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
642 self.send_error(msgno, 550, 'Channel waiting for replies')
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
643 return
24
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
644 self.session.channels[channelno].close()
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
645 self.channel.send_rpy(msgno, Payload(xmlio.Element('ok')))
14
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
646 if not self.session.channels:
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
647 self.session.close()
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
648
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
649 def handle_rpy(self, msgno, message):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
650 """Handle a positive reply."""
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
651 assert message.content_type == BEEP_XML
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
652 elem = xmlio.parse(message.body)
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
653
51
5caccd7b247e Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents: 49
diff changeset
654 if elem.name == 'greeting':
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
655 if isinstance(self.session, Initiator):
51
5caccd7b247e Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents: 49
diff changeset
656 profiles = [p.attr['uri'] for p in elem.children('profile')]
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
657 self.session.greeting_received(profiles)
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
658
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
659 else: # <profile/> and <ok/> are handled by callbacks
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
660 self.send_error(msgno, 501, 'What are you replying to, son?')
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
661
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
662 def handle_err(self, msgno, message):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
663 """Handle a negative reply."""
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
664 # Probably an error on connect, because other errors should get handled
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
665 # by the corresponding callbacks
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
666 # TODO: Terminate the session, I guess
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
667 assert message.content_type == BEEP_XML
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
668 elem = xmlio.parse(message.body)
51
5caccd7b247e Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents: 49
diff changeset
669 assert elem.name == 'error'
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
670 log.warning('Received error in response to message #%d: %s (%d)',
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
671 msgno, elem.gettext(), int(elem.attr['code']))
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
672
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
673 def send_close(self, channelno=0, code=200, handle_ok=None,
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
674 handle_error=None):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
675 """Send a request to close a channel to the peer."""
53
f8a678d08296 Pass answer number to reply handlers
cmlenz
parents: 51
diff changeset
676 def handle_reply(cmd, msgno, ansno, message):
14
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
677 if cmd == 'RPY':
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
678 log.debug('Channel %d closed', channelno)
24
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
679 self.session.channels[channelno].close()
34
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
680 if not self.session.channels:
6da9468a6879 The build master now gracefully exits by first terminating all active sessions. Fixes #7.
cmlenz
parents: 33
diff changeset
681 self.session.close()
14
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
682 if handle_ok is not None:
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
683 handle_ok()
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
684 elif cmd == 'ERR':
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
685 elem = xmlio.parse(message.body)
15
06207499c58c * Use logging in the BEEP core as well as in the master and slave scripts. Closes #4.
cmlenz
parents: 14
diff changeset
686 text = elem.gettext()
51
5caccd7b247e Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents: 49
diff changeset
687 code = int(elem.attr['code'])
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
688 log.debug('Peer refused to start channel %d: %s (%d)',
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
689 channelno, text, code)
14
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
690 if handle_error is not None:
15
06207499c58c * Use logging in the BEEP core as well as in the master and slave scripts. Closes #4.
cmlenz
parents: 14
diff changeset
691 handle_error(code, text)
06207499c58c * Use logging in the BEEP core as well as in the master and slave scripts. Closes #4.
cmlenz
parents: 14
diff changeset
692
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
693 log.debug('Requesting closure of channel %d', channelno)
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
694 xml = xmlio.Element('close', number=channelno, code=code)
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
695 return self.channel.send_msg(Payload(xml), handle_reply)
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
696
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
697 def send_error(self, msgno, code, message=''):
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
698 """Send an error reply to the peer."""
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
699 log.warning('%s (%d)', message, code)
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
700 xml = xmlio.Element('error', code=code)[message]
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
701 self.channel.send_err(msgno, Payload(xml))
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
702
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
703 def send_start(self, profiles, handle_ok=None, handle_error=None):
33
d8d44216258a Exit the slave script when the master disconnects; and other minor fixes.
cmlenz
parents: 29
diff changeset
704 """Send a request to start a new channel to the peer.
d8d44216258a Exit the slave script when the master disconnects; and other minor fixes.
cmlenz
parents: 29
diff changeset
705
d8d44216258a Exit the slave script when the master disconnects; and other minor fixes.
cmlenz
parents: 29
diff changeset
706 @param profiles A list of profiles to request for the channel, each
d8d44216258a Exit the slave script when the master disconnects; and other minor fixes.
cmlenz
parents: 29
diff changeset
707 element being an instance of a `ProfileHandler`
d8d44216258a Exit the slave script when the master disconnects; and other minor fixes.
cmlenz
parents: 29
diff changeset
708 sub-class
d8d44216258a Exit the slave script when the master disconnects; and other minor fixes.
cmlenz
parents: 29
diff changeset
709 @param handle_ok An optional callback function that will be invoked when
d8d44216258a Exit the slave script when the master disconnects; and other minor fixes.
cmlenz
parents: 29
diff changeset
710 the channel has been successfully started
d8d44216258a Exit the slave script when the master disconnects; and other minor fixes.
cmlenz
parents: 29
diff changeset
711 @param handle_error An optional callback function that will be invoked
d8d44216258a Exit the slave script when the master disconnects; and other minor fixes.
cmlenz
parents: 29
diff changeset
712 when the peer refuses to start the channel
d8d44216258a Exit the slave script when the master disconnects; and other minor fixes.
cmlenz
parents: 29
diff changeset
713 """
10
2269b705deb9 Improved the BEEP protocol implementation:
cmlenz
parents: 7
diff changeset
714 channelno = self.session.channelno.next()
53
f8a678d08296 Pass answer number to reply handlers
cmlenz
parents: 51
diff changeset
715 def handle_reply(cmd, msgno, ansno, message):
15
06207499c58c * Use logging in the BEEP core as well as in the master and slave scripts. Closes #4.
cmlenz
parents: 14
diff changeset
716 if cmd == 'RPY':
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
717 elem = xmlio.parse(message.body)
51
5caccd7b247e Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents: 49
diff changeset
718 for cls in [p for p in profiles if p.URI == elem.attr['uri']]:
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
719 log.debug('Channel %d started with profile %s', channelno,
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
720 elem.attr['uri'])
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
721 self.session.channels[channelno] = Channel(self.session,
24
cad6d28b8975 * Proper separation between {{{beep.ProfileHandler}}} instances between different channels.
cmlenz
parents: 23
diff changeset
722 channelno, cls)
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
723 break
15
06207499c58c * Use logging in the BEEP core as well as in the master and slave scripts. Closes #4.
cmlenz
parents: 14
diff changeset
724 if handle_ok is not None:
51
5caccd7b247e Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents: 49
diff changeset
725 handle_ok(channelno, elem.attr['uri'])
15
06207499c58c * Use logging in the BEEP core as well as in the master and slave scripts. Closes #4.
cmlenz
parents: 14
diff changeset
726 elif cmd == 'ERR':
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
727 elem = xmlio.parse(message.body)
15
06207499c58c * Use logging in the BEEP core as well as in the master and slave scripts. Closes #4.
cmlenz
parents: 14
diff changeset
728 text = elem.gettext()
51
5caccd7b247e Proper archive format negotiation; improved representation of parsed XML content in {{{bitten.util.xmlio}}}.
cmlenz
parents: 49
diff changeset
729 code = int(elem.attr['code'])
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
730 log.debug('Peer refused to start channel %d: %s (%d)',
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
731 channelno, text, code)
15
06207499c58c * Use logging in the BEEP core as well as in the master and slave scripts. Closes #4.
cmlenz
parents: 14
diff changeset
732 if handle_error is not None:
06207499c58c * Use logging in the BEEP core as well as in the master and slave scripts. Closes #4.
cmlenz
parents: 14
diff changeset
733 handle_error(code, text)
12
fd802a55be55 Added unit tests for frame sequence numbers.
cmlenz
parents: 11
diff changeset
734
93
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
735 log.debug('Requesting start of channel %d with profiles %s', channelno,
b289e572bc7e Improved logging; the build master can now optionally log to a file. Closes #13.
cmlenz
parents: 92
diff changeset
736 [profile.URI for profile in profiles])
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
737 xml = xmlio.Element('start', number=channelno)[
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
738 [xmlio.Element('profile', uri=profile.URI) for profile in profiles]
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
739 ]
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
740 return self.channel.send_msg(Payload(xml), handle_reply)
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
741
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
742
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
743 class Payload(object):
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
744 """MIME message for transmission as payload with BEEP."""
14
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
745
90
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
746 def __init__(self, data=None, content_type=BEEP_XML,
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
747 content_disposition=None, content_encoding=None):
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
748 """Initialize the payload."""
90
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
749 self._hdr_buf = None
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
750 self.content_type = content_type
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
751 self.content_disposition = content_disposition
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
752 self.content_encoding = content_encoding
90
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
753
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
754 if data is None:
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
755 data = ''
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
756 if isinstance(data, xmlio.Element):
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
757 self.body = StringIO(str(data))
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
758 elif isinstance(data, (str, unicode)):
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
759 self.body = StringIO(data)
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
760 else:
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
761 assert hasattr(data, 'read'), \
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
762 'Payload data %s must provide a `read` method' % data
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
763 self.body = data
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
764
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
765 def as_string(self):
90
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
766 return self.read()
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
767
90
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
768 def read(self, size=None):
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
769 if self._hdr_buf is None:
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
770 hdrs = []
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
771 if self.content_type:
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
772 hdrs.append('Content-Type: ' + self.content_type)
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
773 if self.content_disposition:
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
774 hdrs.append('Content-Disposition: ' + self.content_disposition)
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
775 if self.content_encoding:
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
776 hdrs.append('Content-Transfer-Encoding: ' +
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
777 self.content_encoding)
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
778 hdrs.append('')
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
779 self._hdr_buf = '\n'.join(hdrs) + '\n'
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
780
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
781 ret_buf = ''
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
782 if len(self._hdr_buf):
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
783 if size is not None and len(self._hdr_buf) > size:
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
784 ret_buf = self._hdr_buf[:size]
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
785 self._hdr_buf = self._hdr_buf[size:]
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
786 return ret_buf
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
787 ret_buf = self._hdr_buf
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
788 self._hdr_buf = ''
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
789
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
790 if not self.body.closed:
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
791 ret_buf = ret_buf + self.body.read((size or -1) - len(ret_buf))
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
792 if size is None or len(ret_buf) < size:
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
793 self.body.close()
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
794
2c4e104afef8 The build master now transmits snapshot archives without blocking while reading the file and sending the BEEP frames. Closes #17.
cmlenz
parents: 89
diff changeset
795 return ret_buf
88
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
796
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
797 def parse(cls, string):
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
798 message = email.message_from_string(string)
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
799 content_type = message.get('Content-Type')
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
800 content_disposition = message.get('Content-Disposition')
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
801 content_encoding = message.get('Content-Transfer-Encoding')
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
802 return Payload(message.get_payload(), content_type,
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
803 content_disposition, content_encoding)
8ae753a22494 Some refactoring of the BEEP implementation:
cmlenz
parents: 83
diff changeset
804 parse = classmethod(parse)
14
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
805
1733c601d2f8 Refactored the asyncore loop and shutdown procedure into {{{beep.Initiator}}}.
cmlenz
parents: 13
diff changeset
806
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
807 def cycle_through(start, stop=None, step=1):
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
808 """Utility generator that cycles through a defined range of numbers."""
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
809 if stop is None:
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
810 stop = start
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
811 start = 0
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
812 cur = start
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
813 while True:
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
814 yield cur
11
4d31bd0c3eba Improved BEEP implementation.
cmlenz
parents: 10
diff changeset
815 cur += step
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
816 if cur > stop:
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
817 cur = start
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
818
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
819
29
2adc3480e4aa Some cleanup and additional docstrings.
cmlenz
parents: 28
diff changeset
820 class SerialNumber(object):
7
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
821 """Serial number (RFC 1982)."""
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
822
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
823 def __init__(self, limit=4294967295L):
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
824 self.value = 0L
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
825 self.limit = limit
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
826
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
827 def __ne__(self, num):
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
828 return self.value != num
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
829
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
830 def __eq__(self, num):
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
831 return self.value == num
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
832
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
833 def __iadd__(self, num):
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
834 self.value += num
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
835 if self.value > self.limit:
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
836 self.value -= self.limit
8442bcb47a03 Initial draft of a minimal [http://www.beepcore.org/ BEEP] protocol implementation for communication between the build master and build slaves.
cmlenz
parents:
diff changeset
837 return self
Copyright (C) 2012-2017 Edgewall Software