Revision 7e18cd26

b/docs/developers/clients-api.rst
225 225

  
226 226
    user = AstakosClient(AUTHENTICATION_URL, TOKEN)
227 227

  
228
    cyclades_endpoints = user.get_endpoints('compute')
228
    cyclades_endpoints = user.get_service_endpoints('compute')
229 229
    CYCLADES_URL = cyclades_endpoints['publicURL']
230 230
    cyclades = CycladesClient(CYCLADES_URL, TOKEN)
231 231

  
......
255 255

  
256 256
    user = AstakosClient(AUTHENTICATION_URL, TOKEN)
257 257

  
258
    cyclades_endpoints = user.get_endpoints('compute')
258
    cyclades_endpoints = user.get_service_endpoints('compute')
259 259
    CYCLADES_URL = cyclades_endpoints['publicURL']
260 260
    cyclades = CycladesClient(CYCLADES_URL, TOKEN)
261 261

  
......
282 282
    astakos = AstakosClient(AUTHENTICATION_URL, TOKEN)
283 283
    USER_UUID = astakos.user_term('uuid')
284 284

  
285
    PITHOS_URL = astakos.get_endpoints('object-store')['publicURL']
285
    PITHOS_URL = astakos.get_service_endpoints('object-store')['publicURL']
286 286
    pithos = PithosClient(PITHOS_URL, TOKEN, USER_UUID, IMAGE_CONTAINER)
287 287

  
288
    IMAGE_URL = astakos.get_endpoints('image')['publicURL']
288
    IMAGE_URL = astakos.get_service_endpoints('image')['publicURL']
289 289
    plankton = ImageClient(IMAGE_URL, TOKEN)
290 290

  
291 291
    for img in pithos.list_objects():
b/kamaki/cli/__init__.py
157 157
                'No commend in %s (acts as cmd description)' % cls.__name__)
158 158
        _construct_command_syntax(cls)
159 159

  
160
        cmd_tree.add_command(cls_name, cls.description, cls)
160
        cmd_tree.add_command(
161
            cls_name, cls.description, cls, cls.long_description)
161 162
        return cls
162 163
    return wrap
163 164

  
b/kamaki/cli/command_tree/__init__.py
40 40
    subcommands = {}
41 41
    help = ' '
42 42

  
43
    def __init__(self, path, help=' ', subcommands={}, cmd_class=None):
43
    def __init__(
44
            self, path,
45
            help=' ', subcommands={}, cmd_class=None, long_help=''):
44 46
        assert path, 'Cannot initialize a command without a command path'
45 47
        self.path = path
46 48
        self.help = help or ''
47 49
        self.subcommands = dict(subcommands) if subcommands else {}
48 50
        self.cmd_class = cmd_class or None
51
        self.long_help = '%s' % (long_help or '')
49 52

  
50 53
    @property
51 54
    def name(self):
......
109 112

  
110 113
class CommandTree(object):
111 114

  
112
    def __init__(self, name, description=''):
115
    def __init__(self, name, description='', long_description=''):
113 116
        self.name = name
114 117
        self.description = description
118
        self.long_description = '%s' % (long_description or '')
115 119
        self.groups = dict()
116 120
        self._all_commands = dict()
117 121

  
......
119 123
        for group in groups_to_exclude:
120 124
            self.groups.pop(group, None)
121 125

  
122
    def add_command(self, command_path, description=None, cmd_class=None):
126
    def add_command(
127
            self, command_path,
128
            description=None, cmd_class=None, long_description=''):
123 129
        terms = command_path.split('_')
124 130
        try:
125 131
            cmd = self.groups[terms[0]]
......
139 145
                cmd = new_cmd
140 146
        cmd.cmd_class = cmd_class or None
141 147
        cmd.help = description or None
148
        cmd.long_help = long_description or cmd.long_help
142 149

  
143 150
    def find_best_match(self, terms):
144 151
        """Find a command that best matches a given list of terms
b/kamaki/cli/command_tree/test.py
45 45
                (None, '', 'cmd'),
46 46
                (None, '', 'Some help'),
47 47
                (None, '', {}, dict(cmd0a=None, cmd0b=None)),
48
                (None, command_tree.Command('cmd_cmd0'))):
49
            path, help, subcommands, cmd_class = args
48
                (None, command_tree.Command('cmd_cmd0')),
49
                (None, 'long description')):
50
            path, help, subcommands, cmd_class, long_help = args
50 51
            try:
51 52
                cmd = command_tree.Command(*args)
52 53
            except Exception as e:
......
57 58
            self.assertEqual(cmd.help, help or '')
58 59
            self.assertEqual(cmd.subcommands, subcommands or {})
59 60
            self.assertEqual(cmd.cmd_class, cmd_class or None)
61
            self.assertEqual(cmd.long_help, long_help or '')
60 62

  
61 63
    def test_name(self):
62 64
        for path in ('cmd', 'cmd_cmd0', 'cmd_cmd0_cmd1', '', None):
b/kamaki/cli/commands/image.py
402 402

  
403 403
@command(image_cmds)
404 404
class image_register(_init_image, _optional_json):
405
    """(Re)Register an image"""
405
    """(Re)Register an image file to an Image service
406
    The image file must be stored at a pithos repository
