Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / commands / snf-astakos.py @ f17d6cb5

History | View | Annotate | Download (15.2 kB)

1
# Copyright 2013 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.command
33

    
34
from json import loads
35

    
36
from astakosclient import AstakosClient, AstakosClientException
37

    
38
from kamaki.cli import command
39
from kamaki.cli.errors import CLIBaseUrlError
40
from kamaki.cli.commands import (
41
    _command_init, errors, _optional_json, addLogSettings)
42
from kamaki.cli.command_tree import CommandTree
43
from kamaki.cli.utils import print_dict, format_size
44
from kamaki.cli.argument import FlagArgument, ValueArgument
45
from kamaki.cli.argument import CommaSeparatedListArgument
46
from kamaki.cli.logger import get_logger
47

    
48
snfastakos_cmds = CommandTree('astakos', 'astakosclient CLI')
49
_commands = [snfastakos_cmds]
50

    
51

    
52
def astakoserror(foo):
53
    def _raise(self, *args, **kwargs):
54
        try:
55
            return foo(self, *args, **kwargs)
56
        except AstakosClientException as ace:
57
            try:
58
                ace.details = ['%s' % ace.details]
59
            except Exception:
60
                pass
61
            finally:
62
                raise ace
63
    return _raise
64

    
65

    
66
class _astakos_init(_command_init):
67

    
68
    def __init__(self, arguments=dict(), auth_base=None, cloud=None):
69
        super(_astakos_init, self).__init__(arguments, auth_base, cloud)
70
        self['token'] = ValueArgument('Custom token', '--token')
71

    
72
    @errors.generic.all
73
    @astakoserror
74
    @addLogSettings
75
    def _run(self):
76
        self.cloud = self.cloud if self.cloud else 'default'
77
        self.token = self['token'] or self._custom_token('astakos')\
78
            or self.config.get_cloud(self.cloud, 'token')
79
        if getattr(self, 'auth_base', False):
80
            astakos_endpoints = self.auth_base.get_service_endpoints(
81
                self._custom_type('astakos') or 'identity',
82
                self._custom_version('astakos') or '')
83
            base_url = astakos_endpoints['SNF:uiURL']
84
            base_url = base_url[:-3]
85
            #base_url = ''.join(base_url.split('/ui'))
86
        else:
87
            base_url = self._custom_url('astakos')
88
        if not base_url:
89
            raise CLIBaseUrlError(service='astakos')
90
        self.client = AstakosClient(
91
            base_url, logger=get_logger('kamaki.clients'))
92

    
93
    def main(self):
94
        self._run()
95

    
96

    
97
@command(snfastakos_cmds)
98
class astakos_user_info(_astakos_init, _optional_json):
99
    """Authenticate a user
100
    Get user information (e.g. unique account name) from token
101
    Token should be set in settings:
102
    *  check if a token is set    /config get cloud.default.token
103
    *  permanently set a token    /config set cloud.default.token <token>
104
    Token can also be provided as a parameter
105
    (To use a named cloud, use its name instead of "default")
106
    """
107

    
108
    arguments = dict(
109
        usage=FlagArgument('also return usage information', ('--with-usage'))
110
    )
111

    
112
    @errors.generic.all
113
    @astakoserror
114
    def _run(self):
115
        self._print(
116
            self.client.get_user_info(self.token, self['usage']), print_dict)
117

    
118
    def main(self):
119
        super(self.__class__, self)._run()
120
        self._run()
121

    
122

    
123
@command(snfastakos_cmds)
124
class astakos_user_name(_astakos_init, _optional_json):
125
    """Get username(s) from uuid(s)"""
126

    
127
    arguments = dict(
128
        service_token=ValueArgument(
129
            'Use service token instead', '--service-token')
130
    )
131

    
132
    @errors.generic.all
133
    @astakoserror
134
    def _run(self, uuids):
135
        assert uuids and isinstance(uuids, list), 'No valid uuids'
136
        if 1 == len(uuids):
