Revision 00336c85

b/Changelog
54 54
- Add a download_to_string method in pithos client [#3608]
55 55
- Add an upload_from_string method in pithos client [#3608]
56 56
- Add pithos client method create_container [#3756]
57
- Store image properties on remote location after image registration [#3769]
58
- Add runtime args to image register for forcing or unsettitng property
59
    storage [#3769]
57 60

  
b/kamaki/cli/commands/image.py
39 39
from kamaki.cli.command_tree import CommandTree
40 40
from kamaki.cli.utils import print_dict, print_items, print_json
41 41
from kamaki.clients.image import ImageClient
42
from kamaki.clients.pithos import PithosClient
43
from kamaki.clients.astakos import AstakosClient
44
from kamaki.clients import ClientError
42 45
from kamaki.cli.argument import FlagArgument, ValueArgument, KeyValueArgument
43 46
from kamaki.cli.argument import IntArgument
44 47
from kamaki.cli.commands.cyclades import _init_cyclades
45 48
from kamaki.cli.commands import _command_init, errors, _optional_output_cmd
49
from kamaki.cli.errors import raiseCLIError
46 50

  
47 51

  
48 52
image_cmds = CommandTree(
......
262 266
        #    ('-u', '--update')),
263 267
        json_output=FlagArgument('Show results in json', ('-j', '--json')),
264 268
        property_file=ValueArgument(
265
            'Load properties from a json-formated file. Contents:'
269
            'Load properties from a json-formated file <img-file>.meta :'
266 270
            '{"key1": "val1", "key2": "val2", ...}',
267
            ('--property-file'))
271
            ('--property-file')),
272
        prop_file_force=FlagArgument(
273
            'Store remote property object, even it already exists',
274
            ('-f', '--force-upload-property-file')),
275
        no_prop_file_upload=FlagArgument(
276
            'Do not store properties in remote property file',
277
            ('--no-property-file-upload')),
278
        container=ValueArgument(
279
            'Remote image container', ('-C', '--container')),
280
        fileowner=ValueArgument(
281
            'UUID of the user who owns the image file', ('--fileowner'))
268 282
    )
269 283

  
284
    def _get_uuid(self):
285
        uuid = self['fileowner'] or self.config.get('image', 'fileowner')
286
        if uuid:
287
            return uuid
288
        atoken = self.client.token
289
        user = AstakosClient(self.config.get('user', 'url'), atoken)
290
        return user.term('uuid')
291

  
292
    def _get_pithos_client(self, uuid, container):
293
        purl = self.config.get('file', 'url')
294
        ptoken = self.client.token
295
        return PithosClient(purl, ptoken, uuid, container)
296

  
297
    def _store_remote_property_file(self, pclient, remote_path, properties):
298
        return pclient.upload_from_string(
299
            remote_path, _validate_image_props(properties, return_str=True))
300

  
301
    def _get_container_path(self, container_path):
302
        container = self['container'] or self.config.get('image', 'container')
303
        if container:
304
            return container, container_path
305

  
306
        container, sep, path = container_path.partition(':')
307
        if not sep or not container or not path:
308
            raiseCLIError(
309
                '%s is not a valid pithos remote location' % container_path,
310
                details=[
311
                    'To set "image" as container and "my_dir/img.diskdump" as',
312
                    'the image path, try one of the following as '
313
                    'container:path',
314
                    '- <image container>:<remote path>',
315
                    '    e.g. image:/my_dir/img.diskdump',
316
                    '- <remote path> -C <image container>',
317
                    '    e.g. /my_dir/img.diskdump -C image'])
318
        return container, path
319

  
270 320
    @errors.generic.all
271 321
    @errors.plankton.connection
272
    def _run(self, name, location):
273
        if not location.startswith('pithos://'):
274
            account = self.config.get('file', 'account') \
275
                or self.config.get('global', 'account')
276
            assert account, 'No user account provided'
277
            if account[-1] == '/':
278
                account = account[:-1]
279
            container = self.config.get('file', 'container') \
280
                or self.config.get('global', 'container')
281
            if not container:
282
                location = 'pithos://%s/%s' % (account, location)
283
            else:
284
                location = 'pithos://%s/%s/%s' % (account, container, location)
322
    def _run(self, name, container_path):
323
        container, path = self._get_container_path(container_path)
324
        uuid = self._get_uuid()
325
        prop_path = '%s.meta' % path
326

  
327
        pclient = None if (
328
            self['no_prop_file_upload']) else self._get_pithos_client(
329
                uuid, container)
330
        if pclient and not self['prop_file_force']:
331
            try:
332
                pclient.get_object_info(prop_path)
333
                raiseCLIError('Property file %s: %s already exists' % (
334
                    container, prop_path))
335
            except ClientError as ce:
336
                if ce.status != 404:
337
                    raise
338

  
339
        location = 'pithos://%s/%s/%s' % (uuid, container, path)
285 340

  
286 341
        params = {}
287 342
        for key in set([
......
301 356
        printer = print_json if self['json_output'] else print_dict
302 357
        printer(self.client.register(name, location, params, properties))
303 358

  
304
    def main(self, name, location):
359
        if pclient:
360
            prop_headers = pclient.upload_from_string(
361
                prop_path, _validate_image_props(properties, return_str=True))
362
            print('Property file location is %s: %s' % (container, prop_path))
363
            print('\twith version %s' % prop_headers['x-object-version'])
364

  
365
    def main(self, name, container___path):
305 366
        super(self.__class__, self)._run()
306
        self._run(name, location)
367
        self._run(name, container___path)
307 368

  
308 369

  
309 370
@command(image_cmds)
b/kamaki/cli/commands/pithos.py
1645 1645
    """
1646 1646

  
1647 1647
    @errors.generic.all
1648
    def format_permition_dict(self, permissions):
1648
    def format_permission_dict(self, permissions):
1649 1649
        read = False
1650 1650
        write = False
1651 1651
        for perms in permissions:
......
1666 1666
    def _run(self, read, write):
1667 1667
        self._optional_output(self.client.set_object_sharing(
1668 1668
            self.path,
1669
            read_permition=read, write_permition=write))
1669
            read_permission=read, write_permission=write))
1670 1670

  
1671 1671
    def main(self, container___path, *permissions):
1672 1672
        super(self.__class__, self)._run(
1673 1673
            container___path,
1674 1674
            path_is_optional=False)
1675
        (read, write) = self.format_permition_dict(permissions)
1675
        (read, write) = self.format_permission_dict(permissions)
1676 1676
        self._run(read, write)
1677 1677

  
1678 1678

  
b/kamaki/clients/pithos/__init__.py
1236 1236

  
1237 1237
    def set_object_sharing(
1238 1238
            self, obj,
1239
            read_permition=False, write_permition=False):
1239
            read_permission=False, write_permission=False):
1240 1240
        """Give read/write permisions to an object.
1241 1241

  
1242 1242
        :param obj: (str) remote object path
1243 1243

  
1244
        :param read_permition: (list - bool) users and user groups that get
1245
            read permition for this object - False means all previous read
1244
        :param read_permission: (list - bool) users and user groups that get
1245
            read permission for this object - False means all previous read
1246 1246
            permissions will be removed
1247 1247

  
1248
        :param write_perimition: (list - bool) of users and user groups to get
1249
           write permition for this object - False means all previous write
1248
        :param write_permission: (list - bool) of users and user groups to get
1249
           write permission for this object - False means all previous write
1250 1250
           permissions will be removed
1251 1251

  
1252 1252
        :returns: (dict) response headers
1253 1253
        """
1254 1254

  
1255
        perms = dict(read=read_permition or '', write=write_permition or '')
1255
        perms = dict(read=read_permission or '', write=write_permission or '')
1256 1256
        r = self.object_post(obj, update=True, permissions=perms)
1257 1257
        return r.headers
1258 1258

  

Also available in: Unified diff