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.
1535 lines
46 KiB
Python
1535 lines
46 KiB
Python
#!/usr/bin/env seiscomp-python
|
|
|
|
from __future__ import division, print_function
|
|
|
|
import glob
|
|
import importlib
|
|
import math
|
|
import os
|
|
import platform
|
|
import shutil
|
|
import signal
|
|
import socket
|
|
import subprocess
|
|
import sys
|
|
import traceback
|
|
import seiscomp.shell
|
|
|
|
# Problem: if
|
|
# import seiscomp.config
|
|
# fails, then in any case a sometimes misleading exception
|
|
# ImportError: No module named _config
|
|
# is raised, even if the seiscomp._config module exists but for
|
|
# another reason fails to import. We therefore...
|
|
import seiscomp._config
|
|
# ...here explicitly to get a meaningful exception if this fails.
|
|
|
|
import seiscomp.config
|
|
import seiscomp.kernel
|
|
|
|
# Python version depended string conversion
|
|
if sys.version_info[0] < 3:
|
|
py3ustr = str
|
|
else:
|
|
py3ustr = lambda s: s.decode('utf-8', 'replace')
|
|
|
|
try:
|
|
real_raw_input = raw_input
|
|
except NameError:
|
|
real_raw_input = input
|
|
|
|
|
|
# request and optionally enforce user input
|
|
# @param question The question to be answered.
|
|
# @param default The default value to use if no input was made
|
|
# @param options List or string of available options. If defined the input must
|
|
# match one of the options (unless a default is specified). If the input
|
|
# is invalid the question is repeated.
|
|
def getInput(question, default=None, options=None):
|
|
|
|
def _default(text):
|
|
# print default value to previous line if no input was made
|
|
if default:
|
|
print("\033[F\033[{}G{}".format(len(text)+1, default))
|
|
return default
|
|
|
|
# no options: accept any type of input
|
|
if not options:
|
|
defaultStr = "" if default is None else " [{}]".format(default)
|
|
question = "{}{}: ".format(question, defaultStr)
|
|
return real_raw_input(question) or _default(question)
|
|
|
|
if default is not None:
|
|
default = str(default).lower()
|
|
|
|
# options supplied: check and enforce input
|
|
opts = [str(o).lower() for o in options]
|
|
optStr = "/".join(o.upper() if o == default else o for o in opts)
|
|
question = "{} [{}]: ".format(question, optStr)
|
|
while True:
|
|
res = real_raw_input(question)
|
|
if not res and default:
|
|
return _default(question)
|
|
|
|
if res.lower() in opts:
|
|
return res.lower()
|
|
|
|
|
|
if sys.platform == "darwin":
|
|
SysLibraryPathVar = "DYLD_FALLBACK_LIBRARY_PATH"
|
|
SysFrameworkPathVar = "DYLD_FALLBACK_FRAMEWORK_PATH"
|
|
else:
|
|
SysLibraryPathVar = "LD_LIBRARY_PATH"
|
|
SysFrameworkPathVar = None
|
|
|
|
|
|
def get_library_path():
|
|
if sys.platform == "darwin":
|
|
return LD_LIBRARY_PATH + ":" + DYLD_FALLBACK_FRAMEWORK_PATH
|
|
|
|
return LD_LIBRARY_PATH
|
|
|
|
|
|
def get_framework_path():
|
|
return DYLD_FALLBACK_FRAMEWORK_PATH
|
|
|
|
|
|
# Python 3 compatible string check
|
|
def is_string(variable):
|
|
try:
|
|
string_class = basestring
|
|
except NameError:
|
|
string_class = str
|
|
|
|
return isinstance(variable, string_class)
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Helper functions
|
|
# ------------------------------------------------------------------------------
|
|
SIGTERM_SENT = False
|
|
|
|
|
|
def sigterm_handler(_signum, _):
|
|
# pylint: disable=W0603
|
|
global SIGTERM_SENT
|
|
if not SIGTERM_SENT:
|
|
SIGTERM_SENT = True
|
|
os.killpg(0, signal.SIGTERM)
|
|
|
|
sys.exit()
|
|
|
|
|
|
def system(args):
|
|
proc = subprocess.Popen(args, shell=False, env=os.environ)
|
|
while True:
|
|
try:
|
|
return proc.wait()
|
|
except KeyboardInterrupt:
|
|
continue
|
|
except Exception as e:
|
|
try:
|
|
proc.terminate()
|
|
except Exception:
|
|
pass
|
|
sys.stderr.write("Exception: %s\n" % str(e))
|
|
continue
|
|
|
|
# return subprocess.call(cmd, shell=True)
|
|
|
|
|
|
def error(msg):
|
|
sys.stderr.write("error: %s\n" % msg)
|
|
sys.stderr.flush()
|
|
|
|
|
|
def warning(msg):
|
|
sys.stderr.write("warning: %s\n" % msg)
|
|
sys.stderr.flush()
|
|
|
|
|
|
# Returns a seiscomp.kernel.Module instance
|
|
# from a given path with a given name
|
|
def load_module(path):
|
|
modname0 = os.path.splitext(os.path.basename(path))[0].replace('.', '_')
|
|
modname = '__seiscomp_modules_' + modname0
|
|
|
|
if modname in sys.modules:
|
|
mod = sys.modules[modname]
|
|
else:
|
|
if sys.path[0] != INIT_PATH:
|
|
sys.path.insert(0, INIT_PATH)
|
|
mod = importlib.import_module(modname0)
|
|
mod.__file__ = path
|
|
|
|
# store it in sys.modules
|
|
sys.modules[modname] = mod
|
|
|
|
module = mod.Module
|
|
|
|
return module
|
|
|
|
|
|
def module_key(module):
|
|
return (module.order, module.name)
|
|
|
|
|
|
def load_init_modules(path):
|
|
modules = []
|
|
|
|
if not os.path.exists(path):
|
|
error("Cannot load any module - path not existing: %s" % path)
|
|
return modules
|
|
|
|
files = glob.glob(os.path.join(path, "*.py"))
|
|
for f in files:
|
|
try:
|
|
pmod = load_module(f)
|
|
except Exception as exc:
|
|
error(("%s: " % f) + str(exc))
|
|
continue
|
|
|
|
try:
|
|
mod = pmod(env) # .Module(env)
|
|
except Exception as exc:
|
|
error(("%s: " % f) + str(exc))
|
|
continue
|
|
|
|
modules.append(mod)
|
|
|
|
#mods = sorted(mods, key=lambda mod: mod.order)
|
|
modules = sorted(modules, key=module_key)
|
|
|
|
return modules
|
|
|
|
|
|
def get_module(name):
|
|
for module in mods:
|
|
if module.name == name:
|
|
return module
|
|
return None
|
|
|
|
|
|
def has_module(name):
|
|
return get_module(name) is not None
|
|
|
|
|
|
def dump_paths():
|
|
print('--------------------')
|
|
print('SEISCOMP_ROOT="%s"' % SEISCOMP_ROOT)
|
|
print('PATH="%s"' % os.environ["PATH"])
|
|
print('%s="%s"' % (SysLibraryPathVar, os.environ[SysLibraryPathVar]))
|
|
if SysFrameworkPathVar:
|
|
print(
|
|
'%s="%s"' %
|
|
(SysFrameworkPathVar,
|
|
os.environ[SysFrameworkPathVar]))
|
|
print('PYTHONPATH="%s"' % sys.path)
|
|
print('CWD="%s"' % os.getcwd())
|
|
print('--------------------')
|
|
|
|
|
|
# Returns whether a module should run or not. It simply returns if its
|
|
# runfile exists.
|
|
def shouldModuleRun(mod_name):
|
|
return os.path.exists(env.runFile(mod_name))
|
|
|
|
|
|
def touch(filename):
|
|
try:
|
|
open(filename, 'w').close()
|
|
except Exception as exc:
|
|
error(str(exc))
|
|
|
|
|
|
def start_module(mod):
|
|
# Create runfile
|
|
touch(env.runFile(mod.name))
|
|
return mod.start()
|
|
|
|
|
|
def stop_module(mod):
|
|
try:
|
|
if not mod.stop():
|
|
error("Failed to stop %s: unknown error" % mod.name)
|
|
return 1
|
|
except Exception as e:
|
|
error("Failed to stop %s: %s" % (mod.name, str(e)))
|
|
return 1
|
|
|
|
# Delete runfile
|
|
try:
|
|
os.remove(env.runFile(mod.name))
|
|
except BaseException:
|
|
return 1
|
|
|
|
return 0
|
|
|
|
|
|
def start_kernel_modules():
|
|
for mod in mods:
|
|
if isinstance(mod, seiscomp.kernel.CoreModule):
|
|
return start_module(mod)
|
|
|
|
return 1
|
|
|
|
|
|
def stop_kernel_modules():
|
|
for mod in reversed(mods):
|
|
if isinstance(mod, seiscomp.kernel.CoreModule):
|
|
return stop_module(mod)
|
|
|
|
return 1
|
|
|
|
def detectOS():
|
|
OSReleaseMap = {
|
|
'centos': 'rhel',
|
|
'rocky': 'rhel',
|
|
'raspbian': 'debian'
|
|
}
|
|
|
|
try:
|
|
arch = platform.machine()
|
|
except BaseException:
|
|
arch = 'x86_64'
|
|
|
|
data = {}
|
|
with open('/etc/os-release', 'r') as f:
|
|
for line in f:
|
|
toks = line.split("=")
|
|
if len(toks) != 2:
|
|
continue
|
|
|
|
data[toks[0].strip().upper()] = toks[1].strip()
|
|
|
|
osID = OSReleaseMap.get(data['ID'].strip('"'))
|
|
if not osID:
|
|
osID = data['ID'].strip('"')
|
|
|
|
version = data['VERSION_ID'].strip('"')
|
|
if osID == 'rhel':
|
|
try:
|
|
version = str(math.floor(float(version)))
|
|
except Exception:
|
|
pass
|
|
|
|
name = data['NAME'].strip('"')
|
|
return name, osID, version, arch
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Commandline action handler
|
|
# ------------------------------------------------------------------------------
|
|
def on_setup(args, flags):
|
|
# pylint: disable=W0621
|
|
import seiscomp.setup
|
|
|
|
if "stdin" in flags:
|
|
cfg = seiscomp.config.Config()
|
|
if not cfg.readConfig("-"):
|
|
error("invalid configuration from stdin")
|
|
return 1
|
|
else:
|
|
setup = seiscomp.setup.Simple()
|
|
cfg = setup.run(env)
|
|
|
|
retCode = 0
|
|
|
|
for mod in config_mods:
|
|
if len(args) == 0 or mod.name in args:
|
|
try:
|
|
hasSetupHandler = callable(getattr(mod, 'setup'))
|
|
except BaseException:
|
|
hasSetupHandler = False
|
|
|
|
if hasSetupHandler:
|
|
print("* setup %s" % mod.name)
|
|
if mod.setup(cfg) != 0:
|
|
error("module '%s' failed to setup" % mod.name)
|
|
retCode = 1
|
|
|
|
if retCode == 0:
|
|
runpath = os.path.join(SEISCOMP_ROOT, "var", "run")
|
|
if not os.path.exists(runpath):
|
|
try:
|
|
os.makedirs(runpath)
|
|
except BaseException:
|
|
error("failed to create directory: %s" % runpath)
|
|
|
|
statfile = os.path.join(runpath, "seiscomp.init")
|
|
if not os.path.exists(statfile):
|
|
try:
|
|
open(statfile, "w").close()
|
|
except BaseException:
|
|
error("failed to create status file: %s" % statfile)
|
|
|
|
return retCode
|
|
|
|
|
|
def on_setup_help(_):
|
|
print("Initialize the configuration of all available modules. Each module")
|
|
print("implements its own setup handler which is called at this point. The")
|
|
print("initialization takes the installation directory into account and")
|
|
print("should be repeated when copying the system to another directory.")
|
|
print("NOTE:")
|
|
print("Setup might overwrite already made settings with default values.")
|
|
return 0
|
|
|
|
|
|
def on_shell(_args, _):
|
|
shell = seiscomp.shell.CLI()
|
|
try:
|
|
shell.run(env)
|
|
except Exception as e:
|
|
error(str(e))
|
|
return 1
|
|
return 0
|
|
|
|
|
|
def on_shell_help(_):
|
|
print("Launches the SeisComP shell, a commandline interface which allows")
|
|
print("to manage modules configurations and bindings.")
|
|
return 0
|
|
|
|
|
|
def on_enable(args, _):
|
|
if not args:
|
|
error("module name required")
|
|
return 1
|
|
|
|
for name in args:
|
|
modName = get_module(name)
|
|
if modName is None:
|
|
error("%s is not available" % name)
|
|
elif isinstance(modName, seiscomp.kernel.CoreModule):
|
|
error("%s is a kernel module and is enabled automatically" % name)
|
|
else:
|
|
env.enableModule(name)
|
|
return 0
|
|
|
|
|
|
def on_enable_help(_):
|
|
print("Enables all given modules to be started when 'seiscomp start' is")
|
|
print("invoked without a module list.")
|
|
print()
|
|
print("Examples:")
|
|
print("seiscomp enable seedlink slarchive")
|
|
|
|
|
|
def on_disable(args, _):
|
|
if not args:
|
|
error("module name required")
|
|
return 1
|
|
|
|
for name in args:
|
|
modName = get_module(name)
|
|
if modName is None:
|
|
error("%s is not available" % modName)
|
|
elif isinstance(modName, seiscomp.kernel.CoreModule):
|
|
error("%s is a kernel module and cannot be disabled" % name)
|
|
else:
|
|
env.disableModule(name)
|
|
return 0
|
|
|
|
|
|
def on_disable_help(_):
|
|
print("Disables all given modules. See 'enable'.")
|
|
print()
|
|
print("Examples:")
|
|
print("seiscomp disable seedlink slarchive")
|
|
|
|
|
|
def on_start(args, _):
|
|
cntStarted = 0
|
|
if not args:
|
|
if start_kernel_modules() == 0:
|
|
cntStarted += 1
|
|
for mod in mods:
|
|
# Kernel modules have been started already
|
|
if isinstance(mod, seiscomp.kernel.CoreModule):
|
|
continue
|
|
# Module in autorun?
|
|
if env.isModuleEnabled(mod.name):
|
|
if start_module(mod) == 0:
|
|
cntStarted += 1
|
|
else:
|
|
for mod in mods:
|
|
if mod.name in args or len(args) == 0:
|
|
if start_module(mod) == 0:
|
|
cntStarted += 1
|
|
|
|
if not useCSV:
|
|
print("Summary: {} modules started".format(cntStarted))
|
|
|
|
return 0
|
|
|
|
|
|
def on_start_help(_):
|
|
print("Starts all enabled modules or a list of modules given.")
|
|
print()
|
|
print("Examples:")
|
|
print("seiscomp start")
|
|
print("seiscomp start seedlink slarchive")
|
|
|
|
|
|
def on_stop(args, _):
|
|
cntStopped = 0
|
|
if not args:
|
|
for mod in reversed(mods):
|
|
# Kernel modules will be stopped latter
|
|
if isinstance(mod, seiscomp.kernel.CoreModule):
|
|
continue
|
|
if stop_module(mod) == 0:
|
|
cntStopped += 1
|
|
|
|
# Stop all kernel modules
|
|
if stop_kernel_modules() == 0:
|
|
cntStopped += 1
|
|
else:
|
|
for mod in reversed(mods):
|
|
if mod.name in args or len(args) == 0:
|
|
if stop_module(mod) == 0:
|
|
cntStopped += 1
|
|
|
|
if not useCSV:
|
|
print("Summary: {} modules stopped".format(cntStopped))
|
|
|
|
return 0
|
|
|
|
|
|
def on_stop_help(_):
|
|
print("Stops all enabled modules or a list of modules given.")
|
|
print()
|
|
print("Examples:")
|
|
print("seiscomp stop")
|
|
print("seiscomp stop seedlink slarchive")
|
|
|
|
|
|
def on_restart(args, flags):
|
|
on_stop(args, flags)
|
|
on_start(args, flags)
|
|
return 0
|
|
|
|
|
|
def on_restart_help(_):
|
|
print("Restarts all enabled modules or a list of modules given.")
|
|
print("This command is equal to:")
|
|
print("seiscomp stop {args}")
|
|
print("seiscomp start {args}")
|
|
print()
|
|
print("Examples:")
|
|
print("seiscomp restart")
|
|
print("seiscomp restart seedlink slarchive")
|
|
|
|
|
|
def on_reload(args, _):
|
|
if not args:
|
|
for mod in mods:
|
|
# Reload not supported by kernel modules
|
|
if isinstance(mod, seiscomp.kernel.CoreModule):
|
|
continue
|
|
|
|
if shouldModuleRun(mod.name):
|
|
mod.reload()
|
|
else:
|
|
for mod in mods:
|
|
if mod.name in args or len(args) == 0:
|
|
mod.reload()
|
|
|
|
return 0
|
|
|
|
|
|
def on_reload_help(_):
|
|
print("Reloads all enabled modules or a list of modules given.")
|
|
print("This operation is module specific and implemented only for some")
|
|
print("modules.")
|
|
print()
|
|
print("Examples:")
|
|
print("seiscomp reload")
|
|
print("seiscomp reload fdsnws")
|
|
|
|
|
|
def on_check(args, _):
|
|
cntStarted = 0
|
|
for mod in mods:
|
|
if mod.name in args or len(args) == 0:
|
|
if shouldModuleRun(mod.name):
|
|
cntStarted += 1
|
|
mod.check()
|
|
|
|
if not useCSV:
|
|
print("Summary: {} started modules checked".format(cntStarted))
|
|
|
|
return 0
|
|
|
|
|
|
def on_check_help(_):
|
|
print("Checks if a started module is still running. If not, it is")
|
|
print("restarted. If no modules are given, all started modules are")
|
|
print("checked.")
|
|
print()
|
|
print("Examples:")
|
|
print("$ seiscomp check seedlink")
|
|
print("seedlink is already running")
|
|
|
|
|
|
def on_exec(args, _):
|
|
if len(args) < 1:
|
|
error("no module name given")
|
|
return False
|
|
|
|
# Change back into the working dir
|
|
env.chback()
|
|
return system(args)
|
|
|
|
|
|
def on_exec_help(_):
|
|
print("Executes a command like calling a command from commandline.")
|
|
print("It will setup all paths and execute the command.")
|
|
print("'seiscomp run' will block until the command terminates.")
|
|
print("Example:")
|
|
print("seiscomp exec scolv")
|
|
|
|
|
|
def on_list(args, _):
|
|
if len(args) < 1:
|
|
error("expected argument: {modules|aliases|enabled|disabled|started}")
|
|
return 1
|
|
|
|
if args[0] == "modules":
|
|
found = 0
|
|
for mod in mods:
|
|
if env.isModuleEnabled(mod.name) or \
|
|
isinstance(mod, seiscomp.kernel.CoreModule):
|
|
state = "enabled"
|
|
else:
|
|
state = "disabled"
|
|
found += 1
|
|
print("%s is %s" % (mod.name, state))
|
|
|
|
if not useCSV:
|
|
print("Summary: {} modules reported".format(found))
|
|
|
|
return 0
|
|
|
|
if args[0] == "aliases":
|
|
f = open(ALIAS_FILE, 'r')
|
|
lines = [line.rstrip() for line in f.readlines()]
|
|
for line in lines:
|
|
if line.lstrip().startswith('#') or not line.strip():
|
|
continue
|
|
toks = [t.strip() for t in line.split('=')]
|
|
# Remove invalid lines
|
|
if len(toks) != 2:
|
|
continue
|
|
if useCSV:
|
|
print("%s;%s" % (toks[0], toks[1]))
|
|
else:
|
|
print("%s -> %s" % (toks[0], toks[1]))
|
|
f.close()
|
|
return 0
|
|
|
|
if args[0] == "enabled":
|
|
found = 0
|
|
for mod in mods:
|
|
if env.isModuleEnabled(mod.name) or \
|
|
isinstance(mod, seiscomp.kernel.CoreModule):
|
|
print(mod.name)
|
|
found += 1
|
|
|
|
if not useCSV:
|
|
print("Summary: {} modules enabled".format(found))
|
|
|
|
return 0
|
|
|
|
if args[0] == "disabled":
|
|
found = 0
|
|
for mod in mods:
|
|
if not env.isModuleEnabled(mod.name) and \
|
|
not isinstance(mod, seiscomp.kernel.CoreModule):
|
|
print(mod.name)
|
|
found += 1
|
|
|
|
if not useCSV:
|
|
print("Summary: {} modules disabled".format(found))
|
|
|
|
return 0
|
|
|
|
if args[0] == "started":
|
|
found = 0
|
|
for mod in mods:
|
|
if shouldModuleRun(mod.name):
|
|
print(mod.name)
|
|
found += 1
|
|
|
|
if not useCSV:
|
|
print("Summary: {} modules started".format(found))
|
|
|
|
return 0
|
|
|
|
error(
|
|
"wrong argument: {modules|aliases|enabled|disabled|started} expected")
|
|
return 1
|
|
|
|
|
|
def on_list_help(_):
|
|
print("Prints the result of a query. 5 queries are currently supported:")
|
|
print(" modules: lists all existing modules")
|
|
print(" aliases: lists all existing aliases")
|
|
print(" enabled: lists all enabled modules")
|
|
print(" disabled: lists all disabled modules")
|
|
print(" started: lists all started modules")
|
|
print()
|
|
print("Examples:")
|
|
print("$ seiscomp list aliases")
|
|
print("l1autopick -> scautopick")
|
|
|
|
|
|
def on_status(args, _):
|
|
found = 0
|
|
if len(args) > 0 and args[0] == "enabled":
|
|
for mod in mods:
|
|
if env.isModuleEnabled(mod.name) or isinstance(
|
|
mod, seiscomp.kernel.CoreModule):
|
|
mod.status(shouldModuleRun(mod.name))
|
|
found += 1
|
|
|
|
if not useCSV:
|
|
print("Summary: {} modules enabled".format(found))
|
|
|
|
return 0
|
|
|
|
if len(args) > 0 and args[0] == "started":
|
|
for mod in mods:
|
|
if shouldModuleRun(mod.name):
|
|
mod.status(shouldModuleRun(mod.name))
|
|
found += 1
|
|
|
|
if not useCSV:
|
|
print("Summary: {} modules started".format(found))
|
|
|
|
return 0
|
|
|
|
for mod in mods:
|
|
if mod.name in args or len(args) == 0:
|
|
mod.status(shouldModuleRun(mod.name))
|
|
found += 1
|
|
|
|
if not useCSV:
|
|
print("Summary: {} modules reported".format(found))
|
|
return 0
|
|
|
|
|
|
def on_status_help(_):
|
|
print("Prints the status of ")
|
|
print(" * all modules")
|
|
print(" * all enabled modules")
|
|
print(" * all started modules")
|
|
print(" * a list of modules")
|
|
print("and gives a warning if a module should run but doesn't.")
|
|
print("This command supports csv formatted output via '--csv' switch.")
|
|
print()
|
|
print("Examples:")
|
|
print("$ seiscomp status started")
|
|
print("$ seiscomp status enabled")
|
|
print("scmaster is not running [WARNING]")
|
|
print("$ seiscomp status scautopick")
|
|
print("scautopick is not running")
|
|
print("$ seiscomp --csv status scautopick")
|
|
print("scautopick;0;0;0")
|
|
print()
|
|
print("CSV format:")
|
|
print(" column 1: module name")
|
|
print(" column 2: running flag")
|
|
print(" column 3: should run flag")
|
|
print(" column 4: enabled flag")
|
|
|
|
|
|
def on_print(args, _):
|
|
if len(args) < 1:
|
|
error("expected argument: {crontab|env}")
|
|
return 1
|
|
|
|
if args[0] == "crontab":
|
|
print("*/3 * * * * %s check >/dev/null 2>&1" %
|
|
os.path.join(env.SEISCOMP_ROOT, "bin", "seiscomp"))
|
|
for mod in mods:
|
|
mod.printCrontab()
|
|
elif args[0] == "env":
|
|
print('export SEISCOMP_ROOT="%s"' % SEISCOMP_ROOT)
|
|
print('export PATH="%s:$PATH"' % BIN_PATH)
|
|
print('export %s="%s:$%s"' %
|
|
(SysLibraryPathVar, get_library_path(), SysLibraryPathVar))
|
|
if sys.platform == "darwin":
|
|
print(
|
|
'export %s="%s:$%s"' %
|
|
(SysFrameworkPathVar,
|
|
get_framework_path(),
|
|
SysFrameworkPathVar))
|
|
|
|
print('export PYTHONPATH="%s:$PYTHONPATH"' % PYTHONPATH)
|
|
print('export MANPATH="%s:$MANPATH"' % MANPATH)
|
|
print(
|
|
'source "%s/share/shell-completion/seiscomp.bash"' %
|
|
SEISCOMP_ROOT)
|
|
hostenv = os.path.join(SEISCOMP_ROOT, "etc", "env", "by-hostname",
|
|
socket.gethostname())
|
|
if os.path.isfile(hostenv):
|
|
print('source %s' % hostenv)
|
|
else:
|
|
error("wrong argument: {crontab|env} expected")
|
|
return 1
|
|
|
|
return 0
|
|
|
|
|
|
def on_print_help(_):
|
|
print("seiscomp print {crontab|env}")
|
|
print(" crontab: prints crontab entries of all registered or given modules.")
|
|
print(" env: prints environment variables necessary to run SeisComP modules.")
|
|
print()
|
|
print("Examples:")
|
|
print("Source SC environment into current bash session")
|
|
print("$ eval $(seiscomp/bin/seiscomp print env)")
|
|
|
|
|
|
def on_install_deps_linux(args, _):
|
|
|
|
try:
|
|
name, release, version, arch = detectOS()
|
|
except BaseException as err:
|
|
print("*********************************************************************")
|
|
print("seiscomp was not able to figure out the installed distribution")
|
|
print("You need to check the documentation for required packages and install")
|
|
print("them manually.")
|
|
print("Error: {}".format(err))
|
|
print("*********************************************************************")
|
|
|
|
return 1
|
|
|
|
print("Distribution: {}-{}-{}({}-{})".format(name, version, arch, release, version))
|
|
|
|
for n in range(version.count('.') + 1):
|
|
ver = version.rsplit('.', n)[0]
|
|
script_dir = os.path.join(
|
|
env.SEISCOMP_ROOT, "share", "deps", release.lower(), ver.lower())
|
|
if os.path.exists(script_dir):
|
|
break
|
|
|
|
if not os.path.exists(script_dir):
|
|
print("*********************************************************************")
|
|
print("Sorry, the installed distribution is not supported.")
|
|
print("You need to check the documentation for required packages and install")
|
|
print("them manually.")
|
|
print("*********************************************************************")
|
|
return 1
|
|
|
|
for pkg in args:
|
|
script = os.path.join(script_dir, "install-" + pkg + ".sh")
|
|
if not os.path.exists(script):
|
|
error("no handler available for package '%s'" % pkg)
|
|
return 1
|
|
|
|
if system(["sudo", "sh", script]) != 0:
|
|
error("installation failed")
|
|
return 1
|
|
|
|
return 0
|
|
|
|
|
|
def on_install_deps(args, flags):
|
|
if not args:
|
|
error("expected package list: PKG1 [PKG2 [..]]")
|
|
print("Example: seiscomp install-deps base gui mysql-server")
|
|
print("For a list of available packages issue: seiscomp help install-deps")
|
|
|
|
if sys.platform.startswith("linux"):
|
|
return on_install_deps_linux(args, flags)
|
|
|
|
error("unsupported platform")
|
|
print("*********************************************************************")
|
|
print("The platform you are currently running on is not supported to install")
|
|
print("dependencies automatically.")
|
|
print("You need to check the documentation for required packages and install")
|
|
print("them manually.")
|
|
print("*********************************************************************")
|
|
return 1
|
|
|
|
|
|
def on_install_deps_help(_):
|
|
print("seiscomp install-deps PKG1 [PKG2 [..]]")
|
|
print("Installs OS dependencies to run SeisComP. This requires either a 'sudo'")
|
|
print("or root account. Available packages are:")
|
|
print(" base: basic packages required by all installations")
|
|
print(" gui: required by graphical user interfaces, e.g. on workstations")
|
|
print(" [mysql,mariadb,postgresql]-server:")
|
|
print(" database management system required by the machine running")
|
|
print(" the SeisComP messaging system (scmaster)")
|
|
print(" fdsnws: required for data sharing via the FDSN web services")
|
|
|
|
return 0
|
|
|
|
|
|
def on_update_config(args, _):
|
|
kernelModsStarted = False
|
|
configuredMods = {}
|
|
|
|
listOfMods = args
|
|
if not listOfMods:
|
|
listOfMods = []
|
|
for mod in config_mods:
|
|
listOfMods.append(mod.name)
|
|
|
|
while len(listOfMods) > 0:
|
|
for mod in config_mods:
|
|
if mod.name in listOfMods:
|
|
if not kernelModsStarted and mod.requiresKernelModules():
|
|
print("* starting kernel modules")
|
|
start_kernel_modules()
|
|
kernelModsStarted = True
|
|
print("* configure %s" % mod.name)
|
|
|
|
proxy = None
|
|
|
|
try:
|
|
proxy = mod.updateConfigProxy()
|
|
if is_string(proxy):
|
|
configuredMods.setdefault(proxy, False)
|
|
except Exception:
|
|
pass
|
|
|
|
if proxy is None:
|
|
result = mod.updateConfig()
|
|
|
|
try:
|
|
error_code = int(result)
|
|
except ValueError:
|
|
error("unexpected return type when updating "
|
|
"configuration of %s" % mod.name)
|
|
return 1
|
|
|
|
if error_code != 0:
|
|
error(
|
|
"updating configuration for %s failed" % mod.name)
|
|
return 1
|
|
|
|
configuredMods[mod.name] = True
|
|
|
|
listOfMods = []
|
|
# Collect all unconfigured but indirectly requested mods
|
|
for name, configured in configuredMods.items():
|
|
if not configured:
|
|
listOfMods.append(name)
|
|
|
|
return 0
|
|
|
|
|
|
def on_update_config_help(_):
|
|
print("Updates the configuration of all available modules. This command")
|
|
print("will convert the etc/*.cfg to the modules native configuration")
|
|
print("including its bindings.")
|
|
return 0
|
|
|
|
|
|
def on_alias(args, _):
|
|
if len(args) < 2:
|
|
error("expected arguments: {create|remove} ALIAS_NAME APP_NAME")
|
|
return 1
|
|
|
|
aliasName = args[1]
|
|
|
|
if args[0] == "create":
|
|
if len(args) != 3:
|
|
error("expected two arguments for create: ALIAS_NAME APP_NAME")
|
|
return 1
|
|
|
|
mod = None
|
|
for module in mods:
|
|
if module.name == args[2]:
|
|
mod = module
|
|
break
|
|
|
|
if not mod:
|
|
error("module '%s' not found" % args[2])
|
|
return 1
|
|
|
|
supportsAliases = False
|
|
try:
|
|
supportsAliases = mod.supportsAliases()
|
|
except BaseException:
|
|
pass
|
|
|
|
if not supportsAliases:
|
|
error("module '%s' does not support aliases" % args[2])
|
|
return 1
|
|
|
|
mod2 = args[2]
|
|
if os.path.exists(os.path.join("bin", mod2)):
|
|
mod1 = os.path.join("bin", aliasName)
|
|
elif os.path.exists(os.path.join("sbin", mod2)):
|
|
mod1 = os.path.join("sbin", aliasName)
|
|
else:
|
|
error("no %s binary found (neither bin nor sbin)")
|
|
return 1
|
|
|
|
# create alias line in etc/descriptions/aliases
|
|
if not os.path.exists(DESC_PATH):
|
|
try:
|
|
os.makedirs(DESC_PATH)
|
|
except Exception:
|
|
error("failed to create directory: %s" % DESC_PATH)
|
|
return 1
|
|
|
|
has_alias = False
|
|
lines = []
|
|
new_lines = []
|
|
try:
|
|
f = open(ALIAS_FILE, 'r')
|
|
lines = [line.rstrip() for line in f.readlines()]
|
|
for line in lines:
|
|
if line.lstrip().startswith('#') or not line.strip():
|
|
# Keep comments or empty lines
|
|
new_lines.append(line)
|
|
continue
|
|
toks = [t.strip() for t in line.split('=')]
|
|
# Remove invalid lines
|
|
if len(toks) != 2:
|
|
continue
|
|
if toks[0] == aliasName:
|
|
has_alias = True
|
|
break
|
|
|
|
new_lines.append(line)
|
|
f.close()
|
|
except BaseException:
|
|
pass
|
|
|
|
if has_alias:
|
|
warning("%s is already registered as alias for %s in " \
|
|
"$SEISCOMP_ROOT/etc/descriptions/aliases" % (aliasName, toks[1]))
|
|
warning(" + do not register again but trying to link the required files")
|
|
else:
|
|
print(
|
|
"Registered alias '%s' in $SEISCOMP_ROOT/etc/descriptions/aliases" %
|
|
(aliasName))
|
|
|
|
# Check if target exists already
|
|
if os.path.exists(os.path.join(SEISCOMP_ROOT, mod1)):
|
|
warning(
|
|
"link '%s' to '%s' exists already in %s/bin/" %
|
|
(aliasName, mod2, SEISCOMP_ROOT))
|
|
warning(" + do not link again")
|
|
|
|
try:
|
|
f = open(ALIAS_FILE, 'w')
|
|
except BaseException:
|
|
error("failed to open/create alias file: %s" % ALIAS_FILE)
|
|
return 1
|
|
|
|
new_lines.append("%s = %s" % (aliasName, args[2]))
|
|
|
|
f.write("\n".join(new_lines) + "\n")
|
|
f.close()
|
|
|
|
# create symlink of defaults from etc/defaults/mod1.cfg to etc/defaults/mod2.cfg
|
|
# use relative path to default_cfg2
|
|
cwdAlias = os.getcwd()
|
|
os.chdir(os.path.join(SEISCOMP_ROOT, "etc", "defaults"))
|
|
default_cfg1 = aliasName + ".cfg"
|
|
default_cfg2 = args[2] + ".cfg"
|
|
if os.path.exists(default_cfg2):
|
|
print("Linking default configuration: %s -> %s" %
|
|
(default_cfg2, default_cfg1))
|
|
# - first: remove target
|
|
try:
|
|
os.remove(default_cfg1)
|
|
except BaseException:
|
|
pass
|
|
# create symlink
|
|
os.symlink(os.path.relpath(default_cfg2), default_cfg1)
|
|
else:
|
|
print("No default configuration to link")
|
|
# return to initial directory
|
|
os.chdir(cwdAlias)
|
|
|
|
# create symlink from bin/mod1 to bin/mod2
|
|
# - first: remove target
|
|
try:
|
|
os.remove(os.path.join(SEISCOMP_ROOT, mod1))
|
|
except BaseException:
|
|
pass
|
|
print("Creating app symlink: %s -> %s" % (mod2, mod1))
|
|
os.symlink(mod2, os.path.join(SEISCOMP_ROOT, mod1))
|
|
|
|
# create symlink from etc/init/mod1.py to etc/init/mod2.py
|
|
cwdAlias = os.getcwd()
|
|
os.chdir(os.path.join(SEISCOMP_ROOT, "etc", "init"))
|
|
init1 = aliasName + ".py"
|
|
init2 = args[2] + ".py"
|
|
print("Linking init script: %s -> %s" % (init2, init1))
|
|
# - first: remove target
|
|
try:
|
|
os.remove(init1)
|
|
except BaseException:
|
|
pass
|
|
# create symlink with relative path
|
|
os.symlink(os.path.relpath(init2), init1)
|
|
# return to initial directory
|
|
os.chdir(cwdAlias)
|
|
|
|
return 0
|
|
|
|
if args[0] == "remove":
|
|
if len(args) != 2:
|
|
error("expected one argument for remove: alias-name")
|
|
return 1
|
|
|
|
print("Removing alias '%s'" % aliasName)
|
|
# check and remove alias line in etc/descriptions/aliases
|
|
has_alias = False
|
|
lines = []
|
|
new_lines = []
|
|
try:
|
|
f = open(ALIAS_FILE, 'r')
|
|
lines = [line.rstrip() for line in f.readlines()]
|
|
for line in lines:
|
|
if line.lstrip().startswith('#') or not line.strip():
|
|
# Keep comments or empty lines
|
|
new_lines.append(line)
|
|
continue
|
|
toks = [t.strip() for t in line.split('=')]
|
|
# Remove invalid lines
|
|
if len(toks) != 2:
|
|
continue
|
|
if toks[0] == aliasName:
|
|
has_alias = True
|
|
else:
|
|
new_lines.append(line)
|
|
f.close()
|
|
except BaseException:
|
|
pass
|
|
|
|
if not has_alias:
|
|
print(" + {} is not defined as an alias".format(aliasName))
|
|
if not interactiveMode:
|
|
print(" + remove related configuration with '--interactive'")
|
|
if len(lines) == len(new_lines):
|
|
return 1
|
|
|
|
try:
|
|
f = open(ALIAS_FILE, 'w')
|
|
except BaseException:
|
|
error(" + failed to open/create alias file: %s" % ALIAS_FILE)
|
|
return 1
|
|
|
|
if len(lines) > 0:
|
|
f.write("\n".join(new_lines) + "\n")
|
|
f.close()
|
|
|
|
if not has_alias:
|
|
if not interactiveMode:
|
|
return 1
|
|
|
|
# remove symlink from bin/mod1
|
|
if os.path.exists(os.path.join("bin", aliasName)):
|
|
sym_link = os.path.join("bin", aliasName)
|
|
elif os.path.exists(os.path.join("sbin", aliasName)):
|
|
sym_link = os.path.join("sbin", aliasName)
|
|
else:
|
|
sym_link = ""
|
|
|
|
if sym_link:
|
|
print(" + removing app symlink: %s" % sym_link)
|
|
try:
|
|
os.remove(os.path.join(SEISCOMP_ROOT, sym_link))
|
|
except BaseException:
|
|
pass
|
|
|
|
# remove symlink from etc/init/mod1.py
|
|
init_scr = os.path.join("etc", "init", aliasName + ".py")
|
|
print(" + removing init script: %s" % init_scr)
|
|
try:
|
|
os.remove(os.path.join(SEISCOMP_ROOT, init_scr))
|
|
except BaseException:
|
|
pass
|
|
|
|
# delete defaults etc/defaults/mod1.cfg
|
|
default_cfg = os.path.join("etc", "defaults", aliasName + ".cfg")
|
|
print(" + removing default configuration: {}/{}"
|
|
.format(SEISCOMP_ROOT, default_cfg))
|
|
try:
|
|
os.remove(os.path.join(SEISCOMP_ROOT, default_cfg))
|
|
except BaseException as e:
|
|
error(" + could not remove %s" % e)
|
|
|
|
if not interactiveMode:
|
|
warning("No other configuration removed for '%s' - interactive"
|
|
" removal is supported by '--interactive'" % aliasName)
|
|
return 0
|
|
|
|
# test module configuration files
|
|
# SYSTEMCONFIGDIR
|
|
cfg = os.path.join("etc", aliasName + ".cfg")
|
|
if os.path.isfile(cfg):
|
|
print(" + found module configuration file: {}/{}"
|
|
.format(SEISCOMP_ROOT, cfg))
|
|
answer = getInput(" + do you wish to remove it?", 'n', 'yn')
|
|
if answer == "y":
|
|
try:
|
|
os.remove(cfg)
|
|
except Exception as e:
|
|
error(" + could not remove '%s' - try manually" % e)
|
|
|
|
# CONFIGDIR
|
|
cfg = os.path.join(
|
|
os.path.expanduser("~"),
|
|
".seiscomp",
|
|
aliasName + ".cfg")
|
|
if os.path.isfile(cfg):
|
|
print(" + found module configuration file: {}".format(cfg))
|
|
answer = getInput(" + do you wish to remove it?", 'n', 'yn')
|
|
if answer == "y":
|
|
try:
|
|
os.remove(cfg)
|
|
except Exception as e:
|
|
error(" + could not remove the file: %s - try manually" % e)
|
|
|
|
# test module binding files
|
|
bindingDir = os.path.join(SEISCOMP_ROOT, "etc", "key", aliasName)
|
|
if os.path.exists(bindingDir):
|
|
print(" + found binding directory: {}".format(bindingDir))
|
|
answer = getInput(" + do you wish to remove it?", 'n', 'yn')
|
|
if answer == "y":
|
|
try:
|
|
shutil.rmtree(bindingDir)
|
|
except Exception as e:
|
|
error(" + could not remove the directory: %s - try manually" % e)
|
|
|
|
# test key files
|
|
keyDir = os.path.join(SEISCOMP_ROOT, 'etc', 'key')
|
|
dirContent = os.listdir(keyDir)
|
|
keyFiles = []
|
|
print(" + testing key files")
|
|
for f in dirContent:
|
|
if not os.path.isfile(os.path.join(keyDir, f)) or \
|
|
not f.startswith("station_"):
|
|
continue
|
|
|
|
keyFile = os.path.join(keyDir, f)
|
|
with open(keyFile, 'r') as fp:
|
|
# Read all lines in the file one by one
|
|
for line in fp:
|
|
# check if the line starts with the module name
|
|
if line.startswith(aliasName):
|
|
keyFiles.append(keyFile)
|
|
print(" + found binding for '{}' in: {}".format(aliasName, keyFile))
|
|
|
|
if keyFiles:
|
|
print(" + found {} bindings for '{}' in key files".format(len(keyFiles), aliasName))
|
|
question = " + remove all '{}' bindings from key files?".format(aliasName)
|
|
answer = getInput(question, 'n', 'yn')
|
|
if answer == "y":
|
|
shell = seiscomp.shell.CLI(env)
|
|
shell.commandRemove(["module", aliasName, "*.*"])
|
|
else:
|
|
print(" + found no key files")
|
|
|
|
return 0
|
|
|
|
error("Wrong command '%s': expected 'create' or 'remove'" % args[0])
|
|
return 1
|
|
|
|
|
|
def on_alias_help(_):
|
|
print("seiscomp alias {create|remove} ALIAS_NAME APP_NAME")
|
|
print("Creates/removes symlinks to applications. Symlinks to symlinks are not allowed.")
|
|
print()
|
|
print("Examples:")
|
|
print("$ seiscomp alias create scautopick2 scautopick")
|
|
print("Copy default configuration: etc/defaults/scautopick.cfg -> etc/defaults/scautopick2.cfg")
|
|
print("Create app symlink: scautopick -> bin/scautopick2")
|
|
print("Copy init script: etc/init/scautopick.py -> etc/init/scautopick2.py")
|
|
print()
|
|
print("$ seiscomp alias remove scautopick2")
|
|
print("Remove default configuration: etc/defaults/scautopick2.cfg")
|
|
print("Remove app symlink: bin/scautopick2")
|
|
print("Remove init script: etc/init/scautopick2.py")
|
|
|
|
|
|
allowed_actions = [
|
|
"install-deps",
|
|
"setup",
|
|
"shell",
|
|
"enable",
|
|
"disable",
|
|
"start",
|
|
"stop",
|
|
"restart",
|
|
"reload",
|
|
"check",
|
|
"status",
|
|
"list",
|
|
"exec",
|
|
"update-config",
|
|
"alias",
|
|
"print",
|
|
"help"
|
|
]
|
|
|
|
|
|
# Define all actions that do not need locking of seiscomp
|
|
actions_without_lock = [
|
|
# "install-deps",
|
|
"help",
|
|
"list",
|
|
"exec",
|
|
"print"
|
|
]
|
|
|
|
|
|
def on_help(args, _):
|
|
if not args:
|
|
print("Name:")
|
|
print(" seiscomp - Load the environment of the SeisComP installation from " \
|
|
"where seiscomp is executed and run a command")
|
|
print("\nSynopsis:")
|
|
print(" seiscomp [flags] [commands] [arguments]")
|
|
print("\nFlags:")
|
|
print(" --asroot Allow running a command as root")
|
|
print(" --csv Print output as csv in machine-readable format")
|
|
print(" -i, [--interactive] Interactive mode: Allow deleting files " \
|
|
"interactively when removing aliases")
|
|
print(" --wait arg Define a timeout in seconds for acquiring the seiscomp " \
|
|
"lock file, e.g. `seiscomp --wait 10 update-config`")
|
|
print("\nAvailable commands:")
|
|
for helpAction in allowed_actions:
|
|
print(" %s" % helpAction)
|
|
|
|
print("\nUse 'help [command]' to get more help about a command")
|
|
print("\nExamples:")
|
|
print(" seiscomp help update-config Show help for update-config")
|
|
print(" seiscomp update-config Run update-config for allmodules")
|
|
print(" seiscomp update-config trunk Run update-config for all trunk modules")
|
|
print(" seiscomp update-config scautopick Run update-config for scautopick")
|
|
return 0
|
|
|
|
cmd = args[0]
|
|
try:
|
|
func = globals()["on_" + cmd.replace("-", "_") + "_help"]
|
|
except BaseException:
|
|
print("Sorry, no help available for %s" % cmd)
|
|
return 1
|
|
func(args[1:])
|
|
return 0
|
|
|
|
|
|
def run_action(runAction, args, flags):
|
|
try:
|
|
func = globals()["on_" + runAction.replace("-", "_")]
|
|
return func(args, flags)
|
|
except Exception as exc:
|
|
error("command '%s' failed: %s" % (runAction, str(exc)))
|
|
if "debug" in flags:
|
|
info = traceback.format_exception(*sys.exc_info())
|
|
for i in info:
|
|
sys.stderr.write(i)
|
|
return 2
|
|
|
|
|
|
def on_csv_help(_):
|
|
print("If --csv is prepended to a usual command the internal output is")
|
|
print("set to comma separated values. The only command that currently")
|
|
print("uses this output format is 'status'.")
|
|
print()
|
|
print("Example:")
|
|
print("seiscomp --csv status")
|
|
return 0
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Check command line
|
|
# ------------------------------------------------------------------------------
|
|
useCSV = False
|
|
asRoot = False
|
|
lockTimeout = None
|
|
interactiveMode = False
|
|
|
|
argv = sys.argv[1:]
|
|
argflags = []
|
|
|
|
# Check for flags
|
|
while argv:
|
|
if argv[0] == "--csv":
|
|
useCSV = True
|
|
argv = argv[1:]
|
|
elif argv[0] == "--asroot":
|
|
asRoot = True
|
|
argv = argv[1:]
|
|
if argv[0] == "--interactive" or argv[0] == "-i":
|
|
interactiveMode = True
|
|
argv = argv[1:]
|
|
elif argv[0] == "--wait":
|
|
argv = argv[1:]
|
|
if not argv:
|
|
print("--wait expects an integer value in seconds")
|
|
sys.exit(1)
|
|
try:
|
|
lockTimeout = int(argv[0])
|
|
except BaseException:
|
|
print("Wait timeout is not an integer: %s" % argv[0])
|
|
sys.exit(1)
|
|
if lockTimeout < 0:
|
|
print("Wait timeout must be positive: %s" % argv[0])
|
|
sys.exit(1)
|
|
argv = argv[1:]
|
|
elif argv[0].startswith("--"):
|
|
argflags.append(argv[0][2:])
|
|
argv = argv[1:]
|
|
else:
|
|
break
|
|
|
|
if len(argv) < 1:
|
|
print("seiscomp [flags] {%s} [args]" % "|".join(allowed_actions))
|
|
print("\nUse 'seiscomp help' to get more help")
|
|
sys.exit(1)
|
|
|
|
action = argv[0]
|
|
arguments = argv[1:]
|
|
|
|
if action not in allowed_actions:
|
|
print("seiscomp [flags] {%s} [args]" % "|".join(allowed_actions))
|
|
sys.exit(1)
|
|
|
|
if os.getuid() == 0 and not asRoot and action != "install-deps":
|
|
print("Running 'seiscomp' as root is dangerous. Use --asroot only if you")
|
|
print("know exactly what you are doing!")
|
|
sys.exit(1)
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Initialize the environment
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Resolve symlinks to files (if any)
|
|
if os.path.islink(sys.argv[0]):
|
|
# Read the link target
|
|
target = os.readlink(sys.argv[0])
|
|
# Is the target an absolute path then take it as is
|
|
if os.path.isabs(target):
|
|
sys.argv[0] = target
|
|
# Otherwise join the dirname of the script with the target
|
|
# to get the semi-real path of the seiscomp script. Semi-real
|
|
# refers to the fact that symlinks are not completely resolved
|
|
# and why the usage of os.path.realpath is avoided. If the
|
|
# seiscomp directory itself is a symlink it should be preserved.
|
|
else:
|
|
sys.argv[0] = os.path.join(os.path.dirname(sys.argv[0]), target)
|
|
|
|
# Guess SEISCOMP_ROOT from path of called script, directory links are not
|
|
# resolved allowing to create separate SeisComP environments
|
|
if os.path.isabs(sys.argv[0]):
|
|
root_path = sys.argv[0]
|
|
else:
|
|
cwd = os.getenv('PWD')
|
|
if cwd is None:
|
|
cwd = os.getcwd()
|
|
root_path = os.path.join(cwd, sys.argv[0])
|
|
|
|
SEISCOMP_ROOT = os.path.dirname(os.path.dirname(os.path.normpath(root_path)))
|
|
INIT_PATH = os.path.join(SEISCOMP_ROOT, "etc", "init")
|
|
DESC_PATH = os.path.join(SEISCOMP_ROOT, "etc", "descriptions")
|
|
ALIAS_FILE = os.path.join(DESC_PATH, "aliases")
|
|
BIN_PATH = os.path.join(SEISCOMP_ROOT, "bin")
|
|
SBIN_PATH = os.path.join(SEISCOMP_ROOT, "sbin")
|
|
PYTHONPATH = os.path.join(SEISCOMP_ROOT, "lib", "python")
|
|
MANPATH = os.path.join(SEISCOMP_ROOT, "share", "man")
|
|
LD_LIBRARY_PATH = os.path.join(SEISCOMP_ROOT, "lib")
|
|
DYLD_FALLBACK_FRAMEWORK_PATH = os.path.join(SEISCOMP_ROOT, "lib", "3rd-party")
|
|
|
|
# Run another process with proper LD_LIBRARY_PATH set otherwise the dynamic
|
|
# linker will not find dependent SC3 libraries
|
|
isWrapped = False
|
|
try:
|
|
if os.environ["SEISCOMP_WRAP"] == "TRUE":
|
|
isWrapped = True
|
|
except BaseException:
|
|
pass
|
|
|
|
|
|
# Setup signal handler
|
|
#signal.signal(signal.SIGTERM, sigterm_handler)
|
|
|
|
if not isWrapped:
|
|
try:
|
|
os.environ["PATH"] = BIN_PATH + ":" + os.environ["PATH"]
|
|
except BaseException:
|
|
os.environ["PATH"] = BIN_PATH
|
|
|
|
try:
|
|
os.environ[SysLibraryPathVar] = get_library_path() + ":" + \
|
|
os.environ[SysLibraryPathVar]
|
|
except BaseException:
|
|
os.environ[SysLibraryPathVar] = get_library_path()
|
|
|
|
if sys.platform == "darwin":
|
|
os.environ[SysFrameworkPathVar] = get_framework_path()
|
|
|
|
try:
|
|
os.environ["PYTHONPATH"] = PYTHONPATH + ":" + os.environ["PYTHONPATH"]
|
|
except BaseException:
|
|
os.environ["PYTHONPATH"] = PYTHONPATH
|
|
try:
|
|
os.environ["MANPATH"] = MANPATH + ":" + os.environ["MANPATH"]
|
|
except BaseException:
|
|
os.environ["MANPATH"] = MANPATH
|
|
|
|
os.environ["SEISCOMP_WRAP"] = "TRUE"
|
|
|
|
sys.exit(system(sys.argv))
|
|
|
|
# Register local lib/python in SEARCH PATH
|
|
sys.path.insert(0, PYTHONPATH)
|
|
|
|
# Create environment which supports queries for various SeisComP
|
|
# directoris and sets PATH, LD_LIBRARY_PATH and PYTHONPATH
|
|
env = seiscomp.kernel.Environment(SEISCOMP_ROOT)
|
|
env.setCSVOutput(useCSV)
|
|
|
|
# Check for lock file
|
|
isChild = False
|
|
|
|
if action in actions_without_lock:
|
|
isChild = True
|
|
else:
|
|
try:
|
|
isChild = os.environ["SEISCOMP_LOCK"] == "TRUE"
|
|
except KeyError:
|
|
pass
|
|
|
|
if not isChild:
|
|
if not env.tryLock("seiscomp", lockTimeout):
|
|
error("Could not get lock %s - is another process using it?" %
|
|
env.lockFile("seiscomp"))
|
|
sys.exit(1)
|
|
|
|
os.environ["SEISCOMP_LOCK"] = "TRUE"
|
|
exitcode = system(
|
|
["run_with_lock", "-q", env.lockFile("seiscomp")] + sys.argv)
|
|
sys.exit(exitcode)
|
|
|
|
|
|
# Change into SEISCOMP_ROOT directory. The env instance will change
|
|
# back into the current working directory automatically if destroyed.
|
|
env.chroot()
|
|
|
|
simpleCommand = (action == "install-deps") or \
|
|
(action == "print" and arguments == "env")
|
|
|
|
if not simpleCommand:
|
|
config_mods = load_init_modules(INIT_PATH)
|
|
mods = []
|
|
for m in config_mods:
|
|
if m.isConfigModule:
|
|
continue
|
|
mods.append(m)
|
|
|
|
sys.exit(run_action(action, arguments, argflags))
|