137
            self._print(self.client.get_username(self.token, uuids[0]))
138
        else:
139
            self._print(
140
                self.client.get_username(self.token, uuids), print_dict)
141

    
142
    def main(self, uuid, *more_uuids):
143
        super(self.__class__, self)._run()
144
        self._run([uuid] + list(more_uuids))
145

    
146

    
147
@command(snfastakos_cmds)
148
class astakos_user_uuid(_astakos_init, _optional_json):
149
    """Get uuid(s) from username(s)"""
150

    
151
    @errors.generic.all
152
    @astakoserror
153
    def _run(self, usernames):
154
        assert usernames and isinstance(usernames, list), 'No valid usernames'
155
        if 1 == len(usernames):
156
            self._print(self.client.get_uuid(self.token, usernames[0]))
157
        else:
158
            self._print(
159
                self.client.get_uuids(self.token, usernames), print_dict)
160

    
161
    def main(self, usernames, *more_usernames):
162
        super(self.__class__, self)._run()
163
        self._run([usernames] + list(more_usernames))
164

    
165

    
166
@command(snfastakos_cmds)
167
class astakos_quotas(_astakos_init, _optional_json):
168
    """Get user (or service) quotas"""
169

    
170
    @staticmethod
171
    def _print_with_format(d):
172
        """ Print d with size formating when needed
173
        :param d: (dict) {system: {<service>: {usage: ..., limit: ..., }, ...}}
174
        """
175
        newd = dict()
176
        for k, service in d['system'].items():
177
            newd[k] = dict(service)
178
            for term in ('usage', 'limit'):
179
                if term in service:
180
                    newd[k][term] = format_size(service[term])
181
        print_dict(newd)
182

    
183
    @errors.generic.all
184
    @astakoserror
185
    def _run(self):
186
            self._print(
187
                self.client.get_quotas(self.token), self._print_with_format)
188

    
189
    def main(self):
190
        super(self.__class__, self)._run()
191
        self._run()
192

    
193

    
194
@command(snfastakos_cmds)
195
class astakos_services(_astakos_init):
196
    """Astakos operations filtered by services"""
197

    
198

    
199
@command(snfastakos_cmds)
200
class astakos_services_list(_astakos_init, _optional_json):
201
    """List available services"""
202

    
203
    @errors.generic.all
204
    @astakoserror
205
    def _run(self):
206
        self._print(self.client.get_services())
207

    
208
    def main(self):
209
        super(self.__class__, self)._run()
210
        self._run()
211

    
212

    
213
@command(snfastakos_cmds)
214
class astakos_services_username(_astakos_init, _optional_json):
215
    """Get service username(s) from uuid(s)"""
216

    
217
    @errors.generic.all
218
    @astakoserror
219
    def _run(self, stoken, uuids):
220
        assert uuids and isinstance(uuids, list), 'No valid uuids'
221
        if 1 == len(uuids):
222
            self._print(self.client.service_get_username(stoken, uuids[0]))
223
        else:
224
            self._print(
225
                self.client.service_get_usernames(stoken, uuids), print_dict)
226

    
227
    def main(self, service_token, uuid, *more_uuids):
228
        super(self.__class__, self)._run()
229
        self._run(service_token, [uuid] + list(more_uuids))
230

    
231

    
232
@command(snfastakos_cmds)
233
class astakos_services_uuid(_astakos_init, _optional_json):
234
    """Get service uuid(s) from username(s)"""
235

    
236
    @errors.generic.all
237
    @astakoserror
238
    def _run(self, stoken, usernames):
239
        assert usernames and isinstance(usernames, list), 'No valid usernames'
240
        if 1 == len(usernames):
241
            self._print(self.client.service_get_uuid(self.token, usernames[0]))
242
        else:
243
            self._print(
244
                self.client.service_get_uuids(self.token, usernames),
245
                print_dict)
246

    
247
    def main(self, service_token, usernames, *more_usernames):
248
        super(self.__class__, self)._run()
249
        self._run(service_token, [usernames] + list(more_usernames))
