diff options
author | Alexandru DAMIAN <alexandru.damian@intel.com> | 2013-05-28 13:55:09 +0000 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2013-05-30 10:44:00 +0100 |
commit | 0fc3a1eddfbab5cbf61c028cf8bc0d6b27b6c420 (patch) | |
tree | 7ad43bd30a1d39a4968debc06d728cd03d79bd5e /bitbake/lib/bb/server | |
parent | b6b30095de0f5549a6cd3526170c70f39e803de6 (diff) | |
download | poky-0fc3a1eddfbab5cbf61c028cf8bc0d6b27b6c420.tar.gz |
bitbake: bitbake: xmlrpc transport has identification token
In order to be able to identify different clients over a
stateless XMLRPC connection, we add a custom header named
Bitbake-token, which identifies each client.
We refactor the rest of the code to use the new transport.
Based on a patch by Bogdan Marinescu <bogdan.a.marinescu@intel.com>
(Bitbake rev: a00c2186bffe848a7cedf31969b904f8f7322ae6)
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/bb/server')
-rw-r--r-- | bitbake/lib/bb/server/xmlrpc.py | 166 |
1 files changed, 100 insertions, 66 deletions
diff --git a/bitbake/lib/bb/server/xmlrpc.py b/bitbake/lib/bb/server/xmlrpc.py index ca3a401013..e9c106b20e 100644 --- a/bitbake/lib/bb/server/xmlrpc.py +++ b/bitbake/lib/bb/server/xmlrpc.py | |||
@@ -54,82 +54,104 @@ if sys.hexversion < 0x020600F0: | |||
54 | # Upstream Python bug is #8194 (http://bugs.python.org/issue8194) | 54 | # Upstream Python bug is #8194 (http://bugs.python.org/issue8194) |
55 | # This bug is relevant for Python 2.7.0 and 2.7.1 but was fixed for | 55 | # This bug is relevant for Python 2.7.0 and 2.7.1 but was fixed for |
56 | # Python > 2.7.2 | 56 | # Python > 2.7.2 |
57 | # | ||
58 | # To implement a simple form of client control, we use a special transport | ||
59 | # that adds a HTTP header field ("Bitbake-token") to ensure that a server | ||
60 | # can communicate with only a client at a given time (the client must use | ||
61 | # the same token). | ||
57 | ## | 62 | ## |
63 | if (2, 7, 0) <= sys.version_info < (2, 7, 2): | ||
64 | class BBTransport(xmlrpclib.Transport): | ||
65 | def __init__(self): | ||
66 | self.connection_token = None | ||
67 | xmlrpclib.Transport.__init__(self) | ||
68 | |||
69 | def request(self, host, handler, request_body, verbose=0): | ||
70 | h = self.make_connection(host) | ||
71 | if verbose: | ||
72 | h.set_debuglevel(1) | ||
73 | |||
74 | self.send_request(h, handler, request_body) | ||
75 | self.send_host(h, host) | ||
76 | self.send_user_agent(h) | ||
77 | if self.connection_token: | ||
78 | h.putheader("Bitbake-token", self.connection_token) | ||
79 | self.send_content(h, request_body) | ||
80 | |||
81 | errcode, errmsg, headers = h.getreply() | ||
82 | |||
83 | if errcode != 200: | ||
84 | raise ProtocolError( | ||
85 | host + handler, | ||
86 | errcode, errmsg, | ||
87 | headers | ||
88 | ) | ||
89 | |||
90 | self.verbose = verbose | ||
58 | 91 | ||
59 | class BBTransport(xmlrpclib.Transport): | 92 | try: |
60 | def request(self, host, handler, request_body, verbose=0): | 93 | sock = h._conn.sock |
61 | h = self.make_connection(host) | 94 | except AttributeError: |
62 | if verbose: | 95 | sock = None |
63 | h.set_debuglevel(1) | 96 | |
64 | 97 | return self._parse_response(h.getfile(), sock) | |
65 | self.send_request(h, handler, request_body) | 98 | |
66 | self.send_host(h, host) | 99 | def make_connection(self, host): |
67 | self.send_user_agent(h) | 100 | import httplib |
68 | self.send_content(h, request_body) | 101 | host, extra_headers, x509 = self.get_host_info(host) |
69 | 102 | return httplib.HTTP(host) | |
70 | errcode, errmsg, headers = h.getreply() | 103 | |
71 | 104 | def _parse_response(self, file, sock): | |
72 | if errcode != 200: | 105 | p, u = self.getparser() |
73 | raise ProtocolError( | 106 | |
74 | host + handler, | 107 | while 1: |
75 | errcode, errmsg, | 108 | if sock: |
76 | headers | 109 | response = sock.recv(1024) |
77 | ) | 110 | else: |
78 | 111 | response = file.read(1024) | |
79 | self.verbose = verbose | 112 | if not response: |
80 | 113 | break | |
81 | try: | 114 | if self.verbose: |
82 | sock = h._conn.sock | 115 | print("body:", repr(response)) |
83 | except AttributeError: | 116 | p.feed(response) |
84 | sock = None | 117 | |
85 | 118 | file.close() | |
86 | return self._parse_response(h.getfile(), sock) | 119 | p.close() |
87 | 120 | ||
88 | def make_connection(self, host): | 121 | return u.close() |
89 | import httplib | 122 | |
90 | host, extra_headers, x509 = self.get_host_info(host) | 123 | def set_connection_token(self, token): |
91 | return httplib.HTTP(host) | 124 | self.connection_token = token |
92 | 125 | else: | |
93 | def _parse_response(self, file, sock): | 126 | class BBTransport(xmlrpclib.Transport): |
94 | p, u = self.getparser() | 127 | def __init__(self): |
95 | 128 | self.connection_token = None | |
96 | while 1: | 129 | xmlrpclib.Transport.__init__(self) |
97 | if sock: | 130 | |
98 | response = sock.recv(1024) | 131 | def set_connection_token(self, token): |
99 | else: | 132 | self.connection_token = token |
100 | response = file.read(1024) | 133 | |
101 | if not response: | 134 | def send_content(self, h, body): |
102 | break | 135 | if self.connection_token: |
103 | if self.verbose: | 136 | h.putheader("Bitbake-token", self.connection_token) |
104 | print("body:", repr(response)) | 137 | xmlrpclib.Transport.send_content(self, h, body) |
105 | p.feed(response) | ||
106 | |||
107 | file.close() | ||
108 | p.close() | ||
109 | |||
110 | return u.close() | ||
111 | 138 | ||
112 | def _create_server(host, port): | 139 | def _create_server(host, port): |
113 | # Python 2.7.0 and 2.7.1 have a buggy Transport implementation | 140 | t = BBTransport() |
114 | # For those versions of Python, and only those versions, use our | 141 | s = xmlrpclib.Server("http://%s:%d/" % (host, port), transport=t, allow_none=True) |
115 | # own copy/paste BBTransport class. | 142 | return s, t |
116 | if (2, 7, 0) <= sys.version_info < (2, 7, 2): | ||
117 | t = BBTransport() | ||
118 | s = xmlrpclib.Server("http://%s:%d/" % (host, port), transport=t, allow_none=True) | ||
119 | else: | ||
120 | s = xmlrpclib.Server("http://%s:%d/" % (host, port), allow_none=True) | ||
121 | |||
122 | return s | ||
123 | 143 | ||
124 | class BitBakeServerCommands(): | 144 | class BitBakeServerCommands(): |
145 | |||
125 | def __init__(self, server): | 146 | def __init__(self, server): |
126 | self.server = server | 147 | self.server = server |
148 | self.has_client = False | ||
127 | 149 | ||
128 | def registerEventHandler(self, host, port): | 150 | def registerEventHandler(self, host, port): |
129 | """ | 151 | """ |
130 | Register a remote UI Event Handler | 152 | Register a remote UI Event Handler |
131 | """ | 153 | """ |
132 | s = _create_server(host, port) | 154 | s, t = _create_server(host, port) |
133 | 155 | ||
134 | return bb.event.register_UIHhandler(s) | 156 | return bb.event.register_UIHhandler(s) |
135 | 157 | ||
@@ -248,10 +270,22 @@ class BitbakeServerInfo(): | |||
248 | 270 | ||
249 | class BitBakeServerConnection(): | 271 | class BitBakeServerConnection(): |
250 | def __init__(self, serverinfo, clientinfo=("localhost", 0)): | 272 | def __init__(self, serverinfo, clientinfo=("localhost", 0)): |
251 | self.connection = _create_server(serverinfo.host, serverinfo.port) | 273 | self.connection, self.transport = _create_server(serverinfo.host, serverinfo.port) |
252 | self.events = uievent.BBUIEventQueue(self.connection, clientinfo) | 274 | self.clientinfo = clientinfo |
275 | self.serverinfo = serverinfo | ||
276 | |||
277 | def connect(self): | ||
278 | token = self.connection.addClient() | ||
279 | if token is None: | ||
280 | return None | ||
281 | self.transport.set_connection_token(token) | ||
282 | self.events = uievent.BBUIEventQueue(self.connection, self.clientinfo) | ||
253 | for event in bb.event.ui_queue: | 283 | for event in bb.event.ui_queue: |
254 | self.events.queue_event(event) | 284 | self.events.queue_event(event) |
285 | return self | ||
286 | |||
287 | def removeClient(self): | ||
288 | self.connection.removeClient() | ||
255 | 289 | ||
256 | def terminate(self): | 290 | def terminate(self): |
257 | # Don't wait for server indefinitely | 291 | # Don't wait for server indefinitely |
@@ -277,7 +311,7 @@ class BitBakeServer(object): | |||
277 | def getServerIdleCB(self): | 311 | def getServerIdleCB(self): |
278 | return self.server.register_idle_function | 312 | return self.server.register_idle_function |
279 | 313 | ||
280 | def saveConnectionDetails(self): | 314 | def saveConnectionDetails(self): |
281 | self.serverinfo = BitbakeServerInfo(self.server.host, self.server.port) | 315 | self.serverinfo = BitbakeServerInfo(self.server.host, self.server.port) |
282 | 316 | ||
283 | def detach(self): | 317 | def detach(self): |