Browse Source

fetch node data from ALFRED and use it to find nodes

Helge Jung 9 years ago
parent
commit
09587185e6
1 changed files with 95 additions and 34 deletions
  1. 95 34
      modules/ffpb.py

+ 95 - 34
modules/ffpb.py

@@ -20,6 +20,9 @@ msgserver = None
 peers_repo = None
 stats = None
 
+alfred_method = None
+alfred_data = None
+
 ffpb_resolver = dns.resolver.Resolver ()
 ffpb_resolver.nameservers = ['10.132.254.53']
 
@@ -55,13 +58,11 @@ class MsgHandler(SocketServer.BaseRequestHandler):
 		except dns.resolver.NXDOMAIN:
 			return ip
 
-
-
 class ThreadingTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
 	pass
 
 def setup(bot):
-	global msgserver, peers_repo
+	global msgserver, peers_repo, alfred_method
 
 	if not bot.config.has_section('ffpb'):
 		return
@@ -85,6 +86,9 @@ def setup(bot):
 		msgserver_thread.daemon = True
 		msgserver_thread.start()
 
+	alfred_method = bot.config.ffpb.alfred_method
+	ffpb_updatealfred(bot)
+
 def shutdown(bot):
 	global msgserver
 
@@ -93,6 +97,81 @@ def shutdown(bot):
 		print("Closed messaging server.")
 		msgserver = None
 
+def ffpb_findnode(name):
+	if name is None or len(name) == 0:
+		return None
+
+	name = str(name).strip()
+
+	# try to match MAC
+	m = re.search("^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$", name)
+	if (not m is None):
+		mac = m.group(0).lower()
+		if mac in alfred_data:
+			return alfred_data[mac]
+
+		# try to find alias MAC
+		for nodeid in alfred_data:
+			node = alfred_data[nodeid]
+			if "network" in node:
+				if "mac" in node["network"] and node["network"]["mac"].lower() == mac:
+					return node
+				if "mesh_interfaces" in node["network"]:
+					for mim in node["network"]["mesh_interfaces"]:
+						if mim.lower() == mac:
+							return node
+
+	# look through the ALFRED peers
+	possible_matches = []
+	for nodeid in alfred_data:
+		node = alfred_data[nodeid]
+		if "hostname" in node and node["hostname"].lower() == name.lower():
+			return node
+
+	# still not found -> try peers_repo
+	peerfilename = '/home/ffpb-statusbot/knoten/' + name
+	peer_mac = None
+
+	if os.path.exists(peerfilename):
+		peerfile = open(peerfilename, "r")
+		for line in peerfile:
+			if line.startswith("# MAC:"):
+				peer_mac = line[6:].strip()
+		peerfile.close()
+
+	print("peer '", name, "': file '", peerfilename, "', MAC ", peer_mac, sep='')
+
+	if not (peer_mac is None):
+		return mac2ipv6(peer_mac)
+
+	return None
+
+def mac2ipv6(mac):
+	return str(netaddr.EUI(mac).ipv6_link_local())
+
+@willie.module.interval(30)
+def ffpb_updatealfred(bot):
+	"""Aktualisiere ALFRED-Daten"""
+	global alfred_data
+
+	if alfred_method is None or alfred_method == "None":
+		return
+
+	if alfred_method == "exec":
+		rawdata = subprocess.check_output(['alfred-json', '-z', '-r', '158'])
+		alfred_data = json.load(rawdata)
+		#print("Fetched new ALFRED data:", len(alfred_data), "entries")
+		return
+
+	if alfred_method.startswith("http"):
+		rawdata = urllib2.urlopen(alfred_method)
+		alfred_data = json.load(rawdata)
+		#print("Downloaded new ALFRED data:", len(alfred_data), "entries")
+		return
+
+	print("Unknown ALFRED data method '", alfred_method, "', cannot load new data.", sep="")
+	alfred_data = None
+
 @willie.module.interval(60)
 def ffpb_updatepeers(bot):
 	"""Aktualisiere die Knotenliste und melde das Diff"""
