root / docs / developers / clients-api.rst @ 6362f3e1
History | View | Annotate | Download (7.8 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 initialize services |
42 |
-------------------------------------- |
43 |
|
44 |
The OpenStack identity service, which is implemented my the Synnefo/Astakos |
45 |
server, can be used to get the base_url values needed for initializing any |
46 |
kamaki client. Kamaki simplifies this proccess with the astakos client. |
47 |
|
48 |
First, an astakos client must be initialized (Example 1.2). An |
49 |
AUTHENTICATION_URL and a TOKEN can be acquired from the synnefo deployment UI. |
50 |
|
51 |
.. code-block:: python |
52 |
:emphasize-lines: 1 |
53 |
|
54 |
Example 1.2: Initialize an astakos client |
55 |
|
56 |
from kamaki.clients.astakos import AstakosClient |
57 |
my_astakos_client = AstakosClient(AUTHENTICATION_URL, TOKEN) |
58 |
|
59 |
|
60 |
Next, the astakos client can be used to retrieve the base_url values for the |
61 |
servcers of interest. In this case (Example 1.3) they are *cyclades* |
62 |
and *pithos*. A number of endpoints is assigned to each service, but kamaki |
63 |
clients only need the one labeled as ``publicURL``. |
64 |
|
65 |
.. code-block:: python |
66 |
:emphasize-lines: 1 |
67 |
|
68 |
Example 1.3: Retrieve cyclades and pithos base_url values |
69 |
|
70 |
cyclades_endpoints = my_astakos_client.get_service_endpoints('compute') |
71 |
cyclades_base_url = cyclades_endpoints['publicURL'] |
72 |
|
73 |
pithos_endpoints = my_astakos_client.get_service_endpoints('object-store') |
74 |
pithos_base_url = pithos_endpoints['publicURL'] |
75 |
|
76 |
The ``get_service_endpoints`` method gets the service name as an argument. Here |
77 |
are the service names for the most popular kamaki clients:: |
78 |
|
79 |
storage, pithos --> object-store |
80 |
compute, cyclades --> compute |
81 |
image --> image |
82 |
astakos --> identity |
83 |
|
84 |
Use client methods |
85 |
------------------ |
86 |
|
87 |
Client methods can now be called. Developers are advised to |
88 |
consult :ref:`the-client-api-ref` for details on the available methods and how |
89 |
to use them. |
90 |
|
91 |
In the following example, the *cyclades* and *pithos* clients of example 1.1 |
92 |
are used to extract some information, that is then printed to the standard |
93 |
output. |
94 |
|
95 |
|
96 |
.. code-block:: python |
97 |
:emphasize-lines: 1,2 |
98 |
|
99 |
Example 1.4: Print server name and OS for server with server_id |
100 |
Print objects in container mycont |
101 |
|
102 |
|
103 |
srv = my_cyclades_client.get_server_info(server_id) |
104 |
print("Server Name: %s (with OS %s" % (srv['name'], srv['os'])) |
105 |
|
106 |
obj_list = my_pithos_client.list_objects(mycont) |
107 |
for obj in obj_list: |
108 |
print(' %s of %s bytes' % (obj['name'], obj['bytes'])) |
109 |
|
110 |
.. code-block:: console |
111 |
:emphasize-lines: 1 |
112 |
|
113 |
Run of examples 1.1 + 1.4 |
114 |
|
115 |
|
116 |
$ python test_script.py |
117 |
Server Name: A Debian Server (with OS Debian Base) |
118 |
lala.txt of 34 bytes |
119 |
test.txt of 1232 bytes |
120 |
testDir/ of 0 bytes |
121 |
$ |
122 |
|
123 |
Error handling |
124 |
-------------- |
125 |
|
126 |
The kamaki.clients standard error is ClientError. A ClientError is raised for |
127 |
any kind of kamaki.clients errors (errors reported by servers, type errors in |
128 |
arguments, etc.). |
129 |
|
130 |
A ClientError contains:: |
131 |
|
132 |
message The error message. |
133 |
status An optional error code, e.g. after a server error. |
134 |
details Optional list of messages with error details. |
135 |
|
136 |
The following example concatenates examples 1.1 to 1.4 plus error handling |
137 |
|
138 |
.. code-block:: python |
139 |
|
140 |
Example 1.5: Error handling |
141 |
|
142 |
from kamaki.clients.astakos import AstakosClient |
143 |
from kamaki.clients.cyclades import CycladesClient |
144 |
from kamaki.clients.pithos import PithosClient |
145 |
|
146 |
try: |
147 |
my_astakos_client = AstakosClient(AUTHENTICATION_URL, TOKEN) |
148 |
except ClientError: |
149 |
print('Failed to authenticate user token') |
150 |
return 1 |
151 |
|
152 |
try: |
153 |
cyclades_endpoints = my_astakos_client.get_service_endpoints('compute') |
154 |
cyclades_base_url = cyclades_endpoints['publicURL'] |
155 |
except ClientError: |
156 |
print('Failed to get endpoints for cyclades') |
157 |
|
158 |
try: |
159 |
my_cyclades_client = CycladesClient(cyclades_base_url, token) |
160 |
except ClientError: |
161 |
print('Failed to initialize Cyclades client') |
162 |
|
163 |
try: |
164 |
pithos_endpoints = my_astakos_client.get_service_endpoints('object-store') |
165 |
pithos_base_url = pithos_endpoints['publicURL'] |
166 |
except ClientError: |
167 |
print('Failed to get endpoints for pithos') |
168 |
|
169 |
try: |
170 |
my_pithos_client = PithosClient(pithos_base_url, token, account, container) |
171 |
except ClientError: |
172 |
print('Failed to initialize Pithos+ client') |
173 |
|
174 |
try: |
175 |
srv = my_cyclades_client.get_server_info(server_id) |
176 |
print("Server Name: %s (with OS %s" % (srv['name'], srv['os'])) |
177 |
|
178 |
obj_list = my_pithos_client.list_objects(mycont) |
179 |
for obj in obj_list: |
180 |
print(' %s of %s bytes' % (obj['name'], obj['bytes'])) |
181 |
except ClientError as e: |
182 |
print('Error: %s' % e) |
183 |
if e.status: |
184 |
print('- error code: %s' % e.status) |
185 |
if e.details: |
186 |
for detail in e.details: |
187 |
print('- %s' % detail) |
188 |
|
189 |
|
190 |
Scripts |
191 |
------- |
192 |
|
193 |
Batch-create servers |
194 |
'''''''''''''''''''' |
195 |
|
196 |
.. code-block:: python |
197 |
|
198 |
#/usr/bin/python |
199 |
|
200 |
from kamaki.clients.astakos import AstakosClient |
201 |
from kamaki.clients.cyclades import CycladesClient |
202 |
|
203 |
AUTHENTICATION_URL = 'https://accounts.example.com/identity/v2.0' |
204 |
TOKEN = 'replace this with your token' |
205 |
|
206 |
user = AstakosClient(AUTHENTICATION_URL, TOKEN) |
207 |
|
208 |
cyclades_endpoints = user.get_endpoints('compute') |
209 |
CYCLADES_URL = cyclades_endpoints['publicURL'] |
210 |
cyclades = CycladesClient(CYCLADES_URL, TOKEN) |
211 |
|
212 |
# (name, flavor-id, image-id) |
213 |
servers = [ |
214 |
('My Debian Server', 1, 'my-debian-base-image-id'), |
215 |
('My Windows Server', 3, 'my-windows-8-image-id'), |
216 |
('My Ubuntu Server', 3, 'my-ubuntu-12-image-id'), |
217 |
] |
218 |
|
219 |
for name, flavor_id, image_id in servers: |
220 |
cyclades.create_server(name, flavor_id, image_id) |
221 |
|
222 |
|
223 |
Batch-create 4 servers of the same kind |
224 |
''''''''''''''''''''''''''''''''''''''' |
225 |
|
226 |
.. code-block:: python |
227 |
|
228 |
#/usr/bin/python |
229 |
|
230 |
from kamaki.clients.astakos import AstakosClient |
231 |
from kamaki.clients.cyclades import CycladesClient |
232 |
|
233 |
AUTHENTICATION_URL = 'https://accounts.example.com/identity/v2.0' |
234 |
TOKEN = 'replace this with your token' |
235 |
|
236 |
user = AstakosClient(AUTHENTICATION_URL, TOKEN) |
237 |
|
238 |
cyclades_endpoints = user.get_endpoints('compute') |
239 |
CYCLADES_URL = cyclades_endpoints['publicURL'] |
240 |
cyclades = CycladesClient(CYCLADES_URL, TOKEN) |
241 |
|
242 |
for i in range(4): |
243 |
name, flavor_id, image_id = 'Server %s' % (i + 1), 3, 'some-image-id' |
244 |
cyclades.create_server(name, flavor_id, image_id) |