Revision d88ba587

b/docs/commands.rst
60 60
    name             :  C4R2048D10
61 61
    ram              :  2048
62 62

  
63
image (Compute/Cyclades + Glance)
64
---------------------------------
63
image (Compute/Cyclades + Plankton)
64
-----------------------------------
65 65

  
66 66
.. code-block:: text
67 67

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

  
7 7
A good example of an application build on kamaki.clients is kamaki.cli, the command line interface of kamaki. 
8 8

  
9
Since synnefo services are build as OpenStack extensions, an inheritance approach has been chosen for implementing clients for both. In specific, the *compute*, *storage* and *image* modules are clients of the OS compute, OS storage and Glance APIs, respectively. On the contrary, all the other modules are Synnefo extensions (*cyclades* extents *compute*, *pithos* and *pithos_rest_api* extent *storage*) or novel synnefo services (e.g. *astakos*).
9
Since synnefo services are build as OpenStack extensions, an inheritance approach has been chosen for implementing clients for both. In specific, the *compute*, *storage* and *image* modules are clients of the OS compute, OS storage, respectively. On the contrary, all the other modules are Synnefo extensions (*cyclades* extents *compute*, *pithos* and *pithos_rest_api* extent *storage*) or novel synnefo services (e.g. *astakos*, *image* for *plankton*).
10 10

  
11 11
Setup a client instance
12 12
-----------------------
b/docs/man/kamaki.rst
50 50

  
51 51
image 
52 52

  
53
    Manage compute API and glance images.
53
    Manage compute API and Plankton images.
54 54

  
55 55
store
56 56

  
b/docs/setup.rst
123 123
* network.cli <UI command specifications for virtual networks>
124 124
    a special package that is used to load cyclades virtual network commands to kamaki UIs. Don't touch this unless you know what you are doing.
125 125

  
126
* image.url <Glance image service url>
127
    the url of the Glance service. Set to Okeanos.grnet.gr Plankton service be default. Users should set a different value if they need to use a different service.
126
* image.url <Plankton image service url>
127
    the url of the Plankton service. Set to Okeanos.grnet.gr Plankton service be default. Users should set a different value if they need to use a different service.
128 128

  
129
* image.cli <UI command specifications for Glance and Cyclades image service>
129
* image.cli <UI command specifications for Plankton and Cyclades image service>
130 130
    a special package that is used to load image-related commands to kamaki UIs. Don't touch this unless you know what you are doing.
131 131

  
132 132
* astakos.url <Astakos authentication service url>
b/docs/usage.rst
128 128
    config :  Configuration commands
129 129
    flavor :  Compute/Cyclades API flavor commands
130 130
    history:  Command history
131
    image  :  Compute/Cyclades or Glance API image commands
131
    image  :  Compute/Cyclades or Plankton API image commands
132 132
    network:  Compute/Cyclades API network commands
133 133
    server :  Compute/Cyclades API server commands
134 134
    store  :  Pithos+ storage commands
b/kamaki/clients/pithos.py
110 110

  
111 111
        :param public: (bool)
112 112
        """
113
        self.assert_container()
113
        self._assert_container()
114 114

  
115 115
        if withHashFile:
116 116
            data = f.read()
......
159 159

  
160 160
        :param public: (bool)
161 161
        """
162
        self.assert_container()
162
        self._assert_container()