250

    
251

    
252
@command(snfastakos_cmds)
253
class astakos_services_quotas(_astakos_init, _optional_json):
254
    """Get user (or service) quotas"""
255

    
256
    arguments = dict(
257
        uuid=ValueArgument('A user unique id to get quotas for', '--uuid')
258
    )
259

    
260
    @errors.generic.all
261
    @astakoserror
262
    def _run(self, stoken):
263
        self._print(self.client.service_get_quotas(stoken, self['uuid']))
264

    
265
    def main(self, service_token):
266
        super(self.__class__, self)._run()
267
        self._run(service_token)
268

    
269

    
270
@command(snfastakos_cmds)
271
class astakos_resources(_astakos_init, _optional_json):
272
    """List user resources"""
273

    
274
    @errors.generic.all
275
    @astakoserror
276
    def _run(self):
277
        self._print(self.client.get_resources(), print_dict)
278

    
279
    def main(self):
280
        super(self.__class__, self)._run()
281
        self._run()
282

    
283

    
284
@command(snfastakos_cmds)
285
class astakos_feedback(_astakos_init):
286
    """Send feedback to astakos server"""
287

    
288
    @errors.generic.all
289
    @astakoserror
290
    def _run(self, msg, more_info=None):
291
        self.client.send_feedback(self.token, msg, more_info or '')
292

    
293
    def main(self, message, more_info=None):
294
        super(self.__class__, self)._run()
295
        self._run(message, more_info)
296

    
297

    
298
@command(snfastakos_cmds)
299
class astakos_endpoints(_astakos_init, _optional_json):
300
    """Get endpoints service endpoints"""
301

    
302
    arguments = dict(uuid=ValueArgument('User uuid', '--uuid'))
303

    
304
    @errors.generic.all
305
    @astakoserror
306
    def _run(self):
307
        self._print(
308
            self.client.get_endpoints(self.token, self['uuid']),
309
            print_dict)
310

    
311
    def main(self):
312
        super(self.__class__, self)._run()
313
        self._run()
314

    
315

    
316
@command(snfastakos_cmds)
317
class astakos_commission(_astakos_init):
318
    """Manage commissions (special privileges required)"""
319

    
320

    
321
@command(snfastakos_cmds)
322
class astakos_commission_pending(_astakos_init, _optional_json):
323
    """List pending commissions (special privileges required)"""
324

    
325
    @errors.generic.all
326
    @astakoserror
327
    def _run(self):
328
        self._print(self.client.get_pending_commissions(self.token))
329

    
330
    def main(self):
331
        super(self.__class__, self)._run()
332
        self._run()
333

    
334

    
335
@command(snfastakos_cmds)
336
class astakos_commission_info(_astakos_init, _optional_json):
337
    """Get commission info (special privileges required)"""
338

    
339
    @errors.generic.all
340
    @astakoserror
341
    def _run(self, commission_id):
342
        commission_id = int(commission_id)
343
        self._print(
344
            self.client.get_commission_info(self.token, commission_id),
345
            print_dict)
346

    
347
    def main(self, commission_id):
348
        super(self.__class__, self)._run()
349
        self._run(commission_id)
350

    
351

    
352
@command(snfastakos_cmds)
353
class astakos_commission_action(_astakos_init, _optional_json):
354
    """Invoke an action in a commission (special privileges required)
355
    Actions can be accept or reject
356
    """
357

    
358
    actions = ('accept', 'reject')
359

    
360
    @errors.generic.all
361
    @astakoserror
362
    def _run(self, commission_id, action):
363
        commission_id = int(commission_id)
364
        action = action.lower()
365
        assert action in self.actions, 'Actions can be %s' % (
366
            ' or '.join(self.actions))
367
        self._print(
368
            self.client.commission_acction(self.token, commission_id, action),
369
            print_dict)
370

    
371
    def main(self, commission_id, action):
372
        super(self.__class__, self)._run()
373
        self._run(commission_id, action)
