[Pkg-nagios-changes] [SCM] UNNAMED PROJECT branch, debian/master, updated. 810edbdd3feedbfe37f4a65bee50b57b2f60fa2a

Gerhard Lausser gerhard.lausser at consol.de
Tue Feb 28 22:21:32 UTC 2012


The following commit has been merged in the debian/master branch:
commit 34768d04677e6610dd0f9b050be6adfd20e8bc59
Author: Gerhard Lausser <gerhard.lausser at consol.de>
Date:   Fri Feb 17 21:09:48 2012 +0100

    Add better error handling for invalid livestatus queries

diff --git a/shinken/modules/livestatus_broker/livestatus.py b/shinken/modules/livestatus_broker/livestatus.py
index 93e5a66..8ef1be9 100644
--- a/shinken/modules/livestatus_broker/livestatus.py
+++ b/shinken/modules/livestatus_broker/livestatus.py
@@ -25,6 +25,8 @@
 import time
 from livestatus_counters import LiveStatusCounters
 from livestatus_request import LiveStatusRequest
+from livestatus_response import LiveStatusResponse
+from livestatus_query import LiveStatusQueryError
 
 
 class LiveStatus(object):
@@ -40,6 +42,27 @@ class LiveStatus(object):
         self.counters = LiveStatusCounters()
 
     def handle_request(self, data):
+        try:
+            return self.handle_request_and_fail(data)
+        except LiveStatusQueryError, exp:
+            # LiveStatusQueryError(404, table)
+            # LiveStatusQueryError(450, column)
+            code, detail = exp.args
+            response = LiveStatusResponse()
+            response.output = LiveStatusQueryError.messages[code] % detail
+            response.statuscode = code
+            if 'fixed16' in data:
+                response.responseheader = 'fixed16'
+            return response.respond()
+        except Exception, exp:
+            response = LiveStatusResponse()
+            response.output = LiveStatusQueryError.messages[452] % data
+            response.statuscode = 452
+            if 'fixed16' in data:
+                response.responseheader = 'fixed16'
+            return response.respond()
+
+    def handle_request_and_fail(self, data):
         """Execute the livestatus request.
 
         This function creates a LiveStatusRequest method, calls the parser,
@@ -47,11 +70,7 @@ class LiveStatus(object):
 
         """
         request = LiveStatusRequest(data, self.datamgr, self.query_cache, self.db, self.pnp_path, self.return_queue, self.counters)
-        try:
-            request.parse_input(data)
-        except:
-            print "THIS QUERY IS INVALID", data
-            return '', False
+        request.parse_input(data)
         if sorted([q.my_type for q in request.queries]) == ['command', 'query', 'wait']:
             # The Multisite way
             for query in [q for q in request.queries if q.my_type == 'command']:
diff --git a/shinken/modules/livestatus_broker/livestatus_query.py b/shinken/modules/livestatus_broker/livestatus_query.py
index ee00388..8a24103 100644
--- a/shinken/modules/livestatus_broker/livestatus_query.py
+++ b/shinken/modules/livestatus_broker/livestatus_query.py
@@ -32,6 +32,15 @@ from livestatus_stack import LiveStatusStack
 from livestatus_constraints import LiveStatusConstraints
 
 
+class LiveStatusQueryError(Exception):
+    messages = {
+        200: 'OK',
+        404: 'Invalid GET request, no such table \'%s\'',
+        450: 'Invalid GET request, no such column \'%s\'',
+        452: 'Completely invalid GET request \'%s\'',
+    }
+    pass
+
 class LiveStatusQuery(object):
 
     my_type = 'query'
@@ -122,6 +131,8 @@ class LiveStatusQuery(object):
             keyword = line.split(' ')[0].rstrip(':')
             if keyword == 'GET': # Get the name of the base table
                 _, self.table = self.split_command(line)
+                if self.table not in table_class_map.keys():
+                    raise LiveStatusQueryError(404, self.table)
             elif keyword == 'Columns': # Get the names of the desired columns
                 _, self.columns = self.split_option_with_columns(line)
                 self.response.columnheaders = 'off'
@@ -743,7 +754,7 @@ class LiveStatusQuery(object):
                 if hasattr(item, attribute):
                     return getattr(item.__class__, attribute).im_func.default == reference
                 else:
-                    return getattr(item.__class__, attribute).im_func.default == reference
+                    raise LiveStatusQueryError(450, attribute.replace('lsm_', ''))
 
         def eq_nocase_filter(item):
             return getattr(item, attribute)(self).lower() == reference.lower()
@@ -756,7 +767,7 @@ class LiveStatusQuery(object):
                 if hasattr(item, attribute):
                     return getattr(item.__class__, attribute).im_func.default != reference
                 else:
-                    return getattr(item.__class__, attribute).im_func.default != reference
+                    raise LiveStatusQueryError(450, attribute.replace('lsm_', ''))
 
         def gt_filter(item):
             try:
@@ -765,7 +776,7 @@ class LiveStatusQuery(object):
                 if hasattr(item, attribute):
                     return getattr(item.__class__, attribute).im_func.default > reference
                 else:
