#!/usr/bin/env python3 import logging import sys import importlib import argparse import os from etcd3.exceptions import ConnectionFailedError from uncloud.common import settings from uncloud import UncloudException from uncloud.common.cli import resolve_otp_credentials # Components that use etcd ETCD_COMPONENTS = ['api', 'scheduler', 'host', 'filescanner', 'imagescanner', 'metadata', 'configure', 'hack'] ALL_COMPONENTS = ETCD_COMPONENTS.copy() ALL_COMPONENTS.append('oneshot') #ALL_COMPONENTS.append('cli') if __name__ == '__main__': arg_parser = argparse.ArgumentParser() subparsers = arg_parser.add_subparsers(dest='command') parent_parser = argparse.ArgumentParser(add_help=False) parent_parser.add_argument('--debug', '-d', action='store_true', default=False, help='More verbose logging') parent_parser.add_argument('--conf-dir', '-c', help='Configuration directory', default=os.path.expanduser('~/uncloud')) etcd_parser = argparse.ArgumentParser(add_help=False) etcd_parser.add_argument('--etcd-host') etcd_parser.add_argument('--etcd-port') etcd_parser.add_argument('--etcd-ca-cert', help='CA that signed the etcd certificate') etcd_parser.add_argument('--etcd-cert-cert', help='Path to client certificate') etcd_parser.add_argument('--etcd-cert-key', help='Path to client certificate key') for component in ALL_COMPONENTS: mod = importlib.import_module('uncloud.{}.main'.format(component)) parser = getattr(mod, 'arg_parser') if component in ETCD_COMPONENTS: subparsers.add_parser(name=parser.prog, parents=[parser, parent_parser, etcd_parser]) else: subparsers.add_parser(name=parser.prog, parents=[parser, parent_parser]) arguments = vars(arg_parser.parse_args()) etcd_arguments = [key for key, value in arguments.items() if key.startswith('etcd_') and value] etcd_arguments = { 'etcd': { key.replace('etcd_', ''): arguments[key] for key in etcd_arguments } } if not arguments['command']: arg_parser.print_help() else: # Initializing Settings and resolving otp_credentials # It is neccessary to resolve_otp_credentials after argument parsing is done because # previously we were reading config file which was fixed to ~/uncloud/uncloud.conf and # providing the default values for --name, --realm and --seed arguments from the values # we read from file. But, now we are asking user about where the config file lives. So, # to providing default value is not possible before parsing arguments. So, we are doing # it after.. # settings.settings = settings.Settings(arguments['conf_dir'], seed_value=etcd_arguments) # resolve_otp_credentials(arguments) name = arguments.pop('command') mod = importlib.import_module('uncloud.{}.main'.format(name)) main = getattr(mod, 'main') if arguments['debug']: logging.basicConfig(level=logging.DEBUG) else: logging.basicConfig(level=logging.INFO) log = logging.getLogger() try: main(arguments) except UncloudException as err: log.error(err) # except ConnectionFailedError as err: # log.error('Cannot connect to etcd: {}'.format(err)) except Exception as err: log.exception(err)