Browse Source

add /nodes.csv

Helge Jung 8 years ago
parent
commit
0dc57e5f7c
1 changed files with 43 additions and 0 deletions
  1. 43 0
      ffstatus/server.py

+ 43 - 0
ffstatus/server.py

@@ -57,6 +57,16 @@ def normalize_ispname(isp):
     return isp
 
 
+def csvize_values(values):
+    for x in values:
+        if x is None:
+            yield '-/-'
+        elif ' ' in x:
+            yield '"' + x + '"'
+        else:
+            yield str(x)
+
+
 class BatcaveHttpRequestHandler(BaseHTTPRequestHandler):
     """Handles a single HTTP request to the BATCAVE."""
 
@@ -97,6 +107,11 @@ class BatcaveHttpRequestHandler(BaseHTTPRequestHandler):
             self.__respond_nodes(query)
             return
 
+        # /nodes.csv
+        if path == 'nodes.csv':
+            self.__respond_nodes_csv(query)
+            return
+
         # /list - list stored nodes
         if path == 'list':
             self.__respond_list(query)
@@ -372,6 +387,34 @@ angesprochen und sollte aus einer Mehrzahl von Gründen nicht
                             extra={'Content-Disposition': 'inline'})
         self.wfile.write(json.dumps(result, indent=indent))
 
+    def __respond_nodes_csv(self, query):
+        self.__send_headers(content_type='text/csv', nocache=True)
+
+        csv_fs = ";"
+
+        fields = query.get('fields', 'ID,Name,Firmware,Autoupdater,Location,Status,Clients').split(',')
+        fieldmapping = {
+            'ID': 'node_id',
+            'Name': 'hostname',
+            'Status': lambda n: self.server.storage.get_nodestatus(node=n),
+            'Location': lambda n: ' '.join(n.get('location')) if isinstance(n.get('location'), list) else '{latitude} {longitude}'.format(**n.get('location')) if n.get('location') is not None else '',
+            'Firmware': lambda n: n.get('software', {}).get('firmware'),
+            'Autoupdater': lambda n: n.get('software', {}).get('autoupdater', 'unknown'),
+            'Clients': lambda n: str(len(n.get('clients', []))),
+        }
+
+        # write CSV header line
+        self.wfile.write(csv_fs.join(csvize_values(
+            [f for f in fields if f in fieldmapping])))
+        self.wfile.write('\n')
+
+        # output each node
+        for node in self.server.storage.get_nodes():
+            value_gen = [fieldmapping[f] for f in fields if f in fieldmapping]
+            values = [gen(node) if not isinstance(gen, basestring) else node.get(gen) for gen in value_gen]
+            self.wfile.write(csv_fs.join(csvize_values(values)))
+            self.wfile.write('\n')
+
     def __respond_node(self, rawid, query):
         """Display node data."""