root / docs / developers / clients-api.rst @ cedde35d
History | View | Annotate | Download (8.7 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_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_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) |