Revision 231db3a5 lib/luxi.py
b/lib/luxi.py | ||
---|---|---|
33 | 33 |
import collections |
34 | 34 |
import time |
35 | 35 |
import errno |
36 |
import logging |
|
36 | 37 |
|
37 | 38 |
from ganeti import serializer |
38 | 39 |
from ganeti import constants |
39 | 40 |
from ganeti import errors |
40 | 41 |
|
41 | 42 |
|
42 |
KEY_METHOD = 'method'
|
|
43 |
KEY_ARGS = 'args'
|
|
43 |
KEY_METHOD = "method"
|
|
44 |
KEY_ARGS = "args"
|
|
44 | 45 |
KEY_SUCCESS = "success" |
45 | 46 |
KEY_RESULT = "result" |
46 | 47 |
|
... | ... | |
233 | 234 |
self.socket = None |
234 | 235 |
|
235 | 236 |
|
237 |
def ParseRequest(msg): |
|
238 |
"""Parses a LUXI request message. |
|
239 |
|
|
240 |
""" |
|
241 |
try: |
|
242 |
request = serializer.LoadJson(msg) |
|
243 |
except ValueError, err: |
|
244 |
raise ProtocolError("Invalid LUXI request (parsing error): %s" % err) |
|
245 |
|
|
246 |
logging.debug("LUXI request: %s", request) |
|
247 |
|
|
248 |
if not isinstance(request, dict): |
|
249 |
logging.error("LUXI request not a dict: %r", msg) |
|
250 |
raise ProtocolError("Invalid LUXI request (not a dict)") |
|
251 |
|
|
252 |
method = request.get(KEY_METHOD, None) |
|
253 |
args = request.get(KEY_ARGS, None) |
|
254 |
if method is None or args is None: |
|
255 |
logging.error("LUXI request missing method or arguments: %r", msg) |
|
256 |
raise ProtocolError(("Invalid LUXI request (no method or arguments" |
|
257 |
" in request): %r") % msg) |
|
258 |
|
|
259 |
return (method, args) |
|
260 |
|
|
261 |
|
|
262 |
def ParseResponse(msg): |
|
263 |
"""Parses a LUXI response message. |
|
264 |
|
|
265 |
""" |
|
266 |
# Parse the result |
|
267 |
try: |
|
268 |
data = serializer.LoadJson(msg) |
|
269 |
except Exception, err: |
|
270 |
raise ProtocolError("Error while deserializing response: %s" % str(err)) |
|
271 |
|
|
272 |
# Validate response |
|
273 |
if not (isinstance(data, dict) and |
|
274 |
KEY_SUCCESS in data and |
|
275 |
KEY_RESULT in data): |
|
276 |
raise ProtocolError("Invalid response from server: %r" % data) |
|
277 |
|
|
278 |
return (data[KEY_SUCCESS], data[KEY_RESULT]) |
|
279 |
|
|
280 |
|
|
281 |
def FormatResponse(success, result): |
|
282 |
"""Formats a LUXI response message. |
|
283 |
|
|
284 |
""" |
|
285 |
response = { |
|
286 |
KEY_SUCCESS: success, |
|
287 |
KEY_RESULT: result, |
|
288 |
} |
|
289 |
|
|
290 |
logging.debug("LUXI response: %s", response) |
|
291 |
|
|
292 |
return serializer.DumpJson(response) |
|
293 |
|
|
294 |
|
|
295 |
def FormatRequest(method, args): |
|
296 |
"""Formats a LUXI request message. |
|
297 |
|
|
298 |
""" |
|
299 |
# Build request |
|
300 |
request = { |
|
301 |
KEY_METHOD: method, |
|
302 |
KEY_ARGS: args, |
|
303 |
} |
|
304 |
|
|
305 |
# Serialize the request |
|
306 |
return serializer.DumpJson(request, indent=False) |
|
307 |
|
|
308 |
|
|
309 |
def CallLuxiMethod(transport_cb, method, args): |
|
310 |
"""Send a LUXI request via a transport and return the response. |
|
311 |
|
|
312 |
""" |
|
313 |
assert callable(transport_cb) |
|
314 |
|
|
315 |
request_msg = FormatRequest(method, args) |
|
316 |
|
|
317 |
# Send request and wait for response |
|
318 |
response_msg = transport_cb(request_msg) |
|
319 |
|
|
320 |
(success, result) = ParseResponse(response_msg) |
|
321 |
|
|
322 |
if success: |
|
323 |
return result |
|
324 |
|
|
325 |
errors.MaybeRaise(result) |
|
326 |
raise RequestError(result) |
|
327 |
|
|
328 |
|
|
236 | 329 |
class Client(object): |
237 | 330 |
"""High-level client implementation. |
238 | 331 |
|
... | ... | |
282 | 375 |
except Exception: # pylint: disable-msg=W0703 |
283 | 376 |
pass |
284 | 377 |
|
285 |
def CallMethod(self, method, args): |
|
286 |
"""Send a generic request and return the response. |
|
287 |
|
|
288 |
""" |
|
289 |
# Build request |
|
290 |
request = { |
|
291 |
KEY_METHOD: method, |
|
292 |
KEY_ARGS: args, |
|
293 |
} |
|
294 |
|
|
295 |
# Serialize the request |
|
296 |
send_data = serializer.DumpJson(request, indent=False) |
|
297 |
|
|
378 |
def _SendMethodCall(self, data): |
|
298 | 379 |
# Send request and wait for response |
299 | 380 |
try: |
300 | 381 |
self._InitTransport() |
301 |
result = self.transport.Call(send_data)
|
|
382 |
return self.transport.Call(data)
|
|
302 | 383 |
except Exception: |
303 | 384 |
self._CloseTransport() |
304 | 385 |
raise |
305 | 386 |
|
306 |
# Parse the result |
|
307 |
try: |
|
308 |
data = serializer.LoadJson(result) |
|
309 |
except Exception, err: |
|
310 |
raise ProtocolError("Error while deserializing response: %s" % str(err)) |
|
311 |
|
|
312 |
# Validate response |
|
313 |
if (not isinstance(data, dict) or |
|
314 |
KEY_SUCCESS not in data or |
|
315 |
KEY_RESULT not in data): |
|
316 |
raise ProtocolError("Invalid response from server: %s" % str(data)) |
|
317 |
|
|
318 |
result = data[KEY_RESULT] |
|
319 |
|
|
320 |
if not data[KEY_SUCCESS]: |
|
321 |
errors.MaybeRaise(result) |
|
322 |
raise RequestError(result) |
|
387 |
def CallMethod(self, method, args): |
|
388 |
"""Send a generic request and return the response. |
|
323 | 389 |
|
324 |
return result |
|
390 |
""" |
|
391 |
return CallLuxiMethod(self._SendMethodCall, method, args) |
|
325 | 392 |
|
326 | 393 |
def SetQueueDrainFlag(self, drain_flag): |
327 | 394 |
return self.CallMethod(REQ_QUEUE_SET_DRAIN_FLAG, drain_flag) |
Also available in: Unified diff