commit 8cec3671de66efb93628e29fe060e57aa5abe8e4
Author: Stavros Sachtouris <saxtouri@admin.grnet.gr>
Date:   Mon Jun 3 14:22:58 2013 +0300

    Use explicitely set services urls if no auth_url
    
    Refs: #3874
    
    In current configuration, kamaki checks for auth_url. If that fails,
    it raises an error. If it is not set, it prints a warning and attempts
    to read the <service>.url option from the configuration file.
    
    Service urls: astakos.url, pithos.url, cyclades.url, plankton.url

diff --git a/kamaki/cli/__init__.py b/kamaki/cli/__init__.py
index 939891f..a2916ea 100644
--- a/kamaki/cli/__init__.py
+++ b/kamaki/cli/__init__.py
@@ -226,7 +226,12 @@ def _init_session(arguments):
         global_url = _cnf.get('global', 'auth_url')
     global_token = _cnf.get('global', 'token')
     from kamaki.clients.astakos import AstakosClient as AuthCachedClient
-    return AuthCachedClient(global_url, global_token)
+    try:
+        return AuthCachedClient(global_url, global_token)
+    except AssertionError as ae:
+        kloger.warning('WARNING: Failed to load auth_url %s [ %s ]' % (
+            global_url, ae))
+        return None
 
 
 def _load_spec_module(spec, arguments, module):
diff --git a/kamaki/cli/command_shell.py b/kamaki/cli/command_shell.py
index f464ac8..4e1dfd8 100644
--- a/kamaki/cli/command_shell.py
+++ b/kamaki/cli/command_shell.py
@@ -164,6 +164,7 @@ class Shell(Cmd):
     def _create_help_method(cmd_name, args, descr, syntax):
         tmp_args = dict(args)
         tmp_args.pop('options', None)
+        tmp_args.pop('cloud', None)
         tmp_args.pop('debug', None)
         tmp_args.pop('verbose', None)
         tmp_args.pop('include', None)
diff --git a/kamaki/cli/commands/astakos.py b/kamaki/cli/commands/astakos.py
index c395625..bc8b770 100644
--- a/kamaki/cli/commands/astakos.py
+++ b/kamaki/cli/commands/astakos.py
@@ -32,9 +32,10 @@
 # or implied, of GRNET S.A.command
 
 from kamaki.cli import command
-#from kamaki.clients.astakos import AstakosClient
+from kamaki.clients.astakos import AstakosClient
 from kamaki.cli.commands import _command_init, errors, _optional_json
 from kamaki.cli.command_tree import CommandTree
+from kamaki.cli.errors import CLIBaseUrlError
 
 user_cmds = CommandTree('user', 'Astakos API commands')
 _commands = [user_cmds]
@@ -49,7 +50,16 @@ class _user_init(_command_init):
         #    or self.config.get('global', 'token')
         #base_url = self.config.get('global', 'url')
         #self.client = AstakosClient(base_url=base_url, token=token)
-        self.client = self.auth_base
+        if getattr(self, 'auth_base', False):
+            self.client = self.auth_base
+        else:
+            token = self.config.get('astakos', 'token')\
+                or self.config.get('global', 'token')
+            base_url = 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()
 
@@ -71,7 +81,7 @@ class user_authenticate(_user_init, _optional_json):
     @errors.user.authenticate
     def _run(self, custom_token=None):
         super(self.__class__, self)._run()
-        r = self.auth_base.authenticate(custom_token)
+        r = self.client.authenticate(custom_token)
         self._print([r], title=('uuid', 'name',), with_redundancy=True)
 
     def main(self, custom_token=None):
diff --git a/kamaki/cli/commands/cyclades.py b/kamaki/cli/commands/cyclades.py
index 7a3ab32..6cdb37f 100644
--- a/kamaki/cli/commands/cyclades.py
+++ b/kamaki/cli/commands/cyclades.py
@@ -34,7 +34,7 @@
 from kamaki.cli import command
 from kamaki.cli.command_tree import CommandTree
 from kamaki.cli.utils import print_dict
-from kamaki.cli.errors import raiseCLIError, CLISyntaxError
+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
@@ -70,10 +70,17 @@ class _init_cyclades(_command_init):
     def _run(self, service='compute'):
         token = self.config.get(service, 'token')\
             or self.config.get('global', 'token')
-        cyclades_endpoints = self.auth_base.get_service_endpoints(
-            self.config.get('cyclades', 'type'),
-            self.config.get('cyclades', 'version'))
-        base_url = cyclades_endpoints['publicURL']
+
+        if getattr(self, 'auth_base', False):
+            cyclades_endpoints = self.auth_base.get_service_endpoints(
+                self.config.get('cyclades', 'type'),
+                self.config.get('cyclades', 'version'))
+            base_url = cyclades_endpoints['publicURL']
+        else:
+            base_url = 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()
diff --git a/kamaki/cli/commands/image.py b/kamaki/cli/commands/image.py
index 5d6b28a..1006656 100644
--- a/kamaki/cli/commands/image.py
+++ b/kamaki/cli/commands/image.py
@@ -45,7 +45,7 @@ from kamaki.clients import ClientError
 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
