Revision 961e6040 docs/clients.rst

b/docs/clients.rst
1
Clients lib
2
===========
1
For Developers
2
==============
3 3

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

  
7
Please do!
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:
8 219

  
9 220
The clients API
10 221
---------------
11 222

  
12
The clients API is based on:
223
Imports
224
^^^^^^^
13 225

  
14 226
.. toctree::
15 227
    connection
16 228

  
17
It contains the following modules:
229
Modules list
230
^^^^^^^^^^^^
18 231

  
19 232
compute
20 233
^^^^^^^

Also available in: Unified diff