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