407
    Some metadata can be set by user (e.g. disk-format) while others are set
408
    only automatically (e.g. image id). There are also some custom user
409
    metadata, called properties.
410
    A register command creates a remote meta file at
411
       <container>:<image path>.meta
412
    Users may download and edit this file and use it to re-register one or more
413
    images.
414
    In case of a meta file, runtime arguments for metadata or properties
415
    override meta file settings.
416
    """
406 417

  
407 418
    container_info_cache = {}
408 419

  
409 420
    arguments = dict(
410
        checksum=ValueArgument('set image checksum', '--checksum'),
421
        checksum=ValueArgument('Set image checksum', '--checksum'),
411 422
        container_format=ValueArgument(
412
            'set container format',
423
            'Set container format',
413 424
            '--container-format'),
414
        disk_format=ValueArgument('set disk format', '--disk-format'),
415
        #owner=ValueArgument('set image owner (admin only)', '--owner'),
425
        disk_format=ValueArgument('Set disk format', '--disk-format'),
426
        owner_name=ValueArgument('Set user uuid by user name', '--owner-name'),
416 427
        properties=KeyValueArgument(
417
            'add property in key=value form (can be repeated)',
428
            'Add property (user-specified metadata) in key=value form'
429
            '(can be repeated)',
418 430
            ('-p', '--property')),
419
        is_public=FlagArgument('mark image as public', '--public'),
420
        size=IntArgument('set image size', '--size'),
431
        is_public=FlagArgument('Mark image as public', '--public'),
432
        size=IntArgument('Set image size in bytes', '--size'),
421 433
        metafile=ValueArgument(
422 434
            'Load metadata from a json-formated file <img-file>.meta :'
423 435
            '{"key1": "val1", "key2": "val2", ..., "properties: {...}"}',
424 436
            ('--metafile')),
425 437
        metafile_force=FlagArgument(
426
            'Store remote metadata object, even if it already exists',
427
            ('-f', '--force')),
438
            'Overide remote metadata file', ('-f', '--force')),
428 439
        no_metafile_upload=FlagArgument(
429 440
            'Do not store metadata in remote meta file',
430 441
            ('--no-metafile-upload')),
......
511 522
                'No image file location provided',
512 523
                importance=2, details=[
513 524
                    'An image location is needed. Image location format:',
514
                    '  pithos://<user-id>/<container>/<path>',
525
                    '  <container>:<path>',
515 526
                    ' where an image file at the above location must exist.'
516 527
                    ] + howto_image_file)
517 528
        try:
......
521 532
                ae, 'Invalid image location format',
522 533
                importance=1, details=[
523 534
                    'Valid image location format:',
524
                    '  pithos://<user-id>/<container>/<img-file-path>'
535
                    '  <container>:<img-file-path>'
525 536
                    ] + howto_image_file)
526 537

  
538
    @staticmethod
539
    def _old_location_format(location):
540
        prefix = 'pithos://'
541
        try:
542
            if location.startswith(prefix):
543
                uuid, sep, rest = location[len(prefix):].partition('/')
544
                container, sep, path = rest.partition('/')
545
                return (uuid, container, path)
546
        except Exception as e:
547
            raiseCLIError(e, 'Invalid location format', details=[
548
                'Correct location format:', '  <container>:<image path>'])
549
        return ()
550

  
527 551
    def _mine_location(self, container_path):
528
        uuid = self['uuid'] or self._get_user_id()
552
        old_response = self._old_location_format(container_path)
553
        if old_response:
554
            return old_response
555
        uuid = self['uuid'] or (self._username2uuid(self['owner_name']) if (
556
                    self['owner_name']) else self._get_user_id())
557
        if not uuid:
558
            if self['owner_name']:
559
                raiseCLIError('No user with username %s' % self['owner_name'])
560
            raiseCLIError('Failed to get user uuid', details=[
561
                'For details on current user:',
562
                '  /user whoami',
563
                'To authenticate a new user through a user token:',
564
                '  /user authenticate <token>'])
529 565
        if self['container']:
530 566
            return uuid, self['container'], container_path
531 567
        container, sep, path = container_path.partition(':')
b/kamaki/cli/one_command.py
92 92

  
93 93
    if _help or not cmd.is_command:
94 94
        parser.parser.print_help()
95
        if getattr(cmd, 'long_help', False):
96
            print 'Details:\n', cmd.long_help
95 97
        print_subcommands_help(cmd)
96 98
        exit(0)
97 99

  
b/kamaki/clients/__init__.py
122 122
            url += _encode(path[1:] if path.startswith('/') else path)
123 123
        delim = '?'
124 124
        for key, val in params.items():
125
            val = _encode(val)
125
            val = _encode(u'%s' % val)
126 126
            url += '%s%s%s' % (delim, key, ('=%s' % val) if val else '')
127 127
            delim = '&'
128 128
        parsed = urlparse(url)
b/kamaki/clients/astakos/__init__.py
32 32
# or implied, of GRNET S.A.
33 33

  
34 34
from logging import getLogger
35
from json import dumps
36 35

  
37 36
from kamaki.clients import Client, ClientError
38
from kamaki.clients.utils import path4url
39 37

  
40 38

  
41 39
class AstakosClient(Client):

Also available in: Unified diff