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.
646 lines
20 KiB
Python
646 lines
20 KiB
Python
1 year ago
|
############################################################################
|
||
|
# Copyright (C) by gempa GmbH, GFZ Potsdam #
|
||
|
# #
|
||
|
# You can redistribute and/or modify this program under the #
|
||
|
# terms of the SeisComP Public License. #
|
||
|
# #
|
||
|
# This program is distributed in the hope that it will be useful, #
|
||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||
|
# SeisComP Public License for more details. #
|
||
|
############################################################################
|
||
|
|
||
|
from __future__ import print_function
|
||
|
|
||
|
import os
|
||
|
import sys
|
||
|
import glob
|
||
|
|
||
|
# Python version depended string conversion
|
||
|
if sys.version_info[0] < 3:
|
||
|
py3input = raw_input #pylint: disable=E0602
|
||
|
else:
|
||
|
py3input = input
|
||
|
|
||
|
|
||
|
def split_tokens(line):
|
||
|
return line.split()
|
||
|
|
||
|
|
||
|
def convert_wildcard(s):
|
||
|
wild = s.split(".")
|
||
|
if len(wild) > 2:
|
||
|
raise Exception("station selector: only one dot allowed")
|
||
|
|
||
|
# Add station wildcard if only network is given
|
||
|
if len(wild) == 1:
|
||
|
wild.append('*')
|
||
|
|
||
|
return '_'.join([x if x else '*' for x in wild])
|
||
|
|
||
|
|
||
|
def convert_stations(s):
|
||
|
toks = s.split(".")
|
||
|
if len(toks) != 2:
|
||
|
raise Exception("station: expected format: NET.STA")
|
||
|
return '_'.join(toks)
|
||
|
|
||
|
|
||
|
class CLI:
|
||
|
"""
|
||
|
Simple console shell.
|
||
|
"""
|
||
|
|
||
|
def __init__(self, env = None):
|
||
|
self.env = env
|
||
|
|
||
|
def run(self, env):
|
||
|
self.env = env
|
||
|
|
||
|
sys.stdout.write('''\
|
||
|
%s
|
||
|
SeisComP shell
|
||
|
%s
|
||
|
|
||
|
Welcome to the SeisComP interactive shell. You can get help about
|
||
|
available commands with 'help'. 'exit' leaves the shell.
|
||
|
|
||
|
''' % (("="*80), ("="*80)))
|
||
|
|
||
|
prompt = "$ "
|
||
|
while True:
|
||
|
line = py3input(prompt).strip()
|
||
|
toks = split_tokens(line)
|
||
|
if len(toks) == 0:
|
||
|
continue
|
||
|
|
||
|
if line in ("exit", "quit"):
|
||
|
break
|
||
|
|
||
|
self.handleCommand(toks[0], toks[1:])
|
||
|
|
||
|
def handleCommand(self, cmd, args):
|
||
|
try:
|
||
|
if cmd == "help":
|
||
|
return self.commandHelp(args)
|
||
|
if cmd == "list":
|
||
|
return self.commandList(args)
|
||
|
if cmd == "delete":
|
||
|
return self.commandDelete(args)
|
||
|
if cmd == "print":
|
||
|
return self.commandPrint(args)
|
||
|
if cmd == "set":
|
||
|
return self.commandSet(args)
|
||
|
if cmd == "remove":
|
||
|
return self.commandRemove(args)
|
||
|
|
||
|
raise Exception("Unknown command: %s" % cmd)
|
||
|
except Exception as e:
|
||
|
sys.stdout.write("%s\n" % str(e))
|
||
|
return False
|
||
|
|
||
|
@staticmethod
|
||
|
def commandHelp(args):
|
||
|
if len(args) == 0:
|
||
|
sys.stdout.write("""\
|
||
|
Commands:
|
||
|
list stations
|
||
|
Lists all available stations keys.
|
||
|
|
||
|
list profiles {mod}
|
||
|
Lists all available profiles of a module.
|
||
|
|
||
|
list modules {sta}
|
||
|
Lists all bound modules of a station incl. profiles (if used).
|
||
|
|
||
|
delete profile {mod} {profile}
|
||
|
Deletes the given profile of given module. If the profile does not exist an
|
||
|
error is raised.
|
||
|
The module is removed from all stations that are using this profile.
|
||
|
|
||
|
delete binding {mod} {sta}
|
||
|
Deletes the binding for given module and station. If the station is bound
|
||
|
to module mod using a profile the binding is kept, removed otherwise.
|
||
|
An existing binding file (etc/key/[mod]/station_[sta]) is deleted in any
|
||
|
case.
|
||
|
|
||
|
print station {sta}
|
||
|
Dumps all set binding parameters for the given station.
|
||
|
|
||
|
set profile {mod} {profile} {sta-sel}
|
||
|
Sets for all selected stations a binding profile of a module.
|
||
|
The resulting station file looks like this:
|
||
|
...
|
||
|
mod:profile
|
||
|
...
|
||
|
|
||
|
This command checks for the existence of the specified profile
|
||
|
|
||
|
set module {mod} {sta-sel}
|
||
|
Binds all selected stations to given module. No profiles are used
|
||
|
and if any of the stations is already using a profile it is removed.
|
||
|
The resulting station key file looks like this:
|
||
|
...
|
||
|
mod
|
||
|
...
|
||
|
|
||
|
remove profile {mod} {profile} {sta-sel}
|
||
|
Removes the binding profile of given module for all selected stations if
|
||
|
module is bound already to that station.
|
||
|
As a result all selected stations that are bound to the given module already
|
||
|
will use a station key file afterwards.
|
||
|
|
||
|
mod:profile -> mod
|
||
|
|
||
|
remove module {mod} {sta-sel}
|
||
|
Unbinds given module from selected stations. The line that refers to the
|
||
|
given module is completely removed from the station key files.
|
||
|
|
||
|
exit
|
||
|
Exit the shell.
|
||
|
|
||
|
quit
|
||
|
Alias for exit.
|
||
|
""")
|
||
|
|
||
|
def commandList(self, args):
|
||
|
if len(args) == 0:
|
||
|
raise Exception("Missing operand")
|
||
|
|
||
|
if args[0] == "stations":
|
||
|
if len(args) > 2:
|
||
|
raise Exception("Too many arguments")
|
||
|
|
||
|
if len(args) > 1:
|
||
|
wild = convert_wildcard(args[1])
|
||
|
else:
|
||
|
wild = "*"
|
||
|
|
||
|
stas = []
|
||
|
for f in sorted(glob.glob(os.path.join(self.env.key_dir, "station_" + wild))):
|
||
|
stas.append(os.path.basename(f)[8:].replace("_", "."))
|
||
|
|
||
|
for s in stas:
|
||
|
print(s)
|
||
|
|
||
|
return True
|
||
|
|
||
|
if args[0] == "profiles":
|
||
|
if len(args) > 2:
|
||
|
raise Exception("Too many arguments")
|
||
|
if len(args) < 2:
|
||
|
raise Exception("Expected: mod")
|
||
|
|
||
|
module = args[1]
|
||
|
|
||
|
for f in sorted(glob.glob(os.path.join(self.env.key_dir, module, "profile_*"))):
|
||
|
print(os.path.basename(f)[8:])
|
||
|
|
||
|
return True
|
||
|
|
||
|
if args[0] == "modules":
|
||
|
if len(args) > 2:
|
||
|
raise Exception("Too many arguments")
|
||
|
if len(args) < 2:
|
||
|
raise Exception("Expected: sta")
|
||
|
|
||
|
sta = convert_stations(args[1])
|
||
|
|
||
|
f = os.path.join(self.env.key_dir, "station_" + sta)
|
||
|
if not os.path.exists(f):
|
||
|
raise Exception("%s: station key does not exists" % args[1])
|
||
|
|
||
|
for l in [line.strip() for line in open(f, "r").readlines()]:
|
||
|
if l.startswith("#"):
|
||
|
continue
|
||
|
if len(l) == 0:
|
||
|
continue
|
||
|
print(l)
|
||
|
|
||
|
return True
|
||
|
|
||
|
raise Exception("Invalid argument: %s" % args[0])
|
||
|
|
||
|
def commandDelete(self, args):
|
||
|
if len(args) == 0:
|
||
|
raise Exception("Missing operand")
|
||
|
|
||
|
if args[0] == "profile":
|
||
|
if len(args) > 3:
|
||
|
raise Exception("Too many arguments")
|
||
|
if len(args) < 3:
|
||
|
raise Exception("Expected: mod profile")
|
||
|
|
||
|
module = args[1]
|
||
|
profile = args[2]
|
||
|
|
||
|
if not os.path.exists(os.path.join(self.env.key_dir, module, "profile_" + profile)):
|
||
|
raise Exception("%s/%s: profile not found" % (module, profile))
|
||
|
|
||
|
os.remove(os.path.join(self.env.key_dir,
|
||
|
module, "profile_" + profile))
|
||
|
|
||
|
modified = 0
|
||
|
for f in glob.glob(os.path.join(self.env.key_dir, "station_*")):
|
||
|
lines = [line.strip() for line in open(f, "r").readlines()]
|
||
|
|
||
|
new_lines = []
|
||
|
is_modified = False
|
||
|
|
||
|
for line in lines:
|
||
|
# Comment line
|
||
|
if line.startswith("#"):
|
||
|
new_lines.append(line)
|
||
|
continue
|
||
|
|
||
|
# Empty line
|
||
|
if not line:
|
||
|
new_lines.append(line)
|
||
|
continue
|
||
|
|
||
|
toks = line.split(':')
|
||
|
|
||
|
# Wrong module name
|
||
|
if toks[0] != module:
|
||
|
new_lines.append(line)
|
||
|
continue
|
||
|
|
||
|
# Profile found
|
||
|
if len(toks) > 1 and toks[1] == profile:
|
||
|
# Filter line
|
||
|
is_modified = True
|
||
|
continue
|
||
|
|
||
|
new_lines.append(line)
|
||
|
|
||
|
if is_modified:
|
||
|
modified += 1
|
||
|
try:
|
||
|
open(f, "w").write('\n'.join(new_lines))
|
||
|
except Exception as e:
|
||
|
sys.stdout.write("%s: %s\n" % (f, str(e)))
|
||
|
|
||
|
sys.stdout.write("OK, %d files modified\n" % modified)
|
||
|
|
||
|
return True
|
||
|
|
||
|
if args[0] == "binding":
|
||
|
if len(args) > 3:
|
||
|
raise Exception("Too many arguments")
|
||
|
if len(args) < 3:
|
||
|
raise Exception("Expected: mod profile")
|
||
|
|
||
|
module = args[1]
|
||
|
sta = convert_stations(args[2])
|
||
|
|
||
|
if not os.path.exists(os.path.join(self.env.key_dir, module, "station_" + sta)):
|
||
|
raise Exception("%s/%s: binding not found" % (module, args[2]))
|
||
|
|
||
|
os.remove(os.path.join(self.env.key_dir, module, "station_" + sta))
|
||
|
|
||
|
f = os.path.join(self.env.key_dir, "station_" + sta)
|
||
|
try:
|
||
|
lines = [line.strip() for line in open(f, "r").readlines()]
|
||
|
except OSError:
|
||
|
pass
|
||
|
|
||
|
new_lines = []
|
||
|
is_modified = False
|
||
|
|
||
|
for line in lines:
|
||
|
# Comment line
|
||
|
if line.startswith("#"):
|
||
|
new_lines.append(line)
|
||
|
continue
|
||
|
|
||
|
# Empty line
|
||
|
if len(line) == 0:
|
||
|
new_lines.append(line)
|
||
|
continue
|
||
|
|
||
|
toks = line.split(':')
|
||
|
|
||
|
# Wrong module name
|
||
|
if toks[0] != module:
|
||
|
new_lines.append(line)
|
||
|
continue
|
||
|
|
||
|
# Profile found
|
||
|
if len(toks) == 1:
|
||
|
# Filter line
|
||
|
is_modified = True
|
||
|
continue
|
||
|
|
||
|
new_lines.append(line)
|
||
|
|
||
|
if is_modified:
|
||
|
try:
|
||
|
open(f, "w").write('\n'.join(new_lines))
|
||
|
except Exception as e:
|
||
|
sys.stdout.write("%s: %s\n" % (f, str(e)))
|
||
|
|
||
|
return True
|
||
|
|
||
|
raise Exception("Invalid argument: %s" % args[0])
|
||
|
|
||
|
def commandPrint(self, args):
|
||
|
if len(args) == 0:
|
||
|
raise Exception("Missing operand")
|
||
|
|
||
|
if args[0] == "station":
|
||
|
if len(args) != 2:
|
||
|
raise Exception("missing argument, expected: sta")
|
||
|
|
||
|
sta = convert_stations(args[1])
|
||
|
key = os.path.join(self.env.key_dir, "station_" + sta)
|
||
|
try:
|
||
|
lines = [line.strip() for line in open(key, "r").readlines()]
|
||
|
except IOError as e:
|
||
|
raise Exception("%s: station not configured" % sta)
|
||
|
except Exception as e:
|
||
|
raise Exception("%s: unexpected error: %s" % (sta, str(e)))
|
||
|
|
||
|
first = True
|
||
|
|
||
|
for line in lines:
|
||
|
# Comment line
|
||
|
if line.startswith("#"):
|
||
|
continue
|
||
|
# Empty line
|
||
|
if len(line) == 0:
|
||
|
continue
|
||
|
|
||
|
toks = line.split(':')
|
||
|
|
||
|
if len(toks) == 1:
|
||
|
binding = os.path.join(
|
||
|
self.env.key_dir, toks[0], "station_" + sta)
|
||
|
else:
|
||
|
binding = os.path.join(
|
||
|
self.env.key_dir, toks[0], "profile_" + toks[1])
|
||
|
|
||
|
if not first:
|
||
|
sys.stdout.write("\n")
|
||
|
|
||
|
first = False
|
||
|
sys.stdout.write("[%s]\n" % toks[0])
|
||
|
sys.stdout.write("%s\n" % binding)
|
||
|
try:
|
||
|
data = open(binding).read()
|
||
|
sys.stdout.write("-"*80 + "\n")
|
||
|
sys.stdout.write(data)
|
||
|
sys.stdout.write("-"*80 + "\n")
|
||
|
except IOError as e:
|
||
|
sys.stdout.write("!binding not found\n")
|
||
|
except Exception as e:
|
||
|
sys.stdout.write("!unexpected error: %s\n" % str(e))
|
||
|
|
||
|
else:
|
||
|
raise Exception("Invalid argument: %s" % args[0])
|
||
|
|
||
|
def commandSet(self, args):
|
||
|
if len(args) == 0:
|
||
|
raise Exception("Missing operand")
|
||
|
|
||
|
if args[0] == "profile":
|
||
|
if len(args) != 4:
|
||
|
raise Exception(
|
||
|
"missing arguments, expected: module profile station-selector")
|
||
|
|
||
|
module = args[1]
|
||
|
profile = args[2]
|
||
|
|
||
|
wild = convert_wildcard(args[3])
|
||
|
|
||
|
if not os.path.exists(os.path.join(self.env.key_dir, module, "profile_" + profile)):
|
||
|
raise Exception("%s/%s: profile not found" % (module, profile))
|
||
|
|
||
|
modified = 0
|
||
|
for f in glob.glob(os.path.join(self.env.key_dir, "station_" + wild)):
|
||
|
lines = [line.strip() for line in open(f, "r").readlines()]
|
||
|
|
||
|
module_found = False
|
||
|
is_modified = False
|
||
|
|
||
|
for i in range(len(lines)): #pylint: disable=C0200
|
||
|
line = lines[i]
|
||
|
|
||
|
# Comment line
|
||
|
if line.startswith("#"):
|
||
|
continue
|
||
|
# Empty line
|
||
|
if len(line) == 0:
|
||
|
continue
|
||
|
|
||
|
toks = line.split(':')
|
||
|
|
||
|
# Wrong module name
|
||
|
if toks[0] != module:
|
||
|
continue
|
||
|
|
||
|
module_found = True
|
||
|
|
||
|
# No profile
|
||
|
if len(toks) == 1:
|
||
|
toks.append("")
|
||
|
# Profile already set
|
||
|
elif toks[1] == profile:
|
||
|
continue
|
||
|
|
||
|
toks[1] = profile
|
||
|
lines[i] = ':'.join(toks)
|
||
|
|
||
|
is_modified = True
|
||
|
|
||
|
if not module_found:
|
||
|
lines.append("%s:%s\n" % (module, profile))
|
||
|
is_modified = True
|
||
|
|
||
|
if is_modified:
|
||
|
modified += 1
|
||
|
try:
|
||
|
open(f, "w").write('\n'.join(lines))
|
||
|
except Exception as e:
|
||
|
sys.stdout.write("%s: %s\n" % (f, str(e)))
|
||
|
|
||
|
sys.stdout.write("OK, %d files modified\n" % modified)
|
||
|
|
||
|
return True
|
||
|
|
||
|
if args[0] == "module":
|
||
|
if len(args) != 3:
|
||
|
raise Exception(
|
||
|
"missing arguments, expected: module station-selector")
|
||
|
|
||
|
module = args[1]
|
||
|
|
||
|
wild = convert_wildcard(args[2])
|
||
|
|
||
|
modified = 0
|
||
|
for f in glob.glob(os.path.join(self.env.key_dir, "station_" + wild)):
|
||
|
lines = [line.strip() for line in open(f, "r").readlines()]
|
||
|
|
||
|
module_found = False
|
||
|
is_modified = False
|
||
|
|
||
|
for i in range(len(lines)): #pylint: disable=C0200
|
||
|
line = lines[i]
|
||
|
|
||
|
# Comment line
|
||
|
if line.startswith("#"):
|
||
|
continue
|
||
|
# Empty line
|
||
|
if len(line) == 0:
|
||
|
continue
|
||
|
|
||
|
toks = line.split(':')
|
||
|
|
||
|
# Wrong module name
|
||
|
if toks[0] != module:
|
||
|
continue
|
||
|
|
||
|
module_found = True
|
||
|
|
||
|
lines[i] = module
|
||
|
|
||
|
is_modified = True
|
||
|
|
||
|
if not module_found:
|
||
|
lines.append("%s\n" % module)
|
||
|
is_modified = True
|
||
|
|
||
|
if is_modified:
|
||
|
modified += 1
|
||
|
try:
|
||
|
open(f, "w").write('\n'.join(lines))
|
||
|
except Exception as e:
|
||
|
sys.stdout.write("%s: %s\n" % (f, str(e)))
|
||
|
|
||
|
sys.stdout.write("OK, %d files modified\n" % modified)
|
||
|
|
||
|
return True
|
||
|
|
||
|
raise Exception("Invalid argument: %s" % args[0])
|
||
|
|
||
|
def commandRemove(self, args):
|
||
|
if len(args) == 0:
|
||
|
raise Exception("Missing operand")
|
||
|
|
||
|
if args[0] == "profile":
|
||
|
if len(args) != 4:
|
||
|
raise Exception(
|
||
|
"Missing arguments, expected: module profile station-selector")
|
||
|
|
||
|
module = args[1]
|
||
|
profile = args[2]
|
||
|
|
||
|
wild = convert_wildcard(args[3])
|
||
|
|
||
|
modified = 0
|
||
|
for f in glob.glob(os.path.join(self.env.key_dir, "station_" + wild)):
|
||
|
lines = [line.strip() for line in open(f, "r").readlines()]
|
||
|
|
||
|
is_modified = False
|
||
|
for i in range(len(lines)): #pylint: disable=C0200
|
||
|
line = lines[i]
|
||
|
|
||
|
# Comment line
|
||
|
if line.startswith("#"):
|
||
|
continue
|
||
|
|
||
|
# Empty line
|
||
|
if len(line) == 0:
|
||
|
continue
|
||
|
|
||
|
toks = line.split(':')
|
||
|
|
||
|
# No profile
|
||
|
if len(toks) == 1:
|
||
|
continue
|
||
|
|
||
|
# Wrong module name
|
||
|
if toks[0] != module:
|
||
|
continue
|
||
|
|
||
|
# Wrong profile name
|
||
|
if toks[1] != profile:
|
||
|
continue
|
||
|
|
||
|
lines[i] = module
|
||
|
is_modified = True
|
||
|
|
||
|
continue
|
||
|
|
||
|
if is_modified:
|
||
|
modified += 1
|
||
|
|
||
|
if (len(lines) > 0) and (len(lines[-1]) > 0):
|
||
|
lines.append("")
|
||
|
|
||
|
try:
|
||
|
open(f, "w").write('\n'.join(lines))
|
||
|
except Exception as e:
|
||
|
sys.stdout.write("%s: %s\n" % (f, str(e)))
|
||
|
|
||
|
sys.stdout.write("OK, %d files modified\n" % modified)
|
||
|
|
||
|
return True
|
||
|
|
||
|
if args[0] == "module":
|
||
|
if len(args) != 3:
|
||
|
raise Exception(
|
||
|
"Missing arguments, expected: module station-selector")
|
||
|
|
||
|
module = args[1]
|
||
|
|
||
|
wild = convert_wildcard(args[2])
|
||
|
|
||
|
modified = 0
|
||
|
for f in glob.glob(os.path.join(self.env.key_dir, "station_" + wild)):
|
||
|
lines = [line.strip() for line in open(f, "r").readlines()]
|
||
|
new_lines = []
|
||
|
|
||
|
is_modified = False
|
||
|
for line in lines:
|
||
|
# Comment line
|
||
|
if line.startswith("#"):
|
||
|
new_lines.append(line)
|
||
|
continue
|
||
|
|
||
|
# Empty line
|
||
|
if len(line) == 0:
|
||
|
new_lines.append(line)
|
||
|
continue
|
||
|
|
||
|
toks = line.split(':')
|
||
|
|
||
|
# Wrong module name
|
||
|
if toks[0] != module:
|
||
|
new_lines.append(line)
|
||
|
continue
|
||
|
|
||
|
# Filter line
|
||
|
is_modified = True
|
||
|
|
||
|
if is_modified:
|
||
|
modified += 1
|
||
|
if (len(new_lines) > 0) and (len(new_lines[-1]) > 0):
|
||
|
new_lines.append("")
|
||
|
|
||
|
try:
|
||
|
open(f, "w").write('\n'.join(new_lines))
|
||
|
except Exception as e:
|
||
|
sys.stdout.write("%s: %s\n" % (f, str(e)))
|
||
|
|
||
|
try:
|
||
|
os.remove(os.path.join(self.env.key_dir,
|
||
|
module, os.path.basename(f)))
|
||
|
except OSError:
|
||
|
pass
|
||
|
|
||
|
sys.stdout.write("OK, %d files modified\n" % modified)
|
||
|
|
||
|
return True
|
||
|
|
||
|
raise Exception("Invalid argument: %s" % args[0])
|