commit b4f69041244d25c332e7291961503efc328285c9
Author: Stavros Sachtouris <saxtouri@admin.grnet.gr>
Date:   Thu Jun 6 17:29:43 2013 +0300

    Adjust all command specs to multicloud/singleauth
    
    Refs: #3934

diff --git a/kamaki/cli/commands/__init__.py b/kamaki/cli/commands/__init__.py
index 10ddfa4..64abc32 100644
--- a/kamaki/cli/commands/__init__.py
+++ b/kamaki/cli/commands/__init__.py
@@ -38,6 +38,25 @@ from kamaki.cli.argument import FlagArgument
 log = get_logger(__name__)
 
 
+def DontRaiseKeyError(foo):
+    def wrap(*args, **kwargs):
+        try:
+            return foo(*args, **kwargs)
+        except KeyError:
+            return None
+    return wrap
+
+
+def addLogSettings(foo):
+    def wrap(self, *args, **kwargs):
+        try:
+            return foo(self, *args, **kwargs)
+        finally:
+            self._set_log_params()
+            self._update_max_threads
+    return wrap
+
+
 class _command_init(object):
 
     def __init__(self, arguments={}, auth_base=None, cloud=None):
@@ -55,6 +74,22 @@ class _command_init(object):
         self.auth_base = auth_base or getattr(self, 'auth_base', None)
         self.cloud = cloud or getattr(self, 'cloud', None)
 
+    @DontRaiseKeyError
+    def _custom_url(self, service):
+        return self.config.get_remote(self.cloud, '%s_url' % service)
+
+    @DontRaiseKeyError
+    def _custom_token(self, service):
+        return self.config.get_remote(self.cloud, '%s_token' % service)
+
+    @DontRaiseKeyError
+    def _custom_type(self, service):
+        return self.config.get_remote(self.cloud, '%s_type' % service)
+
+    @DontRaiseKeyError
+    def _custom_version(self, service):
+        return self.config.get_remote(self.cloud, '%s_version' % service)
+
     def _set_log_params(self):
         try:
             self.client.LOG_TOKEN, self.client.LOG_DATA = (
@@ -65,14 +100,10 @@ class _command_init(object):
                 '%s\n defaults for token and data logging are off' % e)
 
     def _update_max_threads(self):
-        try:
+        if getattr(self, 'client', None):
             max_threads = int(self['config'].get_global('max_threads'))
             assert max_threads > 0
             self.client.MAX_THREADS = max_threads
-        except Exception as e:
-            log.warning('Failed to read custom thread settings: '
-                '%s, use default max threads (%s)' % (
-                    e, self.client.MAX_THREADS))
 
     def _safe_progress_bar(self, msg, arg='progress_bar'):
         """Try to get a progress bar, but do not raise errors"""
diff --git a/kamaki/cli/commands/astakos.py b/kamaki/cli/commands/astakos.py
index 0f3f375..bdf4cdf 100644
--- a/kamaki/cli/commands/astakos.py
+++ b/kamaki/cli/commands/astakos.py
@@ -33,7 +33,8 @@
 
 from kamaki.cli import command
 from kamaki.clients.astakos import AstakosClient
-from kamaki.cli.commands import _command_init, errors, _optional_json
+from kamaki.cli.commands import (
+    _command_init, errors, _optional_json, addLogSettings)
 from kamaki.cli.command_tree import CommandTree
 from kamaki.cli.errors import CLIBaseUrlError
 from kamaki.cli.utils import print_dict
@@ -46,21 +47,21 @@ class _user_init(_command_init):
 
     @errors.generic.all
     @errors.user.load
+    @addLogSettings
     def _run(self):
+        if getattr(self, 'cloud', False):
+            base_url = self._custom_url('astakos')
+            if base_url:
+                token = self._custom_token('astakos')\
+                    or self.config.get_remote(self.cloud, 'token')
+                self.client = AstakosClient(base_url=base_url, token=token)
+                return
+        else:
+            self.cloud = 'default'
         if getattr(self, 'auth_base', False):
             self.client = self.auth_base
-        else:
-            token = self.config.get('user', 'token')\
-                or self.config.get('astakos', 'token')\
-                or self.config.get('global', 'token')
-            base_url = self.config.get('user', 'url')\
-                or self.config.get('astakos', 'url')
-            if not base_url:
-                raise CLIBaseUrlError(service='astakos')
-            self.client = AstakosClient(base_url=base_url, token=token)
-
-        self._set_log_params()
-        self._update_max_threads()
+            return
+        raise CLIBaseUrlError(service='astakos')
 
     def main(self):
         self._run()
