Browse Source

new /find?name=...&fuzzy=1

allows to search node detail by giving a node's hostname,
an optional flag enables fuzzy matching
Helge Jung 10 years ago
parent
commit
cbf4e9d5ef
1 changed files with 56 additions and 0 deletions
  1. 56 0
      ffstatus/server.py

+ 56 - 0
ffstatus/server.py

@@ -5,6 +5,7 @@ from __future__ import print_function, unicode_literals
 from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
 
 import cgi
+import difflib
 import json
 import logging
 import re
@@ -111,6 +112,11 @@ class BatcaveHttpRequestHandler(BaseHTTPRequestHandler):
             self.__respond_providers(query)
             return
 
+        # /find?name=foo&fuzzy=1
+        if path == 'find':
+            self.__respond_findnode(query)
+            return
+
         # /node/<id>.json - node's data
         # /node/<id>/field - return specific field from node's data
         match = REGEX_URL_NODEINFO.match(path)
@@ -321,6 +327,56 @@ angesprochen und sollte aus einer Mehrzahl von Gr&uuml;nden nicht
         self.__send_headers('text/plain')
         self.wfile.write(status)
 
+    def __respond_findnode(self, query):
+        """Find nodes matching the supplied name."""
+
+        self.__send_headers('application/json',
+                            extra={'Content-Disposition': 'inline'})
+
+        name = query.get('name').lower()
+        fuzzy = query.get('fuzzy', '0') == '1'
+
+        names = {}
+        for node in self.server.storage.get_nodes():
+            nodename = node.get('hostname').lower()
+            if nodename not in names:
+                # first time we see this name
+                names[nodename] = [node]
+            else:
+                # we've seen this name before
+                names[nodename].append(node)
+
+        allnames = [x for x in names]
+        resultnames = []
+
+        # check for exact match
+        if name in allnames:
+            # write the exact matches and we're done
+            resultnames = [name]
+
+        else:
+            # are we allowed to fuzzy match?
+            if not fuzzy:
+                # no -> return zero matches
+                self.wfile.write('[]')
+                return
+
+            # let's do fuzzy matching
+            resultnames = difflib.get_close_matches(name, allnames,
+                                                    cutoff=0.75)
+
+        result = []
+        for possibility in resultnames:
+            for x in names[possibility]:
+                x_id = x.get('node_id')
+                result.append({
+                    'id': x_id,
+                    'name': x.get('hostname'),
+                    'status': self.server.storage.get_nodestatus(x_id),
+                })
+
+        self.wfile.write(json.dumps(result))
+
     def __respond_nodeidmac2name(self, ids):
         """Return a mapping of the given IDs (or MACs) into their hostname."""