mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Move moulinette initialization and other stuff to src/yunohost/__init__.py
This commit is contained in:
parent
233c962710
commit
dee08a16fe
3 changed files with 216 additions and 191 deletions
113
bin/yunohost
113
bin/yunohost
|
@ -4,34 +4,29 @@
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import argparse
|
import argparse
|
||||||
import glob
|
|
||||||
|
|
||||||
import moulinette
|
sys.path.insert(0, "/usr/lib/moulinette/")
|
||||||
|
import yunohost
|
||||||
|
|
||||||
# Directory and file to be used by logging
|
|
||||||
LOG_DIR = '/var/log/yunohost'
|
|
||||||
LOG_FILE = 'yunohost-cli.log'
|
|
||||||
|
|
||||||
# Initialization & helpers functions -----------------------------------
|
|
||||||
|
|
||||||
def _parse_cli_args():
|
def _parse_cli_args():
|
||||||
"""Parse additional arguments for the cli"""
|
"""Parse additional arguments for the cli"""
|
||||||
parser = argparse.ArgumentParser(add_help=False)
|
parser = argparse.ArgumentParser(add_help=False)
|
||||||
parser.add_argument('--output-as',
|
parser.add_argument('--output-as',
|
||||||
choices=['json', 'plain', 'none'], default=None,
|
choices=['json', 'plain', 'none'], default=None,
|
||||||
help="Output result in another format",
|
help="Output result in another format"
|
||||||
)
|
)
|
||||||
parser.add_argument('--debug',
|
parser.add_argument('--debug',
|
||||||
action='store_true', default=False,
|
action='store_true', default=False,
|
||||||
help="Log and print debug messages",
|
help="Log and print debug messages"
|
||||||
)
|
)
|
||||||
parser.add_argument('--quiet',
|
parser.add_argument('--quiet',
|
||||||
action='store_true', default=False,
|
action='store_true', default=False,
|
||||||
help="Don't produce any output",
|
help="Don't produce any output"
|
||||||
)
|
)
|
||||||
parser.add_argument('--timeout',
|
parser.add_argument('--timeout',
|
||||||
type=int, default=None,
|
type=int, default=None,
|
||||||
help="Number of seconds before this command will timeout because it can't acquire the lock (meaning that another command is currently running), by default there is no timeout and the command will wait until it can get the lock",
|
help="Number of seconds before this command will timeout because it can't acquire the lock (meaning that another command is currently running), by default there is no timeout and the command will wait until it can get the lock"
|
||||||
)
|
)
|
||||||
# deprecated arguments
|
# deprecated arguments
|
||||||
parser.add_argument('--plain',
|
parser.add_argument('--plain',
|
||||||
|
@ -52,72 +47,6 @@ def _parse_cli_args():
|
||||||
return (parser, opts, args)
|
return (parser, opts, args)
|
||||||
|
|
||||||
|
|
||||||
def init(debug=False, quiet=False, logfile='%s/%s' % (LOG_DIR, LOG_FILE)):
|
|
||||||
|
|
||||||
logdir = os.path.dirname(logfile)
|
|
||||||
if not os.path.isdir(logdir):
|
|
||||||
os.makedirs(logdir, 0750)
|
|
||||||
|
|
||||||
moulinette.init(logging_config={
|
|
||||||
'version': 1,
|
|
||||||
'disable_existing_loggers': True,
|
|
||||||
'formatters': {
|
|
||||||
'tty-debug': {
|
|
||||||
'format': '%(relativeCreated)-4d %(fmessage)s'
|
|
||||||
},
|
|
||||||
'precise': {
|
|
||||||
'format': '%(asctime)-15s %(levelname)-8s %(name)s %(funcName)s - %(fmessage)s'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'filters': {
|
|
||||||
'action': {
|
|
||||||
'()': 'moulinette.utils.log.ActionFilter',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'handlers': {
|
|
||||||
'tty': {
|
|
||||||
'level': 'DEBUG' if debug else 'INFO',
|
|
||||||
'class': 'moulinette.interfaces.cli.TTYHandler',
|
|
||||||
'formatter': 'tty-debug' if debug else '',
|
|
||||||
},
|
|
||||||
'file': {
|
|
||||||
'class': 'logging.FileHandler',
|
|
||||||
'formatter': 'precise',
|
|
||||||
'filename': logfile,
|
|
||||||
'filters': ['action'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'loggers': {
|
|
||||||
'yunohost': {
|
|
||||||
'level': 'DEBUG',
|
|
||||||
'handlers': ['file', 'tty'] if not quiet else ['file'],
|
|
||||||
'propagate': False,
|
|
||||||
},
|
|
||||||
'moulinette': {
|
|
||||||
'level': 'DEBUG',
|
|
||||||
'handlers': [],
|
|
||||||
'propagate': True,
|
|
||||||
},
|
|
||||||
'moulinette.interface': {
|
|
||||||
'level': 'DEBUG',
|
|
||||||
'handlers': ['file', 'tty'] if not quiet else ['file'],
|
|
||||||
'propagate': False,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'root': {
|
|
||||||
'level': 'DEBUG',
|
|
||||||
'handlers': ['file', 'tty'] if debug else ['file'],
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _retrieve_namespaces():
|
|
||||||
"""Return the list of namespaces to load"""
|
|
||||||
extensions = [n for n in ActionsMap.get_namespaces() if n.startswith('ynh_')]
|
|
||||||
return ['yunohost'] + extensions
|
|
||||||
|
|
||||||
|
|
||||||
# Stupid PATH management because sometimes (e.g. some cron job) PATH is only /usr/bin:/bin ...
|
# Stupid PATH management because sometimes (e.g. some cron job) PATH is only /usr/bin:/bin ...
|
||||||
default_path = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
default_path = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||||
if os.environ["PATH"] != default_path:
|
if os.environ["PATH"] != default_path:
|
||||||
|
@ -127,38 +56,18 @@ if os.environ["PATH"] != default_path:
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
if os.geteuid() != 0:
|
if os.geteuid() != 0:
|
||||||
# since moulinette isn't initialized, we can't use m18n here
|
|
||||||
sys.stderr.write("\033[1;31mError:\033[0m yunohost command must be "
|
sys.stderr.write("\033[1;31mError:\033[0m yunohost command must be "
|
||||||
"run as root or with sudo.\n")
|
"run as root or with sudo.\n")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
parser, opts, args = _parse_cli_args()
|
parser, opts, args = _parse_cli_args()
|
||||||
init(debug=opts.debug, quiet=opts.quiet)
|
|
||||||
|
|
||||||
# Check that YunoHost is installed
|
|
||||||
allowed_if_not_installed = ['tools postinstall', 'backup restore', 'log display']
|
|
||||||
if not os.path.isfile('/etc/yunohost/installed') and \
|
|
||||||
(len(args) < 2 or (args[0] + ' ' + args[1] not in allowed_if_not_installed)):
|
|
||||||
|
|
||||||
from moulinette import m18n
|
|
||||||
from moulinette.interfaces.cli import colorize, get_locale
|
|
||||||
|
|
||||||
# Init i18n
|
|
||||||
m18n.load_namespace('yunohost')
|
|
||||||
m18n.set_locale(get_locale())
|
|
||||||
|
|
||||||
# Print error and exit
|
|
||||||
print(colorize(m18n.g('error'), 'red') + " " + m18n.n('yunohost_not_installed'))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
extensions = [f.split('/')[-1][:-4] for f in glob.glob("/usr/share/moulinette/actionsmap/ynh_*.yml")]
|
|
||||||
|
|
||||||
# Execute the action
|
# Execute the action
|
||||||
ret = moulinette.cli(
|
yunohost.cli(
|
||||||
['yunohost'] + extensions,
|
debug=opts.debug,
|
||||||
args,
|
quiet=opts.quiet,
|
||||||
output_as=opts.output_as,
|
output_as=opts.output_as,
|
||||||
timeout=opts.timeout,
|
timeout=opts.timeout,
|
||||||
parser_kwargs={'top_parser': parser},
|
args=args,
|
||||||
|
parser=parser
|
||||||
)
|
)
|
||||||
sys.exit(ret)
|
|
||||||
|
|
|
@ -1,23 +1,16 @@
|
||||||
#! /usr/bin/python
|
#! /usr/bin/python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
import sys
|
||||||
import argparse
|
import argparse
|
||||||
import glob
|
|
||||||
|
|
||||||
import moulinette
|
sys.path.insert(0, "/usr/lib/moulinette/")
|
||||||
|
import yunohost
|
||||||
|
|
||||||
# Default server configuration
|
# Default server configuration
|
||||||
DEFAULT_HOST = 'localhost'
|
DEFAULT_HOST = 'localhost'
|
||||||
DEFAULT_PORT = 6787
|
DEFAULT_PORT = 6787
|
||||||
|
|
||||||
# Directory and file to be used by logging
|
|
||||||
LOG_DIR = '/var/log/yunohost'
|
|
||||||
LOG_FILE = 'yunohost-api.log'
|
|
||||||
|
|
||||||
# Initialization & helpers functions -----------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
def _parse_api_args():
|
def _parse_api_args():
|
||||||
"""Parse main arguments for the api"""
|
"""Parse main arguments for the api"""
|
||||||
|
@ -45,86 +38,7 @@ def _parse_api_args():
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
def init_api(debug=False, logfile='%s/%s' % (LOG_DIR, LOG_FILE)):
|
|
||||||
|
|
||||||
logdir = os.path.dirname(logfile)
|
|
||||||
if not os.path.isdir(logdir):
|
|
||||||
os.makedirs(logdir, 0750)
|
|
||||||
|
|
||||||
moulinette.init(logging_config={
|
|
||||||
'version': 1,
|
|
||||||
'disable_existing_loggers': True,
|
|
||||||
'formatters': {
|
|
||||||
'console': {
|
|
||||||
'format': '%(relativeCreated)-5d %(levelname)-8s %(name)s %(funcName)s - %(fmessage)s'
|
|
||||||
},
|
|
||||||
'precise': {
|
|
||||||
'format': '%(asctime)-15s %(levelname)-8s %(name)s %(funcName)s - %(fmessage)s'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'filters': {
|
|
||||||
'action': {
|
|
||||||
'()': 'moulinette.utils.log.ActionFilter',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'handlers': {
|
|
||||||
'api': {
|
|
||||||
'level': 'DEBUG' if debug else 'INFO',
|
|
||||||
'class': 'moulinette.interfaces.api.APIQueueHandler',
|
|
||||||
},
|
|
||||||
'file': {
|
|
||||||
'class': 'logging.handlers.WatchedFileHandler',
|
|
||||||
'formatter': 'precise',
|
|
||||||
'filename': logfile,
|
|
||||||
'filters': ['action'],
|
|
||||||
},
|
|
||||||
'console': {
|
|
||||||
'class': 'logging.StreamHandler',
|
|
||||||
'formatter': 'console',
|
|
||||||
'stream': 'ext://sys.stdout',
|
|
||||||
'filters': ['action'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'loggers': {
|
|
||||||
'yunohost': {
|
|
||||||
'level': 'DEBUG',
|
|
||||||
'handlers': ['file', 'api'] + ['console'] if debug else [],
|
|
||||||
'propagate': False,
|
|
||||||
},
|
|
||||||
'moulinette': {
|
|
||||||
'level': 'DEBUG',
|
|
||||||
'handlers': [],
|
|
||||||
'propagate': True,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'root': {
|
|
||||||
'level': 'DEBUG',
|
|
||||||
'handlers': ['file'] + ['console'] if debug else [],
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
# Callbacks for additional routes --------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
def is_installed():
|
|
||||||
""" Check whether YunoHost is installed or not """
|
|
||||||
return {'installed': os.path.isfile('/etc/yunohost/installed')}
|
|
||||||
|
|
||||||
|
|
||||||
# Main action ----------------------------------------------------------
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
opts = _parse_api_args()
|
opts = _parse_api_args()
|
||||||
init_api(opts.debug)
|
|
||||||
|
|
||||||
extensions = [f.split('/')[-1][:-4] for f in glob.glob("/usr/share/moulinette/actionsmap/ynh_*.yml")]
|
|
||||||
|
|
||||||
# Run the server
|
# Run the server
|
||||||
ret = moulinette.api(
|
yunohost.api(debug=opts.debug, host=opts.host, port=opts.port)
|
||||||
['yunohost'] + extensions,
|
|
||||||
host=opts.host,
|
|
||||||
port=opts.port,
|
|
||||||
routes={('GET', '/installed'): is_installed},
|
|
||||||
use_websocket=True
|
|
||||||
)
|
|
||||||
sys.exit(ret)
|
|
||||||
|
|
|
@ -0,0 +1,202 @@
|
||||||
|
#! /usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import glob
|
||||||
|
|
||||||
|
import moulinette
|
||||||
|
from moulinette.utils.log import configure_logging
|
||||||
|
|
||||||
|
|
||||||
|
def is_installed():
|
||||||
|
return os.path.isfile('/etc/yunohost/installed')
|
||||||
|
|
||||||
|
|
||||||
|
def cli(debug, quiet, output_as, timeout, args, parser):
|
||||||
|
|
||||||
|
init_logging(interface="cli", debug=debug, quiet=quiet)
|
||||||
|
|
||||||
|
# Check that YunoHost is installed
|
||||||
|
if not is_installed():
|
||||||
|
check_command_is_valid_before_postinstall(args)
|
||||||
|
|
||||||
|
ret = moulinette.cli(
|
||||||
|
['yunohost'] + extensions(),
|
||||||
|
args,
|
||||||
|
output_as=output_as,
|
||||||
|
timeout=timeout,
|
||||||
|
parser_kwargs={'top_parser': parser},
|
||||||
|
)
|
||||||
|
sys.exit(ret)
|
||||||
|
|
||||||
|
|
||||||
|
def api(debug, host, port):
|
||||||
|
|
||||||
|
init_logging(debug=debug)
|
||||||
|
|
||||||
|
def is_installed_api():
|
||||||
|
return {'installed': is_installed()}
|
||||||
|
|
||||||
|
# FIXME : someday, maybe find a way to disable route /postinstall if
|
||||||
|
# postinstall already done ...
|
||||||
|
|
||||||
|
ret = moulinette.api(
|
||||||
|
['yunohost'] + extensions(),
|
||||||
|
host=host,
|
||||||
|
port=port,
|
||||||
|
routes={('GET', '/installed'): is_installed_api},
|
||||||
|
use_websocket=True
|
||||||
|
)
|
||||||
|
sys.exit(ret)
|
||||||
|
|
||||||
|
|
||||||
|
def extensions():
|
||||||
|
# This is probably not used anywhere, but the actionsmap and code can be
|
||||||
|
# extended by creating such files that contain bits of actionmap...
|
||||||
|
return [f.split('/')[-1][:-4] for f in glob.glob("/usr/share/moulinette/actionsmap/ynh_*.yml")]
|
||||||
|
|
||||||
|
|
||||||
|
def check_command_is_valid_before_postinstall(args):
|
||||||
|
|
||||||
|
allowed_if_not_postinstalled = ['tools postinstall',
|
||||||
|
'tools versions',
|
||||||
|
'backup list',
|
||||||
|
'backup restore',
|
||||||
|
'log display']
|
||||||
|
|
||||||
|
if (len(args) < 2 or (args[0] + ' ' + args[1] not in allowed_if_not_postinstalled)):
|
||||||
|
|
||||||
|
# This function is called before m18n is initialized, so we only initialized
|
||||||
|
# the specific bit to be able to call m18n.n/g()...
|
||||||
|
from moulinette import m18n
|
||||||
|
from moulinette.interfaces.cli import colorize, get_locale
|
||||||
|
|
||||||
|
# Init i18n
|
||||||
|
m18n.load_namespace('yunohost')
|
||||||
|
m18n.set_locale(get_locale())
|
||||||
|
|
||||||
|
print(colorize(m18n.g('error'), 'red') + " " + m18n.n('yunohost_not_installed'))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def init_logging(interface="cli",
|
||||||
|
debug=False,
|
||||||
|
quiet=False,
|
||||||
|
logdir="/var/log/yunohost"):
|
||||||
|
|
||||||
|
logfile = os.path.join(logdir, "yunohost-%s.log" % interface)
|
||||||
|
|
||||||
|
if not os.path.isdir(logdir):
|
||||||
|
os.makedirs(logdir, 0750)
|
||||||
|
|
||||||
|
# ####################################################################### #
|
||||||
|
# Logging configuration for CLI (or any other interface than api...) #
|
||||||
|
# ####################################################################### #
|
||||||
|
if interface != "api":
|
||||||
|
configure_logging({
|
||||||
|
'version': 1,
|
||||||
|
'disable_existing_loggers': True,
|
||||||
|
'formatters': {
|
||||||
|
'tty-debug': {
|
||||||
|
'format': '%(relativeCreated)-4d %(fmessage)s'
|
||||||
|
},
|
||||||
|
'precise': {
|
||||||
|
'format': '%(asctime)-15s %(levelname)-8s %(name)s %(funcName)s - %(fmessage)s'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'filters': {
|
||||||
|
'action': {
|
||||||
|
'()': 'moulinette.utils.log.ActionFilter',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'handlers': {
|
||||||
|
'tty': {
|
||||||
|
'level': 'DEBUG' if debug else 'INFO',
|
||||||
|
'class': 'moulinette.interfaces.cli.TTYHandler',
|
||||||
|
'formatter': 'tty-debug' if debug else '',
|
||||||
|
},
|
||||||
|
'file': {
|
||||||
|
'class': 'logging.FileHandler',
|
||||||
|
'formatter': 'precise',
|
||||||
|
'filename': logfile,
|
||||||
|
'filters': ['action'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'loggers': {
|
||||||
|
'yunohost': {
|
||||||
|
'level': 'DEBUG',
|
||||||
|
'handlers': ['file', 'tty'] if not quiet else ['file'],
|
||||||
|
'propagate': False,
|
||||||
|
},
|
||||||
|
'moulinette': {
|
||||||
|
'level': 'DEBUG',
|
||||||
|
'handlers': [],
|
||||||
|
'propagate': True,
|
||||||
|
},
|
||||||
|
'moulinette.interface': {
|
||||||
|
'level': 'DEBUG',
|
||||||
|
'handlers': ['file', 'tty'] if not quiet else ['file'],
|
||||||
|
'propagate': False,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'root': {
|
||||||
|
'level': 'DEBUG',
|
||||||
|
'handlers': ['file', 'tty'] if debug else ['file'],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
# ####################################################################### #
|
||||||
|
# Logging configuration for API #
|
||||||
|
# ####################################################################### #
|
||||||
|
else:
|
||||||
|
configure_logging({
|
||||||
|
'version': 1,
|
||||||
|
'disable_existing_loggers': True,
|
||||||
|
'formatters': {
|
||||||
|
'console': {
|
||||||
|
'format': '%(relativeCreated)-5d %(levelname)-8s %(name)s %(funcName)s - %(fmessage)s'
|
||||||
|
},
|
||||||
|
'precise': {
|
||||||
|
'format': '%(asctime)-15s %(levelname)-8s %(name)s %(funcName)s - %(fmessage)s'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'filters': {
|
||||||
|
'action': {
|
||||||
|
'()': 'moulinette.utils.log.ActionFilter',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'handlers': {
|
||||||
|
'api': {
|
||||||
|
'level': 'DEBUG' if debug else 'INFO',
|
||||||
|
'class': 'moulinette.interfaces.api.APIQueueHandler',
|
||||||
|
},
|
||||||
|
'file': {
|
||||||
|
'class': 'logging.handlers.WatchedFileHandler',
|
||||||
|
'formatter': 'precise',
|
||||||
|
'filename': logfile,
|
||||||
|
'filters': ['action'],
|
||||||
|
},
|
||||||
|
'console': {
|
||||||
|
'class': 'logging.StreamHandler',
|
||||||
|
'formatter': 'console',
|
||||||
|
'stream': 'ext://sys.stdout',
|
||||||
|
'filters': ['action'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'loggers': {
|
||||||
|
'yunohost': {
|
||||||
|
'level': 'DEBUG',
|
||||||
|
'handlers': ['file', 'api'] + ['console'] if debug else [],
|
||||||
|
'propagate': False,
|
||||||
|
},
|
||||||
|
'moulinette': {
|
||||||
|
'level': 'DEBUG',
|
||||||
|
'handlers': [],
|
||||||
|
'propagate': True,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'root': {
|
||||||
|
'level': 'DEBUG',
|
||||||
|
'handlers': ['file'] + ['console'] if debug else [],
|
||||||
|
},
|
||||||
|
})
|
Loading…
Add table
Reference in a new issue