|
@@ -91,6 +91,11 @@ class BatcaveHttpRequestHandler(BaseHTTPRequestHandler):
|
|
|
self.__respond_index(query)
|
|
|
return
|
|
|
|
|
|
+ # /nodes.json
|
|
|
+ if path == 'nodes.json':
|
|
|
+ self.__respond_nodes(query)
|
|
|
+ return
|
|
|
+
|
|
|
# /list - list stored nodes
|
|
|
if path == 'list':
|
|
|
self.__respond_list(query)
|
|
@@ -254,6 +259,41 @@ angesprochen und sollte aus einer Mehrzahl von Gründen nicht
|
|
|
self.wfile.write('</tbody>\n')
|
|
|
self.wfile.write('</table>\n')
|
|
|
|
|
|
+ def __map_item(self, haystack, needle, prefix=None):
|
|
|
+ if not isinstance(haystack, dict):
|
|
|
+ raise Exception("haystack must be a dict")
|
|
|
+ if needle in haystack:
|
|
|
+ return haystack[needle]
|
|
|
+
|
|
|
+ idx = len(haystack) + 1
|
|
|
+ name = prefix + str(idx)
|
|
|
+ while name in haystack:
|
|
|
+ idx += 1
|
|
|
+ name = prefix + str(idx)
|
|
|
+ haystack[needle] = name
|
|
|
+ return name
|
|
|
+
|
|
|
+ def __respond_nodes(self, query):
|
|
|
+ indent = 2 if query.get('pretty', 0) == '1' else None
|
|
|
+ nodes = []
|
|
|
+ clientmapping = {}
|
|
|
+ for node in self.server.storage.get_nodes():
|
|
|
+ entry = {
|
|
|
+ 'id': node.get('node_id'),
|
|
|
+ 'name': node.get('hostname'),
|
|
|
+ 'clients': [self.__map_item(clientmapping, x, "c")
|
|
|
+ for x in node.get('clients', [])],
|
|
|
+ }
|
|
|
+ geo = node.get('location', None)
|
|
|
+ if geo is not None:
|
|
|
+ entry['geo'] = [geo['latitude'], geo['longitude']]
|
|
|
+ nodes.append(entry)
|
|
|
+
|
|
|
+ result = {'nodes': nodes}
|
|
|
+ self.__send_headers(content_type='application/json',
|
|
|
+ extra={'Content-Disposition': 'inline'})
|
|
|
+ self.wfile.write(json.dumps(result, indent=indent))
|
|
|
+
|
|
|
def __respond_node(self, rawid):
|
|
|
"""Display node data."""
|
|
|
|