Statistics
| Branch: | Tag: | Revision:

root / docs / developers / clients-api.rst @ 38db356b

History | View | Annotate | Download (9.9 kB)

1
Creating applications with kamaki API
2
=====================================
3

    
4
Kamaki features a clients API for building third-party client applications that
5
communicate with OpenStack and / or Synnefo cloud services. The package is
6
called kamaki.clients and servers as a lib.
7

    
8
A showcase of an application built on kamaki.clients is kamaki.cli, the command
9
line interface of kamaki.
10

    
11
Since synnefo services are build as OpenStack extensions, an inheritance
12
approach has been chosen for implementing clients for both. In specific,
13
the *compute*, *storage* and *image* modules are clients of the OS compute, OS
14
object-store, respectively. On the contrary, all the other modules are Synnefo
15
extensions (*cyclades* extents *compute*, *pithos* and *pithos_rest_api*
16
extent *storage*) or novel synnefo services (e.g. *astakos* for IM, *image*
17
for *plankton*).
18

    
19
Setup a client instance
20
-----------------------
21

    
22
External applications may instantiate one or more kamaki clients.
23

    
24
.. code-block:: python
25
    :emphasize-lines: 1
26

    
27
    Example 1.1: Instantiate Cyclades and Pithos client
28

    
29

    
30
    from kamaki.clients.cyclades import CycladesClient
31
    from kamaki.clients.pithos import PithosClient
32

    
33
    my_cyclades_client = CycladesClient(base_url, token)
34
    my_pithos_client = PithosClient(base_url, token, account, container)
35

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

    
41
Using endpoints to get the base_url
42
-----------------------------------
43

    
44
In OpenStack, each service (e.g. `compute`, `object-store`, etc.) has a number
45
of `endpoints`. These `endpoints` are actually URIs that are needed as prefixes
46
for the API calls the kamaki client generates. In this context, we need just
47
one of these these `endpoints`, the `publicURL`, which is also referred to as
48
`base_url` in kamaki client libraries.
49

    
50
In general, this is the suggested way of getting the base_url::
51

    
52
    1. From the deployment UI get the AUTHENTICATION_URL and TOKEN
53
        (Example 1.2)
54
    2. Use them to instantiate an AstakosClient
55
        (Example 1.2)
56
    3. Use AstakosClient instance to get the endpoints of the service of interest
57
        (Example 1.3)
58
    4. The 'publicURL' endpoint is the base_url we are looking for
59
        (Example 1.3)
60

    
61
The AstakosClient is a client for the Synnefo/Astakos server. Synnefo/Astakos
62
is an advanced identity server based on OpenStack identity specifications.
63
Therefore, it can be used to get the `base_url` values needed for initializing
64
kamaki clients. Kamaki simplifies this process with the astakos client library.
65

    
66
Let's review the process with examples.
67

    
68
First, an astakos client must be initialized (Example 1.2). An
69
AUTHENTICATION_URL and a TOKEN can be acquired from the synnefo deployment UI.
70

    
71
.. code-block:: python
72
    :emphasize-lines: 1
73

    
74
    Example 1.2: Initialize an astakos client
75

    
76
    from kamaki.clients.astakos import AstakosClient
77
    my_astakos_client = AstakosClient(AUTHENTICATION_URL, TOKEN)
78
        
79

    
80
Next, the astakos client can be used to retrieve the base_url values for the
81
servers of interest. In this case (Example 1.3) they are *cyclades*
82
and *pithos*. A number of endpoints is assigned to each service, but kamaki
83
clients only need the one labeled as ``publicURL``.
84

    
85
.. code-block:: python
86
    :emphasize-lines: 1
87

    
88
    Example 1.3: Retrieve cyclades and pithos base_url values
89

    
90
    cyclades_endpoints = my_astakos_client.get_service_endpoints('compute')
91
    cyclades_base_url = cyclades_endpoints['publicURL']
92

    
93
    pithos_endpoints = my_astakos_client.get_service_endpoints('object-store')
94
    pithos_base_url = pithos_endpoints['publicURL']
95

    
96
The ``get_service_endpoints`` method gets the service name as an argument. Here
97
are the service names for the most popular kamaki clients::
98

    
99
    storage, pithos     -->     object-store
100
    compute, cyclades   -->     compute
101
    image               -->     image
102
    astakos             -->     identity
103

    
104
Use client methods
105
------------------
106

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

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

    
115

    
116
.. code-block:: python
117
    :emphasize-lines: 1,2
118

    
119
    Example 1.4: Print server name and OS for server with server_id
120
                Print objects in container mycont
121

    
122

    
123
    srv = my_cyclades_client.get_server_info(server_id)
124
    print("Server Name: %s (with OS %s" % (srv['name'], srv['os']))
125

    
126
    obj_list = my_pithos_client.list_objects(mycont)
127
    for obj in obj_list:
128
        print('  %s of %s bytes' % (obj['name'], obj['bytes']))
129

    
130
.. code-block:: console
131
    :emphasize-lines: 1
132

    
133
    Run of examples 1.1 + 1.4
134

    
135

    
136
    $ python test_script.py
137
    Server Name: A Debian Server (with OS Debian Base)
138
      lala.txt of 34 bytes
139
      test.txt of 1232 bytes
140
      testDir/ of 0 bytes
141
    $ 
142

    
143
Error handling
144
--------------
145

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

    
150
A ClientError contains::
151

    
152
    message     The error message.
153
    status      An optional error code, e.g. after a server error.
154
    details     Optional list of messages with error details.
155

    
156
The following example concatenates examples 1.1 to 1.4 plus error handling
157

    
158
.. code-block:: python
159

    
160
    Example 1.5: Error handling
