Revision 16d7b9ff docs/developers/clients-api.rst
b/docs/developers/clients-api.rst | ||
---|---|---|
3 | 3 |
|
4 | 4 |
Kamaki features a clients API for building third-party client applications that |
5 | 5 |
communicate with OpenStack and / or Synnefo cloud services. The package is |
6 |
called kamaki.clients and servers as a lib.
|
|
6 |
called *kamaki.clients* and serves as a lib.
|
|
7 | 7 |
|
8 |
A showcase of an application built on kamaki.clients is kamaki.cli, the command
|
|
9 |
line interface of kamaki. |
|
8 |
A showcase of an application built on *kamaki.clients* is *kamaki.cli*, the
|
|
9 |
command line interface of kamaki.
|
|
10 | 10 |
|
11 | 11 |
Since Synnefo services are build as OpenStack extensions, an inheritance |
12 | 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*). |
|
13 |
the *compute*, *storage* and *image* modules are client implementations for the
|
|
14 |
OpenStack compute and OpenStack object-store APIs, respectively. The rest of the
|
|
15 |
modules implement the Synnefo extensions (i.e., *cyclades* and
|
|
16 |
*cyclades_rest_api* extents *compute*, *pithos* and *pithos_rest_api* extent
|
|
17 |
*storage*) or novel Synnefo services (*image* for *plankton*).
|
|
18 | 18 |
|
19 | 19 |
Setup a client instance |
20 | 20 |
----------------------- |
21 | 21 |
|
22 |
External applications may instantiate one or more kamaki clients. |
|
22 |
There is a client for every API, therefore an external applications should |
|
23 |
instantiate they kamaki clients they need. For example, to manage virtual |
|
24 |
servers and stored objects / files, an application would probably need to |
|
25 |
instantiate the CycladesClient and PithosClient respectively. |
|
23 | 26 |
|
24 | 27 |
.. code-block:: python |
25 | 28 |
:emphasize-lines: 1 |
26 | 29 |
|
27 |
Example 1.1: Instantiate Cyclades and Pithos client |
|
30 |
Example 1.1: Instantiate Cyclades and Pithos clients
|
|
28 | 31 |
|
29 | 32 |
|
30 | 33 |
from kamaki.clients.cyclades import CycladesClient |
... | ... | |
33 | 36 |
my_cyclades_client = CycladesClient(base_url, token) |
34 | 37 |
my_pithos_client = PithosClient(base_url, token, account, container) |
35 | 38 |
|
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.
|
|
39 |
.. note:: *cyclades* and *pithos* clients inherit ComputeClient from *compute*
|
|
40 |
and StorageClient from *storage*, respectively. Separate ComputeClient or
|
|
41 |
StorageClient objects should be used only when implementing applications for
|
|
42 |
strict OpenStack Compute or Storage services.
|
|
40 | 43 |
|
41 | 44 |
Using endpoints to get the base_url |
42 | 45 |
----------------------------------- |
43 | 46 |
|
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. |
|
47 |
In OpenStack, each service (e.g., `compute`, `object-store`, etc.) has a number
|
|
48 |
of `endpoints`. These `endpoints` are actually URIs that are used by kamaki as
|
|
49 |
prefixes to form the corresponding API calls. Client applications need just
|
|
50 |
one of these these `endpoints`, namely the `publicURL`, which is also referred
|
|
51 |
to as `base_url` in kamaki client libraries.
|
|
49 | 52 |
|
50 |
In general, this is the suggested way of getting the base_url::
|
|
53 |
Here are instructions for getting the base_url for a service::
|
|
51 | 54 |
|
52 | 55 |
1. From the deployment UI get the AUTHENTICATION_URL and TOKEN |
53 | 56 |
(Example 1.2) |
... | ... | |
59 | 62 |
(Example 1.3) |
60 | 63 |
|
61 | 64 |
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 |
is an identity server that implements the OpenStack identity API. Therefore, it
|
|
66 |
can be used to get the `base_url` values needed for initializing kamaki clients.
|
|
67 |
Kamaki simplifies this process with the astakos client library. |
|
65 | 68 |
|
66 | 69 |
Let's review the process with examples. |
67 | 70 |
|
... | ... | |
93 | 96 |
pithos_endpoints = my_astakos_client.get_service_endpoints('object-store') |
94 | 97 |
pithos_base_url = pithos_endpoints['publicURL'] |
95 | 98 |
|
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::
|
|
99 |
The ``get_service_endpoints`` method is called with the service name as an
|
|
100 |
argument. Here are the service names for the kamaki clients::
|
|
98 | 101 |
|
99 |
storage, pithos --> object-store
|
|
100 |
compute, cyclades --> compute
|
|
101 |
image --> image |
|
102 |
astakos --> identity
|
|
102 |
storage.StorageClient, pithos.PithosClient --> object-store
|
|
103 |
compute.ComputeClient, cyclades.CycladesClient --> compute
|
|
104 |
image.ImageClient --> image
|
|
105 |
astakos.AstakosClient --> identity, account
|
|
103 | 106 |
|
104 | 107 |
Use client methods |
105 | 108 |
------------------ |
106 | 109 |
|
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 |
At this point we assume that we can initialize a client, so the initialization |
|
111 |
step will be omitted in most of the examples that follow. |
|
112 |
|
|
113 |
The next step is to take a look at the member methods of each particular client. |
|
114 |
A detailed catalog of the member methods for all client classes can be found at |
|
115 |
:ref:`the-client-api-ref` |
|
110 | 116 |
|
111 | 117 |
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. |
|
118 |
are used to extract some information through the remote service APIs. The information is then printed to the standard output. |
|
114 | 119 |
|
115 | 120 |
|
116 | 121 |
.. code-block:: python |
... | ... | |
119 | 124 |
Example 1.4: Print server name and OS for server with server_id |
120 | 125 |
Print objects in container mycont |
121 | 126 |
|
122 |
|
|
123 | 127 |
srv = my_cyclades_client.get_server_info(server_id) |
124 | 128 |
print("Server Name: %s (with OS %s" % (srv['name'], srv['os'])) |
125 | 129 |
|
... | ... | |
130 | 134 |
.. code-block:: console |
131 | 135 |
:emphasize-lines: 1 |
132 | 136 |
|
133 |
Run of examples 1.1 + 1.4
|
|
137 |
* A run of examples 1.1 + 1.4 *
|
|
134 | 138 |
|
135 | 139 |
|
136 | 140 |
$ python test_script.py |
... | ... | |
143 | 147 |
Error handling |
144 | 148 |
-------------- |
145 | 149 |
|
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
|
|
150 |
The *kamaki.clients* error class is ClientError. A ClientError is raised for
|
|
151 |
any kind of *kamaki.clients* errors (errors reported by servers, type errors in
|
|
148 | 152 |
arguments, etc.). |
149 | 153 |
|
150 | 154 |
A ClientError contains:: |
151 | 155 |
|
152 | 156 |
message The error message. |
153 |
status An optional error code, e.g. after a server error. |
|
157 |
status An optional error code, e.g., after a server error.
|
|
154 | 158 |
details Optional list of messages with error details. |
155 | 159 |
|
156 | 160 |
The following example concatenates examples 1.1 to 1.4 plus error handling |
... | ... | |
159 | 163 |
|
160 | 164 |
Example 1.5: Error handling |
161 | 165 |
|
166 |
from kamaki.clients import ClientError |
|
167 |
|
|
162 | 168 |
from kamaki.clients.astakos import AstakosClient |
163 | 169 |
from kamaki.clients.cyclades import CycladesClient |
164 | 170 |
from kamaki.clients.pithos import PithosClient |
165 | 171 |
|
166 | 172 |
try: |
167 | 173 |
my_astakos_client = AstakosClient(AUTHENTICATION_URL, TOKEN) |
174 |
my_astakos_client.authenticate() |
|
168 | 175 |
except ClientError: |
169 | 176 |
print('Failed to authenticate user token') |
170 | 177 |
return 1 |
... | ... | |
297 | 304 |
print 'Image %s registered with id %s' % (r['name'], r['id']) |
298 | 305 |
except ClientError: |
299 | 306 |
print 'Failed to register image %s' % IMAGE_PATH |
307 |
|
|
308 |
Two servers and a private network |
|
309 |
''''''''''''''''''''''''''''''''' |
|
310 |
|
|
311 |
.. code-block:: python |
|
312 |
|
|
313 |
#! /user/bin/python |
|
314 |
|
|
315 |
from kamaki.clients.astakos import AstakosClient |
|
316 |
from kamaki.clients.cyclades import CycladesClient |
|
317 |
|
|
318 |
AUTHENTICATION_URL = 'https://accounts.example.com/identity/v2.0' |
|
319 |
TOKEN = 'replace this with your token' |
|
320 |
|
|
321 |
astakos = AstakosClient(AUTHENTICATION_URL, TOKEN) |
|
322 |
|
|
323 |
cyclades_endpoints = user.get_service_endpoints('compute') |
|
324 |
CYCLADES_URL = cyclades_endpoints['publicURL'] |
|
325 |
|
|
326 |
FLAVOR_ID = 'put your flavor id here' |
|
327 |
IMAGE_ID = 'put your image id here' |
|
328 |
|
|
329 |
cyclades = CycladesClient(CYCLADES_URL, TOKEN) |
|
330 |
|
|
331 |
srv1 = cyclades.create_server('server 1', FLAVOR_ID, IMAGE_ID) |
|
332 |
srv2 = cyclades.create_server('server 2', FLAVOR_ID, IMAGE_ID) |
|
333 |
|
|
334 |
srv_state1 = cyclades.wait_server(srv1['id']) |
|
335 |
assert srv_state1 in ('ACTIVE'), 'Server 1 built failure' |
|
336 |
|
|
337 |
srv_state2 = cyclades.wait_server(srv2['id']) |
|
338 |
assert srv_state2 in ('ACTIVE'), 'Server 2 built failure' |
|
339 |
|
|
340 |
net = cyclades.create_network('My private network') |
|
341 |
net_state = cyclades.wait_network(net['id']) |
|
342 |
assert net_state in ('ACTIVE', ), 'Network built failure' |
|
343 |
|
|
344 |
cyclades.connect_server(srv1['id'], net['id']) |
|
345 |
cyclades.connect_server(srv2['id'], net['id']) |
Also available in: Unified diff