Statistics
| Branch: | Tag: | Revision:

root / snf-stats-app / synnefo_stats / grapher.py @ fde2c1f7

History | View | Annotate | Download (8.3 kB)

1 e6ad6878 Stratos Psomadakis
# Copyright 2011-2013 GRNET S.A. All rights reserved.
2 7fcec5d7 Stratos Psomadakis
#
3 7fcec5d7 Stratos Psomadakis
# Redistribution and use in source and binary forms, with or
4 7fcec5d7 Stratos Psomadakis
# without modification, are permitted provided that the following
5 7fcec5d7 Stratos Psomadakis
# conditions are met:
6 7fcec5d7 Stratos Psomadakis
#
7 7fcec5d7 Stratos Psomadakis
#   1. Redistributions of source code must retain the above
8 7fcec5d7 Stratos Psomadakis
#      copyright notice, this list of conditions and the following
9 7fcec5d7 Stratos Psomadakis
#      disclaimer.
10 7fcec5d7 Stratos Psomadakis
#
11 7fcec5d7 Stratos Psomadakis
#   2. Redistributions in binary form must reproduce the above
12 7fcec5d7 Stratos Psomadakis
#      copyright notice, this list of conditions and the following
13 7fcec5d7 Stratos Psomadakis
#      disclaimer in the documentation and/or other materials
14 7fcec5d7 Stratos Psomadakis
#      provided with the distribution.
15 7fcec5d7 Stratos Psomadakis
#
16 7fcec5d7 Stratos Psomadakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 7fcec5d7 Stratos Psomadakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 7fcec5d7 Stratos Psomadakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 7fcec5d7 Stratos Psomadakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 7fcec5d7 Stratos Psomadakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 7fcec5d7 Stratos Psomadakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 7fcec5d7 Stratos Psomadakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 7fcec5d7 Stratos Psomadakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 7fcec5d7 Stratos Psomadakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 7fcec5d7 Stratos Psomadakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 7fcec5d7 Stratos Psomadakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 7fcec5d7 Stratos Psomadakis
# POSSIBILITY OF SUCH DAMAGE.
28 7fcec5d7 Stratos Psomadakis
#
29 7fcec5d7 Stratos Psomadakis
# The views and conclusions contained in the software and
30 7fcec5d7 Stratos Psomadakis
# documentation are those of the authors and should not be
31 7fcec5d7 Stratos Psomadakis
# interpreted as representing official policies, either expressed
32 7fcec5d7 Stratos Psomadakis
# or implied, of GRNET S.A.
33 7fcec5d7 Stratos Psomadakis
34 7fcec5d7 Stratos Psomadakis
from django.http import HttpResponse
35 7fcec5d7 Stratos Psomadakis
36 7fcec5d7 Stratos Psomadakis
import gd
37 7fcec5d7 Stratos Psomadakis
import os
38 7fcec5d7 Stratos Psomadakis
import sys
39 7fcec5d7 Stratos Psomadakis
import subprocess
40 7fcec5d7 Stratos Psomadakis
41 7fcec5d7 Stratos Psomadakis
from cgi import escape
42 7fcec5d7 Stratos Psomadakis
from cStringIO import StringIO
43 7fcec5d7 Stratos Psomadakis
44 7fcec5d7 Stratos Psomadakis
import rrdtool
45 7fcec5d7 Stratos Psomadakis
46 7fcec5d7 Stratos Psomadakis
from synnefo_stats import settings
47 7fcec5d7 Stratos Psomadakis
48 592bfc3b Stratos Psomadakis
from synnefo.util.text import uenc
49 592bfc3b Stratos Psomadakis
from snf_django.lib.api import faults, api_method
50 592bfc3b Stratos Psomadakis
51 592bfc3b Stratos Psomadakis
from logging import getLogger
52 592bfc3b Stratos Psomadakis
log = getLogger(__name__)
53 7fcec5d7 Stratos Psomadakis
54 7fcec5d7 Stratos Psomadakis
55 7fcec5d7 Stratos Psomadakis
def read_file(filepath):
56 592bfc3b Stratos Psomadakis
    f = open(filepath, "r")
57 7fcec5d7 Stratos Psomadakis
58 7fcec5d7 Stratos Psomadakis
    try:
59 7fcec5d7 Stratos Psomadakis
        data = f.read()
60 7fcec5d7 Stratos Psomadakis
    finally:
61 7fcec5d7 Stratos Psomadakis
        f.close()
