瀏覽代碼

server: add POST /idmac2name

Example: curl -d ident1 -d ident2 http://batcave:8888/idmac2name

Result: a line per ident in the format "ident=name" if the ident could be resolved
or "ident=ident" if the id could not be resolved. The ident may be a node id or one
of its MAC addresses.
Helge Jung 9 年之前
父節點
當前提交
478ecd4ecc
共有 1 個文件被更改,包括 62 次插入0 次删除
  1. 62 0
      ffstatus/server.py

+ 62 - 0
ffstatus/server.py

@@ -4,6 +4,7 @@
 from __future__ import print_function
 from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
 
+import cgi
 from storage import Storage
 import json
 import logging
@@ -70,6 +71,23 @@ class BatcaveHttpRequestHandler(BaseHTTPRequestHandler):
 		# no match -> 404
 		self.send_error(404, 'The URL \'{0}\' was not found here.'.format(path))
 
+	def do_POST(self):
+		"""Handles all HTTP POST requests."""
+
+		path, query = self.parse_url_pathquery()
+		if path is None:
+			self.send_error(400, 'Could not parse URL (' + str(self.path) + ')')
+                        return
+		params = self.parse_post_params()
+
+		# node id/mac to name mapping
+		if path == 'idmac2name':
+			self.respond_nodeidmac2name(params)
+			return
+
+		# no match -> 404
+		self.send_error(404, 'The URL \'{0}\' was not found here.'.format(path))
+
 	def send_nocache_headers(self):
 		"""Sets HTTP headers indicating that this response shall not be cached."""
 
@@ -86,6 +104,17 @@ class BatcaveHttpRequestHandler(BaseHTTPRequestHandler):
 		if nocache: self.send_nocache_headers()
 		self.end_headers()
 
+	def parse_post_params(self):
+		ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
+		if ctype == 'multipart/form-data':
+			postvars = cgi.parse_multipart(self.rfile, pdict)
+		elif ctype == 'application/x-www-form-urlencoded':
+			length = int(self.headers.getheader('content-length'))
+			postvars = cgi.parse_qs(self.rfile.read(length), keep_blank_values=1)
+		else:
+			postvars = {}
+		return postvars
+
 	def respond_index(self, query):
 		"""Display the index page."""
 
@@ -162,6 +191,30 @@ class BatcaveHttpRequestHandler(BaseHTTPRequestHandler):
 		# return found node
 		return storage.data[nodeid] if nodeid in storage.data else None
 
+	def find_node_by_mac(self, mac):
+		"""Fetch node data from storage by given MAC address."""
+
+		storage = self.server.storage
+		needle = mac.lower()
+
+		# iterate over all nodes
+		for nodeid in storage.data:
+			if nodeid.startswith('__'): continue
+			node = storage.data[nodeid]
+
+			# check node's primary MAC
+			if 'mac' in node and needle == node['mac'].lower():
+				return node
+
+			# check alias MACs
+			if 'macs' in node:
+				haystack = [ x.lower() for x in node['macs'] ]
+				if mac in haystack:
+					return node
+
+		# MAC address not found
+		return None
+
 	def respond_node(self, rawid):
 		"""Display node data."""
 
@@ -187,6 +240,15 @@ class BatcaveHttpRequestHandler(BaseHTTPRequestHandler):
 		self.send_headers('text/json')
 		self.wfile.write(json.dumps(node))
 
+	def respond_nodeidmac2name(self, ids):
+		storage = self.server.storage
+		
+		self.send_headers('text/plain')
+		for nodeid in ids:
+			node = self.find_node(nodeid) if not ':' in nodeid else self.find_node_by_mac(nodeid)
+			nodename = node['hostname'] if (not node is None) and 'hostname' in node else nodeid
+			self.wfile.write('{0}={1}\n'.format(nodeid, nodename))
+			
 	def respond_nodedetail(self, nodeid, field):
 		"""Return a field from the given node - a string is returned as text, all other as JSON."""