You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
272 lines
9.1 KiB
Python
272 lines
9.1 KiB
Python
from __future__ import print_function
|
|
import os, glob
|
|
|
|
'''
|
|
Plugin handler for the chain plugin. The plugin handler needs
|
|
to support two methods: push and flush.
|
|
|
|
push Pushes a Seedlink station binding. Can be used to either
|
|
create configuration files immediately or to manage the
|
|
information until flush is called.
|
|
|
|
flush Flush the configuration and return a unique key for this
|
|
station that is used by seedlink to group eg templates for
|
|
plugins.ini.
|
|
'''
|
|
class SeedlinkPluginHandler:
|
|
# Create defaults
|
|
def __init__(self):
|
|
self.chain_group = {}
|
|
self.activeDialupConnections = 0
|
|
self.stations = {}
|
|
|
|
|
|
# Generates the group tag
|
|
def generateGroupTag(self, seedlink, source_address):
|
|
try: maxDialupConnections = int(seedlink.param('plugins.chain.dialupConnections', False))
|
|
except: maxDialupConnections = 0
|
|
|
|
dialup = seedlink._get('sources.chain.dialup.enable').lower() in ("yes", "true", "1")
|
|
|
|
status_file = source_address
|
|
|
|
group_tag = \
|
|
' <group address="%s"\n' % source_address + \
|
|
' seqfile="%s/#status_file#.seq"\n' % seedlink.run_dir + \
|
|
' lockfile="%s/' % seedlink.run_dir
|
|
|
|
if not dialup or maxDialupConnections <= 0:
|
|
group_tag += '#status_file#.pid"'
|
|
else:
|
|
group_tag += 'dial%d.pid"' % self.activeDialupConnections
|
|
self.activeDialupConnections += 1
|
|
if self.activeDialupConnections >= maxDialupConnections:
|
|
self.activeDialupConnections = 0
|
|
|
|
try:
|
|
group_tag += '\n' + \
|
|
' overlap_removal="%s"' % seedlink.param('sources.chain.overlapRemoval')
|
|
except: pass
|
|
|
|
try:
|
|
if seedlink.param('sources.chain.batchmode').lower() in ("yes", "true", "1"):
|
|
batchmode = "yes"
|
|
else:
|
|
batchmode = "no"
|
|
except:
|
|
# Default batchmode is "yes"
|
|
batchmode = "yes"
|
|
|
|
group_tag += '\n' + \
|
|
' batchmode="%s"' % batchmode
|
|
|
|
if dialup:
|
|
status_file += ".dial"
|
|
group_tag += '\n' + \
|
|
' uptime="%s"\n' % seedlink._get('sources.chain.dialup.uptime') + \
|
|
' schedule="%s"' % seedlink._get('sources.chain.dialup.schedule')
|
|
|
|
try:
|
|
group_tag += '\n' + \
|
|
' ifup="%s"' % seedlink.param('sources.chain.dialup.ifup')
|
|
except: pass
|
|
try:
|
|
group_tag += '\n' + \
|
|
' ifdown="%s"' % seedlink.param('sources.chain.dialup.ifdown')
|
|
except: pass
|
|
|
|
group_tag += '>\n'
|
|
return group_tag, status_file
|
|
|
|
|
|
# Generates the station tag, child of <group>
|
|
def generateStationTag(self, seedlink):
|
|
# Create station XML tag
|
|
id = seedlink._get('seedlink.station.id')
|
|
station_tpl = " <station id=\"%s\"" % id
|
|
|
|
# set station override if configured
|
|
try: sta = seedlink.param("sources.chain.station")
|
|
except: sta = seedlink.sta
|
|
station_tpl += " name=\"%s\"" % sta
|
|
|
|
# set out name to match the stations code if sta is not equal to
|
|
# configured station code
|
|
if sta != seedlink.sta:
|
|
station_tpl += " out_name=\"%s\"" % seedlink.sta
|
|
|
|
# set network override if configured
|
|
try: net = seedlink.param("sources.chain.network")
|
|
except: net = seedlink.net
|
|
station_tpl += " network=\"%s\"" % net
|
|
|
|
# set out network to match the stations network if net is not equal to
|
|
# configured network code
|
|
if net != seedlink.net:
|
|
station_tpl += " out_network=\"%s\"" % seedlink.net
|
|
|
|
station_tpl += " selectors=\"%s\"" % seedlink._get("sources.chain.selectors").replace(',', ' ')
|
|
|
|
renameMap = []
|
|
unpackMap = []
|
|
|
|
# Read and parse channel rename map
|
|
if seedlink._get('sources.chain.channels.rename'):
|
|
renameItems = [x.strip() for x in seedlink._get('sources.chain.channels.rename').split(',')]
|
|
for item in renameItems:
|
|
mapping = [x.strip() for x in item.split(':')]
|
|
if len(mapping) != 2:
|
|
raise Exception("Error: invalid rename mapping '%s' in %s" % (item, seedlink.station_config_file))
|
|
if not mapping[0] or not mapping[1]:
|
|
raise Exception("Error: invalid rename mapping '%s' in %s" % (item, seedlink.station_config_file))
|
|
renameMap.append(mapping)
|
|
|
|
# Read and parse channel unpack map
|
|
if seedlink._get('sources.chain.channels.unpack'):
|
|
unpackItems = [x.strip() for x in seedlink._get('sources.chain.channels.unpack').split(',')]
|
|
for item in unpackItems:
|
|
mapping = [x.strip() for x in item.split(':')]
|
|
if len(mapping) != 2 and len(mapping) != 3:
|
|
raise Exception("Error: invalid unpack definition '%s' in %s" % (item, seedlink.station_config_file))
|
|
if not mapping[0] or not mapping[1]:
|
|
raise Exception("Error: invalid unpack definition '%s' in %s" % (item, seedlink.station_config_file))
|
|
# If double_rate is not enabled, remove the last item
|
|
if len(mapping) == 3 and mapping[2] != "1":
|
|
mapping.pop(2)
|
|
unpackMap.append(mapping)
|
|
|
|
if len(renameMap) == 0 and len(unpackMap) == 0:
|
|
# Close tag
|
|
station_tpl += "/>\n"
|
|
else:
|
|
station_tpl += ">\n"
|
|
for mapping in renameMap:
|
|
station_tpl += ' <rename from="%s" to="%s"/>\n' % (mapping[0], mapping[1])
|
|
for mapping in unpackMap:
|
|
station_tpl += ' <unpack src="%s" dest="%s"' % (mapping[0], mapping[1])
|
|
if len(mapping) == 3:
|
|
station_tpl += ' double_rate="yes"'
|
|
station_tpl += '/>\n'
|
|
station_tpl += " </station>\n"
|
|
|
|
return station_tpl
|
|
|
|
|
|
# Store the information internally and create chain.xml and
|
|
# the seedlink.ini configuration when flush is called
|
|
def push(self, seedlink):
|
|
try: host = seedlink.param('sources.chain.address')
|
|
except:
|
|
host = "geofon.gfz-potsdam.de"
|
|
seedlink.setParam('sources.chain.address', host)
|
|
|
|
try: port = seedlink.param('sources.chain.port')
|
|
except:
|
|
port = "18000"
|
|
seedlink.setParam('sources.chain.port', port)
|
|
|
|
try: dialuptime = seedlink.param('sources.chain.dialup.uptime')
|
|
except: seedlink.setParam('sources.chain.dialup.uptime', 600)
|
|
|
|
try: dialuptime = seedlink.param('sources.chain.dialup.schedule')
|
|
except: seedlink.setParam('sources.chain.dialup.schedule', '0,30 * * * *')
|
|
|
|
# The default grouping behaviour is enabled
|
|
try: group = seedlink.param('sources.chain.group')
|
|
except: group = ""
|
|
|
|
group = group.replace(' ', '_')\
|
|
.replace("$NET", seedlink.net)\
|
|
.replace("$STA", seedlink.sta)
|
|
|
|
source_address = host + ":" + port
|
|
group_tag, status_file = self.generateGroupTag(seedlink, source_address)
|
|
if group: status_file += "." + group
|
|
|
|
chain_key = (group_tag, status_file)
|
|
|
|
# Find out what chain.xml instance to use
|
|
try:
|
|
sta = seedlink.param("sources.chain.station")
|
|
except: sta = seedlink.sta
|
|
|
|
station_key = seedlink.net + "." + sta
|
|
|
|
chain_instance = 0
|
|
if station_key in self.stations:
|
|
chain_instance = self.stations[station_key]+1
|
|
|
|
self.stations[station_key] = chain_instance
|
|
|
|
# Register the new chainX.xml instance
|
|
if chain_instance not in self.chain_group:
|
|
self.chain_group[chain_instance] = {}
|
|
|
|
chain_group = self.chain_group[chain_instance]
|
|
|
|
if not chain_key in chain_group:
|
|
chain_group[chain_key] = group_tag
|
|
|
|
station_tpl = self.generateStationTag(seedlink)
|
|
|
|
# Register tag to be flushed when flush is called
|
|
chain_group[chain_key] += station_tpl
|
|
|
|
# Set the name of the current chainX.xml file
|
|
seedlink._set("seedlink.chain.id", chain_instance, False)
|
|
|
|
return chain_instance
|
|
|
|
|
|
# Create chain.xml and return the plugin commands for all
|
|
# chain plugins
|
|
def flush(self, seedlink):
|
|
status_map = {}
|
|
|
|
# Create chainX.xml
|
|
chains = {}
|
|
for x in self.chain_group.keys():
|
|
chainxmlbase = "chain%d.xml" % x
|
|
chainxml = os.path.join(seedlink.config_dir, chainxmlbase)
|
|
chain_group = self.chain_group[x]
|
|
if chain_group:
|
|
# Mark this file as used
|
|
chains[chainxml] = 1
|
|
fd = open(chainxml, "w")
|
|
|
|
try:
|
|
if seedlink.param('plugins.chain.loadTimeTable', False).lower() in ("yes", "true", "1"):
|
|
loadTimeTable = True
|
|
else:
|
|
loadTimeTable = False
|
|
except: loadTimeTable = True
|
|
|
|
if loadTimeTable:
|
|
fd.write(seedlink._process_template("chain_head.tpl", "chain", False))
|
|
else:
|
|
fd.write(seedlink._process_template("chain_head_notimetable.tpl", "chain", False))
|
|
first = True
|
|
for ((g,s),i) in sorted(chain_group.items()):
|
|
if not first: fd.write('\n')
|
|
if s in status_map:
|
|
status_map[s] += 1
|
|
s += ".%d" % status_map[s]
|
|
else:
|
|
status_map[s] = 0
|
|
|
|
fd.write(i.replace("#status_file#", s))
|
|
fd.write(" </group>\n")
|
|
first = False
|
|
fd.write("</chain>\n")
|
|
fd.close()
|
|
else:
|
|
# If no groups are configured, delete chainX.xml
|
|
try: os.remove(chainxml)
|
|
except: print("Warning: %s could not be removed" % chainxml)
|
|
|
|
files = glob.glob(os.path.join(seedlink.config_dir, "chain*"))
|
|
for f in files:
|
|
if f in chains: continue
|
|
try: os.remove(f)
|
|
except: print("Warning: %s could not be removed" % f)
|