summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/server/xmlrpcserver.py
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2017-07-18 22:28:40 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2017-07-21 08:41:11 +0100
commit4602408c69132315c3784718fe4ce155b12464cf (patch)
tree2262f6d8b5e89930b4da4efd72e226ae8f740611 /bitbake/lib/bb/server/xmlrpcserver.py
parent21a19e0e0bf1b39969f6f2ec37a5784d0069715b (diff)
downloadpoky-4602408c69132315c3784718fe4ce155b12464cf.tar.gz
bitbake: server: Rework the server API so process and xmlrpc servers coexist
This changes the way bitbake server works quite radically. Now, the server is always a process based server with the option of starting an XMLRPC listener on a specific inferface/port. Behind the scenes this is done with a "bitbake.sock" file alongside the bitbake.lock file. If we can obtain the lock, we know we need to start a server. The server always listens on the socket and UIs can then connect to this. UIs connect by sending a set of three file descriptors over the domain socket, one for sending commands, one for receiving command results and the other for receiving events. These changes meant we can throw away all the horrid server abstraction code, the plugable transport option to bitbake and the code becomes much more readable and debuggable. It also likely removes a ton of ways you could hang the UI/cooker in weird ways due to all the race conditions that existed with previous processes. Changes: * The foreground option for bitbake-server was dropped. Just tail the log if you really want this, the codepaths were complicated enough without adding one for this. * BBSERVER="autodetect" was dropped. The server will autostart and autoconnect in process mode. You have to specify an xmlrpc server address since that can't be autodetected. I can't see a use case for autodetect now. * The transport/servetype option to bitbake was dropped. * A BB_SERVER_TIMEOUT variable is added which allows the server to stay resident for a period of time after the last client disconnects before unloading. This is used if the -T/--idle-timeout option is not passed to bitbake. This change is invasive and may well introduce new issues however I believe the codebase is in a much better position for further development and debugging. (Bitbake rev: 72a3dbe13a23588e24c0baca6d58c35cdeba3f63) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/bb/server/xmlrpcserver.py')
-rw-r--r--bitbake/lib/bb/server/xmlrpcserver.py158
1 files changed, 158 insertions, 0 deletions
diff --git a/bitbake/lib/bb/server/xmlrpcserver.py b/bitbake/lib/bb/server/xmlrpcserver.py
new file mode 100644
index 0000000000..875b1282e5
--- /dev/null
+++ b/bitbake/lib/bb/server/xmlrpcserver.py
@@ -0,0 +1,158 @@
1#
2# BitBake XMLRPC Server Interface
3#
4# Copyright (C) 2006 - 2007 Michael 'Mickey' Lauer
5# Copyright (C) 2006 - 2008 Richard Purdie
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License version 2 as
9# published by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program; if not, write to the Free Software Foundation, Inc.,
18# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20import os
21import sys
22
23import hashlib
24import time
25import inspect
26from xmlrpc.server import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
27
28import bb
29
30# This request handler checks if the request has a "Bitbake-token" header
31# field (this comes from the client side) and compares it with its internal
32# "Bitbake-token" field (this comes from the server). If the two are not
33# equal, it is assumed that a client is trying to connect to the server
34# while another client is connected to the server. In this case, a 503 error
35# ("service unavailable") is returned to the client.
36class BitBakeXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
37 def __init__(self, request, client_address, server):
38 self.server = server
39 SimpleXMLRPCRequestHandler.__init__(self, request, client_address, server)
40
41 def do_POST(self):
42 try:
43 remote_token = self.headers["Bitbake-token"]
44 except:
45 remote_token = None
46 if 0 and remote_token != self.server.connection_token and remote_token != "observer":
47 self.report_503()
48 else:
49 if remote_token == "observer":
50 self.server.readonly = True
51 else:
52 self.server.readonly = False
53 SimpleXMLRPCRequestHandler.do_POST(self)
54
55 def report_503(self):
56 self.send_response(503)
57 response = 'No more client allowed'
58 self.send_header("Content-type", "text/plain")
59 self.send_header("Content-length", str(len(response)))
60 self.end_headers()
61 self.wfile.write(bytes(response, 'utf-8'))
62
63class BitBakeXMLRPCServer(SimpleXMLRPCServer):
64 # remove this when you're done with debugging
65 # allow_reuse_address = True
66
67 def __init__(self, interface, cooker, parent):
68 # Use auto port configuration
69 if (interface[1] == -1):
70 interface = (interface[0], 0)
71 SimpleXMLRPCServer.__init__(self, interface,
72 requestHandler=BitBakeXMLRPCRequestHandler,
73 logRequests=False, allow_none=True)
74 self.host, self.port = self.socket.getsockname()
75 self.interface = interface
76
77 self.connection_token = None
78 self.commands = BitBakeXMLRPCServerCommands(self)
79 self.register_functions(self.commands, "")
80
81 self.cooker = cooker
82 self.parent = parent
83
84
85 def register_functions(self, context, prefix):
86 """
87 Convenience method for registering all functions in the scope
88 of this class that start with a common prefix
89 """
90 methodlist = inspect.getmembers(context, inspect.ismethod)
91 for name, method in methodlist:
92 if name.startswith(prefix):
93 self.register_function(method, name[len(prefix):])
94
95 def get_timeout(self, delay):
96 socktimeout = self.socket.gettimeout() or delay
97 return min(socktimeout, delay)
98
99 def handle_requests(self):
100 self._handle_request_noblock()
101
102class BitBakeXMLRPCServerCommands():
103
104 def __init__(self, server):
105 self.server = server
106 self.has_client = False
107
108 def registerEventHandler(self, host, port):
109 """
110 Register a remote UI Event Handler
111 """
112 s, t = bb.server.xmlrpcclient._create_server(host, port)
113
114 # we don't allow connections if the cooker is running
115 if (self.server.cooker.state in [bb.cooker.state.parsing, bb.cooker.state.running]):
116 return None, "Cooker is busy: %s" % bb.cooker.state.get_name(self.server.cooker.state)
117
118 self.event_handle = bb.event.register_UIHhandler(s, True)
119 return self.event_handle, 'OK'
120
121 def unregisterEventHandler(self, handlerNum):
122 """
123 Unregister a remote UI Event Handler
124 """
125 ret = bb.event.unregister_UIHhandler(handlerNum, True)
126 self.event_handle = None
127 return ret
128
129 def runCommand(self, command):
130 """
131 Run a cooker command on the server
132 """
133 return self.server.cooker.command.runCommand(command, self.server.readonly)
134
135 def getEventHandle(self):
136 return self.event_handle
137
138 def terminateServer(self):
139 """
140 Trigger the server to quit
141 """
142 self.server.parent.quit = True
143 print("XMLRPC Server triggering exit")
144 return
145
146 def addClient(self):
147 if self.server.parent.haveui:
148 return None
149 token = hashlib.md5(str(time.time()).encode("utf-8")).hexdigest()
150 self.server.connection_token = token
151 self.server.parent.haveui = True
152 return token
153
154 def removeClient(self):
155 if self.server.parent.haveui:
156 self.server.connection_token = None
157 self.server.parent.haveui = False
158