Revision bda47e03 snf-cyclades-app/synnefo/logic/management/commands/stats-cyclades.py

b/snf-cyclades-app/synnefo/logic/management/commands/stats-cyclades.py
32 32
# or implied, of GRNET S.A.
33 33

  
34 34

  
35
import itertools
36
import operator
37
import datetime
38 35
import json
39 36
import string
40 37

  
41 38
from optparse import make_option
42 39

  
43
from collections import defaultdict  # , OrderedDict
44
from django.conf import settings
45
from django.db.models import Count
46 40
from snf_django.management.utils import pprint_table, parse_bool
47 41

  
48
from synnefo.db.models import Backend
49 42
from snf_django.management.commands import SynnefoCommand, CommandError
50
from snf_django.lib.astakos import UserCache
51
from synnefo.api.util import get_image
52
from synnefo.db.models import VirtualMachine, Network
53
from synnefo.logic import backend as backend_mod
54 43
from synnefo.management.common import get_backend
44
from synnefo.admin import stats as statistics
55 45

  
56 46

  
57 47
class Command(SynnefoCommand):
......
107 97
        networks = parse_bool(options["networks"])
108 98
        images = parse_bool(options["images"])
109 99

  
110
        stats = get_cyclades_stats(backend, clusters, servers, resources,
111
                                   networks, images)
100
        stats = statistics.get_cyclades_stats(backend, clusters, servers,
101
                                              resources, networks, images)
112 102

  
113 103
        output_format = options["output_format"]
114 104
        if output_format == "json":
......
120 110
                               output_format)
121 111

  
122 112

  
123
def get_cyclades_stats(backend=None, clusters=True, servers=True,
124
                       resources=True, networks=True, images=True):
125
    stats = {"datetime": datetime.datetime.now().strftime("%c")}
126
    if clusters:
127
        stats["clusters"] = get_cluster_stats(backend=backend)
128
    if servers:
129
        stats["servers"] = get_servers_stats(backend=backend)
130
    if resources:
131
        stats["resources"] = get_resources_stats(backend=backend)
132
    if networks:
133
        stats["networks"] = get_networks_stats()
134
    if images:
135
        stats["images"] = get_images_stats(backend=None)
136
    return stats
137

  
138

  
139 113
def columns_from_fields(fields, values):
140 114
    return zip(map(string.lower, fields), [values.get(f, 0) for f in fields])
141 115

  
......
143 117
def pretty_print_stats(stats, stdout):
144 118
    newline = lambda: stdout.write("\n")
145 119

  
146
    datetime = stats.get("datetime")
147
    stdout.write("datetime: %s\n" % datetime)
120
    _datetime = stats.get("datetime")
121
    stdout.write("datetime: %s\n" % _datetime)
148 122
    newline()
149 123

  
150 124
    clusters = stats.get("clusters")
......
192 166
        pprint_table(stdout, sorted(images.items()), None,
193 167
                     title="Statistics for Images")
194 168
        newline()
195

  
196

  
197
def get_cluster_stats(backend):
198
    total = Backend.objects.all()
199
    stats = {"total": total.count(),
200
             "drained": total.filter(drained=True).count(),
201
             "offline": total.filter(offline=True).count()}
202
    return stats
203

  
204

  
205
def _get_total_servers(backend=None):
206
    total_servers = VirtualMachine.objects.all()
207
    if backend is not None:
208
        total_servers = total_servers.filter(backend=backend)
209
    return total_servers
210

  
211

  
212
def get_servers_stats(backend=None):
213
    total_servers = _get_total_servers(backend=backend)
214
    per_state = total_servers.values("operstate")\
215
                             .annotate(count=Count("operstate"))
216
    stats = {"total": 0}
217
    for x in per_state:
218
        stats[x["operstate"]] = x["count"]
219
        stats["total"] += x["count"]
220
    return stats
221

  
222

  
223
def get_resources_stats(backend=None):
224
    total_servers = _get_total_servers(backend=backend)
225
    active_servers = total_servers.filter(deleted=False)
226

  
227
    allocated = {}
228
    server_count = {}
229
    for res in ["cpu", "ram", "disk", "disk_template"]:
230
        server_count[res] = {}
