diff options
Diffstat (limited to 'bitbake/lib/bb/server/xmlrpcclient.py')
-rw-r--r-- | bitbake/lib/bb/server/xmlrpcclient.py | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/bitbake/lib/bb/server/xmlrpcclient.py b/bitbake/lib/bb/server/xmlrpcclient.py new file mode 100644 index 0000000000..4661a9e5a0 --- /dev/null +++ b/bitbake/lib/bb/server/xmlrpcclient.py | |||
@@ -0,0 +1,154 @@ | |||
1 | # | ||
2 | # BitBake XMLRPC Client 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 | |||
20 | import os | ||
21 | import sys | ||
22 | |||
23 | import socket | ||
24 | import http.client | ||
25 | import xmlrpc.client | ||
26 | |||
27 | import bb | ||
28 | from bb.ui import uievent | ||
29 | |||
30 | class BBTransport(xmlrpc.client.Transport): | ||
31 | def __init__(self, timeout): | ||
32 | self.timeout = timeout | ||
33 | self.connection_token = None | ||
34 | xmlrpc.client.Transport.__init__(self) | ||
35 | |||
36 | # Modified from default to pass timeout to HTTPConnection | ||
37 | def make_connection(self, host): | ||
38 | #return an existing connection if possible. This allows | ||
39 | #HTTP/1.1 keep-alive. | ||
40 | if self._connection and host == self._connection[0]: | ||
41 | return self._connection[1] | ||
42 | |||
43 | # create a HTTP connection object from a host descriptor | ||
44 | chost, self._extra_headers, x509 = self.get_host_info(host) | ||
45 | #store the host argument along with the connection object | ||
46 | self._connection = host, http.client.HTTPConnection(chost, timeout=self.timeout) | ||
47 | return self._connection[1] | ||
48 | |||
49 | def set_connection_token(self, token): | ||
50 | self.connection_token = token | ||
51 | |||
52 | def send_content(self, h, body): | ||
53 | if self.connection_token: | ||
54 | h.putheader("Bitbake-token", self.connection_token) | ||
55 | xmlrpc.client.Transport.send_content(self, h, body) | ||
56 | |||
57 | def _create_server(host, port, timeout = 60): | ||
58 | t = BBTransport(timeout) | ||
59 | s = xmlrpc.client.ServerProxy("http://%s:%d/" % (host, port), transport=t, allow_none=True, use_builtin_types=True) | ||
60 | return s, t | ||
61 | |||
62 | def check_connection(remote, timeout): | ||
63 | try: | ||
64 | host, port = remote.split(":") | ||
65 | port = int(port) | ||
66 | except Exception as e: | ||
67 | bb.warn("Failed to read remote definition (%s)" % str(e)) | ||
68 | raise e | ||
69 | |||
70 | server, _transport = _create_server(host, port, timeout) | ||
71 | try: | ||
72 | ret, err = server.runCommand(['getVariable', 'TOPDIR']) | ||
73 | if err or not ret: | ||
74 | return False | ||
75 | except ConnectionError: | ||
76 | return False | ||
77 | return True | ||
78 | |||
79 | class BitBakeXMLRPCServerConnection(object): | ||
80 | def __init__(self, host, port, clientinfo=("localhost", 0), observer_only = False, featureset = None): | ||
81 | self.connection, self.transport = _create_server(host, port) | ||
82 | self.clientinfo = clientinfo | ||
83 | self.observer_only = observer_only | ||
84 | if featureset: | ||
85 | self.featureset = featureset | ||
86 | else: | ||
87 | self.featureset = [] | ||
88 | |||
89 | self.events = uievent.BBUIEventQueue(self.connection, self.clientinfo) | ||
90 | |||
91 | _, error = self.connection.runCommand(["setFeatures", self.featureset]) | ||
92 | if error: | ||
93 | # disconnect the client, we can't make the setFeature work | ||
94 | self.connection.removeClient() | ||
95 | # no need to log it here, the error shall be sent to the client | ||
96 | raise BaseException(error) | ||
97 | |||
98 | def connect(self, token = None): | ||
99 | if token is None: | ||
100 | if self.observer_only: | ||
101 | token = "observer" | ||
102 | else: | ||
103 | token = self.connection.addClient() | ||
104 | |||
105 | if token is None: | ||
106 | return None | ||
107 | |||
108 | self.transport.set_connection_token(token) | ||
109 | return self | ||
110 | |||
111 | def removeClient(self): | ||
112 | if not self.observer_only: | ||
113 | self.connection.removeClient() | ||
114 | |||
115 | def terminate(self): | ||
116 | # Don't wait for server indefinitely | ||
117 | socket.setdefaulttimeout(2) | ||
118 | try: | ||
119 | self.events.system_quit() | ||
120 | except: | ||
121 | pass | ||
122 | try: | ||
123 | self.connection.removeClient() | ||
124 | except: | ||
125 | pass | ||
126 | |||
127 | def connectXMLRPC(remote, featureset, observer_only = False, token = None): | ||
128 | # The format of "remote" must be "server:port" | ||
129 | try: | ||
130 | [host, port] = remote.split(":") | ||
131 | port = int(port) | ||
132 | except Exception as e: | ||
133 | bb.warn("Failed to parse remote definition %s (%s)" % (remote, str(e))) | ||
134 | raise e | ||
135 | |||
136 | # We need our IP for the server connection. We get the IP | ||
137 | # by trying to connect with the server | ||
138 | try: | ||
139 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | ||
140 | s.connect((host, port)) | ||
141 | ip = s.getsockname()[0] | ||
142 | s.close() | ||
143 | except Exception as e: | ||
144 | bb.warn("Could not create socket for %s:%s (%s)" % (host, port, str(e))) | ||
145 | raise e | ||
146 | try: | ||
147 | connection = BitBakeXMLRPCServerConnection(host, port, (ip, 0), observer_only, featureset) | ||
148 | return connection.connect(token) | ||
149 | except Exception as e: | ||
150 | bb.warn("Could not connect to server at %s:%s (%s)" % (host, port, str(e))) | ||
151 | raise e | ||
152 | |||
153 | |||
154 | |||