def _runRequest(self, ctx, request): if self._threadFactory is None: self._serveRequest(ctx, request) else: try: self._threadFactory( JsonRpcTask(self._serveRequest, ctx, request)) except vdsmexception.ContextException as e: ctx.requestDone(JsonRpcResponse(None, e, request.id)) except Exception as e: self.log.exception("could not serve request %s", request) ctx.requestDone( JsonRpcResponse(None, exception.JsonRpcInternalError(str(e)), request.id))
def _parseMessage(self, obj): client, server_address, context, msg = obj ctx = _JsonRpcServeRequestContext(client, server_address, context) try: rawRequests = json.loads(msg) except: ctx.addResponse( JsonRpcResponse(None, exception.JsonRpcParseError(), None)) ctx.sendReply() return if isinstance(rawRequests, list): # Empty batch request if len(rawRequests) == 0: ctx.addResponse( JsonRpcResponse( None, exception.JsonRpcInvalidRequestError( "request batch is empty", request=rawRequests), None)) ctx.sendReply() return else: # From this point on we know it's always a list rawRequests = [rawRequests] # JSON Parsed handling each request requests = [] for rawRequest in rawRequests: try: req = JsonRpcRequest.fromRawObject(rawRequest) requests.append(req) except vdsmexception.VdsmException as err: ctx.addResponse(JsonRpcResponse(None, err, None)) except: ctx.addResponse( JsonRpcResponse(None, exception.JsonRpcInternalError(), None)) ctx.setRequests(requests) # No request was built successfully or is only notifications if ctx.counter == 0: ctx.sendReply() for request in requests: self._runRequest(ctx, request)
def _handle_request(self, req, ctx): self._attempt_log_stats() logLevel = logging.DEBUG # VDSM should never respond to any request before all information about # running VMs is recovered, see https://bugzilla.redhat.com/1339291 if not self._cif.ready: self.log.info("In recovery, ignoring '%s' in bridge with %s", req.method, req.params) return JsonRpcResponse(None, vdsmexception.RecoveryInProgress(), req.id) self.log.log(logLevel, "Calling '%s' in bridge with %s", req.method, req.params) try: method = self._bridge.dispatch(req.method) except exception.JsonRpcMethodNotFoundError as e: if req.isNotification(): return None return JsonRpcResponse(None, e, req.id) vars.context = ctx.context try: params = req.params self._bridge.register_server_address(ctx.server_address) if isinstance(req.params, list): res = method(*params) else: res = method(**params) self._bridge.unregister_server_address() except vdsmexception.VdsmException as e: return JsonRpcResponse(None, e, req.id) except Exception as e: self.log.exception("Internal server error") return JsonRpcResponse(None, exception.JsonRpcInternalError(str(e)), req.id) else: res = True if res is None else res self.log.log(logLevel, "Return '%s' in bridge with %s", req.method, res) if isinstance(res, Suppressed): res = res.value return JsonRpcResponse(res, None, req.id) finally: vars.context = None
def sendReply(self): if len(self._requests) > 0: return encodedObjects = [] for response in self._responses: try: encodedObjects.append(response.encode()) except: # Error encoding data response = JsonRpcResponse(None, exception.JsonRpcInternalError(), response.id) encodedObjects.append(response.encode()) if len(encodedObjects) == 1: data = encodedObjects[0] else: data = '[' + ','.join(encodedObjects) + ']' self._client.send(data.encode('utf-8'))