62 7fcec5d7 Stratos Psomadakis
63 7fcec5d7 Stratos Psomadakis
    return data
64 7fcec5d7 Stratos Psomadakis
65 7fcec5d7 Stratos Psomadakis
66 592bfc3b Stratos Psomadakis
def draw_cpu_bar(fname, outfname=None):
67 592bfc3b Stratos Psomadakis
    fname = os.path.join(fname, "cpu", "virt_cpu_total.rrd")
68 7fcec5d7 Stratos Psomadakis
69 7fcec5d7 Stratos Psomadakis
    try:
70 7fcec5d7 Stratos Psomadakis
        values = rrdtool.fetch(fname, "AVERAGE")[2][-20:]
71 7fcec5d7 Stratos Psomadakis
    except rrdtool.error, e:
72 7fcec5d7 Stratos Psomadakis
        values = [(0.0, )]
73 7fcec5d7 Stratos Psomadakis
74 7fcec5d7 Stratos Psomadakis
    v = [x[0] for x in values if x[0] is not None]
75 7fcec5d7 Stratos Psomadakis
    if not v:
76 7fcec5d7 Stratos Psomadakis
        # Fallback in case we only get NaNs
77 7fcec5d7 Stratos Psomadakis
        v = [0.0]
78 7fcec5d7 Stratos Psomadakis
    # Pick the last value
79 7fcec5d7 Stratos Psomadakis
    value = v[-1]
80 7fcec5d7 Stratos Psomadakis
81 7fcec5d7 Stratos Psomadakis
    image = gd.image((settings.IMAGE_WIDTH, settings.HEIGHT))
82 7fcec5d7 Stratos Psomadakis
83 7fcec5d7 Stratos Psomadakis
    border_color = image.colorAllocate(settings.BAR_BORDER_COLOR)
84 7fcec5d7 Stratos Psomadakis
    white = image.colorAllocate((0xff, 0xff, 0xff))
85 7fcec5d7 Stratos Psomadakis
    background_color = image.colorAllocate(settings.BAR_BG_COLOR)
86 7fcec5d7 Stratos Psomadakis
87 7fcec5d7 Stratos Psomadakis
    if value >= 90.0:
88 7fcec5d7 Stratos Psomadakis
        line_color = image.colorAllocate((0xff, 0x00, 0x00))
89 7fcec5d7 Stratos Psomadakis
    elif value >= 75.0:
90 7fcec5d7 Stratos Psomadakis
        line_color = image.colorAllocate((0xda, 0xaa, 0x00))
91 7fcec5d7 Stratos Psomadakis
    else:
92 7fcec5d7 Stratos Psomadakis
        line_color = image.colorAllocate((0x00, 0xa1, 0x00))
93 7fcec5d7 Stratos Psomadakis
94 592bfc3b Stratos Psomadakis
    image.rectangle((0, 0),
95 592bfc3b Stratos Psomadakis
                    (settings.WIDTH - 1, settings.HEIGHT - 1),
96 592bfc3b Stratos Psomadakis
                    border_color, background_color)
97 592bfc3b Stratos Psomadakis
    image.rectangle((1, 1),
98 592bfc3b Stratos Psomadakis
                    (int(value / 100.0 * (settings.WIDTH - 2)),
99 592bfc3b Stratos Psomadakis
                     settings.HEIGHT - 2),
100 592bfc3b Stratos Psomadakis
                    line_color, line_color)
101 592bfc3b Stratos Psomadakis
    image.string_ttf(settings.FONT, 8.0, 0.0,
102 592bfc3b Stratos Psomadakis
                     (settings.WIDTH + 1, settings.HEIGHT - 1),
103 592bfc3b Stratos Psomadakis
                     "CPU: %.1f%%" % value, white)
104 7fcec5d7 Stratos Psomadakis
105 7fcec5d7 Stratos Psomadakis
    io = StringIO()
106 7fcec5d7 Stratos Psomadakis
    image.writePng(io)
107 7fcec5d7 Stratos Psomadakis
    io.seek(0)
108 7fcec5d7 Stratos Psomadakis
    data = io.getvalue()
109 7fcec5d7 Stratos Psomadakis
    io.close()
110 7fcec5d7 Stratos Psomadakis
    return data
111 7fcec5d7 Stratos Psomadakis
112 7fcec5d7 Stratos Psomadakis
113 592bfc3b Stratos Psomadakis
def draw_net_bar(fname, outfname=None):
114 592bfc3b Stratos Psomadakis
    fname = os.path.join(fname, "interface", "if_octets-eth0.rrd")
