Revision fe29fb25
b/snf-tools/cloud | ||
---|---|---|
33 | 33 |
# interpreted as representing official policies, either expressed |
34 | 34 |
# or implied, of GRNET S.A. |
35 | 35 |
|
36 |
from httplib import HTTPConnection |
|
36 |
from httplib import HTTPConnection, HTTPSConnection
|
|
37 | 37 |
from optparse import OptionParser |
38 | 38 |
from os.path import basename |
39 | 39 |
from sys import argv, exit |
40 |
from urlparse import urlparse |
|
40 | 41 |
|
41 | 42 |
import json |
42 | 43 |
|
43 |
DEFAULT_HOST = '127.0.0.1:8000' |
|
44 |
DEFAULT_API = 'v1.1' |
|
45 | 44 |
|
46 |
TOKEN = '46e427d657b20defe352804f0eb6f8a2' |
|
45 |
DEFAULT_API_URL = 'http://127.0.0.1:8000/api/v1.1' |
|
46 |
DEFAULT_TOKEN = '46e427d657b20defe352804f0eb6f8a2' |
|
47 | 47 |
|
48 | 48 |
MARGIN = 14 |
49 | 49 |
|
... | ... | |
84 | 84 |
class Command(object): |
85 | 85 |
def __init__(self, argv): |
86 | 86 |
parser = OptionParser() |
87 |
parser.add_option('--host', dest='host', metavar='HOST', default=DEFAULT_HOST, |
|
88 |
help='use server HOST') |
|
89 |
parser.add_option('--api', dest='api', metavar='API', default=DEFAULT_API, |
|
87 |
parser.add_option('--apiurl', |
|
88 |
dest='apiurl', |
|
89 |
metavar='URL', |
|
90 |
default=DEFAULT_API_URL, |
|
90 | 91 |
help='use api API') |
91 |
parser.add_option('-v', action='store_true', dest='verbose', default=False, |
|
92 |
parser.add_option('--token', |
|
93 |
dest='token', |
|
94 |
metavar='TOKEN', |
|
95 |
default=DEFAULT_TOKEN, |
|
96 |
help='use user token TOKEN') |
|
97 |
parser.add_option('-v', |
|
98 |
action='store_true', |
|
99 |
dest='verbose', |
|
100 |
default=False, |
|
92 | 101 |
help='use verbose output') |
93 | 102 |
self.add_options(parser) |
94 | 103 |
options, args = parser.parse_args(argv) |
... | ... | |
109 | 118 |
pass |
110 | 119 |
|
111 | 120 |
def http_cmd(self, method, path, body=None, expected_status=200): |
112 |
conn = HTTPConnection(self.host) |
|
121 |
p = urlparse(self.apiurl) |
|
122 |
if p.scheme == 'https': |
|
123 |
conn = HTTPSConnection(p.netloc) |
|
124 |
else: |
|
125 |
conn = HTTPConnection(p.netloc) |
|
113 | 126 |
|
114 | 127 |
kwargs = {} |
115 |
kwargs['headers'] = {'X-Auth-Token': TOKEN}
|
|
128 |
kwargs['headers'] = {'X-Auth-Token': self.token}
|
|
116 | 129 |
if body: |
117 | 130 |
kwargs['headers']['Content-Type'] = 'application/json' |
118 | 131 |
kwargs['body'] = body |
119 |
conn.request(method, path, **kwargs) |
|
132 |
conn.request(method, p.path + path, **kwargs)
|
|
120 | 133 |
|
121 | 134 |
resp = conn.getresponse() |
122 | 135 |
if self.verbose: |
... | ... | |
174 | 187 |
help='include empty values') |
175 | 188 |
|
176 | 189 |
def execute(self): |
177 |
path = '/api/%s/servers' % self.api |
|
178 |
if self.detail: |
|
179 |
path += '/detail' |
|
180 |
|
|
190 |
path = '/servers/detail' if self.detail else '/servers' |
|
181 | 191 |
reply = self.http_get(path) |
182 | 192 |
|
183 | 193 |
for server in reply['servers']['values']: |
... | ... | |
201 | 211 |
help='include empty values') |
202 | 212 |
|
203 | 213 |
def execute(self, server_id): |
204 |
path = '/api/%s/servers/%d' % (self.api, int(server_id))
|
|
214 |
path = '/servers/%d' % int(server_id)
|
|
205 | 215 |
reply = self.http_get(path) |
206 | 216 |
server = reply['server'] |
207 | 217 |
server.pop('id') |
... | ... | |
220 | 230 |
help='use image IMAGE_ID') |
221 | 231 |
|
222 | 232 |
def execute(self, name): |
223 |
path = '/api/%s/servers' % self.api |
|
224 |
server = {'name': name, 'flavorRef': self.flavor, 'imageRef': self.image} |
|
233 |
server = { |
|
234 |
'name': name, |
|
235 |
'flavorRef': self.flavor, |
|
236 |
'imageRef': self.image} |
|
225 | 237 |
body = json.dumps({'server': server}) |
226 |
reply = self.http_post(path, body)
|
|
238 |
reply = self.http_post('/servers', body)
|
|
227 | 239 |
server = reply['server'] |
228 | 240 |
print_dict(server) |
229 | 241 |
|
... | ... | |
234 | 246 |
syntax = '<server id> <new name>' |
235 | 247 |
|
236 | 248 |
def execute(self, server_id, name): |
237 |
path = '/api/%s/servers/%d' % (self.api, int(server_id))
|
|
249 |
path = '/servers/%d' % int(server_id)
|
|
238 | 250 |
body = json.dumps({'server': {'name': name}}) |
239 | 251 |
self.http_put(path, body) |
240 | 252 |
|
... | ... | |
245 | 257 |
syntax = '<server id>' |
246 | 258 |
|
247 | 259 |
def execute(self, server_id): |
248 |
path = '/api/%s/servers/%d' % (self.api, int(server_id))
|
|
260 |
path = '/servers/%d' % int(server_id)
|
|
249 | 261 |
self.http_delete(path) |
250 | 262 |
|
251 | 263 |
|
... | ... | |
259 | 271 |
help='perform a hard reboot') |
260 | 272 |
|
261 | 273 |
def execute(self, server_id): |
262 |
path = '/api/%s/servers/%d/action' % (self.api, int(server_id))
|
|
274 |
path = '/servers/%d/action' % int(server_id)
|
|
263 | 275 |
type = 'HARD' if self.hard else 'SOFT' |
264 | 276 |
body = json.dumps({'reboot': {'type': type}}) |
265 | 277 |
self.http_post(path, body) |
... | ... | |
271 | 283 |
syntax = '<server id>' |
272 | 284 |
|
273 | 285 |
def execute(self, server_id): |
274 |
path = '/api/%s/servers/%d/action' % (self.api, int(server_id))
|
|
286 |
path = '/servers/%d/action' % int(server_id)
|
|
275 | 287 |
body = json.dumps({'start': {}}) |
276 | 288 |
self.http_post(path, body) |
277 | 289 |
|
... | ... | |
282 | 294 |
syntax = '<server id>' |
283 | 295 |
|
284 | 296 |
def execute(self, server_id): |
285 |
path = '/api/%s/servers/%d/action' % (self.api, int(server_id))
|
|
297 |
path = '/servers/%d/action' % int(server_id)
|
|
286 | 298 |
body = json.dumps({'shutdown': {}}) |
287 | 299 |
self.http_post(path, body) |
288 | 300 |
|
... | ... | |
293 | 305 |
syntax = '<server id>' |
294 | 306 |
|
295 | 307 |
def execute(self, server_id): |
296 |
path = '/api/%s/servers/%d/action' % (self.api, int(server_id))
|
|
308 |
path = '/servers/%d/action' % int(server_id)
|
|
297 | 309 |
body = json.dumps({'console': {'type': 'vnc'}}) |
298 | 310 |
reply = self.http_cmd('POST', path, body, 200) |
299 | 311 |
print_dict(reply['console']) |
... | ... | |
305 | 317 |
syntax = '<server id> <profile>' |
306 | 318 |
|
307 | 319 |
def execute(self, server_id, profile): |
308 |
path = '/api/%s/servers/%d/action' % (self.api, int(server_id))
|
|
320 |
path = '/servers/%d/action' % int(server_id)
|
|
309 | 321 |
body = json.dumps({'firewallProfile': {'profile': profile}}) |
310 | 322 |
self.http_cmd('POST', path, body, 202) |
311 | 323 |
|
... | ... | |
316 | 328 |
syntax = '<server id> [network]' |
317 | 329 |
|
318 | 330 |
def execute(self, server_id, network=None): |
319 |
path = '/api/%s/servers/%d/ips' % (self.api, int(server_id))
|
|
331 |
path = '/servers/%d/ips' % int(server_id)
|
|
320 | 332 |
if network: |
321 | 333 |
path += '/%s' % network |
322 | 334 |
reply = self.http_get(path) |
... | ... | |
334 | 346 |
help='show detailed output') |
335 | 347 |
|
336 | 348 |
def execute(self): |
337 |
path = '/api/%s/flavors' % self.api |
|
338 |
if self.detail: |
|
339 |
path += '/detail' |
|
349 |
path = '/flavors/detail' if self.detail else '/flavors' |
|
340 | 350 |
reply = self.http_get(path) |
341 | 351 |
|
342 | 352 |
for flavor in reply['flavors']['values']: |
... | ... | |
352 | 362 |
syntax = '<flavor id>' |
353 | 363 |
|
354 | 364 |
def execute(self, flavor_id): |
355 |
path = '/api/%s/flavors/%d' % (self.api, int(flavor_id))
|
|
365 |
path = '/flavors/%d' % int(flavor_id)
|
|
356 | 366 |
reply = self.http_get(path) |
357 | 367 |
|
358 | 368 |
flavor = reply['flavor'] |
... | ... | |
371 | 381 |
help='show detailed output') |
372 | 382 |
|
373 | 383 |
def execute(self): |
374 |
path = '/api/%s/images' % self.api |
|
375 |
if self.detail: |
|
376 |
path += '/detail' |
|
384 |
path = '/images/detail' if self.detail else '/images' |
|
377 | 385 |
reply = self.http_get(path) |
378 | 386 |
|
379 | 387 |
for image in reply['images']['values']: |
... | ... | |
393 | 401 |
syntax = '<image id>' |
394 | 402 |
|
395 | 403 |
def execute(self, image_id): |
396 |
path = '/api/%s/images/%d' % (self.api, int(image_id))
|
|
404 |
path = '/images/%d' % int(image_id)
|
|
397 | 405 |
reply = self.http_get(path) |
398 | 406 |
image = reply['image'] |
399 | 407 |
image.pop('id') |
... | ... | |
406 | 414 |
syntax = '<server id> <image name>' |
407 | 415 |
|
408 | 416 |
def execute(self, server_id, name): |
409 |
path = '/api/%s/images' % self.api |
|
410 | 417 |
image = {'name': name, 'serverRef': int(server_id)} |
411 | 418 |
body = json.dumps({'image': image}) |
412 |
reply = self.http_post(path, body)
|
|
419 |
reply = self.http_post('/images', body)
|
|
413 | 420 |
print_dict(reply['image']) |
414 | 421 |
|
415 | 422 |
@command_name('deleteimg') |
... | ... | |
418 | 425 |
syntax = '<image id>' |
419 | 426 |
|
420 | 427 |
def execute(self, image_id): |
421 |
path = '/api/%s/images/%d' % (self.api, int(image_id))
|
|
428 |
path = '/images/%d' % int(image_id)
|
|
422 | 429 |
self.http_delete(path) |
423 | 430 |
|
424 | 431 |
@command_name('lsmeta') |
... | ... | |
427 | 434 |
syntax = '<server id> [key]' |
428 | 435 |
|
429 | 436 |
def execute(self, server_id, key=None): |
430 |
path = '/api/%s/servers/%d/meta' % (self.api, int(server_id))
|
|
437 |
path = '/servers/%d/meta' % int(server_id)
|
|
431 | 438 |
if key: |
432 | 439 |
path += '/' + key |
433 | 440 |
reply = self.http_get(path) |
... | ... | |
442 | 449 |
syntax = '<server id> <key> <val>' |
443 | 450 |
|
444 | 451 |
def execute(self, server_id, key, val): |
445 |
path = '/api/%s/servers/%d/meta' % (self.api, int(server_id))
|
|
452 |
path = '/servers/%d/meta' % int(server_id)
|
|
446 | 453 |
metadata = {key: val} |
447 | 454 |
body = json.dumps({'metadata': metadata}) |
448 | 455 |
reply = self.http_post(path, body, expected_status=201) |
... | ... | |
454 | 461 |
syntax = '<server id> <key> <val>' |
455 | 462 |
|
456 | 463 |
def execute(self, server_id, key, val): |
457 |
path = '/api/%s/servers/%d/meta/%s' % (self.api, int(server_id), key)
|
|
464 |
path = '/servers/%d/meta/%s' % (int(server_id), key)
|
|
458 | 465 |
meta = {key: val} |
459 | 466 |
body = json.dumps({'meta': meta}) |
460 | 467 |
reply = self.http_put(path, body, expected_status=201) |
... | ... | |
466 | 473 |
syntax = '<server id> <key>' |
467 | 474 |
|
468 | 475 |
def execute(self, server_id, key): |
469 |
path = '/api/%s/servers/%d/meta/%s' % (self.api, int(server_id), key)
|
|
476 |
path = '/servers/%d/meta/%s' % (int(server_id), key)
|
|
470 | 477 |
reply = self.http_delete(path) |
471 | 478 |
|
472 | 479 |
@command_name('lsimgmeta') |
... | ... | |
475 | 482 |
syntax = '<image id> [key]' |
476 | 483 |
|
477 | 484 |
def execute(self, image_id, key=None): |
478 |
path = '/api/%s/images/%d/meta' % (self.api, int(image_id))
|
|
485 |
path = '/images/%d/meta' % int(image_id)
|
|
479 | 486 |
if key: |
480 | 487 |
path += '/' + key |
481 | 488 |
reply = self.http_get(path) |
... | ... | |
490 | 497 |
syntax = '<image id> <key> <val>' |
491 | 498 |
|
492 | 499 |
def execute(self, image_id, key, val): |
493 |
path = '/api/%s/images/%d/meta' % (self.api, int(image_id))
|
|
500 |
path = '/images/%d/meta' % int(image_id)
|
|
494 | 501 |
metadata = {key: val} |
495 | 502 |
body = json.dumps({'metadata': metadata}) |
496 | 503 |
reply = self.http_post(path, body, expected_status=201) |
... | ... | |
502 | 509 |
syntax = '<image id> <key> <val>' |
503 | 510 |
|
504 | 511 |
def execute(self, image_id, key, val): |
505 |
path = '/api/%s/images/%d/meta/%s' % (self.api, int(image_id), key)
|
|
512 |
path = '/images/%d/meta/%s' % (int(image_id), key)
|
|
506 | 513 |
meta = {key: val} |
507 | 514 |
body = json.dumps({'meta': meta}) |
508 | 515 |
reply = self.http_put(path, body, expected_status=201) |
... | ... | |
514 | 521 |
syntax = '<image id> <key>' |
515 | 522 |
|
516 | 523 |
def execute(self, image_id, key): |
517 |
path = '/api/%s/images/%d/meta/%s' % (self.api, int(image_id), key)
|
|
524 |
path = '/images/%d/meta/%s' % (int(image_id), key)
|
|
518 | 525 |
reply = self.http_delete(path) |
519 | 526 |
|
520 | 527 |
|
... | ... | |
527 | 534 |
help='show detailed output') |
528 | 535 |
|
529 | 536 |
def execute(self): |
530 |
path = '/api/%s/networks' % self.api |
|
531 |
if self.detail: |
|
532 |
path += '/detail' |
|
537 |
path = '/networks/detail' if self.detail else '/networks' |
|
533 | 538 |
reply = self.http_get(path) |
534 | 539 |
|
535 | 540 |
for network in reply['networks']['values']: |
... | ... | |
549 | 554 |
syntax = '<network name>' |
550 | 555 |
|
551 | 556 |
def execute(self, name): |
552 |
path = '/api/%s/networks' % self.api |
|
553 | 557 |
network = {'name': name} |
554 | 558 |
body = json.dumps({'network': network}) |
555 |
reply = self.http_post(path, body)
|
|
559 |
reply = self.http_post('/networks', body)
|
|
556 | 560 |
print_dict(reply['network']) |
557 | 561 |
|
558 | 562 |
|
... | ... | |
562 | 566 |
syntax = '<network id>' |
563 | 567 |
|
564 | 568 |
def execute(self, network_id): |
565 |
path = '/api/%s/networks/%d' % (self.api, int(network_id))
|
|
569 |
path = '/networks/%d' % int(network_id)
|
|
566 | 570 |
reply = self.http_get(path) |
567 | 571 |
net = reply['network'] |
568 | 572 |
name = net.pop('id') |
... | ... | |
575 | 579 |
syntax = '<network_id> <new name>' |
576 | 580 |
|
577 | 581 |
def execute(self, network_id, name): |
578 |
path = '/api/%s/networks/%d' % (self.api, int(network_id))
|
|
582 |
path = '/networks/%d' % int(network_id)
|
|
579 | 583 |
body = json.dumps({'network': {'name': name}}) |
580 | 584 |
self.http_put(path, body) |
581 | 585 |
|
... | ... | |
586 | 590 |
syntax = '<network id>' |
587 | 591 |
|
588 | 592 |
def execute(self, network_id): |
589 |
path = '/api/%s/networks/%d' % (self.api, int(network_id))
|
|
593 |
path = '/networks/%d' % int(network_id)
|
|
590 | 594 |
self.http_delete(path) |
591 | 595 |
|
592 | 596 |
|
... | ... | |
596 | 600 |
syntax = '<server id> <network id>' |
597 | 601 |
|
598 | 602 |
def execute(self, server_id, network_id): |
599 |
path = '/api/%s/networks/%d/action' % (self.api, int(network_id))
|
|
603 |
path = '/networks/%d/action' % int(network_id)
|
|
600 | 604 |
body = json.dumps({'add': {'serverRef': server_id}}) |
601 | 605 |
self.http_post(path, body, expected_status=202) |
602 | 606 |
|
... | ... | |
607 | 611 |
syntax = '<server id> <network id>' |
608 | 612 |
|
609 | 613 |
def execute(self, server_id, network_id): |
610 |
path = '/api/%s/networks/%s/action' % (self.api, int(network_id))
|
|
614 |
path = '/networks/%s/action' % int(network_id)
|
|
611 | 615 |
body = json.dumps({'remove': {'serverRef': server_id}}) |
612 | 616 |
self.http_post(path, body, expected_status=202) |
613 | 617 |
|
... | ... | |
617 | 621 |
syntax = '<server id>' |
618 | 622 |
|
619 | 623 |
def execute(self, server_id): |
620 |
path = '/api/%s/servers/%d/stats' % (self.api, int(server_id))
|
|
624 |
path = '/servers/%d/stats' % int(server_id)
|
|
621 | 625 |
reply = self.http_get(path) |
622 | 626 |
stats = reply['stats'] |
623 | 627 |
stats.pop('serverRef') |
Also available in: Unified diff