+ name_terms = cls_name.split('_')
+ if not _update_best_match(name_terms, prefix):
+ if _debug:
+ kloger.warning('%s failed to update_best_match' % cls_name)
+ return None
+
+ global _best_match
+ max_len = len(_best_match) + descedants_depth
+ if len(name_terms) > max_len:
+ partial = '_'.join(name_terms[:max_len])
+ if not cmd_tree.has_command(partial): # add partial path
+ cmd_tree.add_command(partial)
+ if _debug:
+ kloger.warning('%s failed max_len test' % cls_name)
+ return None
+
+ (
+ cls.description, sep, cls.long_description
+ ) = cls.__doc__.partition('\n')
+ _construct_command_syntax(cls)
+
+ cmd_tree.add_command(cls_name, cls.description, cls)
+ return cls
+ return wrap
+
+
+cmd_spec_locations = [
+ 'kamaki.cli.commands',
+ 'kamaki.commands',
+ 'kamaki.cli',
+ 'kamaki',
+ '']
+
+
+# Generic init auxiliary functions
+
+
+def _setup_logging(silent=False, debug=False, verbose=False, include=False):
+ """handle logging for clients package"""
+
+ if silent:
+ logger.add_stream_logger(__name__, logging.CRITICAL)
+ return
+
+ sfmt, rfmt = '> %(message)s', '< %(message)s'
+ if debug:
+ print('Logging location: %s' % logger.get_log_filename())
+ logger.add_stream_logger('kamaki.clients.send', logging.DEBUG, sfmt)
+ logger.add_stream_logger('kamaki.clients.recv', logging.DEBUG, rfmt)
+ logger.add_stream_logger(__name__, logging.DEBUG)
+ elif verbose:
+ logger.add_stream_logger('kamaki.clients.send', logging.INFO, sfmt)
+ logger.add_stream_logger('kamaki.clients.recv', logging.INFO, rfmt)
+ logger.add_stream_logger(__name__, logging.INFO)
+ if include:
+ logger.add_stream_logger('kamaki.clients.send', logging.INFO, sfmt)
+ logger.add_stream_logger('kamaki.clients.recv', logging.INFO, rfmt)
+ logger.add_stream_logger(__name__, logging.WARNING)
+ global kloger
+ kloger = logger.get_logger(__name__)
+
+
+def _check_config_version(cnf):
+ guess = cnf.guess_version()
+ if exists(cnf.path) and guess < 0.9:
+ print('Config file format version >= 9.0 is required')
+ print('Configuration file: %s' % cnf.path)
+ print('but kamaki can fix this:')
+ print('Calculating changes while preserving information')
+ lost_terms = cnf.rescue_old_file()
+ print('... DONE')
+ if lost_terms:
+ print 'The following information will NOT be preserved:'
+ print '\t', '\n\t'.join(lost_terms)
+ print('Kamaki is ready to convert the config file to version 3.0')
+ stdout.write('Create (overwrite) file %s ? [y/N] ' % cnf.path)
+ from sys import stdin
+ reply = stdin.readline()
+ if reply in ('Y\n', 'y\n'):
+ cnf.write()
+ print('... DONE')
+ else:
+ print('... ABORTING')
+ raise CLIError(
+ 'Invalid format for config file %s' % cnf.path,
+ importance=3, details=[
+ 'Please, update config file to v3.0',
+ 'For automatic conversion, rerun and say Y'])
+
+
+def _init_session(arguments, is_non_API=False):
+ """
+ :returns: (AuthCachedClient, str) authenticator and cloud name
+ """
+ global _help
+ _help = arguments['help'].value
+ global _debug
+ _debug = arguments['debug'].value
+ global _include
+ _include = arguments['include'].value
+ global _verbose
+ _verbose = arguments['verbose'].value
+ _cnf = arguments['config']
+
+ if _help or is_non_API:
+ return None, None
+
+ _check_config_version(_cnf.value)
+
+ global _colors
+ _colors = _cnf.value.get_global('colors')
+ if not (stdout.isatty() and _colors == 'on'):
+ from kamaki.cli.utils import remove_colors
+ remove_colors()
+ _silent = arguments['silent'].value
+ _setup_logging(_silent, _debug, _verbose, _include)
+
+ cloud = arguments['cloud'].value or _cnf.value.get(
+ 'global', 'default_cloud')
+ if not cloud:
+ num_of_clouds = len(_cnf.value.keys('cloud'))
+ if num_of_clouds == 1:
+ cloud = _cnf.value.keys('cloud')[0]
+ elif num_of_clouds > 1:
+ raise CLIError(
+ 'Found %s clouds but none of them is set as default' % (
+ num_of_clouds),
+ importance=2, details=[
+ 'Please, choose one of the following cloud names:',
+ ', '.join(_cnf.value.keys('cloud')),
+ 'To see all cloud settings:',
+ ' kamaki config get cloud.<cloud name>',
+ 'To set a default cloud:',
+ ' kamaki config set default_cloud <cloud name>',
+ 'To pick a cloud for the current session, use --cloud:',
+ ' kamaki --cloud=<cloud name> ...'])
+ if not cloud in _cnf.value.keys('cloud'):
+ raise CLIError(
+ 'No cloud%s is configured' % ((' "%s"' % cloud) if cloud else ''),
+ importance=3, details=[
+ 'To configure a new cloud "%s", find and set the' % (
+ cloud or '<cloud name>'),
+ 'single authentication URL and token:',
+ ' kamaki config set cloud.%s.url <URL>' % (
+ cloud or '<cloud name>'),
+ ' kamaki config set cloud.%s.token <t0k3n>' % (
+ cloud or '<cloud name>')])
+ auth_args = dict()
+ for term in ('url', 'token'):
+ try:
+ auth_args[term] = _cnf.get_cloud(cloud, term)
+ except KeyError:
+ auth_args[term] = ''
+ if not auth_args[term]:
+ raise CLIError(
+ 'No authentication %s provided for cloud "%s"' % (term, cloud),
+ importance=3, details=[
+ 'Set a %s for cloud %s:' % (term, cloud),
+ ' kamaki config set cloud.%s.%s <%s>' % (
+ cloud, term, term)])
+
+ from kamaki.clients.astakos import AstakosClient as AuthCachedClient
+ try:
+ return AuthCachedClient(auth_args['url'], auth_args['token']), cloud
+ except AssertionError as ae:
+ kloger.warning('WARNING: Failed to load authenticator [%s]' % ae)
+ return None, cloud