Revision 4067cdaf

b/docs/installation.rst
12 12
Ubuntu and Debian packages
13 13
^^^^^^^^^^^^^^^^^^^^^^^^^^
14 14

  
15
Max OS
15
Mac OS
16 16
------
17 17

  
18 18
Windows
b/docs/man/kamaki.rst
60 60
Options
61 61
-------
62 62

  
63
--help, -h              Show help message and exit.
64
-v                      Use verbose output.
65
-d                      Use debug output.
66
-o KEY=VAL              Override a config value (can be used multiple times)
63
.. code-block:: console
64

  
65
    --help, -h              Show help message and exit.
66
    -v                      Use verbose output.
67
    -d                      Use debug output.
68
    -o KEY=VAL              Override a config value (can be used multiple times)
67 69

  
68 70

  
69 71
Commands
b/docs/overview.rst
4 4
History
5 5
-------
6 6

  
7
Here, at the *Greek Research and Technology Network*, we have been developing an IaaS cloud management software called **synnefo** (or **+nefo**) that is accessed and managed via an extended OpenStack Compute API v1.1. Synnefo has been deployed in many environments to cover multiple needs. For example, the `~okeanos `_ IaaS service, running in our datacenters, is used to offer services for the Greek Research and Academic Community.
7
Here, at the *Greek Research and Technology Network*, we have been developing an IaaS cloud management software called **synnefo** (or **+nefo**) that is accessed and managed via an extended OpenStack Compute API v1.1. Synnefo has been deployed in many environments to cover multiple needs. For example, the `~okeanos <http://okeanos.grnet.gr>`_ IaaS service, running in our datacenters, is used to offer services for the Greek Research and Academic Community.
8 8

  
9 9
From the early start, we needed a simple command-line tool to test the OpenStack API. That's why we developed *kamaki*, which proved to be powerful and intuitive enough, to be used not only for testing purposes but also as a complete Openstack Compute API v1.1 client, able to manage our cloud from the command line.
10 10

  
b/docs/usage.rst
107 107
    $ kamaki store list mycontainer
108 108

  
109 109

  
110
    Example 3.1.1: List stored files in container mycontainer
110
    Example 3.1.1: List stored files in container mycontainer.
111 111

  
112 112
Example 2.3.2 showcases a command without parameters (the group is "server", the command is "list").
113 113

  
......
118 118
    $ kamaki server info 42
119 119

  
120 120

  
121
    Example 3.1.2: Show information about a user-managed VM with id 42
121
    Example 3.1.2 Show information about a user-managed VM with id 42
122 122

  
123 123
Client commands can feature an arbitarry number of terms:
124 124

  
......
134 134

  
135 135
    kamaki <group> <command> [arguments]
136 136

  
137
The commands supported in version 0.6.1 are described bellow, grouped by service. The examples showcase a sample set of group commands and were run in the kamaki interactive shell:
137
The commands supported in version 0.6.1 are described bellow, grouped by service. The examples showcase a sample set of group commands. The kamaki interactive shell has been chosen as the execution enviroment:
138 138

  
139 139
astakos (Identity Manager)
140 140
""""""""""""""""""""""""""
......
146 146
Showcase: get user information, provided the token was set
147 147

  
148 148
.. code-block:: console
149
    :emphasize-lines: 1, 2, 12
149
    :emphasize-lines: 3-11
150 150

  
151 151
    [kamaki]:astakos
152 152
    [astakos]:authenticate
......
172 172
Showcase: show details for flavor with id 43
173 173

  
174 174
.. code-block:: console
175
    :emphasize-lines: 1, 2, 9
175
    :emphasize-lines: 3-8
176 176

  
177 177
    [kamaki]: flavor
178 178
    [flavor]: info 43
......
208 208
Showcase: show a list of public images, list the properties of Debian Base
209 209

  
210 210
.. code-block:: console
211
    :emphasize-lines: 1, 2, 14, 23
211
    :emphasize-lines: 3-13,15-22
212 212

  
213 213
    [kamaki]:image
214 214
    [image]:list