115 7fcec5d7 Stratos Psomadakis
116 7fcec5d7 Stratos Psomadakis
    try:
117 7fcec5d7 Stratos Psomadakis
        values = rrdtool.fetch(fname, "AVERAGE")[2][-20:]
118 7fcec5d7 Stratos Psomadakis
    except rrdtool.error, e:
119 7fcec5d7 Stratos Psomadakis
        values = [(0.0, 0.0)]
120 7fcec5d7 Stratos Psomadakis
121 7fcec5d7 Stratos Psomadakis
    v = [x for x in values if x[0] is not None and x[1] is not None]
122 7fcec5d7 Stratos Psomadakis
    if not v:
123 7fcec5d7 Stratos Psomadakis
        # Fallback in case we only get NaNs
124 7fcec5d7 Stratos Psomadakis
        v = [(0.0, 0.0)]
125 7fcec5d7 Stratos Psomadakis
126 7fcec5d7 Stratos Psomadakis
    rx_value, tx_value = v[-1]
127 7fcec5d7 Stratos Psomadakis
128 7fcec5d7 Stratos Psomadakis
    # Convert to bits
129 592bfc3b Stratos Psomadakis
    rx_value = rx_value * 8 / 10 ** 6
130 592bfc3b Stratos Psomadakis
    tx_value = tx_value * 8 / 10 ** 6
131 7fcec5d7 Stratos Psomadakis
132 592bfc3b Stratos Psomadakis
    max_value = (int(max(rx_value, tx_value) / 50) + 1) * 50.0
133 7fcec5d7 Stratos Psomadakis
134 7fcec5d7 Stratos Psomadakis
    image = gd.image((settings.IMAGE_WIDTH, settings.HEIGHT))
135 7fcec5d7 Stratos Psomadakis
136 7fcec5d7 Stratos Psomadakis
    border_color = image.colorAllocate(settings.BAR_BORDER_COLOR)
137 7fcec5d7 Stratos Psomadakis
    white = image.colorAllocate((0xff, 0xff, 0xff))
138 7fcec5d7 Stratos Psomadakis
    background_color = image.colorAllocate(settings.BAR_BG_COLOR)
139 7fcec5d7 Stratos Psomadakis
140 7fcec5d7 Stratos Psomadakis
    tx_line_color = image.colorAllocate((0x00, 0xa1, 0x00))
141 7fcec5d7 Stratos Psomadakis
    rx_line_color = image.colorAllocate((0x00, 0x00, 0xa1))
142 7fcec5d7 Stratos Psomadakis
143 592bfc3b Stratos Psomadakis
    image.rectangle((0, 0),
144 592bfc3b Stratos Psomadakis
                    (settings.WIDTH - 1, settings.HEIGHT - 1),
145 592bfc3b Stratos Psomadakis
                    border_color, background_color)
146 592bfc3b Stratos Psomadakis
    image.rectangle((1, 1),
147 592bfc3b Stratos Psomadakis
                    (int(tx_value / max_value * (settings.WIDTH - 2)),
148 592bfc3b Stratos Psomadakis
                     settings.HEIGHT / 2 - 1),
149 592bfc3b Stratos Psomadakis
                    tx_line_color, tx_line_color)
150 592bfc3b Stratos Psomadakis
    image.rectangle((1, settings.HEIGHT / 2),
151 592bfc3b Stratos Psomadakis
                    (int(rx_value / max_value * (settings.WIDTH - 2)),
152 592bfc3b Stratos Psomadakis
                     settings.HEIGHT - 2),
153 592bfc3b Stratos Psomadakis
                    rx_line_color, rx_line_color)
154 592bfc3b Stratos Psomadakis
    image.string_ttf(settings.FONT, 8.0, 0.0,
155 592bfc3b Stratos Psomadakis
                     (settings.WIDTH + 1, settings.HEIGHT - 1),
156 592bfc3b Stratos Psomadakis
                     "TX/RX: %.2f/%.2f Mbps" % (tx_value, rx_value), white)
157 7fcec5d7 Stratos Psomadakis
158 7fcec5d7 Stratos Psomadakis
    io = StringIO()
159 7fcec5d7 Stratos Psomadakis
    image.writePng(io)
160 7fcec5d7 Stratos Psomadakis
    io.seek(0)
