]> git.ipfire.org Git - people/ms/ipfire-2.x.git/commitdiff
alfred: Create announce scripts
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 2 Dec 2014 01:08:23 +0000 (02:08 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 9 Mar 2015 15:39:08 +0000 (16:39 +0100)
config/alfred/announce.py [new file with mode: 0644]
config/rootfiles/common/alfred
html/cgi-bin/freifunk.cgi
lfs/alfred

diff --git a/config/alfred/announce.py b/config/alfred/announce.py
new file mode 100644 (file)
index 0000000..51e7d93
--- /dev/null
@@ -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()
index 79b81a1a5f61c95e2774062cbb475bcab370835a..5180abef6552411235346124c33f08bb32486d40 100644 (file)
@@ -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
index 5e85793d21bf18b06c64f0e3cf3f46ae83d49ec2..1a7c84d6ad221d92df4b84c1436fd09cc6dc23d9 100755 (executable)
@@ -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");
index 80fc1a7dc8b83e6971a42fbe970efa3f1bcc2404..5f6dfa511bfd93e8a2a3384cdfc8854fca1ce227 100644 (file)
@@ -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)