......
260 260
Showcase: Create a server: Show create help, find a flavor and an image make a server. Wait for server to be build, get server details. Note that the progress bar feature is optional (see )
261 261

  
262 262
.. code-block:: console
263
    :emphasize-lines: 1, 2, 17, 34, 41, 57, 60, 67
263
    :emphasize-lines: 3-16,18-33,35-40,42-56,58,59,61-66
264 264

  
265 265
    [kamaki]:server
266 266
    [server]:create -h
......
279 279
      --config CONFIG       Path to configuration file
280 280
      -s, --silent          Do not output anything
281 281
    [server]:/image list
282
    1395fdfb-51b4-419f-bb02-f7d632860611 (Ubuntu Desktop LTS (Long Term Support))
283

  
282
    1395fdfb-51b4-419f-bb02-f7d632860611 (Ubuntu Desktop LTS)
284 283
    1580deb4-edb3-4496-a27f-7a246c4c0528 (Ubuntu Desktop)
285

  
286
    18a82962-43eb-4b32-8e28-8f8880af89d7 (Kubuntu LTS (Long Term Support))
287

  
288
    6aa6eafd-dccb-422d-a904-67fe2bdde87e (Debian Desktop)
289

  
290
    6b5681e4-7502-46ae-b1e9-9fd837932095 (maelstrom)
291

  
292
    78262ee7-949e-4d70-af3a-85360c3de57a (Windows Server 2012)
293
    86bc2414-0fb3-4898-a637-240292243302 (Fedora)
294
    926ab1c5-2d85-49d4-aebe-0fce712789b9 (Windows Server 2008)
295
    b2dffe52-64a4-48c3-8a4c-8214cc3165cf (Debian Base)
296
    baf2321c-57a0-4a69-825d-49f49cea163a (CentOS)
297
    c1d27b46-d875-4f5c-b7f1-f39b5af62905 (Kubuntu)
284
    |18a82962-43eb-4b32-8e28-8f8880af89d7 (Kubuntu LTS)
285
    |6aa6eafd-dccb-422d-a904-67fe2bdde87e (Debian Desktop)
286
    |6b5681e4-7502-46ae-b1e9-9fd837932095 (maelstrom)
287
    |78262ee7-949e-4d70-af3a-85360c3de57a (Windows Server 2012)
288
    |86bc2414-0fb3-4898-a637-240292243302 (Fedora)
289
    |926ab1c5-2d85-49d4-aebe-0fce712789b9 (Windows Server 2008)
290
    |b2dffe52-64a4-48c3-8a4c-8214cc3165cf (Debian Base)
291
    |baf2321c-57a0-4a69-825d-49f49cea163a (CentOS)
292
    |c1d27b46-d875-4f5c-b7f1-f39b5af62905 (Kubuntu)
298 293
    [server]:/flavor info 1
299 294
    SNF:disk_template:  drbd
300 295
    cpu              :  1
b/kamaki/clients/pithos.py
670 670
        read_permition=False,
671 671
        write_permition=False):
672 672
        """Give read/write permisions to an object.
673
           @param object is the object to change sharing permissions
674
 onto
675
           @param read_permition is a list of users and user groups that
676
                get read permition for this object
677
                False means all previous read permissions
678
 will be removed
679
           @param write_perimition is a list of users and user groups to
680
                get write permition for this object
681
                False means all previous read permissions
682
 will be removed
673
           @param object is the object to change sharing permissions onto
674
           @param read_permition is a list of users and user groups that get
675
           read permition for this object False means all previous read
676
           permissions will be removed
677
           @param write_perimition is a list of users and user groups to get
678
           write permition for this object False means all previous read
679
           permissions will be removed
683 680
        """
681

  
684 682
        perms = dict(read='' if not read_permition else read_permition,
685 683
            write='' if not write_permition else write_permition)
686 684
        r = self.object_post(object, update=True, permissions=perms)
......
694 692
            to caller application, e.g. a progress bar. Its next is called
695 693
            whenever a block is uploaded
696 694
        """
695

  
697 696
        self.assert_container()
698 697
        meta = self.get_container_info()
699 698
        blocksize = int(meta['x-container-block-size'])
......
732 731
        source_file,
733 732
        upload_cb=None):
734 733
        """Overwrite a part of an object with given source file