diff --git a/kamaki/cli/commands/cyclades.py b/kamaki/cli/commands/cyclades.py
index 052d4e2..2ee068a 100644
--- a/kamaki/cli/commands/cyclades.py
+++ b/kamaki/cli/commands/cyclades.py
@@ -38,7 +38,7 @@ from kamaki.cli.errors import raiseCLIError, CLISyntaxError, CLIBaseUrlError
 from kamaki.clients.cyclades import CycladesClient, ClientError
 from kamaki.cli.argument import FlagArgument, ValueArgument, KeyValueArgument
 from kamaki.cli.argument import ProgressBarArgument, DateArgument, IntArgument
-from kamaki.cli.commands import _command_init, errors
+from kamaki.cli.commands import _command_init, errors, addLogSettings
 from kamaki.cli.commands import _optional_output_cmd, _optional_json
 
 from base64 import b64encode
@@ -67,25 +67,30 @@ howto_personality = [
 
 class _init_cyclades(_command_init):
     @errors.generic.all
+    @addLogSettings
     def _run(self, service='compute'):
-        token = self.config.get(service, 'token')\
-            or self.config.get('global', 'token')
-
+        if getattr(self, 'cloud', None):
+            base_url = self._custom_url(service)\
+                or self._custom_url('cyclades')
+            if base_url:
+                token = self._custom_token(service)\
+                    or self._custom_token('cyclades')\
+                    or self.config.get_remote('token')
+                self.client = CycladesClient(
+                    base_url=base_url, token=token)
+                return
+        else:
+            self.cloud = 'default'
         if getattr(self, 'auth_base', False):
             cyclades_endpoints = self.auth_base.get_service_endpoints(
-                self.config.get('cyclades', 'type'),
-                self.config.get('cyclades', 'version'))
+                self._custom_type('cyclades') or 'compute',
+                self._custom_version('cyclades') or '')
             base_url = cyclades_endpoints['publicURL']
+            token = self.auth_base.token
+            self.client = CycladesClient(base_url=base_url, token=token)
         else:
-            base_url = self.config.get('compute', 'url')\
-                or self.config.get('cyclades', 'url')
-        if not base_url:
             raise CLIBaseUrlError(service='cyclades')
 
-        self.client = CycladesClient(base_url=base_url, token=token)
-        self._set_log_params()
-        self._update_max_threads()
-
     def main(self):
         self._run()
 
diff --git a/kamaki/cli/commands/image.py b/kamaki/cli/commands/image.py
index 434b529..5222226 100644
--- a/kamaki/cli/commands/image.py
+++ b/kamaki/cli/commands/image.py
@@ -46,7 +46,7 @@ from kamaki.cli.argument import FlagArgument, ValueArgument, KeyValueArgument
 from kamaki.cli.argument import IntArgument
 from kamaki.cli.commands.cyclades import _init_cyclades
 from kamaki.cli.errors import raiseCLIError, CLIBaseUrlError
-from kamaki.cli.commands import _command_init, errors
+from kamaki.cli.commands import _command_init, errors, addLogSettings
 from kamaki.cli.commands import _optional_output_cmd, _optional_json
 
 
@@ -73,25 +73,27 @@ log = getLogger(__name__)
 
 class _init_image(_command_init):
     @errors.generic.all
+    @addLogSettings
     def _run(self):
-        token = self.config.get('image', 'token')\
-            or self.config.get('plankton', 'token')\
-            or self.config.get('global', 'token')
-
+        if getattr(self, 'cloud', None):
+            img_url = self._custom_url('image') or self._custom_url('plankton')
+            if img_url:
+                token = self._custom_token('image')\
+                    or self._custom_token('plankton')\
+                    or self.config.get_remote(self.cloud, 'token')
+                self.client = ImageClient(base_url=img_url, token=token)
+                return
         if getattr(self, 'auth_base', False):
             plankton_endpoints = self.auth_base.get_service_endpoints(
-                self.config.get('image', 'type'),
-                self.config.get('image', 'version'))
+                self._custom_type('image')\
+                    or self._custom_type('plankton') or 'image',
+                self._custom_version('image')\
+                    or self._custom_version('plankton') or '')
             base_url = plankton_endpoints['publicURL']
+            token = self.auth_base.token
         else:
-            base_url = self.config.get('image', 'url')\
-                or self.config.get('plankton', 'url')
-        if not base_url:
             raise CLIBaseUrlError(service='plankton')
-
         self.client = ImageClient(base_url=base_url, token=token)
-        self._set_log_params()
-        self._update_max_threads()
 
     def main(self):
         self._run()