374

    
375

    
376
@command(snfastakos_cmds)
377
class astakos_commission_accept(_astakos_init):
378
    """Accept a pending commission  (special privileges required)"""
379

    
380
    @errors.generic.all
381
    @astakoserror
382
    def _run(self, commission_id):
383
        commission_id = int(commission_id)
384
        self.client.accept_commission(self.token, commission_id)
385

    
386
    def main(self, commission_id):
387
        super(self.__class__, self)._run()
388
        self._run(commission_id)
389

    
390

    
391
@command(snfastakos_cmds)
392
class astakos_commission_reject(_astakos_init):
393
    """Reject a pending commission  (special privileges required)"""
394

    
395
    @errors.generic.all
396
    @astakoserror
397
    def _run(self, commission_id):
398
        commission_id = int(commission_id)
399
        self.client.reject_commission(self.token, commission_id)
400

    
401
    def main(self, commission_id):
402
        super(self.__class__, self)._run()
403
        self._run(commission_id)
404

    
405

    
406
@command(snfastakos_cmds)
407
class astakos_commission_resolve(_astakos_init, _optional_json):
408
    """Resolve multiple commissions  (special privileges required)"""
409

    
410
    arguments = dict(
411
        accept=CommaSeparatedListArgument(
412
            'commission ids to accept (e.g. --accept=11,12,13,...',
413
            '--accept'),
414
        reject=CommaSeparatedListArgument(
415
            'commission ids to reject (e.g. --reject=11,12,13,...',
416
            '--reject'),
417
    )
418

    
419
    @errors.generic.all
420
    @astakoserror
421
    def _run(self):
422
        print 'accepted ', self['accept']
423
        print 'rejected ', self['reject']
424
        self._print(
425
            self.client.resolve_commissions(
426
                self.token, self['accept'], self['reject']),
427
            print_dict)
428

    
429
    def main(self):
430
        super(self.__class__, self)._run()
431
        self._run()
432

    
433

    
434
@command(snfastakos_cmds)
435
class astakos_commission_issue(_astakos_init, _optional_json):
436
    """Issue commissions as a json string (special privileges required)
437
    Parameters:
438
    holder      -- user's id (string)
439
    source      -- commission's source (ex system) (string)
440
    provisions  -- resources with their quantity (json-dict from string to int)
441
    name        -- description of the commission (string)
442
    """
443

    
444
    arguments = dict(
445
        force=FlagArgument('Force commission', '--force'),
446
        accept=FlagArgument('Do not wait for verification', '--accept')
447
    )
448

    
449
    @errors.generic.all
450
    @astakoserror
451
    def _run(
452
            self, holder, source, provisions, name=''):
453
        provisions = loads(provisions)
454
        self._print(self.client.issue_one_commission(
455
            self.token, holder, source, provisions, name,
456
            self['force'], self['accept']))
457

    
458
    def main(self, holder, source, provisions, name=''):
459
        super(self.__class__, self)._run()
460
        self._run(holder, source, provisions, name)
461

    
462

    
463
@command(snfastakos_cmds)
464
class astakos_commission_issuejson(_astakos_init, _optional_json):
465
    """Issue commissions as a json string (special privileges required)"""
466

    
467
    @errors.generic.all
468
    @astakoserror
469
    def _run(self, info_json):
470
        infodict = loads(info_json)
471
        self._print(self.client.issue_commission(self.token, infodict))
472

    
473
    def main(self, info_json):
474
        super(self.__class__, self)._run()
475
        self._run(info_json)
476

    
477
# XXX issue_commission, issue_one_commission
478

    
479

    
480
@command(snfastakos_cmds)
481
class astakos_test(_astakos_init):
482
    """Test an astakos command"""
483

    
484
    @errors.generic.all
485
    @astakoserror
486
    def _run(self, *args):
487
        r = self.client.get_pending_commissions(self.token)
488
        print r
489

    
490
    def main(self, *args):
491
        super(self.__class__, self)._run()
492
        self._run(*args)