Revision c738c935
b/api/servers.py | ||
---|---|---|
57 | 57 |
(r'^/(\d+)/ips/(.+?)(?:.json|.xml)?$', 'list_addresses_by_network'), |
58 | 58 |
(r'^/(\d+)/meta(?:.json|.xml)?$', 'metadata_demux'), |
59 | 59 |
(r'^/(\d+)/meta/(.+?)(?:.json|.xml)?$', 'metadata_item_demux'), |
60 |
(r'^/(\d+)/stats(?:.json|.xml)?$', 'server_stats'), |
|
60 | 61 |
) |
61 | 62 |
|
62 | 63 |
|
... | ... | |
460 | 461 |
meta.delete() |
461 | 462 |
vm.save() |
462 | 463 |
return HttpResponse(status=204) |
464 |
|
|
465 |
@util.api_method('GET') |
|
466 |
def server_stats(request, server_id): |
|
467 |
# Normal Response Codes: 200 |
|
468 |
# Error Response Codes: computeFault (400, 500), |
|
469 |
# serviceUnavailable (503), |
|
470 |
# unauthorized (401), |
|
471 |
# badRequest (400), |
|
472 |
# itemNotFound (404), |
|
473 |
# overLimit (413) |
|
474 |
|
|
475 |
vm = util.get_vm(server_id, request.user) |
|
476 |
secret = util.encrypt(vm.backend_id) |
|
477 |
cpu = settings.CPU_GRAPH_URL_TEMPLATE % secret |
|
478 |
net = settings.NET_GRAPH_URL_TEMPLATE % secret |
|
479 |
|
|
480 |
stats = { |
|
481 |
'serverRef': vm.id, |
|
482 |
'refresh': settings.STATS_REFRESH_PERIOD, |
|
483 |
'cpu': cpu, |
|
484 |
'net': net} |
|
485 |
|
|
486 |
if request.serialization == 'xml': |
|
487 |
data = render_to_string('server_stats.xml', stats) |
|
488 |
else: |
|
489 |
data = json.dumps({'stats': stats}) |
|
490 |
|
|
491 |
return HttpResponse(data, status=200) |
b/api/util.py | ||
---|---|---|
31 | 31 |
# interpreted as representing official policies, either expressed |
32 | 32 |
# or implied, of GRNET S.A. |
33 | 33 |
|
34 |
import datetime |
|
35 |
import dateutil.parser |
|
36 |
import logging |
|
37 |
|
|
38 |
from base64 import b64encode |
|
34 | 39 |
from datetime import timedelta, tzinfo |
35 | 40 |
from functools import wraps |
41 |
from hashlib import sha256 |
|
36 | 42 |
from random import choice |
37 | 43 |
from string import ascii_letters, digits |
38 | 44 |
from time import time |
39 | 45 |
from traceback import format_exc |
40 | 46 |
from wsgiref.handlers import format_date_time |
41 | 47 |
|
42 |
import datetime |
|
43 |
import dateutil.parser |
|
44 |
import logging |
|
48 |
from Crypto.Cipher import AES |
|
45 | 49 |
|
46 | 50 |
from django.conf import settings |
47 | 51 |
from django.http import HttpResponse |
... | ... | |
96 | 100 |
pool = ascii_letters + digits |
97 | 101 |
return ''.join(choice(pool) for i in range(length)) |
98 | 102 |
|
103 |
def zeropad(s): |
|
104 |
"""Add zeros at the end of a string in order to make its length |
|
105 |
a multiple of 16.""" |
|
106 |
|
|
107 |
npad = 16 - len(s) % 16 |
|
108 |
return s + '\x00' * npad |
|
109 |
|
|
110 |
def encrypt(plaintext): |
|
111 |
# Make sure key is 32 bytes long |
|
112 |
key = sha256(settings.SECRET_KEY).digest() |
|
113 |
|
|
114 |
aes = AES.new(key) |
|
115 |
enc = aes.encrypt(zeropad(plaintext)) |
|
116 |
return b64encode(enc) |
|
117 |
|
|
99 | 118 |
|
100 | 119 |
def get_vm(server_id, owner): |
101 | 120 |
"""Return a VirtualMachine instance or raise ItemNotFound.""" |
b/settings.d/20-api.conf | ||
---|---|---|
76 | 76 |
|
77 | 77 |
# Maximum number of VMs a user is allowed to have |
78 | 78 |
MAX_VMS_PER_USER = 2 |
79 |
|
|
80 |
# URL templates for the stat graphs |
|
81 |
CPU_GRAPH_URL_TEMPLATE = 'http://localhost/%s/cpu-bar.png' |
|
82 |
NET_GRAPH_URL_TEMPLATE = 'http://localhost/%s/net-ts.png' |
|
83 |
|
|
84 |
# Recommended refresh period for server stats |
|
85 |
STATS_REFRESH_PERIOD = 60 |
b/tools/cloud | ||
---|---|---|
610 | 610 |
body = json.dumps({'remove': {'serverRef': server_id}}) |
611 | 611 |
self.http_post(path, body, expected_status=202) |
612 | 612 |
|
613 |
@command_name('stats') |
|
614 |
class ServerStats(Command): |
|
615 |
description = 'get server stats' |
|
616 |
syntax = '<server id>' |
|
617 |
|
|
618 |
def execute(self, server_id): |
|
619 |
path = '/api/%s/servers/%d/stats' % (self.api, int(server_id)) |
|
620 |
reply = self.http_get(path) |
|
621 |
stats = reply['stats'] |
|
622 |
stats.pop('serverRef') |
|
623 |
print_dict(stats) |
|
624 |
|
|
613 | 625 |
|
614 | 626 |
def print_usage(): |
615 | 627 |
print 'Usage: %s <command>' % basename(argv[0]) |
Also available in: Unified diff