735
           @start the part of the remote object to start overwriting from,
736
                in bytes
734
           @start the part of the remote object to start overwriting from, in
735
           bytes
737 736
           @end the part of the remote object to stop overwriting to, in bytes
738 737
        """
738

  
739 739
        self.assert_container()
740 740
        meta = self.get_container_info()
741 741
        blocksize = int(meta['x-container-block-size'])
b/kamaki/clients/pithos_rest_api.py
48 48
        @param until (string): optional timestamp
49 49
        --- --- optional request headers ---
50 50
        @param if_modified_since (string): Retrieve if account has changed
51
            since provided timestamp
51
        since provided timestamp
52 52
        @param if_unmodified_since (string): Retrieve if account has not
53
            change since provided timestamp
53
        change since provided timestamp
54 54
        """
55

  
55 56
        self.assert_account()
56 57
        path = path4url(self.account)
57 58

  
......
75 76
        """  Full Pithos+ GET at account level
76 77
        --- request parameters ---
77 78
        @param limit (integer): The amount of results requested
78
            (server will use default value if None)
79
        (server will use default value if None)
79 80
        @param marker (string): Return containers with name
80
            lexicographically after marker
81
        lexicographically after marker
81 82
        @param format (string): reply format can be json or xml
82
            (default: json)
83
        (default: json)
83 84
        @param shared (bool): If true, only shared containers will be
84
            included in results
85
        included in results
85 86
        @param until (string): optional timestamp
86 87
        --- --- optional request headers ---
87 88
        @param if_modified_since (string): Retrieve if account has changed
88
            since provided timestamp
89
        since provided timestamp
89 90
        @param if_unmodified_since (string): Retrieve if account has not
90
            changed since provided timestamp
91
        changed since provided timestamp
91 92
        """
93

  
92 94
        self.assert_account()
93 95

  
94 96
        self.set_param('format', format, iff=format is not None)
......
117 119
        @param update (bool): if True, Do not replace metadata/groups
118 120
        --- request headers ---
119 121
        @groups (dict): Optional user defined groups in the form
120
                    {   'group1':['user1', 'user2', ...],
121
                        'group2':['userA', 'userB', ...], ...
122
                    }
122
        { 'group1':['user1', 'user2', ...],
123
        'group2':['userA', 'userB', ...], }
123 124
        @metadata (dict): Optional user defined metadata in the form
124
                    {   'name1': 'value1',
125
                        'name2': 'value2', ...
126
                    }
125
        { 'name1': 'value1', 'name2': 'value2', ... }
127 126
        @param quota(integer): If supported, sets the Account quota
128 127
        @param versioning(string): If supported, sets the Account versioning
129
                    to 'auto' or some other supported versioning string
128
        to 'auto' or some other supported versioning string
130 129
        """
130

  
131 131
        self.assert_account()
132 132

  
133 133
        self.set_param('update', iff=update)
......
156 156
        @param until (string): optional timestamp
157 157
        --- optional request headers ---
158 158
        @param if_modified_since (string): Retrieve if account has changed
159
            since provided timestamp
159
        since provided timestamp
160 160
        @param if_unmodified_since (string): Retrieve if account has not
161
            changed since provided timestamp
161
        changed since provided timestamp
162 162
        """
163

  
163 164
        self.assert_container()
164 165

  
165 166
        self.set_param('until', until, iff=until is not None)
......
188 189
        """ Full Pithos+ GET at container level
189 190
        --- request parameters ---
190 191
        @param limit (integer): The amount of results requested
191
            (server qill use default value if None)
192
        (server qill use default value if None)
192 193
        @param marker (string): Return containers with name lexicographically
193
            after marker
194
        after marker
194 195
        @param prefix (string): Return objects starting with prefix
195 196
        @param delimiter (string): Return objects up to the delimiter
196 197
        @param path (string): assume prefix = path and delimiter = /
197
            (overwrites prefix and delimiter)
198
        (overwrites prefix and delimiter)
198 199
        @param format (string): reply format can be json or xml (default:json)
199 200
        @param meta (list): Return objects that satisfy the key queries in
200
            the specified comma separated list (use <key>, !<key> for
201
            existence queries, <key><op><value> for value queries, where <op>
202
            can be one of =, !=, <=, >=, <, >)
201
        the specified comma separated list (use <key>, !<key> for
202
        existence queries, <key><op><value> for value queries, where <op>
203
        can be one of =, !=, <=, >=, <, >)
203 204
        @param shared (bool): If true, only shared containers will be included
204 205
        in results
205 206
        @param until (string): optional timestamp
206 207
        --- --- optional request headers ---
207 208
        @param if_modified_since (string): Retrieve if account has changed
208
            since provided timestamp
209
        since provided timestamp
209 210
        @param if_unmodified_since (string): Retrieve if account has not
210
            changed since provided timestamp
211
        changed since provided timestamp
211 212
        """