231
        allocated[res] = 0
232
        val = "flavor__%s" % res
233
        results = active_servers.values(val).annotate(count=Count(val))
234
        for result in results:
235
            server_count[res][result[val]] = result["count"]
236
            if res != "disk_template":
237
                allocated[res] += result["count"]
238

  
239
    resources_stats = get_backend_stats(backend=backend)
240
    for res in ["cpu", "ram", "disk", "disk_template"]:
241
        if res not in resources_stats:
242
            resources_stats[res] = {}
243
        resources_stats[res]["servers"] = server_count[res]
244
        resources_stats[res]["allocated"] = allocated[res]
245

  
246
    return resources_stats
247

  
248

  
249
def get_images_stats(backend=None):
250
    total_servers = _get_total_servers(backend=backend)
251
    active_servers = total_servers.filter(deleted=False)
252

  
253
    active_servers_images = active_servers.values("imageid", "userid")\
254
                                          .annotate(number=Count("imageid"))
255
    image_cache = ImageCache()
256
    image_stats = defaultdict(int)
257
    for result in active_servers_images:
258
        imageid = image_cache.get_image(result["imageid"], result["userid"])
259
        image_stats[imageid] += result["number"]
260
    return dict(image_stats)
261

  
262

  
263
def get_networks_stats():
264
    total_networks = Network.objects.all()
265
    stats = {"public_ips": get_ip_stats(),
266
             "total": 0}
267
    per_state = total_networks.values("state")\
268
                              .annotate(count=Count("state"))
269
    for x in per_state:
270
        stats[x["state"]] = x["count"]
271
        stats["total"] += x["count"]
272
    return stats
273

  
274

  
275
def group_by_resource(objects, resource):
276
    stats = {}
277
    key = operator.attrgetter("flavor."+resource)
278
    grouped = itertools.groupby(sorted(objects, key=key), key)
279
    for val, group in grouped:
280
        stats[val] = len(list(group))
281
    return stats
282

  
283

  
284
def get_ip_stats():
285
    total, free = 0, 0,
286
    for network in Network.objects.filter(public=True, deleted=False):
287
        try:
288
            net_total, net_free = network.ip_count()
289
        except AttributeError:
290
            # TODO: Check that this works..
291
            pool = network.get_pool(locked=False)
292
            net_total = pool.pool_size
293
            net_free = pool.count_available()
294
        if not network.drained:
295
            total += net_total
296
            free += net_free
297
    return {"total": total,
298
            "free": free}
299

  
300

  
301
def get_backend_stats(backend=None):
302
    if backend is None:
303
        backends = Backend.objects.filter(offline=False)
304
    else:
305
        if backend.offline:
306
            return {}
307
        backends = [backend]
308
    [backend_mod.update_backend_resources(b) for b in backends]
309
    resources = {}
310
    for attr in ("dfree", "dtotal", "mfree", "mtotal", "ctotal"):
311
        resources[attr] = 0
312
        for b in backends:
313
            resources[attr] += getattr(b, attr)
314

  
315
    return {"disk": {"free": resources["dfree"], "total": resources["dtotal"]},
316
            "ram": {"free": resources["mfree"], "total": resources["mtotal"]},
317
            "cpu": {"free": resources["ctotal"], "total": resources["ctotal"]},
318
            "disk_template": {"free": 0, "total": 0}}
319

  
320

  
321
class ImageCache(object):
322
    def __init__(self):
323
        self.images = {}
324
        usercache = UserCache(settings.ASTAKOS_BASE_URL,
325
                              settings.CYCLADES_SERVICE_TOKEN)
326
        self.system_user_uuid = \
327
            usercache.get_uuid(settings.SYSTEM_IMAGES_OWNER)
328

  
329
    def get_image(self, imageid, userid):
330
        if not imageid in self.images:
331
            try:
332
                image = get_image(imageid, userid)
333
                owner = image["owner"]
334
                owner = "system" if image["owner"] == self.system_user_uuid\
335
                        else "user"
336
                self.images[imageid] = owner + ":" + image["name"]
337
            except Exception:
338
                self.images[imageid] = "unknown:unknown"
339

  
340
        return self.images[imageid]

Also available in: Unified diff