diff --git a/module/livestatus_obj.py b/module/livestatus_obj.py index 83a6954..c8ef96b 100644 --- a/module/livestatus_obj.py +++ b/module/livestatus_obj.py @@ -71,6 +71,7 @@ def __init__(self, datamgr, query_cache, db, pnp_path, return_queue, counters=No def handle_request(self, data): try: + outputformat='csv' return self.handle_request_and_fail(data) except LiveStatusQueryError as err: # LiveStatusQueryError(404, table) @@ -84,8 +85,18 @@ def handle_request(self, data): logger.error("[Livestatus] Back trace of this exception: %s", trb) code = 500 output = err + # We need the output format in order to return the error in one way or another + OUTPUT_FORMAT_HEADER = 'OutputFormat:' + outputformat = next( + ( + line[len(OUTPUT_FORMAT_HEADER)+1:].strip() + for line in data.splitlines() + if line.startswith(OUTPUT_FORMAT_HEADER) + ), + 'csv' # Default value + ) # Ok now we can return something - response = LiveStatusResponse() + response = LiveStatusResponse(outputformat=outputformat) response.set_error(code, output) if 'fixed16' in data: response.responseheader = 'fixed16' diff --git a/module/livestatus_response.py b/module/livestatus_response.py index a2824b0..6530ab8 100644 --- a/module/livestatus_response.py +++ b/module/livestatus_response.py @@ -120,6 +120,7 @@ def __init__(self, responseheader='off', outputformat='csv', keepalive='off', co self.separators = separators self.statuscode = 200 self.output = LiveStatusListResponse() + self.error = None def __str__(self): output = "LiveStatusResponse:\n" @@ -128,8 +129,13 @@ def __str__(self): return output def set_error(self, statuscode, data): - del self.output[:] - self.output.append( LiveStatusQueryError.messages[statuscode] % data ) + msg = LiveStatusQueryError.messages[statuscode] % data + if self.outputformat == 'wrapped_json': + self.output = '[]' + self.error = msg + else: + del self.output[:] + self.output.append(msg) self.statuscode = statuscode def load(self, query): @@ -143,12 +149,23 @@ def get_response_len(self, rsp=None): else len(rsp) ) def respond(self): + if self.outputformat == 'wrapped_json': + self._generate_wrapped_json_output() + if self.responseheader == 'fixed16': responselength = 1 + self.get_response_len() # 1 for the final '\n' self.output.insert(0, '%3d %11d\n' % (self.statuscode, responselength)) self.output.append('\n') + return self.output, self.keepalive + def _generate_wrapped_json_output(self): + self.output = loads(reduce(lambda acc, x: acc+x, self.output)) + self.output = {'data': self.output, 'failed': {}, 'total': len(self.output)} + if self.error: + self.output['errors']['shinken-error'] = self.error + self.output = LiveStatusListResponse([dumps(self.output) + '\n']) + def _format_json_python_value(self, value): if isinstance(value, bool): return 1 if value else 0 @@ -198,6 +215,7 @@ def _python_end_row(self, row, line_nr=0): _format_2_value_handler = { 'csv': (_csv_end_row, _format_csv_value), 'json': (_json_end_row, _format_json_python_value), + 'wrapped_json': (_json_end_row, _format_json_python_value), 'python': (_python_end_row, _format_json_python_value) } def make_live_data_generator2(self, result, columns, aliases): @@ -270,15 +288,15 @@ def make_live_data_generator2(self, result, columns, aliases): def make_live_data_generator(self, result, columns, aliases): - assert self.outputformat in ('csv', 'json', 'python') + assert self.outputformat in ('csv', 'json', 'python', 'wrapped_json') - if self.outputformat in ('json', 'python'): + if self.outputformat in ('json', 'python', 'wrapped_json'): yield '[' for value in self.make_live_data_generator2(result, columns, aliases): yield value - if self.outputformat in ('json', 'python'): + if self.outputformat in ('json', 'python', 'wrapped_json'): yield ']' def format_live_data(self, result, columns, aliases):