161

    
162
    from kamaki.clients.astakos import AstakosClient
163
    from kamaki.clients.cyclades import CycladesClient
164
    from kamaki.clients.pithos import PithosClient
165

    
166
    try:
167
        my_astakos_client = AstakosClient(AUTHENTICATION_URL, TOKEN)
168
    except ClientError:
169
        print('Failed to authenticate user token')
170
        return 1
171

    
172
    try:
173
        cyclades_endpoints = my_astakos_client.get_service_endpoints('compute')
174
        cyclades_base_url = cyclades_endpoints['publicURL']
175
    except ClientError:
176
        print('Failed to get endpoints for cyclades')
177

    
178
    try:
179
        my_cyclades_client = CycladesClient(cyclades_base_url, token)
180
    except ClientError:
181
        print('Failed to initialize Cyclades client')
182

    
183
    try:
184
        pithos_endpoints = my_astakos_client.get_service_endpoints('object-store')
185
        pithos_base_url = pithos_endpoints['publicURL']
186
    except ClientError:
187
        print('Failed to get endpoints for pithos')
188

    
189
    try:
190
        my_pithos_client = PithosClient(pithos_base_url, token, account, container)
191
    except ClientError:
192
        print('Failed to initialize Pithos+ client')
193

    
194
    try:
195
        srv = my_cyclades_client.get_server_info(server_id)
196
        print("Server Name: %s (with OS %s" % (srv['name'], srv['os']))
197

    
198
        obj_list = my_pithos_client.list_objects(mycont)
199
        for obj in obj_list:
200
            print('  %s of %s bytes' % (obj['name'], obj['bytes']))
201
    except ClientError as e:
202
        print('Error: %s' % e)
203
        if e.status:
204
            print('- error code: %s' % e.status)
205
        if e.details:
206
            for detail in e.details:
207
                print('- %s' % detail)
208

    
209

    
210
Scripts
211
-------
212

    
213
Batch-create servers
214
''''''''''''''''''''
215

    
216
.. code-block:: python
217

    
218
    #! /usr/bin/python
219

    
220
    from kamaki.clients.astakos import AstakosClient
221
    from kamaki.clients.cyclades import CycladesClient
222

    
223
    AUTHENTICATION_URL = 'https://accounts.example.com/identity/v2.0'
224
    TOKEN = 'replace this with your token'
225

    
226
    user = AstakosClient(AUTHENTICATION_URL, TOKEN)
227

    
228
    cyclades_endpoints = user.get_service_endpoints('compute')
229
    CYCLADES_URL = cyclades_endpoints['publicURL']
230
    cyclades = CycladesClient(CYCLADES_URL, TOKEN)
231

    
232
    #  (name, flavor-id, image-id)
233
    servers = [
234
        ('My Debian Server', 1, 'my-debian-base-image-id'),
235
        ('My Windows Server', 3, 'my-windows-8-image-id'),
236
        ('My Ubuntu Server', 3, 'my-ubuntu-12-image-id'),
237
    ]
238

    
239
    for name, flavor_id, image_id in servers:
240
        cyclades.create_server(name, flavor_id, image_id)
241

    
242

    
243
Batch-create 4 servers of the same kind
244
'''''''''''''''''''''''''''''''''''''''
245

    
246
.. code-block:: python
247

    
248
    #! /usr/bin/python
249

    
250
    from kamaki.clients.astakos import AstakosClient
251
    from kamaki.clients.cyclades import CycladesClient
252

    
253
    AUTHENTICATION_URL = 'https://accounts.example.com/identity/v2.0'
254
    TOKEN = 'replace this with your token'
255

    
256
    user = AstakosClient(AUTHENTICATION_URL, TOKEN)
257

    
258
    cyclades_endpoints = user.get_service_endpoints('compute')
259
    CYCLADES_URL = cyclades_endpoints['publicURL']
260
    cyclades = CycladesClient(CYCLADES_URL, TOKEN)
261

    
262
    for i in range(4):
263
        name, flavor_id, image_id = 'Server %s' % (i + 1), 3, 'some-image-id'
264
        cyclades.create_server(name, flavor_id, image_id)
265

    
266
Register a banch of pre-uploaded images
267
'''''''''''''''''''''''''''''''''''''''
268

    
269
.. code-block:: python
270

    
271
    #! /usr/bin/python
272

    
273
    from kamaki.clients import ClientError
274
    from kamaki.clients.astakos import AstakosClient
275
    from kamaki.clients.pithos import PithosClient
276
    from kamaki.clients.image import ImageClient
277

    
278
    AUTHENTICATION_URL = 'https://accounts.example.com/identity/v2.0'
279
    TOKEN = 'replace this with your token'
280
    IMAGE_CONTAINER = 'images'
281

    
282
    astakos = AstakosClient(AUTHENTICATION_URL, TOKEN)
283
    USER_UUID = astakos.user_term('uuid')
284

    
285
    PITHOS_URL = astakos.get_service_endpoints('object-store')['publicURL']
286
    pithos = PithosClient(PITHOS_URL, TOKEN, USER_UUID, IMAGE_CONTAINER)
287

    
288
    IMAGE_URL = astakos.get_service_endpoints('image')['publicURL']
289
    plankton = ImageClient(IMAGE_URL, TOKEN)
290

    
291
    for img in pithos.list_objects():
292
        IMAGE_PATH = img['name']
293
        try:
294
            r = plankton.register(
295
                name='Image %s' % img,
296
                location=(USER_UUID, IMAGE_CONTAINER, IMAGE_PATH))
297
            print 'Image %s registered with id %s' % (r['name'], r['id'])
298
        except ClientError:
299
            print 'Failed to register image %s' % IMAGE_PATH