@@ -185,24 +264,6 @@ def ffpb_greeting(bot, trigger):
 		'{1} Knoten online, {2} Clients im Netz und {0} gibt uns die Ehre - Herzlich Willkommen :)'))
 	bot.say(greeting.format(trigger.nick, stats["nodes_active"], stats["clients"]))
 
-def ffpb_get_address(name):
-	peerfilename = '/home/ffpb-statusbot/knoten/' + name
-	peer_mac = None
-
-	if os.path.exists(peerfilename):
-		peerfile = open(peerfilename, "r")
-		for line in peerfile:
-			if line.startswith("# MAC:"):
-				peer_mac = line[6:].strip()
-		peerfile.close()
-
-	print("peer '", name, "': file '", peerfilename, "', MAC ", peer_mac, sep='')
-
-	if not (peer_mac is None):
-		return str(netaddr.EUI(peer_mac).ipv6_link_local())
-
-	return None
-
 @willie.module.commands('ping')
 def ffpb_ping(bot, trigger):
 	"""Ping FFPB-Knoten"""
@@ -211,20 +272,20 @@ def ffpb_ping(bot, trigger):
 		bot.say('Alter, wen soll ich denn pingen? Einmal mit Profis arbeiten -.-')
 		return
 
-	target = ffpb_get_address(target_name)
-	if target is None:
+	node = ffpb_findnode(target_name)
+	if node is None:
 		bot.say('Kein Plan wer mit \'' + target_name + '\' gemeint ist :/')
 		return
 
-	if target.startswith('fe80::'):
-		target = 'fdca:ffee:ff12:132:' + target[6:]
+	target = node["network"]["addresses"][0]
+	target_alias = node["hostname"]
 
 	print("ping '", target , '"', sep='')
 	result = os.system('ping6 -c 1 -W 2 ' + target + ' 2>/dev/null')
 	if result == 0:
-		bot.say('Knoten "' + target_name + '" antwortet \o/')
+		bot.say('Knoten "' + target_alias + '" antwortet \o/')
 	elif result == 1 or result == 256:
-		bot.say('Keine Antwort von "' + target_name + '" :-(')
+		bot.say('Keine Antwort von "' + target_alias + '" :-(')
 	else:
 		bot.say('Uh oh, irgendwas ist kaputt. Chef, ping result = ' + str(result) + ' - darf ich das essen?')
 
@@ -252,13 +313,13 @@ def ffpb_remoteexec(bot, trigger):
 		bot.say('Geh weg.')
 		return
 
-	target = ffpb_get_address(target_name)
-	if target is None:
+	node = ffpb_findnode(target_name)
+	if node is None:
 		bot.say('Kein Plan wer mit \'' + target_name + '\' gemeint ist :/')
 		return
 
-	if target.startswith('fe80::'):
-		target = 'fdca:ffee:ff12:132:' + target[6:]
+	target = node["network"]["addresses"][0]
+	target_alias = node["hostname"]
 
 	cmd = 'ssh -6 -l root ' + target + ' -- "' + target_cmd + '"'
 	print("REMOTE EXEC = " + cmd)
@@ -267,10 +328,10 @@ def ffpb_remoteexec(bot, trigger):
 		lines = str(result).splitlines()
 
 		if len(lines) == 0:
-			bot.say('exec-on-peer(' + target_name + '): No output')
+			bot.say('exec-on-peer(' + target_alias + '): No output')
 			return
 
-		msg = 'exec-on-peer(' + target_name + '): ' + str(len(lines)) + ' Zeilen'
+		msg = 'exec-on-peer(' + target_alias + '): ' + str(len(lines)) + ' Zeilen'
 		if len(lines) > 8:
 			msg += ' (zeige max. 8)'
 
@@ -280,4 +341,4 @@ def ffpb_remoteexec(bot, trigger):
 			bot.say(line)
 
 	except subprocess.CalledProcessError as e:
-		bot.say('Fehler '+str(e.returncode)+' bei exec-on-peer('+target_name+'): ' + e.output)
+		bot.say('Fehler '+str(e.returncode)+' bei exec-on-peer('+target_alias+'): ' + e.output)