213

  
212 214
        self.assert_container()
213 215

  
214 216
        self.set_param('format', format, iff=format is not None)
......
307 309
        """ Full Pithos+ DELETE at container level
308 310
        --- request parameters ---
309 311
        @param until (timestamp string): if defined, container is purged up to
310
            that time
312
        that time
311 313
        """
314

  
312 315
        self.assert_container()
313 316

  
314 317
        self.set_param('until', until, iff=until is not None)
......
331 334
        @param version (string): optional version identified
332 335
        --- request headers ---
333 336
        @param if_etag_match (string): if provided, return only results
334
                with etag matching with this
337
        with etag matching with this
335 338
        @param if_etag_not_match (string): if provided, return only results
336
                with etag not matching with this
339
        with etag not matching with this
337 340
        @param if_modified_since (string): Retrieve if account has changed
338
            since provided timestamp
341
        since provided timestamp
339 342
        @param if_unmodified_since (string): Retrieve if account has not
340
            changed since provided timestamp
343
        changed since provided timestamp
341 344
        """
345

  
342 346
        self.assert_container()
343 347

  
344 348
        self.set_param('version', version, iff=version is not None)
......
373 377
        @param data_range (string): Optional range of data to retrieve
374 378
        @param if_range (bool):
375 379
        @param if_etag_match (string): if provided, return only results
376
                with etag matching with this
380
        with etag matching with this
377 381
        @param if_etag_not_match (string): if provided, return only results
378
                with etag not matching with this
382
        with etag not matching with this
379 383
        @param if_modified_since (string): Retrieve if account has changed
380
            since provided timestamp
384
        since provided timestamp
381 385
        @param if_unmodified_since (string): Retrieve if account has not
382
            changed since provided timestamp
386
        changed since provided timestamp
383 387
        """
388

  
384 389
        self.assert_container()
385 390

  
386 391
        self.set_param('format', format, iff=format is not None)
......
427 432
        @param hashmap (bool): Optional hashmap provided instead of data
428 433
        --- request headers ---
429 434
        @param if_etag_match (string): if provided, return only results
430
                with etag matching with this
435
        with etag matching with this
431 436
        @param if_etag_not_match (string): if provided, return only results
432
                with etag not matching with this
437
        with etag not matching with this
433 438
        @param etag (string): The MD5 hash of the object (optional to check
434
            written data)
439
        written data)
435 440
        @param content_length (integer): The size of the data written
436 441
        @param content_type (string): The MIME content type of the object
437 442
        @param transfer_encoding (string): Set to chunked to specify
438
            incremental uploading (if used, Content-Length is ignored)
443
        incremental uploading (if used, Content-Length is ignored)
439 444
        @param copy_from (string): The source path in the form
440
            /<container>/<object>
445
        /<container>/<object>
441 446
        @param move_from (string): The source path in the form
442
            /<container>/<object>
447
        /<container>/<object>
443 448
        @param source_account (string): The source account to copy/move from
444 449
        @param source_version (string): The source version to copy from
445 450
        @param conent_encoding (string): The encoding of the object
446 451
        @param content_disposition (string): Presentation style of the object
447 452
        @param manifest (string): Object parts prefix in
448
            /<container>/<object> form
453
        /<container>/<object> form
449 454
        @param permissions (dict): Object permissions in the form (all fields
450
            are optional)
451
            {   'read':[user1, group1, user2, ...],
452
                'write':['user3, group2, group3, ...]
453
            }
455
        are optional)
