Revision cf862450 docs/developers/showcase.rst
b/docs/developers/showcase.rst | ||
---|---|---|
218 | 218 |
FLAVOR_ID = 42 |
219 | 219 |
IMAGE_ID = image['id'] |
220 | 220 |
CLUSTER_SIZE = 2 |
221 |
CLUSTER_PREFIX = 'cluster'
|
|
221 |
CLUSTER_PREFIX = 'node'
|
|
222 | 222 |
|
223 | 223 |
# 4.1 Initialize a cyclades client |
224 | 224 |
try: |
... | ... | |
232 | 232 |
for i in range(1, CLUSTER_SIZE + 1): |
233 | 233 |
server_name = '%s%s' % (CLUSTER_PREFIX, i) |
234 | 234 |
try: |
235 |
servers.append( |
|
236 |
cyclades.create_server(server_name, FLAVOR_ID, IMAGE_ID))
|
|
235 |
servers.append(cyclades.create_server(
|
|
236 |
server_name, FLAVOR_ID, IMAGE_ID, networks=[]))
|
|
237 | 237 |
except ClientError: |
238 | 238 |
stderr.write('Failed while creating server %s\n' % server_name) |
239 | 239 |
raise |
240 | 240 |
|
241 |
.. note:: the **networks=[]** parameter instructs the service to not connect |
|
242 |
the server on any networks. |
|
243 |
|
|
244 |
Networking |
|
245 |
---------- |
|
246 |
|
|
247 |
There are public and private networks. |
|
248 |
|
|
249 |
Public networks are managed by the service administrators. Public IPs, though, |
|
250 |
can be handled through the API: clients can create (reserve) and destroy |
|
251 |
(release) IPs from/to the network pool and attach them on their virtual |
|
252 |
devices. |
|
253 |
|
|
254 |
Private networks can be created by clients and they are considered a user |
|
255 |
resource, limited by user quotas. |
|
256 |
|
|
257 |
Ports are the connections between virtual servers and networks. This is the |
|
258 |
case for IP attachments as well as private network connections. |
|
259 |
|
|
260 |
.. code-block:: python |
|
261 |
|
|
262 |
# 5.1 Initialize a network client |
|
263 |
from kamaki.clients.cyclades import CycladesNetworkClient |
|
264 |
|
|
265 |
try: |
|
266 |
network = CycladesNetworkClient(endpoints['network'], AUTH_TOKEN) |
|
267 |
except ClientError: |
|
268 |
stderr.write('Failed to initialize network client\n') |
|
269 |
raise |
|
270 |
|
|
271 |
# 5.2 Pick a public network |
|
272 |
try: |
|
273 |
public_networks = [ |
|
274 |
net for net in network.list_networks() if net.get('public')] |
|
275 |
except ClientError: |
|
276 |
stderr.write('Failed while listing networks\n') |
|
277 |
raise |
|
278 |
try: |
|
279 |
public_net = public_networks[0] |
|
280 |
except IndexError: |
|
281 |
stderr.write('No public networks\n') |
|
282 |
raise |
|
283 |
|
|
284 |
# 5.3 Reserve IPs and attach them on the servers |
|
285 |
ips = list() |
|
286 |
for vm in servers: |
|
287 |
try: |
|
288 |
ips.append(network.create_floatingip(public_net['id'])) |
|
289 |
addr = ips[-1]['floating_ip_address'] |
|
290 |
stderr.write(' Reserved IP %s\n' % addr) |
|
291 |
|
|
292 |
network.create_port( |
|
293 |
public_net['id'], vm['id'], fixed_ips=dict(ip_address=addr)) |
|
294 |
except ClientError: |
|
295 |
stderr.write('Failed to attach an IP on virtual server %s\n' % ( |
|
296 |
vm['id'])) |
|
297 |
raise |
|
298 |
|
|
299 |
# 5.4 Create a private network |
|
300 |
try: |
|
301 |
private_net = network.create_network('MAC_FILTERED') |
|
302 |
except ClientError: |
|
303 |
stderr.write('Failed to create private network\n') |
|
304 |
raise |
|
305 |
|
|
306 |
# 5.5 Connect server on the private network |
|
307 |
for vm in servers: |
|
308 |
try: |
|
309 |
network.create_port(private_net['id'], vm['id']) |
|
310 |
except ClientError: |
|
311 |
stderr.write('Failed to connect server %s on network %s\n' % ( |
|
312 |
vm['id'], private_net['id'])) |
|
313 |
raise |
|
314 |
|
|
241 | 315 |
Some improvements |
242 | 316 |
----------------- |
243 | 317 |
|
... | ... | |
309 | 383 |
|
310 | 384 |
# 4.3 Wait for servers to built |
311 | 385 |
for server in servers: |
312 |
cyclades.wait_server(server['id']) |
|
386 |
st = cyclades.wait_server(server['id']) |
|
387 |
assert st == 'ACTIVE', 'Server built failed with status %s\n' % st |
|
388 |
|
|
389 |
Wait for ports to built |
|
390 |
''''''''''''''''''''''' |
|
391 |
|
|
392 |
A connect (port) may take more than a moment to be created. A wait method can |
|
393 |
stall the execution of the program until the port built has finished |
|
394 |
(successfully or with an error). |
|
395 |
|
|
396 |
.. code-block:: python |
|
397 |
|
|
398 |
# 5.3 Reserve IPs and attach them on the servers |
|
399 |
... |
|
400 |
port = network.create_port( |
|
401 |
public_net['id'], vm['id'], fixed_ips=dict(ip_address=addr)) |
|
402 |
st = network.wait_port(port['id']) |
|
403 |
assert st == 'ACTIVE', 'Connection failed with status %s\n' % st |
|
313 | 404 |
|
314 | 405 |
Asynchronous server creation |
315 | 406 |
'''''''''''''''''''''''''''' |
... | ... | |
326 | 417 |
flavor_id=FLAVOR_ID, |
327 | 418 |
image_id=IMAGE_ID) for i in range(1, CLUSTER_SIZE + 1)] |
328 | 419 |
try: |
329 |
servers = cyclades.async_run(cyclades.create_server, create_params) |
|
420 |
servers = cyclades.async_run(cyclades.create_server, create_params, networks=[])
|
|
330 | 421 |
except ClientError: |
331 | 422 |
stderr.write('Failed while creating servers\n') |
332 | 423 |
raise |
... | ... | |
353 | 444 |
# 4.3 Create 2 servers prefixed as "cluster" |
354 | 445 |
... |
355 | 446 |
|
447 |
Clean up unused networks and IPs |
|
448 |
'''''''''''''''''''''''''''''''' |
|
449 |
|
|
450 |
IPs and private networks are limited resources. This script identifies unused |
|
451 |
IPs and private networks and destroys them. We know if an IP or private network |
|
452 |
is being used by checking whether a port (connection) is associated with them. |
|
453 |
|
|
454 |
.. code-block:: python |
|
455 |
|
|
456 |
unused_ips = [ |
|
457 |
ip for ip in network.list_floatingips() if not ip['port_id']] |
|
458 |
|
|
459 |
for ip in unused_ips: |
|
460 |
network.delete_floatingip(ip['id']) |
|
461 |
|
|
462 |
used_net_ids = set([port['network_id'] for port in network.list_ports()]) |
|
463 |
unused_nets = [net for net in network.list_ports() if not ( |
|
464 |
net['public'] or net['id'] in used_net_ids)] |
|
465 |
|
|
466 |
for net in unused_nets: |
|
467 |
network.delete_network(net['id']) |
|
468 |
|
|
356 | 469 |
Inject ssh keys |
357 | 470 |
''''''''''''''' |
358 | 471 |
|
... | ... | |
604 | 717 |
raise |
605 | 718 |
|
606 | 719 |
|
720 |
def init_network(endpoint, token): |
|
721 |
from kamaki.clients.cyclades import CycladesNetworkClient |
|
722 |
|
|
723 |
print(' Initialize a network client') |
|
724 |
try: |
|
725 |
return CycladesNetworkClient(endpoint, token) |
|
726 |
except ClientError: |
|
727 |
log.debug('Failed to initialize a network Client') |
|
728 |
raise |
|
729 |
|
|
730 |
|
|
731 |
def connect_servers(network, servers): |
|
732 |
print 'Create a private network' |
|
733 |
try: |
|
734 |
net = network.create_network('MAC_FILTERED', 'A private network') |
|
735 |
except ClientError: |
|
736 |
log.debug('Failed to create a private network') |
|
737 |
raise |
|
738 |
|
|
739 |
for vm in servers: |
|
740 |
port = network.create_port(net['id'], vm['id']) |
|
741 |
msg = 'Connection server %s to network %s' % (vm['id'], net['id']) |
|
742 |
network.wait_port(port['id'], wait_cb=create_pb(msg)) |
|
743 |
|
|
744 |
|
|
607 | 745 |
# Compute / Cyclades |
608 | 746 |
|
609 | 747 |
def init_cyclades(endpoint, token): |
Also available in: Unified diff