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