Statistics
| Branch: | Tag: | Revision:

root / docs / clients.rst @ 961e6040

History | View | Annotate | Download (8.1 kB)

1
For Developers
2
==============
3

    
4
Creating applications with kamaki API
5
-------------------------------------
6

    
7
Kamaki features a clients API for building third-party client applications that communicate with OpenStack and / or Synnefo cloud services. The package is called kamaki.clients and contains a number of 
8

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

    
11
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*).
12

    
13
Setup a client instance
14
^^^^^^^^^^^^^^^^^^^^^^^
15

    
16
External applications may instantiate one or more kamaki clients.
17

    
18
.. code-block:: python
19
    :emphasize-lines: 1
20

    
21
    Example 1.1: Instantiate a Cyclades client
22

    
23

    
24
    from kamaki.clients.cyclades import CycladesClient
25
    from kamaki.clients.pithos import PithosClient
26

    
27
    my_cyclades_client = CycladesClient(base_url, token)
28
    my_pithos_client = PithosClient(base_url, token, account, container)
29

    
30
.. note:: *cyclades* and *pithos* clients inherit all methods of *compute* and *storage* clients respectively. Separate compute or storage objects should be used only when implementing applications for strict OS Compute or OS Storage services.
31

    
32
Use client methods
33
^^^^^^^^^^^^^^^^^^
34

    
35
Client methods can now be called. Developers are advised to consult :ref:`the-client-api-ref` for details on the available methods and how to use them.
36

    
37
In the following example, the *cyclades* and *pithos* clients of example 1.1 are used to extract some information, that is then printed to the standard output.
38

    
39

    
40
.. code-block:: python
41
    :emphasize-lines: 1,2
42

    
43
    Example 1.2: Print server name and OS for server with server_id
44
                Print objects in container mycont
45

    
46

    
47
    srv = my_cyclades_client.get_server_info(server_id)
48
    print("Server Name: %s (with OS %s" % (srv['name'], srv['os']))
49

    
50
    obj_list = my_pithos_client.list_objects(mycont)
51
    for obj in obj_list:
52
        print('  %s of %s bytes' % (obj['name'], obj['bytes']))
53

    
54
.. code-block:: console
55
    :emphasize-lines: 1
56

    
57
    Run of examples 1.1 + 1.2
58

    
59

    
60
    $ python test_script.py
61
    Server Name: A Debian Server (with OS Debian Base)
62
      lala.txt of 34 bytes
63
      test.txt of 1232 bytes
64
      testDir/ of 0 bytes
65
    $ 
66

    
67
Error handling
68
^^^^^^^^^^^^^^
69

    
70
The kamaki.clients standard error is ClientError. A ClientError is raised for any kind of kamaki.clients errors (errors reported by servers, type errors in arguments, etc.).
71

    
72
A ClientError contains::
73

    
74
    message     The error message.
75
    status      An optional error code, e.g. after a server error.
76
    details     Optional list of messages with error details.
77

    
78
The following example concatenates examples 1.1 and 1.2 plus error handling
79

    
80
.. code-block:: python
81

    
82
    Example 1.3: Error handling
83

    
84

    
85
    from kamaki.clients.cyclades import CycladesClient
86
    from kamaki.clients.pithos import PithosClient
87

    
88
    try:
89
        my_cyclades_client = CycladesClient(base_url, token)
90
    except ClientError:
91
        print('Failed to initialize Cyclades client')
92

    
93
    try:
94
        my_pithos_client = PithosClient(base_url, token, account, container)
95
    except ClientError:
96
        print('Failed to initialize Pithos+ client')
97

    
98
    try:
99
        srv = my_cyclades_client.get_server_info(server_id)
100
        print("Server Name: %s (with OS %s" % (srv['name'], srv['os']))
101

    
102
        obj_list = my_pithos_client.list_objects(mycont)
103
        for obj in obj_list:
104
            print('  %s of %s bytes' % (obj['name'], obj['bytes']))
105
    except ClientError as e:
106
        print('Error: %s' % e)
107
        if e.status:
108
            print('- error code: %s' % e.status)
109
        if e.details:
110
            for detail in e.details:
111
                print('- %s' % detail)
112

    
113
Extending kamaki.clients
114
------------------------
115

    
116
By default, kamaki clients are REST clients (they manage HTTP requests and responses to communicate with services). This is achieved by importing the connection module, which is an httplib rapper.
117

    
118
Connection
119
^^^^^^^^^^
120

    
121
The connection module features an error handling and logging system, a lazy response mechanism, a pooling mechanism as well as concurrency control for thread-demanding client functions (e.g. store upload).
122

    
123
How to build a client
124
^^^^^^^^^^^^^^^^^^^^^
125

    
126
All service clients consist of a subclass of the Client class and implement separate client functionalities as member methods. There is also an error class to raise exceptions that can be handled by kamaki interfaces.
127

    
128
.. code-block:: python
129
    