161 7fcec5d7 Stratos Psomadakis
    data = io.getvalue()
162 7fcec5d7 Stratos Psomadakis
    io.close()
163 7fcec5d7 Stratos Psomadakis
    return data
164 7fcec5d7 Stratos Psomadakis
165 7fcec5d7 Stratos Psomadakis
166 592bfc3b Stratos Psomadakis
def draw_cpu_ts(fname, outfname):
167 592bfc3b Stratos Psomadakis
    fname = os.path.join(fname, "cpu", "virt_cpu_total.rrd")
168 592bfc3b Stratos Psomadakis
    outfname += "-cpu.png"
169 7fcec5d7 Stratos Psomadakis
170 592bfc3b Stratos Psomadakis
    rrdtool.graph(outfname, "-s", "-1d", "-e", "-20s",
171 592bfc3b Stratos Psomadakis
                  #"-t", "CPU usage",
172 592bfc3b Stratos Psomadakis
                  "-v", "%",
173 592bfc3b Stratos Psomadakis
                  #"--lazy",
174 592bfc3b Stratos Psomadakis
                  "DEF:cpu=%s:ns:AVERAGE" % fname,
175 592bfc3b Stratos Psomadakis
                  "LINE1:cpu#00ff00:")
176 7fcec5d7 Stratos Psomadakis
177 7fcec5d7 Stratos Psomadakis
    return read_file(outfname)
178 7fcec5d7 Stratos Psomadakis
179 7fcec5d7 Stratos Psomadakis
180 592bfc3b Stratos Psomadakis
def draw_cpu_ts_w(fname, outfname):
181 592bfc3b Stratos Psomadakis
    fname = os.path.join(fname, "cpu", "virt_cpu_total.rrd")
182 592bfc3b Stratos Psomadakis
    outfname += "-cpu-weekly.png"
183 7fcec5d7 Stratos Psomadakis
184 592bfc3b Stratos Psomadakis
    rrdtool.graph(outfname, "-s", "-1w", "-e", "-20s",
185 592bfc3b Stratos Psomadakis
                  #"-t", "CPU usage",
186 592bfc3b Stratos Psomadakis
                  "-v", "%",
187 592bfc3b Stratos Psomadakis
                  #"--lazy",
188 592bfc3b Stratos Psomadakis
                  "DEF:cpu=%s:ns:AVERAGE" % fname,
189 592bfc3b Stratos Psomadakis
                  "LINE1:cpu#00ff00:")
190 7fcec5d7 Stratos Psomadakis
191 7fcec5d7 Stratos Psomadakis
    return read_file(outfname)
192 7fcec5d7 Stratos Psomadakis
193 7fcec5d7 Stratos Psomadakis
194 592bfc3b Stratos Psomadakis
def draw_net_ts(fname, outfname):
195 592bfc3b Stratos Psomadakis
    fname = os.path.join(fname, "interface", "if_octets-eth0.rrd")
196 592bfc3b Stratos Psomadakis
    outfname += "-net.png"
197 592bfc3b Stratos Psomadakis
198 592bfc3b Stratos Psomadakis
    rrdtool.graph(outfname, "-s", "-1d", "-e", "-20s",
199 592bfc3b Stratos Psomadakis
              #"-t", "Network traffic",
200 592bfc3b Stratos Psomadakis
              "--units", "si",
201 592bfc3b Stratos Psomadakis
              "-v", "Bits/s",
202 592bfc3b Stratos Psomadakis
              #"--lazy",
203 592bfc3b Stratos Psomadakis
              "COMMENT:\t\t\tAverage network traffic\\n",
204 592bfc3b Stratos Psomadakis
              "DEF:rx=%s:rx:AVERAGE" % fname,
205 592bfc3b Stratos Psomadakis
              "DEF:tx=%s:tx:AVERAGE" % fname,
206 592bfc3b Stratos Psomadakis
              "CDEF:rxbits=rx,8,*",
207 592bfc3b Stratos Psomadakis
              "CDEF:txbits=tx,8,*",
208 592bfc3b Stratos Psomadakis
              "LINE1:rxbits#00ff00:Incoming",
209 592bfc3b Stratos Psomadakis
              "GPRINT:rxbits:AVERAGE:\t%4.0lf%sbps\t\g",
210 592bfc3b Stratos Psomadakis
              "LINE1:txbits#0000ff:Outgoing",
211 592bfc3b Stratos Psomadakis
              "GPRINT:txbits:AVERAGE:\t%4.0lf%sbps\\n")
