#!/usr/bin/env python3 ## # This file is part of TALER # (C) 2017 INRIA # # TALER is free software; you can redistribute it and/or # modify it under the terms of the GNU Affero General Public # License as published by the Free Software Foundation; either # version 3, or (at your option) any later version. # # TALER 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 GNU General Public License for more details. # # You should have received a copy of the GNU General Public # License along with TALER; see the file COPYING. If not, # see # # @author Florian Dold # @file CLI tool to manage all the bank's tasks. import argparse import django import sys import os import site import logging from talerbank.talerconfig import TalerConfig from django.core.management import call_command os.environ.setdefault("TALER_PREFIX", "@prefix@") SITE_PACKAGES = "%s/lib/python%d.%d/site-packages" % ( "@prefix@", sys.version_info.major, sys.version_info.minor) site.addsitedir(SITE_PACKAGES) ## Not commenting global variables, at least for now. # @cond LOGGER = logging.getLogger(__name__) # No perfect match to our logging format, but good enough ... UWSGI_LOGFMT = "%(ltime) %(proto) %(method) %(uri) %(proto) => %(status)" ## @endcond ## # This function interprets the 'django' subcommand. # This command usually manages database tasks, and in # general what is not related to running the bank. # # @param args command line options. def handle_django(args): django.setup() # always run 'migrate' first, in case a virgin db is being used. call_command('migrate') from django.core.management import execute_from_command_line execute_from_command_line([sys.argv[0] + " django"] + args.command) ## # This function interprets the 'serve-http' subcommand. # The effect it to launch the bank HTTP service. # # @param args command line options. def handle_serve_http(args): import django django.setup() call_command('migrate') call_command('provide_accounts') call_command('check') port = args.port TC = TalerConfig.from_file(os.environ.get("TALER_CONFIG_FILE", args.config)) if port is None: port = TC["bank"]["http_port"].value_int(required=True) httpspec = ":%d" % (port,) params = ["uwsgi", "uwsgi", "--static-map", "/static=%s/talerbank/app/static" % SITE_PACKAGES, "--master", "--die-on-term", "--http", httpspec, "--log-format", UWSGI_LOGFMT, "--wsgi-file", "@prefix@/share/taler-bank/bank.wsgi"] os.execlp(*params) ## # This function interprets the 'serve-uwsgi' subcommand. # The effect is to launch the bank UWSGI service. This # type of service is usually used when the HTTP bank interface # is accessed via a reverse proxy (like Nginx, for example). # # @param command line options. def handle_serve_uwsgi(args): django.setup() call_command('migrate') call_command('provide_accounts') call_command('check') TC = TalerConfig.from_file(os.environ.get("TALER_CONFIG_FILE", args.config)) serve_uwsgi = TC["bank"]["uwsgi_serve"].value_string(required=True).lower() params = ["uwsgi", "uwsgi", "--master", "--static-map", "/static=%s/talerbank/app/static" % SITE_PACKAGES, "--die-on-term", "--log-format", UWSGI_LOGFMT, "--wsgi-file", "@prefix@/share/taler-bank/bank.wsgi"] if serve_uwsgi == "tcp": port = TC["bank"]["uwsgi_port"].value_int(required=True) spec = ":%d" % (port,) params.extend(["--socket", spec]) else: spec = TC["bank"]["uwsgi_unixpath"].value_filename(required=True) mode = TC["bank"]["uwsgi_unixpath_mode"].value_filename(required=True) params.extend(["--socket", spec]) params.extend(["--chmod-socket="+mode]) os.makedirs(os.path.dirname(spec), exist_ok=True) logging.info("launching uwsgi with argv %s", params[1:]) os.execlp(*params) ## # Currently deprecated. def handle_sampledata(): django.setup() call_command('sample_donations') ## # Interprets the '--config' option. # # @param args command line options. def handle_config(args): TC.from_file(args.config) TC.dump() ## Not commenting global variables, at least for now. # @cond PARSER = argparse.ArgumentParser() PARSER.set_defaults(func=None) PARSER.add_argument('--config', '-c', help="configuration file to use", metavar="CONFIG", type=str, dest="config", default=None) PARSER.add_argument('--with-db', type=str, metavar="dbtype:///dbname", dest="altdb", help="use 'dbname' (currently only 'dbtype'=='postgres' is supported)") SUB = PARSER.add_subparsers() P = SUB.add_parser('django', help="Run django-admin command") P.add_argument("command", nargs=argparse.REMAINDER) P.set_defaults(func=handle_django) P = SUB.add_parser('serve-http', help="Serve bank over HTTP") P.add_argument("--port", "-p", dest="port", type=int, default=None, metavar="PORT") P.set_defaults(func=handle_serve_http) P = SUB.add_parser('serve-uwsgi', help="Serve bank over UWSGI") P.set_defaults(func=handle_serve_uwsgi) P = SUB.add_parser('config', help="show config") P.set_defaults(func=handle_config) ARGS = PARSER.parse_args() os.environ.setdefault("DJANGO_SETTINGS_MODULE", "talerbank.settings") if ARGS.altdb: LOGGER.info("Setting alternate db: %s" % ARGS.altdb) os.environ.setdefault("TALER_BANK_ALTDB", ARGS.altdb) if getattr(ARGS, 'func', None) is None: PARSER.print_help() sys.exit(1) if ARGS.config is not None: os.environ["TALER_CONFIG_FILE"] = ARGS.config try: ARGS.func(ARGS) except django.db.utils.OperationalError as error: LOGGER.error(error) sys.exit(4) ## @endcond