130
    #  ${KAMAKI_PATH}/kamaki/clients/mynewclient.py
131

    
132
    from kamaki.clients import Client, ClientError
133

    
134
    class MyNewClient(Client):
135
        """MyNewClient Description Here"""
136

    
137
        def my_first_method(self, **args):
138
            """Method description"""
139
            try:
140
                ...
141
                method code
142
                ...
143
            except SomeKnownException as e1:
144
                raise ClientError('MyError: %s' % e1)
145
            except SomeOtherException as e2:
146
                raise ClientError('MyError: %s' % e2)
147

    
148
        def my_second_method(self, **params):
149
            """Method description"""
150
            ...
151

    
152
Custom clients can use a set of convenience methods for easy HTTP requests
153

    
154
.. code-block:: python
155

    
156
    def get(self, path, **kwargs)
157
    def head(self, path, **kwargs)
158
    def post(self, path, **kwargs)
159
    def put(self, path, **kwargs)
160
    def delete(self, path, **kwargs)
161
    def copy(self, path, **kwargs)
162
    def move(self, path, **kwargs)
163

    
164
How to use your client
165
^^^^^^^^^^^^^^^^^^^^^^
166

    
167
External applications must instantiate a MyNewClient object.
168

    
169
.. code-block:: python
170

    
171
    from kamaki.clients import ClientError
172
    from kamaki.clients.mynewclient import MyNewClient
173

    
174
    ...
175
    try:
176
        cl = MyNewClient(args)
177
        cl.my_first_method(other_args)
178
    except ClientError as cle:
179
        print('Client Error: %s' % cle)
180
    ...
181

    
182
Concurrency control
183
^^^^^^^^^^^^^^^^^^^
184

    
185
Kamaki clients may handle multiple requests at once, using threads. In that case, users might implement their own thread handling mechanism, use an external solution or take advantage of the mechanism featured in kamaki.clients
186

    
187
.. code-block:: python
188

    
189
    from threading import enumerate
190
    from kamaki.clients import SilentEvent
191
    ...
192

    
193
    class MyNewClient(Client):
194
        ...
195

    
196
        def _single_threaded_method(self, **args):
197
            ...
198
            request code
199
            ...
200

    
201
        def multithread_method(self):
202
            thread_list = []
203
            self._init_thread_limit()
204
            while some_condition or thread_list:
205
                ...
206
                event = SilentEvent(self._single_threaded_method, **args)
207
                event.start()
208
                thread_list.append(event)
209
                thread_list = self._watch_thread_limit(thread_list)
210

    
211
The CLI API
212
-----------
213

    
214
.. toctree::
215

    
216
    cli
217

    
218
.. _the-client-api-ref:
219

    
220
The clients API
221
---------------
222

    
223
Imports
224
^^^^^^^
225

    
226
.. toctree::
227
    connection
228

    
229
Modules list
230
^^^^^^^^^^^^
231

    
232
compute
233
^^^^^^^
234

    
235
.. automodule:: kamaki.clients.compute
236
    :members:
237
    :show-inheritance:
238
    :undoc-members:
239

    
240

    
241
cyclades
242
^^^^^^^^
243

    
244
.. automodule:: kamaki.clients.cyclades
245
    :members:
246
    :show-inheritance:
247
    :undoc-members:
248

    
249

    
250
storage
251
^^^^^^^
252

    
253
.. automodule:: kamaki.clients.storage
254
    :members:
255
    :show-inheritance:
256
    :undoc-members:
257

    
258

    
259
pithos
260
^^^^^^
261

    
262
.. automodule:: kamaki.clients.pithos
263
    :members:
264
    :show-inheritance:
265
    :undoc-members:
266

    
267
pithos_rest_api
268
^^^^^^^^^^^^^^^
269

    
270
.. automodule:: kamaki.clients.pithos_rest_api
271
    :members:
272
    :show-inheritance:
273
    :undoc-members:
274

    
275

    
276
image
277
^^^^^
278

    
279
.. automodule:: kamaki.clients.image
280
    :members:
281
    :show-inheritance:
282
    :undoc-members:
283

    
284

    
285
astakos
286
^^^^^^^
287

    
288
.. automodule:: kamaki.clients.astakos
289
    :members:
290
    :show-inheritance:
291
    :undoc-members:
292

    
293

    
294
utils
295
^^^^^
296

    
297
.. automodule:: kamaki.clients.utils
298
    :members:
299
    :show-inheritance:
300
    :undoc-members: