Revision 8b4ba753 docs/developers/clients-api.rst
b/docs/developers/clients-api.rst | ||
---|---|---|
2 | 2 |
===================================== |
3 | 3 |
|
4 | 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 serves as a lib. |
|
5 |
communicate with Synnefo and (in most cases) OpenStack cloud services. The package is
|
|
6 |
called *kamaki.clients* and serves as a library.
|
|
7 | 7 |
|
8 | 8 |
A showcase of an application built on *kamaki.clients* is *kamaki.cli*, the |
9 | 9 |
command line interface of kamaki. |
10 | 10 |
|
11 | 11 |
Since Synnefo services are build as OpenStack extensions, an inheritance |
12 |
approach has been chosen for implementing clients for both. In specific, |
|
12 |
approach has been chosen for implementing clients for both APIs. In specific,
|
|
13 | 13 |
the *compute*, *storage* and *image* modules are client implementations for the |
14 | 14 |
OpenStack compute, OpenStack object-store and Image APIs respectively. The rest |
15 | 15 |
of the modules implement the Synnefo extensions (i.e., *cyclades* and |
... | ... | |
19 | 19 |
Setup a client instance |
20 | 20 |
----------------------- |
21 | 21 |
|
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. |
|
22 |
There is a client for every API. An external applications should instantiate |
|
23 |
the kamaki clients that fit their needs. |
|
24 |
|
|
25 |
For example, to manage virtual servers and stored objects / files, an |
|
26 |
application would probably need the CycladesClient and PithosClient |
|
27 |
respectively. |
|
26 | 28 |
|
27 | 29 |
.. code-block:: python |
28 | 30 |
:emphasize-lines: 1 |
... | ... | |
33 | 35 |
from kamaki.clients.cyclades import CycladesClient |
34 | 36 |
from kamaki.clients.pithos import PithosClient |
35 | 37 |
|
36 |
my_cyclades_client = CycladesClient(base_url, token)
|
|
37 |
my_pithos_client = PithosClient(base_url, token, account, container)
|
|
38 |
cyclades = CycladesClient(computeURL, token)
|
|
39 |
pithos = PithosClient(object-storeURL, token, account, container)
|
|
38 | 40 |
|
39 | 41 |
.. note:: *cyclades* and *pithos* clients inherit ComputeClient from *compute* |
40 | 42 |
and StorageClient from *storage*, respectively. Separate ComputeClient or |
41 | 43 |
StorageClient objects should be used only when implementing applications for |
42 | 44 |
strict OpenStack Compute or Storage services. |
43 | 45 |
|
44 |
Using endpoints to get the base_url
|
|
45 |
----------------------------------- |
|
46 |
Using endpoints to get the authentication url
|
|
47 |
---------------------------------------------
|
|
46 | 48 |
|
47 | 49 |
In OpenStack, each service (e.g., `compute`, `object-store`, etc.) has a number |
48 |
of `endpoints`. These `endpoints` are 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.
|
|
50 |
of `endpoints`. These `endpoints` are URIs which are used by kamaki as prefixes
|
|
51 |
to form the corresponding API calls. Client applications need just one of these
|
|
52 |
`endpoints`, namely the `publicURL` (also referred to as `publicURL` in the
|
|
53 |
internals of kamaki client libraries).
|
|
52 | 54 |
|
53 |
Here are instructions for getting the base_url for a service::
|
|
55 |
Here are instructions for getting the publicURL for a service::
|
|
54 | 56 |
|
55 | 57 |
1. From the deployment UI get the AUTHENTICATION_URL and TOKEN |
56 | 58 |
(Example 1.2) |
... | ... | |
58 | 60 |
(Example 1.2) |
59 | 61 |
3. Use AstakosClient instance to get endpoints for the service of interest |
60 | 62 |
(Example 1.3) |
61 |
4. The 'publicURL' endpoint is the base_url we are looking for
|
|
63 |
4. The 'publicURL' endpoint is the URL we are looking for
|
|
62 | 64 |
(Example 1.3) |
63 | 65 |
|
64 | 66 |
The AstakosClient is a client for the Synnefo/Astakos server. Synnefo/Astakos |
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.
|
|
67 |
is an identity server that implements the OpenStack identity API and it
|
|
68 |
can be used to get the URLs needed for API calls URL construction. The astakos
|
|
69 |
kamaki client library simplifies this process.
|
|
68 | 70 |
|
69 |
Let's review the process with examples.
|
|
71 |
Let's review with a few examples.
|
|
70 | 72 |
|
71 | 73 |
First, an astakos client must be initialized (Example 1.2). An |
72 | 74 |
AUTHENTICATION_URL and a TOKEN can be acquired from the Synnefo deployment UI. |
... | ... | |
77 | 79 |
Example 1.2: Initialize an astakos client |
78 | 80 |
|
79 | 81 |
from kamaki.clients.astakos import AstakosClient |
80 |
my_astakos_client = AstakosClient(AUTHENTICATION_URL, TOKEN)
|
|
82 |
astakos = AstakosClient(AUTHENTICATION_URL, TOKEN)
|
|
81 | 83 |
|
82 | 84 |
|
83 |
Next, the astakos client can be used to retrieve the base_url values for the
|
|
84 |
servers of interest. In this case (Example 1.3) they are *cyclades*
|
|
85 |
and *pithos*. A number of endpoints is assigned to each service, but kamaki
|
|
86 |
clients only need the one labeled as ``publicURL``.
|
|
85 |
Next, the astakos client can be used to retrieve the `publicURL` values for the
|
|
86 |
services of interest. In this case (Example 1.3) they are *cyclades* (compute)
|
|
87 |
and *pithos* (object-store). A number of endpoints is related to each service,
|
|
88 |
but kamaki clients only need the ones labeled ``publicURL``.
|
|
87 | 89 |
|
88 | 90 |
.. code-block:: python |
89 | 91 |
:emphasize-lines: 1 |
90 | 92 |
|
91 |
Example 1.3: Retrieve cyclades and pithos base_url values
|
|
93 |
Example 1.3: Retrieve cyclades and pithos publicURL values
|
|
92 | 94 |
|
93 |
cyclades_endpoints = my_astakos_client.get_service_endpoints('compute')
|
|
94 |
cyclades_base_url = cyclades_endpoints['publicURL']
|
|
95 |
cyclades_endpoints = astakos.get_service_endpoints('compute')
|
|
96 |
cyclades_URL = cyclades_endpoints['publicURL']
|
|
95 | 97 |
|
96 |
pithos_endpoints = my_astakos_client.get_service_endpoints('object-store')
|
|
97 |
pithos_base_url = pithos_endpoints['publicURL']
|
|
98 |
pithos_endpoints = astakos.get_service_endpoints('object-store')
|
|
99 |
pithos_URL = pithos_endpoints['publicURL']
|
|
98 | 100 |
|
99 | 101 |
The ``get_service_endpoints`` method is called with the service name as an |
100 | 102 |
argument. Here are the service names for the kamaki clients:: |
... | ... | |
105 | 107 |
image.ImageClient --> image |
106 | 108 |
astakos.AstakosClient --> identity, account |
107 | 109 |
|
110 |
For example |
|
111 |
|
|
112 |
.. code-block:: python |
|
113 |
:emphasize-lines: 1 |
|
114 |
|
|
115 |
Example 1.3.1 Initialize cyclades and pithos clients |
|
116 |
|
|
117 |
from kamaki.clients.cyclades import CycladesClient |
|
118 |
from kamaki.clients.pithos import PithosClient |
|
119 |
|
|
120 |
cyclades = CycladesClient(cyclades_URL, TOKEN) |
|
121 |
pithos = PithosClient(pithos_URL, TOKEN) |
|
122 |
|
|
123 |
# Also, setup the account UUID and container for pithos client |
|
124 |
pithos.account = astakos.user_info['id'] |
|
125 |
pithos.container = 'pithos' |
|
126 |
|
|
108 | 127 |
Use client methods |
109 | 128 |
------------------ |
110 | 129 |
|
... | ... | |
116 | 135 |
:ref:`the-client-api-ref` |
117 | 136 |
|
118 | 137 |
In the following example, the *cyclades* and *pithos* clients of example 1.1 |
119 |
are used to extract some information through the remote service APIs. The information is then printed to the standard output. |
|
138 |
are used to extract some information through the remote service APIs. The |
|
139 |
information is then printed to the standard output. |
|
120 | 140 |
|
121 | 141 |
|
122 | 142 |
.. code-block:: python |
123 | 143 |
:emphasize-lines: 1,2 |
124 | 144 |
|
125 | 145 |
Example 1.4: Print server name and OS for server with server_id |
126 |
Print objects in container mycont
|
|
146 |
Print objects in default container
|
|
127 | 147 |
|
128 |
srv = my_cyclades_client.get_server_info(server_id)
|
|
148 |
srv = cyclades.get_server_info(server_id)
|
|
129 | 149 |
print("Server Name: %s (with OS %s" % (srv['name'], srv['os'])) |
130 | 150 |
|
131 |
obj_list = my_pithos_client.list_objects(mycont) |
|
151 |
obj_list = pithos.list_objects() |
|
152 |
print("Objects in container '%s':" % pithos.container) |
|
132 | 153 |
for obj in obj_list: |
133 | 154 |
print(' %s of %s bytes' % (obj['name'], obj['bytes'])) |
134 | 155 |
|
... | ... | |
140 | 161 |
|
141 | 162 |
$ python test_script.py |
142 | 163 |
Server Name: A Debian Server (with OS Debian Base) |
164 |
Objects in container 'pithos': |
|
143 | 165 |
lala.txt of 34 bytes |
144 | 166 |
test.txt of 1232 bytes |
145 | 167 |
testDir/ of 0 bytes |
... | ... | |
150 | 172 |
|
151 | 173 |
The *kamaki.clients* error class is ClientError. A ClientError is raised for |
152 | 174 |
any kind of *kamaki.clients* errors (errors reported by servers, type errors in |
153 |
arguments, etc.). |
|
175 |
method arguments, etc.).
|
|
154 | 176 |
|
155 | 177 |
A ClientError contains:: |
156 | 178 |
|
... | ... | |
171 | 193 |
from kamaki.clients.pithos import PithosClient |
172 | 194 |
|
173 | 195 |
try: |
174 |
my_astakos_client = AstakosClient(AUTHENTICATION_URL, TOKEN) |
|
175 |
my_astakos_client.authenticate() |
|
196 |
astakos = AstakosClient(AUTHENTICATION_URL, TOKEN) |
|
176 | 197 |
except ClientError: |
177 | 198 |
print('Failed to authenticate user token') |
178 | 199 |
return 1 |
179 | 200 |
|
180 | 201 |
try: |
181 |
cyclades_endpoints = my_astakos_client.get_service_endpoints('compute')
|
|
182 |
cyclades_base_url = cyclades_endpoints['publicURL']
|
|
202 |
cyclades_endpoints = astakos.get_service_endpoints('compute')
|
|
203 |
cyclades_publicURL = cyclades_endpoints['publicURL']
|
|
183 | 204 |
except ClientError: |
184 | 205 |
print('Failed to get endpoints for cyclades') |
185 | 206 |
|
186 | 207 |
try: |
187 |
my_cyclades_client = CycladesClient(cyclades_base_url, token)
|
|
208 |
cyclades = CycladesClient(cyclades_publicURL, token)
|
|
188 | 209 |
except ClientError: |
189 | 210 |
print('Failed to initialize Cyclades client') |
190 | 211 |
|
191 | 212 |
try: |
192 |
pithos_endpoints = my_astakos_client.get_service_endpoints('object-store')
|
|
193 |
pithos_base_url = pithos_endpoints['publicURL']
|
|
213 |
pithos_endpoints = astakos.get_service_endpoints('object-store')
|
|
214 |
pithos_publicURL = pithos_endpoints['publicURL']
|
|
194 | 215 |
except ClientError: |
195 | 216 |
print('Failed to get endpoints for pithos') |
196 | 217 |
|
197 | 218 |
try: |
198 |
my_pithos_client = PithosClient(pithos_base_url, token, account, container)
|
|
219 |
pithos = PithosClient(pithos_publicURL, token, account, container)
|
|
199 | 220 |
except ClientError: |
200 | 221 |
print('Failed to initialize Pithos+ client') |
201 | 222 |
|
202 | 223 |
try: |
203 |
srv = my_cyclades_client.get_server_info(server_id)
|
|
224 |
srv = cyclades.get_server_info(server_id)
|
|
204 | 225 |
print("Server Name: %s (with OS %s" % (srv['name'], srv['os'])) |
205 | 226 |
|
206 |
obj_list = my_pithos_client.list_objects(mycont)
|
|
227 |
obj_list = pithos.list_objects()
|
|
207 | 228 |
for obj in obj_list: |
208 | 229 |
print(' %s of %s bytes' % (obj['name'], obj['bytes'])) |
209 | 230 |
except ClientError as e: |
Also available in: Unified diff