456
        { 'read':[user1, group1, user2, ...],
457
        'write':['user3, group2, group3, ...] }
454 458
        @param public (bool): If true, Object is publicly accessible,
455
            if false, not
459
        if false, not
456 460
        @param metadata (dict): Optional user defined metadata in the form
457
                {'meta-key-1':'meta-value-1', 'meta-key-2':'meta-value-2', ...}
461
        {'meta-key-1':'meta-value-1', 'meta-key-2':'meta-value-2', ...}
458 462
        """
463

  
459 464
        self.assert_container()
460 465

  
461 466
        self.set_param('format', format, iff=format is not None)
......
516 521
        @param format (string): json (default) or xml
517 522
        @param ignore_content_type (bool): Ignore the supplied Content-Type
518 523
        --- request headers ---
519
         @param if_etag_match (string): if provided, copy only results
520
                with etag matching with this
524
        @param if_etag_match (string): if provided, copy only results
525
        with etag matching with this
521 526
        @param if_etag_not_match (string): if provided, copy only results
522
                with etag not matching with this
527
        with etag not matching with this
523 528
        @param destination (string): The destination path in the form
524
            /<container>/<object>
529
        /<container>/<object>
525 530
        @param destination_account (string): The destination account to copy to
526 531
        @param content_type (string): The MIME content type of the object
527 532
        @param content_encoding (string): The encoding of the object
528 533
        @param content_disposition (string): Object resentation style
529 534
        @param source_version (string): The source version to copy from
530 535
        @param permissions (dict): Object permissions in the form
531
            (all fields are optional)
532
            {   'read':[user1, group1, user2, ...],
533
                'write':['user3, group2, group3, ...]
534
            }
535
            permissions override source permissions,
536
            removing any old permissions
536
        (all fields are optional)
537
        { 'read':[user1, group1, user2, ...],
538
        'write':['user3, group2, group3, ...] }
539
        @permissions override source permissions, removing any old permissions
537 540
        @param public (bool): If true, Object is publicly accessible
538 541
        @param metadata (dict): Optional user defined metadata in the form
539
            {'meta-key-1':'meta-value-1', 'meta-key-2':'meta-value-2', ...}
540
            Metadata are appended to the source metadata. In case of same
541
            keys, they replace the old metadata
542
        {'meta-key-1':'meta-value-1', 'meta-key-2':'meta-value-2', ...}
543
        Metadata are appended to the source metadata. In case of same keys,
544
        they replace the old metadata
542 545
        """
546

  
543 547
        self.assert_container()
544 548

  
545 549
        self.set_param('format', format, iff=format is not None)
......
594 598
        @param format (string): json (default) or xml
595 599
        @param ignore_content_type (bool): Ignore the supplied Content-Type
596 600
        --- request headers ---
597
         @param if_etag_match (string): if provided, return only results
598
                with etag matching with this
601
        @param if_etag_match (string): if provided, return only results
602
        with etag matching with this
599 603
        @param if_etag_not_match (string): if provided, return only results
600
                with etag not matching with this
604
        with etag not matching with this
601 605
        @param destination (string): The destination path in the form
602
            /<container>/<object>
606
        /<container>/<object>
603 607
        @param destination_account (string): The destination account to copy to
604 608
        @param content_type (string): The MIME content type of the object
605 609
        @param content_encoding (string): The encoding of the object
606 610
        @param content_disposition (string): Object presentation style
607 611
        @param source_version (string): The source version to copy from
608 612
        @param permissions (dict): Object permissions in the form
609
            (all fields are optional)
610
            {   'read':[user1, group1, user2, ...],
611
                'write':['user3, group2, group3, ...]
612
            }
613
        (all fields are optional)
614
        { 'read':[user1, group1, user2, ...],
615
        'write':['user3, group2, group3, ...] }
613 616
        @param public (bool): If true, Object is publicly accessible
614 617
        @param metadata (dict): Optional user defined metadata in the form
615
                {'meta-key-1':'meta-value-1', 'meta-key-2':'meta-value-2', ...}
618
        {'meta-key-1':'meta-value-1', 'meta-key-2':'meta-value-2', ...}
616 619
        """
620

  
617 621
        self.assert_container()
618 622

  
619 623
        self.set_param('format', format, iff=format is not None)
......
672 676
        @param update (bool): Do not replace metadata
673 677
        --- request headers ---
674 678
        @param if_etag_match (string): if provided, return only results
675
                with etag matching with this
679
        with etag matching with this
676 680
        @param if_etag_not_match (string): if provided, return only results
677
                with etag not matching with this
681
        with etag not matching with this
678 682
        @param content_length (string): The size of the data written
679 683
        @param content_type (string): The MIME content type of the object
680 684
        @param content_range (string): The range of data supplied
681 685
        @param transfer_encoding (string): Set to chunked to specify
682
            incremental uploading (if used, Content-Length is ignored)
686
        incremental uploading (if used, Content-Length is ignored)
683 687
        @param content_encoding (string): The encoding of the object
684 688
        @param content_disposition (string): Object presentation style
685 689
        @param source_object (string): Update with data from the object at
686
            path /<container>/<object>
690
        path /<container>/<object>
687 691
        @param source_account (string): The source account to update from
688 692
        @param source_version (string): The source version to copy from
689 693
        @param object_bytes (integer): The updated objects final size
690 694
        @param manifest (string): Object parts prefix as /<container>/<object>
691 695
        @param permissions (dict): Object permissions in the form (all fields
692
            are optional)
693
            {   'read':[user1, group1, user2, ...],
694
                'write':['user3, group2, group3, ...]
695
            }
696
        are optional)
697
        { 'read':[user1, group1, user2, ...],
698
        'write':['user3, group2, group3, ...] }
696 699
        @param public (bool): If true, Object is publicly accessible
697 700
        @param metadata (dict): Optional user defined metadata in the form
698
                {'meta-key-1':'meta-value-1', 'meta-key-2':'meta-value-2', ...}
701
        {'meta-key-1':'meta-value-1', 'meta-key-2':'meta-value-2', ...}
699 702
        """
703

  
700 704
        self.assert_container()
701 705

  
702 706
        self.set_param('format', format, iff=format is not None)
b/kamaki/clients/utils.py
34 34

  
35 35
def matches(val1, val2, exactMath=True):
36 36
    """Case Insenstive match"""
37

  
37 38
    if exactMath:
38 39
        return True if val1.lower() == val2.lower() else False
39 40
    else:
......
44 45
    """@return a dict that contains the entries of d
45 46
        that are NOT prefixed with prefic
46 47
    """
48

  
47 49
    ret = {}
48 50
    for key, val in d.items():
49 51
        if not matches(key, prefix, exactMath=exactMatch):
......
55 57
    """@return a dict that contains only the entries of d
56 58
        that are prefixed with prefix
57 59
    """
60

  
58 61
    ret = {}
59 62
    for key, val in d.items():
60 63
        if matches(key, prefix, exactMath=exactMatch):
......
65 68
def prefix_keys(d, prefix):
66 69
    """@return a sallow copy of d with all its keys prefixed with prefix
67 70
    """
71

  
68 72
    ret = {}
69 73
    for key, val in d.items():
70 74
        ret[prefix + key] = val
......
75 79
    """@return a string with all args in the form /arg1/arg2/...
76 80
       @param args must be strings
77 81
    """
82

  
78 83
    path = ''
79 84
    for arg in args:
80 85
        suffix = unicode(arg)
......
92 97

  
93 98
def params4url(params):
94 99
    """@return a string with all params in the form ?key1=val1&key2=val2&...
95
            e.g. input
96
                {'key1':'val1', 'key2':None, 'key3':'val3'}
97
            will return
98
                ?key1=val1&key2&key3=val3
99 100
       @param should be a dict.
100
            Use params['somekey']=None for params that will apear without
101
            a value at the final string
102 101
    """
102

  
103 103
    assert(type(params) is dict)
104 104
    result = ''
105 105
    dlmtr = '?'
......
112 112

  
113 113
def list2str(alist, seperator=','):
114 114
    """@return a string of comma seperated elements of the list"""
115

  
115 116
    ret = ''
116 117
    slist = sorted(alist)
117 118
    for item in slist:

Also available in: Unified diff