+from kamaki.cli.errors import raiseCLIError, CLIBaseUrlError
 from kamaki.cli.commands import _command_init, errors
 from kamaki.cli.commands import _optional_output_cmd, _optional_json
 
@@ -75,15 +75,18 @@ class _init_image(_command_init):
     @errors.generic.all
     def _run(self):
         token = self.config.get('image', 'token')\
-            or self.config.get('compute', 'token')\
             or self.config.get('global', 'token')
-        plankton_endpoints = self.auth_base.get_service_endpoints(
-            self.config.get('plankton', 'type'),
-            self.config.get('plankton', 'version'))
-        base_url = plankton_endpoints['publicURL']
-        #base_url = self.config.get('image', 'url')\
-        #    or self.config.get('compute', 'url')\
-        #    or self.config.get('global', 'url')
+
+        if getattr(self, 'auth_base', False):
+            plankton_endpoints = self.auth_base.get_service_endpoints(
+                self.config.get('plankton', 'type'),
+                self.config.get('plankton', 'version'))
+            base_url = plankton_endpoints['publicURL']
+        else:
+            base_url = 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()
diff --git a/kamaki/cli/commands/pithos.py b/kamaki/cli/commands/pithos.py
index 525f1ee..72a99fb 100644
--- a/kamaki/cli/commands/pithos.py
+++ b/kamaki/cli/commands/pithos.py
@@ -37,7 +37,7 @@ from os import path, makedirs, walk
 
 from kamaki.cli import command
 from kamaki.cli.command_tree import CommandTree
-from kamaki.cli.errors import raiseCLIError, CLISyntaxError
+from kamaki.cli.errors import raiseCLIError, CLISyntaxError, CLIBaseUrlError
 from kamaki.cli.utils import (
     format_size, to_bytes, print_dict, print_items, pretty_keys, pretty_dict,
     page_hold, bold, ask_user, get_path_size, print_json)
@@ -147,17 +147,23 @@ class _pithos_init(_command_init):
     @staticmethod
     def _is_dir(remote_dict):
         return 'application/directory' == remote_dict.get(
-            'content_type',
-            remote_dict.get('content-type', ''))
+            'content_type', remote_dict.get('content-type', ''))
 
     @errors.generic.all
     def _run(self):
         self.token = self.config.get('file', 'token')\
             or self.config.get('global', 'token')
-        pithos_endpoints = self.auth_base.get_service_endpoints(
-            self.config.get('pithos', 'type'),
-            self.config.get('pithos', 'version'))
-        self.base_url = pithos_endpoints['publicURL']
+
+        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('pithos', 'url')
+        if not self.base_url:
+            raise CLIBaseUrlError(service='pithos')
+
         self._set_account()
         self.container = self.config.get('file', 'container')\
             or self.config.get('global', 'container')
diff --git a/kamaki/cli/errors.py b/kamaki/cli/errors.py
index 57e2560..6da31a3 100644
--- a/kamaki/cli/errors.py
+++ b/kamaki/cli/errors.py
@@ -55,6 +55,23 @@ class CLIError(Exception):
             self.importance = 0
 
 
+class CLIBaseUrlError(CLIError):
+    def __init__(self, message='', details=[], importance=2, service=None):
+        message = message or 'No url for %s' % service.lower()
+        details = details or [
+            'Two options to resolve this:',
+            'A. (recommended) Let kamaki discover the endpoint URLs for all',
+            'services by setting a single Authentication URL:',
+            '  /config set auth_url <AUTH_URL>',
+            'B. (advanced users) Explicitly set a valid %s endpoint URL' % (
+                service.upper()),
+            'Note: auth_url option has a higher priority, so delete it to',
+            'make that work',
+            '  /config delete auth_url',
+            '  /config set %s.url <%s_URL>' % (service, service.upper())]
+        super(CLIBaseUrlError, self).__init__(message, details, importance)
+
+
 class CLISyntaxError(CLIError):
     def __init__(self, message='Syntax Error', details=[], importance=1):
         super(CLISyntaxError, self).__init__(message, details, importance)
diff --git a/kamaki/clients/astakos/__init__.py b/kamaki/clients/astakos/__init__.py
index c1599de..5eeae6b 100644
--- a/kamaki/clients/astakos/__init__.py
+++ b/kamaki/clients/astakos/__init__.py
@@ -53,7 +53,9 @@ class AstakosClient(Client):
         :returns: (dict) authentication information
         """
         self.token = token or self.token
-        self._cache[self.token] = self.post('/tokens').json
+        body = dict(auth=dict(token=dict(id=self.token)))
+        self.set_headers('content-type', 'application/json')
+        self._cache[self.token] = self.post('/tokens', data=body).json
         return self._cache[self.token]
 
     def get_services(self, token=None):