-                    return getattr(item.__class__, attribute).im_func.default > reference
+                    raise LiveStatusQueryError(450, attribute.replace('lsm_', ''))
 
         def ge_filter(item):
             try:
@@ -774,7 +785,7 @@ class LiveStatusQuery(object):
                 if hasattr(item, attribute):
                     return getattr(item.__class__, attribute).im_func.default >= reference
                 else:
-                    return getattr(item.__class__, attribute).im_func.default >= reference
+                    raise LiveStatusQueryError(450, attribute.replace('lsm_', ''))
 
         def lt_filter(item):
             try:
@@ -783,7 +794,7 @@ class LiveStatusQuery(object):
                 if hasattr(item, attribute):
                     return getattr(item.__class__, attribute).im_func.default < reference
                 else:
-                    return getattr(item.__class__, attribute).im_func.default < reference
+                    raise LiveStatusQueryError(450, attribute.replace('lsm_', ''))
 
         def le_filter(item):
             try:
@@ -792,7 +803,7 @@ class LiveStatusQuery(object):
                 if hasattr(item, attribute):
                     return getattr(item.__class__, attribute).im_func.default <= reference
                 else:
-                    return getattr(item.__class__, attribute).im_func.default <= reference
+                    raise LiveStatusQueryError(450, attribute.replace('lsm_', ''))
 
         def match_filter(item):
             #print "ma_filter %s %s(%s) ~ %s(%s)" % (attribute, type(getattr(item, attribute)(self)), getattr(item, attribute)(self), type(reference), reference)
@@ -800,7 +811,7 @@ class LiveStatusQuery(object):
                 p = re.compile(reference)
                 return p.search(getattr(item, attribute)(self))
             except Exception:
-                return False
+                raise LiveStatusQueryError(450, attribute.replace('lsm_', ''))
 
         def match_nocase_filter(item):
             p = re.compile(reference, re.I)
diff --git a/shinken/modules/livestatus_broker/livestatus_response.py b/shinken/modules/livestatus_broker/livestatus_response.py
index d8092b5..04ea39b 100644
--- a/shinken/modules/livestatus_broker/livestatus_response.py
+++ b/shinken/modules/livestatus_broker/livestatus_response.py
@@ -70,6 +70,7 @@ class LiveStatusResponse:
         self.keepalive = keepalive
         self.columnheaders = columnheaders
         self.separators = separators
+        self.statuscode = 200
         self.output = ''
         pass
 
@@ -86,9 +87,8 @@ class LiveStatusResponse:
     def respond(self):
         self.output += '\n'
         if self.responseheader == 'fixed16':
-            statuscode = 200 
             responselength = len(self.output)
-            self.output = '%3d %11d\n' % (statuscode, responselength) + self.output
+            self.output = '%3d %11d\n' % (self.statuscode, responselength) + self.output
 
         return self.output, self.keepalive
 
diff --git a/test/test_livestatus.py b/test/test_livestatus.py
index 47841ff..dc9616c 100755
--- a/test/test_livestatus.py
+++ b/test/test_livestatus.py
@@ -371,13 +371,59 @@ ResponseHeader: fixed16
             objlist.append([service, 0, 'OK'])
         self.scheduler_loop(1, objlist)
         self.update_broker()
+
+        # non-existing filter-column
+        request = """GET hosts
+Columns: name state
+Filter: serialnumber = localhost
+"""
+        goodresponse = """Invalid GET request, no such column 'serialnumber'
+"""
+        response, keepalive = self.livestatus_broker.livestatus.handle_request(request)
+        print "response", response
+        self.assert_(response == goodresponse)
+
+        # this time as fixed16
+        request = """GET hosts
+Columns: name state
+Filter: serialnumber = localhost
+ResponseHeader: fixed16
+"""
+        goodresponse = """450          51
+Invalid GET request, no such column 'serialnumber'
+"""
+        response, keepalive = self.livestatus_broker.livestatus.handle_request(request)
+        print "response", response
+        self.assert_(response == goodresponse)
+
+        # invalid filter-clause. attribute, operator missing
         request = """GET hosts
 Columns: name state
 Filter: localhost
+ResponseHeader: fixed16
+"""
+        goodresponse = """452         106
+Completely invalid GET request 'GET hosts
+Columns: name state
+Filter: localhost
+ResponseHeader: fixed16
+'
+"""
+        response, keepalive = self.livestatus_broker.livestatus.handle_request(request)
+        print response
+        self.assert_(response == goodresponse)
+
+        # non-existing table
+        request = """GET hostshundsglumpvarreckts
+Columns: name state
+ResponseHeader: fixed16
+"""
+        goodresponse = """404          62
+Invalid GET request, no such table 'hostshundsglumpvarreckts'
 """
         response, keepalive = self.livestatus_broker.livestatus.handle_request(request)
         print response
-        self.assert_(response == '')
+        self.assert_(response == goodresponse)
 
     def test_bad_column(self):
         self.print_header()

-- 
UNNAMED PROJECT



More information about the Pkg-nagios-changes mailing list