diff --git a/kamaki/cli/commands/pithos.py b/kamaki/cli/commands/pithos.py
index 28918e4..3bd0667 100644
--- a/kamaki/cli/commands/pithos.py
+++ b/kamaki/cli/commands/pithos.py
@@ -45,6 +45,7 @@ from kamaki.cli.argument import FlagArgument, ValueArgument, IntArgument
 from kamaki.cli.argument import KeyValueArgument, DateArgument
 from kamaki.cli.argument import ProgressBarArgument
 from kamaki.cli.commands import _command_init, errors
+from kamaki.cli.commands import addLogSettings, DontRaiseKeyError
 from kamaki.cli.commands import _optional_output_cmd, _optional_json
 from kamaki.clients.pithos import PithosClient, ClientError
 from kamaki.clients.astakos import AstakosClient
@@ -150,56 +151,66 @@ class _pithos_init(_command_init):
         return 'application/directory' == remote_dict.get(
             'content_type', remote_dict.get('content-type', ''))
 
+    @DontRaiseKeyError
+    def _custom_container(self):
+        return self.config.get_remote(self.cloud, 'pithos_container')
+
+    @DontRaiseKeyError
+    def _custom_uuid(self):
+        return self.config.get_remote(self.cloud, 'pithos_uuid')
+
+    def _set_account(self):
+        self.account = self._custom_uuid()
+        if self.account:
+            return
+        if getattr(self, 'auth_base', False):
+            self.account = self.auth_base.user_term('id', self.token)
+        else:
+            astakos_url = self._custom_url('astakos')
+            astakos_token = self._custom_token('astakos') or self.token
+            if not astakos_url:
+                raise CLIBaseUrlError(service='astakos')
+            astakos = AstakosClient(astakos_url, astakos_token)
+            self.account = astakos.user_term('id')
+
     @errors.generic.all
+    @addLogSettings
     def _run(self):
-        self.token = self.config.get('file', 'token')\
-            or self.config.get('global', 'token')
+        self.base_url = None
+        if getattr(self, 'cloud', None):
+            self.base_url = self._custom_url('pithos')
+        else:
+            self.cloud = 'default'
+        self.token = self._custom_token('pithos')
+        self.container = self._custom_container()
 
         if getattr(self, 'auth_base', False):
-            pithos_endpoints = self.auth_base.get_service_endpoints(
-                self.config.get('pithos', 'type'),
-                self.config.get('pithos', 'version'))
-            self.base_url = pithos_endpoints['publicURL']
-        else:
-            self.base_url = self.config.get('file', 'url')\
-                or self.config.get('store', 'url')\
-                or self.config.get('pithos', 'url')
-        if not self.base_url:
+            self.token = self.token or self.auth_base.token
+            if not self.base_url:
+                pithos_endpoints = self.auth_base.get_service_endpoints(
+                    self._custom_type('pithos') or 'object-store',
+                    self._custom_version('pithos') or '')
+                self.base_url = pithos_endpoints['publicURL']
+        elif not self.base_url:
             raise CLIBaseUrlError(service='pithos')
 
         self._set_account()
-        self.container = self.config.get('file', 'container')\
-            or self.config.get('store', 'container')\
-            or self.config.get('pithos', 'container')\
-            or self.config.get('global', 'container')
         self.client = PithosClient(
             base_url=self.base_url,
             token=self.token,
             account=self.account,
             container=self.container)
-        self._set_log_params()
-        self._update_max_threads()
 
     def main(self):
         self._run()
 
-    def _set_account(self):
-        if getattr(self, 'auth_base', False):
-            self.account = self.auth_base.user_term('id', self.token)
-        else:
-            astakos_url = self.config.get('user', 'url')\
-                or self.config.get('astakos', 'url')
-            if not astakos_url:
-                raise CLIBaseUrlError(service='astakos')
-            astakos = AstakosClient(astakos_url, self.token)
-            self.account = astakos.user_term('id')
-
 
 class _file_account_command(_pithos_init):
     """Base class for account level storage commands"""
 
-    def __init__(self, arguments={}, auth_base=None):
-        super(_file_account_command, self).__init__(arguments, auth_base)
+    def __init__(self, arguments={}, auth_base=None, cloud=None):
+        super(_file_account_command, self).__init__(
+            arguments, auth_base, cloud)
         self['account'] = ValueArgument(
             'Set user account (not permanent)', ('-A', '--account'))
 
@@ -221,8 +232,9 @@ class _file_container_command(_file_account_command):
     container = None
     path = None
 