163 163
        r = self.object_put(obj,
164 164
            content_length=0,
165 165
            etag=etag,
......
323 323

  
324 324
        :param public: (bool)
325 325
        """
326
        self.assert_container()
326
        self._assert_container()
327 327

  
328 328
        #init
329 329
        block_info = (blocksize, blockhash, size, nblocks) =\
......
722 722

  
723 723
        :raises ClientError: 409 Container is not empty
724 724
        """
725
        self.assert_container()
725
        self._assert_container()
726 726
        r = self.container_delete(until=until,
727 727
            delimiter=delimiter,
728 728
            success=(204, 404, 409))
......
817 817

  
818 818
        :param delimiter: (str)
819 819
        """
820
        self.assert_container()
820
        self._assert_container()
821 821
        r = self.object_delete(obj, until=until, delimiter=delimiter)
822 822
        r.release()
823 823

  
......
933 933
        :param upload_db: progress.bar for uploading
934 934
        """
935 935

  
936
        self.assert_container()
936
        self._assert_container()
937 937
        meta = self.get_container_info()
938 938
        blocksize = int(meta['x-container-block-size'])
939 939
        filesize = fstat(source_file.fileno()).st_size
......
988 988
        :param upload_db: progress.bar for uploading
989 989
        """
990 990

  
991
        self.assert_container()
991
        self._assert_container()
992 992
        meta = self.get_container_info()
993 993
        blocksize = int(meta['x-container-block-size'])
994 994
        filesize = fstat(source_file.fileno()).st_size
......
1036 1036

  
1037 1037
        :param delimiter: (str)
1038 1038
        """
1039
        self.assert_account()
1039
        self._assert_account()
1040 1040
        self.container = dst_container
1041 1041
        dst_object = dst_object or src_object
1042 1042
        src_path = path4url(src_container, src_object)
......
1073 1073

  
1074 1074
        :param delimiter: (str)
1075 1075
        """
1076
        self.assert_account()
1076
        self._assert_account()
1077 1077
        self.container = dst_container
1078 1078
        dst_object = dst_object or src_object
1079 1079
        src_path = path4url(src_container, src_object)
......
1096 1096

  
1097 1097
        :returns: (dict)
1098 1098
        """
1099
        self.assert_account()
1099
        self._assert_account()
1100 1100

  
1101 1101
        self.set_param('format', 'json')
1102 1102
        self.set_param('limit', limit, iff=limit is not None)
......
1113 1113

  
1114 1114
        :returns: (list)
1115 1115
        """
1116
        self.assert_container()
1116
        self._assert_container()
1117 1117
        r = self.object_get(obj, format='json', version='list')
1118 1118
        return r.json['versions']
b/kamaki/clients/pithos_rest_api.py
60 60
        :returns: ConnectionResponse
61 61
        """
62 62

  
63
        self.assert_account()
63
        self._assert_account()
64 64
        path = path4url(self.account)
65 65

  
66 66
        self.set_param('until', until, iff=until is not None)
......
109 109
        :returns: ConnectionResponse
110 110
        """
111 111

  
112
        self.assert_account()
112
        self._assert_account()
113 113

  
114 114
        self.set_param('format', format, iff=format is not None)
115 115
        self.set_param('limit', limit, iff=limit is not None)
......
155 155
        :returns: ConnectionResponse
156 156
        """
157 157

  
158
        self.assert_account()
158
        self._assert_account()
159 159

  
160 160
        self.set_param('update', iff=update)
161 161

  
......
195 195
        :returns: ConnectionResponse
196 196
        """
197 197

  
198
        self.assert_container()
198
        self._assert_container()
199 199

  
200 200
        self.set_param('until', until, iff=until is not None)
201 201

  
......
260 260
        :returns: ConnectionResponse
261 261
        """
262 262

  
263
        self.assert_container()
263
        self._assert_container()
264 264

  
265 265
        self.set_param('format', format, iff=format is not None)
266 266
        self.set_param('limit', limit, iff=limit is not None)
......
302 302

  
303 303
        :returns: ConnectionResponse
304 304
        """
305
        self.assert_container()
305
        self._assert_container()
306 306

  
307 307
        if metadata is not None:
308 308
            for metaname, metaval in metadata.items():
......
350 350

  
351 351
        :returns: ConnectionResponse
352 352
        """
353
        self.assert_container()
353
        self._assert_container()
354 354

  
355 355
        self.set_param('format', format, iff=format is not None)
356 356
        self.set_param('update', iff=update)
......
379 379
        :returns: ConnectionResponse
380 380
        """
381 381

  
382
        self.assert_container()
382
        self._assert_container()
383 383

  
384 384
        self.set_param('until', until, iff=until is not None)
385 385
        self.set_param('delimiter', delimiter, iff=delimiter is not None)
......
419 419
        :returns: ConnectionResponse
420 420
        """
421 421

  
422
        self.assert_container()
422
        self._assert_container()
423 423

  
424 424
        self.set_param('version', version, iff=version is not None)
425 425

  
......
475 475
        :returns: ConnectionResponse
476 476
        """
477 477

  
478
        self.assert_container()
478
        self._assert_container()
479 479

  
480 480
        self.set_param('format', format, iff=format is not None)
481 481
        self.set_param('version', version, iff=version is not None)
......
572 572
        :returns: ConnectionResponse
573 573
        """
574 574

  
575
        self.assert_container()
575
        self._assert_container()
576 576

  
577 577
        self.set_param('format', format, iff=format is not None)
578 578
        self.set_param('hashmap', hashmap, iff=hashmap)
......
673 673
        :returns: ConnectionResponse
674 674
        """
675 675

  
676
        self.assert_container()
676
        self._assert_container()
677 677

  
678 678
        self.set_param('format', format, iff=format is not None)
679 679
        self.set_param('ignore_content_type', iff=ignore_content_type)
......
764 764
        :returns: ConnectionResponse
765 765
        """
766 766

  
767
        self.assert_container()
767
        self._assert_container()
768 768

  
769 769
        self.set_param('format', format, iff=format is not None)
770 770
        self.set_param('ignore_content_type', iff=ignore_content_type)
......
869 869
        :returns: ConnectionResponse
870 870
        """
871 871

  
872
        self.assert_container()
872
        self._assert_container()
873 873

  
874 874
        self.set_param('format', format, iff=format is not None)
875 875
        self.set_param('update', iff=update)
......
921 921

  
922 922
        :returns: ConnectionResponse
923 923
        """
924
        self.assert_container()
924
        self._assert_container()
925 925

  
926 926
        self.set_param('until', until, iff=until is not None)
927 927
        self.set_param('delimiter', delimiter, iff=delimiter is not None)
b/kamaki/clients/storage.py
43 43
        self.account = account
44 44
        self.container = container
45 45

  
46
    def assert_account(self):
46
    def _assert_account(self):
47 47
        if not self.account:
48 48
            raise ClientError("No account provided")
49 49

  
50
    def assert_container(self):
51
        self.assert_account()
50
    def _assert_container(self):
51
        self._assert_account()
52 52
        if not self.container:
53 53
            raise ClientError("No container provided")
54 54

  
55 55
    def get_account_info(self):
56
        self.assert_account()
56
        """
57
        :returns: (dict)
58
        """
59
        self._assert_account()
57 60
        path = path4url(self.account)
58 61
        r = self.head(path, success=(204, 401))
59 62
        if r.status_code == 401:
......
62 65
        return reply
63 66

  
64 67
    def replace_account_meta(self, metapairs):
65
        self.assert_account()
68
        """
69
        :param metapais: (dict) key:val metadata pairs
70
        """
71
        self._assert_account()
66 72
        path = path4url(self.account)
67 73
        for key, val in metapairs:
68 74
            self.set_header('X-Account-Meta-' + key, val)
......
70 76
        r.release()
71 77

  
72 78
    def del_account_meta(self, metakey):
79
        """
80
        :param metakey: (str) metadatum key
81
        """
73 82
        headers = self.get_account_info()
74 83
        self.headers = filter_out(headers,
75 84
            'X-Account-Meta-' + metakey,
......
81 90
        r.release()
82 91

  
83 92
    def create_container(self, container):
84
        self.assert_account()
93
        """
94
        :param container: (str)
95

  
96
        :raises ClientError: 202 Container already exists
97
        """
98
        self._assert_account()
85 99
        path = path4url(self.account, container)
86 100
        r = self.put(path, success=(201, 202))
101
        r.release()
87 102
        if r.status_code == 202:
88 103
            raise ClientError("Container already exists", r.status_code)
89 104

  
90 105
    def get_container_info(self, container):
91
        self.assert_account()
106
        """
107
        :param container: (str)
108

  
109
        :returns: (dict)
110

  
111
        :raises ClientError: 404 Container does not exist
112
        """
113
        self._assert_account()
92 114
        path = path4url(self.account, container)
93 115
        r = self.head(path, success=(204, 404))
94 116
        if r.status_code == 404:
......
97 119
        return reply
98 120

  
99 121
    def delete_container(self, container):
100
        self.assert_account()
122
        """
123
        :param container: (str)
124

  
125
        :raises ClientError: 404 Container does not exist
126
        :raises ClientError: 409 Container not empty
127
        """
128
        self._assert_account()
101 129
        path = path4url(self.account, container)
102 130
        r = self.delete(path, success=(204, 404, 409))
103 131
        if r.status_code == 404:
......
106 134
            raise ClientError("Container is not empty", r.status_code)
107 135

  
108 136
    def list_containers(self):
109
        self.assert_account()
137
        """
138
        :returns: (dict)
139
        """
140
        self._assert_account()
110 141
        self.set_param('format', 'json')
111 142
        path = path4url(self.account)
112 143
        r = self.get(path, success=(200, 204))
113 144
        reply = r.json
114 145
        return reply
115 146

  
116
    def upload_object(self, object, f, size=None):
117
        # This is a naive implementation, it loads the whole file in memory
118
        #Look in pithos for a nice implementation
119
        self.assert_container()
120
        path = path4url(self.account, self.container, object)
147
    def upload_object(self, obj, f, size=None):
148
        """ A simple (naive) implementation.
149

  
150
        :param obj: (str)
151

  
152
        :param f: an open for reading file descriptor
153

  
154
        :param size: (int) number of bytes to upload
155
        """
156
        self._assert_container()
157
        path = path4url(self.account, self.container, obj)
121 158
        data = f.read(size) if size is not None else f.read()
122 159
        r = self.put(path, data=data, success=201)
123 160
        r.release()
124 161

  
125
    def create_directory(self, object):
126
        self.assert_container()
127
        path = path4url(self.account, self.container, object)
162
    def create_directory(self, obj):
163
        """
164
        :param obj: (str) directory-object name
165
        """
166
        self._assert_container()
167
        path = path4url(self.account, self.container, obj)
128 168
        self.set_header('Content-Type', 'application/directory')
129 169
        self.set_header('Content-length', '0')
130 170
        r = self.put(path, success=201)
131 171
        r.release()
132 172

  
133
    def get_object_info(self, object):
134
        self.assert_container()
135
        path = path4url(self.account, self.container, object)
173
    def get_object_info(self, obj):
174
        """
175
        :param obj: (str)
176

  
177
        :returns: (dict)
178
        """
179
        self._assert_container()
180
        path = path4url(self.account, self.container, obj)
136 181
        r = self.head(path, success=200)
137 182
        reply = r.headers
138 183
        return reply
139 184

  
140
    def get_object_meta(self, object):
141
        r = filter_in(self.get_object_info(object), 'X-Object-Meta-')
185
    def get_object_meta(self, obj):
186
        """
187
        :param obj: (str)
188

  
189
        :returns: (dict)
190
        """
191
        r = filter_in(self.get_object_info(obj), 'X-Object-Meta-')
142 192
        reply = {}
143 193
        for (key, val) in r.items():
144 194
            metakey = key.split('-')[-1]
......
146 196
        return reply
147 197

  
148 198
    def del_object_meta(self, obj, metakey):
149
        self.assert_container()
199
        """
200
        :param obj: (str)
201

  
202
        :param metakey: (str) the metadatum key
203
        """
204
        self._assert_container()
150 205
        self.set_header('X-Object-Meta-' + metakey, '')
151 206
        path = path4url(self.account, self.container, obj)
152 207
        r = self.post(path, success=202)
153 208
        r.release()
154 209

  
155 210
    def replace_object_meta(self, metapairs):
156
        self.assert_container()
211
        """
212
        :param metapairs: (dict) key:val metadata
213
        """
214
        self._assert_container()
157 215
        path = path4url(self.account, self.container)
158 216
        for key, val in metapairs:
159 217
            self.set_header('X-Object-Meta-' + key, val)
160 218
        r = self.post(path, success=202)
161 219
        r.release()
162 220

  
163
    def get_object(self, object):
164
        self.assert_container()
165
        path = path4url(self.account, self.container, object)
221
    def get_object(self, obj):
222
        """
223
        :param obj: (str)
224

  
225
        :returns: (int, int) # of objects, size in bytes
226
        """
227
        self._assert_container()
228
        path = path4url(self.account, self.container, obj)
166 229
        r = self.get(path, success=200)
167 230
        size = int(r.headers['content-length'])
168 231
        cnt = r.content
......
170 233

  
171 234
    def copy_object(self, src_container, src_object, dst_container,
172 235
        dst_object=False):
173
        self.assert_account()
236
        """Copy an objects from src_contaier:src_object to
237
            dst_container[:dst_object]
238

  
239
        :param src_container: (str)
240

  
241
        :param src_object: (str)
242

  
243
        :param dst_container: (str)
244

  
245
        :param dst_object: (str)
246
        """
247
        self._assert_account()
174 248
        dst_object = dst_object or src_object
175 249
        dst_path = path4url(self.account, dst_container, dst_object)
176 250
        self.set_header('X-Copy-From', path4url(src_container, src_object))
......
180 254

  
181 255
    def move_object(self, src_container, src_object, dst_container,
182 256
        dst_object=False):
183
        self.assert_account()
257
        """Move an objects from src_contaier:src_object to
258
            dst_container[:dst_object]
259

  
260
        :param src_container: (str)
261

  
262
        :param src_object: (str)
263

  
264
        :param dst_container: (str)
265

  
266
        :param dst_object: (str)
267
        """
268
        self._assert_account()
184 269
        dst_object = dst_object or src_object
185 270
        dst_path = path4url(self.account, dst_container, dst_object)
186 271
        self.set_header('X-Move-From', path4url(src_container, src_object))
......
188 273
        r = self.put(dst_path, success=201)
189 274
        r.release()
190 275

  
191
    def delete_object(self, object):
192
        self.assert_container()
193
        path = path4url(self.account, self.container, object)
276
    def delete_object(self, obj):
277
        """
278
        :param obj: (str)
279

  
280
        :raises ClientError: 404 Object not found
281
        """
282
        self._assert_container()
283
        path = path4url(self.account, self.container, obj)
194 284
        r = self.delete(path, success=(204, 404))
195 285
        if r.status_code == 404:
196
            raise ClientError("Object %s not found" % object, r.status_code)
286
            raise ClientError("Object %s not found" % obj, r.status_code)
197 287

  
198 288
    def list_objects(self):
199
        self.assert_container()
289
        """
290
        :returns: (dict)
291

  
292
        :raises ClientError: 404 Invalid account
293
        """
294
        self._assert_container()
200 295
        path = path4url(self.account, self.container)
201 296
        self.set_param('format', 'json')
202 297
        r = self.get(path, success=(200, 204, 304, 404), )
203 298
        if r.status_code == 404:
204 299
            raise ClientError(\
205
                "Incorrect account (%s) for that container" % self.account,
300
                "Invalid account (%s) for that container" % self.account,
206 301
                r.status_code)
207 302
        elif r.status_code == 304:
208 303
            return []
......
210 305
        return reply
211 306

  
212 307
    def list_objects_in_path(self, path_prefix):
213
        self.assert_container()
308
        """
309
        :param path_prefix: (str)
310

  
311
        :raises ClientError: 404 Invalid account
312

  
313
        :returns: (dict)
314
        """
315
        self._assert_container()
214 316
        path = path4url(self.account, self.container)
215 317
        self.set_param('format', 'json')
216 318
        self.set_param('path', 'path_prefix')
217 319
        r = self.get(path, success=(200, 204, 404))
218 320
        if r.status_code == 404:
219 321
            raise ClientError(\
220
                "Incorrect account (%s) for that container" % self.account,
322
                "Invalid account (%s) for that container" % self.account,
221 323
                r.status_code)
222 324
        reply = r.json
223 325
        return reply

Also available in: Unified diff