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 | |
| 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')
| -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): |
