203 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			203 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from __future__ import absolute_import, division, print_function
 | 
						|
 | 
						|
import os
 | 
						|
import sys
 | 
						|
import re
 | 
						|
import glob
 | 
						|
import fnmatch
 | 
						|
 | 
						|
import seiscomp.kernel
 | 
						|
import seiscomp.config
 | 
						|
 | 
						|
 | 
						|
class Module(seiscomp.kernel.Module):
 | 
						|
    def __init__(self, env):
 | 
						|
        seiscomp.kernel.Module.__init__(self, env, env.moduleName(__file__))
 | 
						|
        self.net = None
 | 
						|
        self.sta = None
 | 
						|
        self.journalFile = None
 | 
						|
 | 
						|
    def _readConfig(self):
 | 
						|
        cfg = seiscomp.config.Config()
 | 
						|
        cfg.readConfig(os.path.join(self.env.SEISCOMP_ROOT,
 | 
						|
                                    "etc", "defaults", self.name + ".cfg"))
 | 
						|
        cfg.readConfig(os.path.join(
 | 
						|
            self.env.SEISCOMP_ROOT, "etc", self.name + ".cfg"))
 | 
						|
        try:
 | 
						|
            cfg.readConfig(os.path.join(
 | 
						|
                os.environ['HOME'], ".seiscomp", self.name + ".cfg"))
 | 
						|
        except BaseException:
 | 
						|
            pass
 | 
						|
 | 
						|
        self.journalFile = None
 | 
						|
        try:
 | 
						|
            if not cfg.getBool("journal.syncWithBindings"):
 | 
						|
                sys.stderr.write("! bindings synchronization disabled\n")
 | 
						|
                return
 | 
						|
        except BaseException:
 | 
						|
            sys.stderr.write("! bindings synchronization disabled\n")
 | 
						|
            return
 | 
						|
 | 
						|
        try:
 | 
						|
            self.journalFile = cfg.getString("journal.file")
 | 
						|
        except BaseException:
 | 
						|
            self.journalFile = os.path.join(
 | 
						|
                self.env.SEISCOMP_ROOT, "var", "run", self.name + "/journal")
 | 
						|
 | 
						|
    def _processStation(self, key_dir, profile):
 | 
						|
        if profile:
 | 
						|
            station_config_file = "profile_%s" % (profile,)
 | 
						|
        else:
 | 
						|
            station_config_file = "station_%s_%s" % (self.net, self.sta)
 | 
						|
 | 
						|
        cfg = seiscomp.config.Config()
 | 
						|
        cfg.readConfig(os.path.join(key_dir, station_config_file))
 | 
						|
        lines = []
 | 
						|
        try:
 | 
						|
            selectors = cfg.getStrings("selectors")
 | 
						|
        except BaseException:
 | 
						|
            selectors = ["*.*"]
 | 
						|
 | 
						|
        for s in selectors:
 | 
						|
            lines.append(self.net + "." + self.sta + "." + s)
 | 
						|
 | 
						|
        return lines
 | 
						|
 | 
						|
    def requiresKernelModules(self):
 | 
						|
        return False
 | 
						|
 | 
						|
    def supportsAliases(self):
 | 
						|
        return True
 | 
						|
 | 
						|
    def updateConfig(self):
 | 
						|
        self._readConfig()
 | 
						|
 | 
						|
        if not self.journalFile:
 | 
						|
            return 0
 | 
						|
 | 
						|
        rx_binding = re.compile(
 | 
						|
            r'(?P<module>[A-Za-z0-9_\.-]+)(:(?P<profile>[A-Za-z0-9_-]+))?$')
 | 
						|
 | 
						|
        bindings_dir = os.path.join(self.env.SEISCOMP_ROOT, "etc", "key")
 | 
						|
        key_dir = os.path.join(bindings_dir, self.name)
 | 
						|
 | 
						|
        journalEntries = []
 | 
						|
        requestedEntries = []
 | 
						|
        requestedEntriesSet = set()
 | 
						|
        requestedEntriesTree = {}
 | 
						|
 | 
						|
        try:
 | 
						|
            journalFile = open(self.journalFile, "r")
 | 
						|
            for l in journalFile:
 | 
						|
                journalEntries.append(l.strip().split())
 | 
						|
        except BaseException:
 | 
						|
            pass
 | 
						|
            #raise Exception("Error: unable to create rs2caps request file '%s'" %
 | 
						|
            #                self.journalFile)
 | 
						|
 | 
						|
        files = glob.glob(os.path.join(bindings_dir, "station_*"))
 | 
						|
 | 
						|
        for f in files:
 | 
						|
            try:
 | 
						|
                (path, net, sta) = f.split('_')[-3:]
 | 
						|
                if not path.endswith("station"):
 | 
						|
                    print("invalid path", f)
 | 
						|
 | 
						|
            except ValueError:
 | 
						|
                print("invalid path", f)
 | 
						|
                continue
 | 
						|
 | 
						|
            self.net = net
 | 
						|
            self.sta = sta
 | 
						|
 | 
						|
            if net not in requestedEntriesTree:
 | 
						|
                requestedEntriesTree[net] = {}
 | 
						|
 | 
						|
            if sta not in requestedEntriesTree:
 | 
						|
                requestedEntriesTree[net][sta] = []
 | 
						|
 | 
						|
            fd = open(f)
 | 
						|
            line = fd.readline()
 | 
						|
            while line:
 | 
						|
                line = line.strip()
 | 
						|
                if not line or line[0] == '#':
 | 
						|
                    line = fd.readline()
 | 
						|
                    continue
 | 
						|
 | 
						|
                m = rx_binding.match(line)
 | 
						|
                if not m:
 | 
						|
                    print("invalid binding in %s: %s" % (f, line))
 | 
						|
                    line = fd.readline()
 | 
						|
                    continue
 | 
						|
 | 
						|
                if m.group('module') != self.name:
 | 
						|
                    line = fd.readline()
 | 
						|
                    continue
 | 
						|
 | 
						|
                profile = m.group('profile')
 | 
						|
                lines = self._processStation(key_dir, profile)
 | 
						|
                if lines:
 | 
						|
                    #for l in lines: journalFile.write("%s\n" % l)
 | 
						|
                    for l in lines:
 | 
						|
                        requestedEntries.append(l)
 | 
						|
                        requestedEntriesSet.add(l)
 | 
						|
                        requestedEntriesTree[net][sta].append(l)
 | 
						|
                    break
 | 
						|
 | 
						|
            fd.close()
 | 
						|
 | 
						|
        # Intersect requests with journal
 | 
						|
        newJournalEntries = []
 | 
						|
        newRequests = []
 | 
						|
 | 
						|
        oldJournalChannels = set()
 | 
						|
 | 
						|
        for j in journalEntries:
 | 
						|
            oldJournalChannels.add(j[0])
 | 
						|
            if (j[0].find('*') >= 0) or (j[0].find('?') >= 0):
 | 
						|
                continue
 | 
						|
 | 
						|
            foundMatch = False
 | 
						|
            if j[0] in requestedEntriesSet:
 | 
						|
                foundMatch = True
 | 
						|
            else:
 | 
						|
                n, s, _, _ = j[0].split('.')
 | 
						|
                try:
 | 
						|
                    for r in requestedEntriesTree[n][s]:
 | 
						|
                        if fnmatch.fnmatch(j[0], r):
 | 
						|
                            foundMatch = True
 | 
						|
                            break
 | 
						|
                except BaseException:
 | 
						|
                    pass
 | 
						|
 | 
						|
            if foundMatch:
 | 
						|
                newJournalEntries.append(j)
 | 
						|
            else:
 | 
						|
                sys.stderr.write("- %s\n" % j[0])
 | 
						|
 | 
						|
        for r in requestedEntries:
 | 
						|
            foundMatch = False
 | 
						|
            for j in newJournalEntries:
 | 
						|
                if r == j[0]:
 | 
						|
                    foundMatch = True
 | 
						|
                    break
 | 
						|
 | 
						|
            if not foundMatch:
 | 
						|
                newRequests.append(r)
 | 
						|
                if r not in oldJournalChannels:
 | 
						|
                    sys.stderr.write("+ %s\n" % r)
 | 
						|
 | 
						|
        try:
 | 
						|
            journalFile = open(self.journalFile, "w")
 | 
						|
        except BaseException:
 | 
						|
            raise Exception(
 | 
						|
                "Error: unable to write to rs2caps journal file '%s'" %
 | 
						|
                self.journalFile)
 | 
						|
 | 
						|
        for r in newRequests:
 | 
						|
            journalFile.write(r + "\n")
 | 
						|
        for j in newJournalEntries:
 | 
						|
            journalFile.write(" ".join(j) + "\n")
 | 
						|
 | 
						|
        return 0
 |