From 6da8fd0b3276f751ae830e717d63334d869adde2 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Tue, 2 Dec 2014 02:08:23 +0100 Subject: [PATCH] alfred: Create announce scripts --- config/alfred/announce.py | 209 +++++++++++++++++++++++++++++++++ config/rootfiles/common/alfred | 4 + html/cgi-bin/freifunk.cgi | 82 +++++++------ lfs/alfred | 12 ++ 4 files changed, 271 insertions(+), 36 deletions(-) create mode 100644 config/alfred/announce.py diff --git a/config/alfred/announce.py b/config/alfred/announce.py new file mode 100644 index 0000000000..51e7d9331e --- /dev/null +++ b/config/alfred/announce.py @@ -0,0 +1,209 @@ +#!/usr/bin/python + +import io +import gzip +import json +import os +import re +import socket +import subprocess +import sys + +import fireinfo + +SETTINGS_FILE = "/var/ipfire/freifunk/settings" +INTERFACES = ("green0", "blue0", "orange0") + +class Settings(object): + __expr = re.compile(r"^([A-Za-z_][A-Za-z0-9_]*)=([A-Za-z0-9=/,.:%_@#+-]*)$") + + def __init__(self, file): + self._data = self.__parse(file) + + def __parse(self, file): + ret = {} + + with open(file, "r") as f: + for line in f.readlines(): + m = re.match(self.__expr, line) + if not m: + continue + + k, v = m.groups() + ret[k] = v + + return ret + + def get(self, key): + return self._data.get(key, None) + + +class Announce(object): + id = None + + def __init__(self): + self.settings = Settings(SETTINGS_FILE) + + def generate_message(self): + raise NotImplementedError + + def __call__(self): + enabled = self.settings.get("FREIFUNK_ENABLED") + if not enabled == "on": + return + + # Generate message + msg = self.generate_message() + + # Always send the node id + msg.update({ + "node_id" : self.node_id, + }) + + # Export to JSON format + j = json.dumps(msg) + + return self.send(j) + + def send(self, msg): + debug = os.environ.get("DEBUG") + if debug: + print msg + return + + # Compress message with GZIP + msg = self.compress(msg) + + command = ["/usr/sbin/alfred", "-s", "%s" % self.id] + p = subprocess.Popen(command, stdin=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (stdout, stderr) = p.communicate(msg) + + retval = p.wait() + if retval > 0: + print "alfred exited with code: %s" % retval + print stdout + print stderr + sys.exit(retval) + + @staticmethod + def compress(s): + b = io.BytesIO() + + g = gzip.GzipFile(fileobj=b, mode="wb") + g.write(s) + g.close() + + return b.getvalue() + + @property + def node_id(self): + return self.primary_address.replace(":", "") + + @property + def primary_address(self): + for intf in INTERFACES: + addr = self.get_address(intf) + if not addr: + continue + + return addr + + @staticmethod + def get_address(intf): + try: + with open("/sys/class/net/%s/address" % intf) as f: + mac_address = f.read() + + if mac_address: + return mac_address.strip() + except IOError: + pass + + +class AnnounceNodeinfo(Announce): + id = 158 + + def generate_message(self): + ret = { + "hardware" : self.hardware, + "hostname" : self.hostname, + "location" : self.location, + "software" : self.software, + } + + return ret + + @property + def hostname(self): + """ + Returns the fully-qualified domain name + of this machine. + """ + return self.settings.get("FREIFUNK_HOSTNAME") or socket.getfqdn() + + @property + def location(self): + latitude = self.settings.get("FREIFUNK_LATITUDE") + longitude = self.settings.get("FREIFNK_LONGITUDE") + + if latitude and longitude: + return { + "latitude" : latitude, + "longitude" : longitude, + } + + @property + def software(self): + return { + "firmware" : { + "base" : self.firmware_base, + "release" : self.firmware_release, + }, + } + + @property + def firmware_base(self): + return "IPFire" + + @property + def firmware_release(self): + with open("/etc/system-release") as f: + release = f.read() + + if release: + return release.strip() + + @property + def hardware(self): + system = fireinfo.System() + + return { + "fireinfo" : system.public_id, + } + + +class AnnounceStats(Announce): + id = 159 + + def generate_message(self): + return {} + + +def main(): + basename = sys.argv[0] + + if basename == "alfred-announce-nodeinfo": + a = AnnounceNodeinfo() + + elif basename == "alfred-announce-stats": + a = AnnounceStats() + + else: + print "Called with unknown basename" + sys.exit(1) + + # Run the selected action + a() + +main() diff --git a/config/rootfiles/common/alfred b/config/rootfiles/common/alfred index 79b81a1a5f..5180abef65 100644 --- a/config/rootfiles/common/alfred +++ b/config/rootfiles/common/alfred @@ -1,4 +1,8 @@ +etc/fcron.cyclic/alfred-announce-nodeinfo +etc/fcron.cyclic/alfred-announce-stats usr/sbin/alfred +usr/sbin/alfred-announce-nodeinfo +usr/sbin/alfred-announce-stats usr/sbin/batadv-vis #usr/share/man/man8/alfred.8 #usr/share/man/man8/batadv-vis.8 diff --git a/html/cgi-bin/freifunk.cgi b/html/cgi-bin/freifunk.cgi index 5e85793d21..1a7c84d6ad 100755 --- a/html/cgi-bin/freifunk.cgi +++ b/html/cgi-bin/freifunk.cgi @@ -231,59 +231,69 @@ sub BuildConfiguration() { my %settings = (); &General::readhash("${General::swroot}/freifunk/settings", \%settings); + my %mainsettings = (); + &General::readhash("${General::swroot}/main/settings", \%mainsettings); + + my $network = &GetNetwork($settings{"FREIFUNK_COMMUNITY"}); + return unless (defined($network)); + # Create fastd secret if none is set if ($settings{'FASTD_SECRET'} eq '') { $settings{'FASTD_SECRET'} = &fastdCreateKey(); + } - &General::writehash("${General::swroot}/freifunk/settings", \%settings); + # Make hostname + my $hostname = $mainsettings{"HOSTNAME"} . "." . $mainsettings{"DOMAINNAME"}; + if ($network->{"prefix"}) { + $hostname = $network->{"prefix"} . $hostname; } + $settings{"FREIFUNK_HOSTNAME"} = $hostname; - my $network = &GetNetwork($settings{"FREIFUNK_COMMUNITY"}); - if ($network) { - # Write configuration bits... - open(FILE, ">$FASTD_CONFIG"); + &General::writehash("${General::swroot}/freifunk/settings", \%settings); - print FILE "# Logging\n"; - print FILE "log level error;\n"; - print FILE "log to syslog level info;\n\n"; + # Write configuration bits... + open(FILE, ">$FASTD_CONFIG"); - print FILE "# Drop privileges\n"; - print FILE "user \"nobody\";\n\n"; + print FILE "# Logging\n"; + print FILE "log level error;\n"; + print FILE "log to syslog level info;\n\n"; - print FILE "interface \"batvpn0\";\n"; - print FILE "mode tap;\n\n"; + print FILE "# Drop privileges\n"; + print FILE "user \"nobody\";\n\n"; - print FILE "# Authentication credentials\n"; - print FILE "secret \"$settings{'FASTD_SECRET'}\";\n"; - print FILE "secure handshakes yes;\n\n"; + print FILE "interface \"batvpn0\";\n"; + print FILE "mode tap;\n\n"; - print FILE "# Ciphers\n"; - my $ciphers = $network->{'ciphers'}; - foreach my $cipher (@$ciphers) { - print FILE "method \"$cipher\";\n"; - } - print FILE "\n"; + print FILE "# Authentication credentials\n"; + print FILE "secret \"$settings{'FASTD_SECRET'}\";\n"; + print FILE "secure handshakes yes;\n\n"; - print FILE "# Upstream connection\n"; - print FILE "mtu $network->{'mtu-vpn'};\n"; + print FILE "# Ciphers\n"; + my $ciphers = $network->{'ciphers'}; + foreach my $cipher (@$ciphers) { + print FILE "method \"$cipher\";\n"; + } + print FILE "\n"; - my $nodes = $network->{'supernodes'}; - foreach my $node (@$nodes) { - print FILE "peer \"$node->{'peer'}\" {\n"; - print FILE "\tkey \"$node->{'key'}\";\n"; - print FILE "\tremote \"$node->{'remote'}\" port $node->{'port'};\n"; - print FILE "}\n"; - } - print FILE "\n"; + print FILE "# Upstream connection\n"; + print FILE "mtu $network->{'mtu-vpn'};\n"; - print FILE "# Hooks\n"; - foreach my $hook ("pre-up", "up") { - print FILE "on $hook \"/etc/rc.d/init.d/freifunk on-$hook\";\n"; - } + my $nodes = $network->{'supernodes'}; + foreach my $node (@$nodes) { + print FILE "peer \"$node->{'peer'}\" {\n"; + print FILE "\tkey \"$node->{'key'}\";\n"; + print FILE "\tremote \"$node->{'remote'}\" port $node->{'port'};\n"; + print FILE "}\n"; + } + print FILE "\n"; - close(FILE); + print FILE "# Hooks\n"; + foreach my $hook ("pre-up", "up") { + print FILE "on $hook \"/etc/rc.d/init.d/freifunk on-$hook\";\n"; } + close(FILE); + # Restart the service. if ($settings{'FREIFUNK_ENABLED'} eq 'on') { system("/usr/local/bin/freifunkctrl restart &>/dev/null"); diff --git a/lfs/alfred b/lfs/alfred index 80fc1a7dc8..5f6dfa511b 100644 --- a/lfs/alfred +++ b/lfs/alfred @@ -77,5 +77,17 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE) cd $(DIR_APP) && make $(OPTIONS) $(MAKETUNING) cd $(DIR_APP) && make $(OPTIONS) install + + # Announce scripts + install -v -m 755 $(DIR_SRC)/config/alfred/announce.py \ + /usr/sbin/alfred-announce-nodeinfo + ln -svf alfred-announce-nodeinfo /usr/sbin/alfred-announce-stats + + # Install cron jobs + ln -svf ../../usr/sbin/alfred-announce-nodeinfo \ + /etc/fcron.cyclic/alfred-announce-nodeinfo + ln -svf ../../usr/sbin/alfred-announce-stats \ + /etc/fcron.cyclic/alfred-announce-stats + @rm -rf $(DIR_APP) @$(POSTBUILD) -- 2.39.5