212 7fcec5d7 Stratos Psomadakis
213 7fcec5d7 Stratos Psomadakis
    return read_file(outfname)
214 7fcec5d7 Stratos Psomadakis
215 7fcec5d7 Stratos Psomadakis
216 592bfc3b Stratos Psomadakis
def draw_net_ts_w(fname, outfname):
217 592bfc3b Stratos Psomadakis
    fname = os.path.join(fname, "interface", "if_octets-eth0.rrd")
218 592bfc3b Stratos Psomadakis
    outfname += "-net-weekly.png"
219 592bfc3b Stratos Psomadakis
220 592bfc3b Stratos Psomadakis
    rrdtool.graph(outfname, "-s", "-1w", "-e", "-20s",
221 592bfc3b Stratos Psomadakis
              #"-t", "Network traffic",
222 592bfc3b Stratos Psomadakis
              "--units", "si",
223 592bfc3b Stratos Psomadakis
              "-v", "Bits/s",
224 592bfc3b Stratos Psomadakis
              #"--lazy",
225 592bfc3b Stratos Psomadakis
              "COMMENT:\t\t\tAverage network traffic\\n",
226 592bfc3b Stratos Psomadakis
              "DEF:rx=%s:rx:AVERAGE" % fname,
227 592bfc3b Stratos Psomadakis
              "DEF:tx=%s:tx:AVERAGE" % fname,
228 592bfc3b Stratos Psomadakis
              "CDEF:rxbits=rx,8,*",
229 592bfc3b Stratos Psomadakis
              "CDEF:txbits=tx,8,*",
230 592bfc3b Stratos Psomadakis
              "LINE1:rxbits#00ff00:Incoming",
231 592bfc3b Stratos Psomadakis
              "GPRINT:rxbits:AVERAGE:\t%4.0lf%sbps\t\g",
232 592bfc3b Stratos Psomadakis
              "LINE1:txbits#0000ff:Outgoing",
233 592bfc3b Stratos Psomadakis
              "GPRINT:txbits:AVERAGE:\t%4.0lf%sbps\\n")
234 7fcec5d7 Stratos Psomadakis
235 7fcec5d7 Stratos Psomadakis
    return read_file(outfname)
236 7fcec5d7 Stratos Psomadakis
237 7fcec5d7 Stratos Psomadakis
238 592bfc3b Stratos Psomadakis
available_graph_types = {
239 592bfc3b Stratos Psomadakis
        'cpu-bar': draw_cpu_bar,
240 592bfc3b Stratos Psomadakis
        'net-bar': draw_net_bar,
241 592bfc3b Stratos Psomadakis
        'cpu-ts': draw_cpu_ts,
242 592bfc3b Stratos Psomadakis
        'net-ts': draw_net_ts,
243 592bfc3b Stratos Psomadakis
        'cpu-ts-w': draw_cpu_ts_w,
244 592bfc3b Stratos Psomadakis
        'net-ts-w': draw_net_ts_w,
245 592bfc3b Stratos Psomadakis
        }
246 7fcec5d7 Stratos Psomadakis
247 592bfc3b Stratos Psomadakis
248 592bfc3b Stratos Psomadakis
@api_method(http_method='GET', token_required=False, user_required=False,
249 592bfc3b Stratos Psomadakis
            format_allowed=False, logger=log)
250 592bfc3b Stratos Psomadakis
def grapher(request, graph_type, hostname):
251 592bfc3b Stratos Psomadakis
    fname = uenc(os.path.join(settings.RRD_PREFIX, hostname))
252 592bfc3b Stratos Psomadakis
    if not os.path.isdir(fname):
253 592bfc3b Stratos Psomadakis
        raise faults.ItemNotFound('No such instance')
254 592bfc3b Stratos Psomadakis
255 592bfc3b Stratos Psomadakis
    outfname = uenc(os.path.join(settings.GRAPH_PREFIX, hostname))
256 592bfc3b Stratos Psomadakis
    draw_func = available_graph_types[graph_type]
257 592bfc3b Stratos Psomadakis
258 592bfc3b Stratos Psomadakis
    response = HttpResponse(draw_func(fname, outfname),
259 592bfc3b Stratos Psomadakis
                            status=200, content_type="image/png")
260 592bfc3b Stratos Psomadakis
    response.override_serialization = True
261 7fcec5d7 Stratos Psomadakis
262 7fcec5d7 Stratos Psomadakis
    return response