-    def __init__(self, arguments={}, auth_base=None):
-        super(_file_container_command, self).__init__(arguments, auth_base)
+    def __init__(self, arguments={}, auth_base=None, cloud=None):
+        super(_file_container_command, self).__init__(
+            arguments, auth_base, cloud)
         self['container'] = ValueArgument(
             'Set container to work with (temporary)', ('-C', '--container'))
 
@@ -531,10 +543,10 @@ class _source_destination_command(_file_container_command):
         suffix_replace=ValueArgument('', '--suffix-to-replace', default=''),
     )
 
-    def __init__(self, arguments={}, auth_base=None):
+    def __init__(self, arguments={}, auth_base=None, cloud=None):
         self.arguments.update(arguments)
         super(_source_destination_command, self).__init__(
-            self.arguments, auth_base)
+            self.arguments, auth_base, cloud)
 
     def _run(self, source_container___path, path_is_optional=False):
         super(_source_destination_command, self)._run(
@@ -1455,8 +1467,8 @@ class file_delete(_file_container_command, _optional_output_cmd):
             ('-R', '--recursive'))
     )
 
-    def __init__(self, arguments={}, auth_base=None):
-        super(self.__class__, self).__init__(arguments, auth_base)
+    def __init__(self, arguments={}, auth_base=None, cloud=None):
+        super(self.__class__, self).__init__(arguments,  auth_base, cloud)
         self['delimiter'] = DelimiterArgument(
             self,
             parsed_name='--delimiter',
diff --git a/kamaki/cli/commands/snf-astakos.py b/kamaki/cli/commands/snf-astakos.py
index 47c245c..e12917c 100644
--- a/kamaki/cli/commands/snf-astakos.py
+++ b/kamaki/cli/commands/snf-astakos.py
@@ -35,7 +35,8 @@ from astakosclient import AstakosClient
 
 from kamaki.cli import command
 from kamaki.cli.errors import CLIBaseUrlError
-from kamaki.cli.commands import _command_init, errors, _optional_json
+from kamaki.cli.commands import (
+    _command_init, errors, _optional_json, addLogSettings)
 from kamaki.cli.command_tree import CommandTree
 from kamaki.cli.utils import print_dict
 from kamaki.cli.argument import FlagArgument, ValueArgument
@@ -50,29 +51,27 @@ log = add_stream_logger(__name__)
 
 class _astakos_init(_command_init):
 
-    def __init__(self, arguments=dict(), auth_base=None):
-        super(_astakos_init, self).__init__(arguments, auth_base)
+    def __init__(self, arguments=dict(), auth_base=None, cloud=None):
+        super(_astakos_init, self).__init__(arguments, auth_base, cloud)
         self['token'] = ValueArgument('Custom token', '--token')
 
     @errors.generic.all
     #@errors.user.load
+    @addLogSettings
     def _run(self):
-        self.token = self['token']\
-            or self.config.get('astakos', 'token')\
-            or self.config.get('user', 'token')\
-            or self.config.get('global', 'token')
+        self.cloud = self.cloud if self.cloud else 'default'
+        self.token = self['token'] or self._custom_token('astakos')\
+            or self.config.get_remote(self.cloud, 'token')
         if getattr(self, 'auth_base', False):
             astakos_endpoints = self.auth_base.get_service_endpoints(
-                self.config.get('astakos', 'type'),
-                self.config.get('astakos', 'version'))
+                self._custom_type('astakos') or 'identity',
+                self._custom_version('astakos') or '')
             base_url = astakos_endpoints['publicURL']
         else:
-            base_url = self.config.get('astakos', 'url')
+            base_url = self._custom_url('astakos')
         if not base_url:
             raise CLIBaseUrlError(service='astakos')
         self.client = AstakosClient(base_url, logger=log)
-        self._set_log_params()
-        self._update_max_threads()
 
     def main(self):
         self._run()
diff --git a/kamaki/cli/config.py b/kamaki/cli/config.py
index 6056ab7..2fbfe2c 100644
--- a/kamaki/cli/config.py
+++ b/kamaki/cli/config.py
@@ -192,6 +192,12 @@ class Config(RawConfigParser):
                             '... rescue %s.%s => remote.default.%s_%s' % (
                                 s, k, trn['serv'], k))
                         self.set_remote('default', 'pithos_%s' % k, v)
+                    elif (k in ('container', 'uuid')) and (
+                            trn['serv'] in ('pithos',)):
+                        print(
+                            '... rescue %s.%s => remote.default.pithos_%s' % (
+                                    s, k, k))
+                        self.set_remote('default', 'pithos_%s' % k, v)
                     elif v:
                         lost_terms.append('%s.%s = %s' % (s, k, v))
                 self.remove_section(s)
