author | Tero Marttila <terom@paivola.fi> |
Sun, 10 Feb 2013 13:20:29 +0200 | |
changeset 205 | f7658198c224 |
parent 155 | 9f2967ba81ef |
child 232 | 5894c70dc6a8 |
permissions | -rw-r--r-- |
143
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
1 |
import rrdtool |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
2 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
3 |
import pvl.invoke |
148
92fd0898188d
pvl.rrd.api: fix templfile
Tero Marttila <terom@paivola.fi>
parents:
143
diff
changeset
|
4 |
import tempfile |
143
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
5 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
6 |
import logging; log = logging.getLogger('pvl.rrd.api') |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
7 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
8 |
""" |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
9 |
Wrapper around the rrdtool python interface |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
10 |
""" |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
11 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
12 |
def timestamp (time=None) : |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
13 |
""" |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
14 |
Format datetime value for rrdtool. |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
15 |
""" |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
16 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
17 |
if not time : |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
18 |
return None |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
19 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
20 |
elif isinstance(time, datetime.datetime) : |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
21 |
return int(time.mktime(dt.timetuple())) |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
22 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
23 |
elif isinstance(time, datetime.timedelta) : |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
24 |
raise NotImplementedError("pvl.rrd.api.timestamp: timedelta") |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
25 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
26 |
else : |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
27 |
# dunno |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
28 |
return str(dt) |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
29 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
30 |
def cmd (func, pre, opts, post) : |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
31 |
""" |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
32 |
Run the given rrdtool.* function, formatting the given positional arguments and options. |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
33 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
34 |
Returns the return value, which varies... |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
35 |
""" |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
36 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
37 |
log.debug("%s: %s: %s: %s", func, pre, opts, post) |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
38 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
39 |
# { opt: arg } -> [ '--opt', arg ] |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
40 |
opts = pvl.invoke.optargs(**opts) |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
41 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
42 |
# positional arguments |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
43 |
pre = pvl.invoke.optargs(*pre) |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
44 |
post = pvl.invoke.optargs(*post) |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
45 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
46 |
return func(*(pre + opts + post)) |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
47 |
|
155
9f2967ba81ef
pvl.rrd.graph: refactor to use Graph -> Interface -> Mrtg/CollectdIfOctets
Tero Marttila <terom@paivola.fi>
parents:
148
diff
changeset
|
48 |
def graph (out=None, *defs, **opts) : |
143
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
49 |
""" |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
50 |
Render a graph image and/or print a report from data stored in one or several RRDs. |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
51 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
52 |
out - None -> tempfile |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
53 |
- False -> stdout |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
54 |
- path -> write to file |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
55 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
56 |
Returns: |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
57 |
(width, height) - pixel dimensions of the resulting graph image |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
58 |
report_output - any PRINT'd output (?) |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
59 |
graph_file - file-like object containing graph image, unless out=False -> stdout |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
60 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
61 |
With out=None, the returned graph_file is a tempfile which will be cleaned up by Python once close()'d! |
148
92fd0898188d
pvl.rrd.api: fix templfile
Tero Marttila <terom@paivola.fi>
parents:
143
diff
changeset
|
62 |
|
92fd0898188d
pvl.rrd.api: fix templfile
Tero Marttila <terom@paivola.fi>
parents:
143
diff
changeset
|
63 |
XXX: tempfile suffix as .png? |
143
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
64 |
""" |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
65 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
66 |
if out is None : |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
67 |
# tempfile |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
68 |
out_file = tempfile.NamedTemporaryFile(suffix='.png', delete=True) # python2.6 |
148
92fd0898188d
pvl.rrd.api: fix templfile
Tero Marttila <terom@paivola.fi>
parents:
143
diff
changeset
|
69 |
out_path = out_file.name |
143
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
70 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
71 |
elif out is False : |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
72 |
out_file = None |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
73 |
out_path = '-' |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
74 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
75 |
else : |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
76 |
# for reading |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
77 |
out_path = out |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
78 |
out_file = True # open later |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
79 |
|
148
92fd0898188d
pvl.rrd.api: fix templfile
Tero Marttila <terom@paivola.fi>
parents:
143
diff
changeset
|
80 |
log.debug("%s", out_path) |
92fd0898188d
pvl.rrd.api: fix templfile
Tero Marttila <terom@paivola.fi>
parents:
143
diff
changeset
|
81 |
|
143
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
82 |
# XXX: handle tempfile close? |
155
9f2967ba81ef
pvl.rrd.graph: refactor to use Graph -> Interface -> Mrtg/CollectdIfOctets
Tero Marttila <terom@paivola.fi>
parents:
148
diff
changeset
|
83 |
width, height, out_lines = cmd(rrdtool.graph, (out_path, ), opts, defs) |
143
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
84 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
85 |
if out_file is True : |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
86 |
out_file = open(out_path) |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
87 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
88 |
return (width, height), out_lines, out_file |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
89 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
90 |
def fetch (rrd, cf, **opts) : |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
91 |
""" |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
92 |
Fetch values from RRD. |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
93 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
94 |
Returns |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
95 |
(start, end, step) - xrange(...) for row timestamps |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
96 |
(ds, ...) - columns (ds name) |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
97 |
((value, ...), ...) - rows (data by ds) |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
98 |
""" |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
99 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
100 |
return cmd(rrdtool.fetch, (rrd, cf), opts, ()) |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
101 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
102 |
def _fetch (rrd, cf='AVERAGE', resolution=None, start=None, end=None, **opts) : |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
103 |
""" |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
104 |
Yields (timestamp, { ds: value }) for given ds-values, or all. |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
105 |
""" |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
106 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
107 |
steps, sources, rows = fetch(rrd, cf, |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
108 |
resolution = resolution, |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
109 |
start = timestamp(start), |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
110 |
end = timestamp(end), |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
111 |
**opts |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
112 |
) |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
113 |
|
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
114 |
for ts, row in zip(xrange(*steps), rows) : |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
115 |
yield datetime.fromtimestamp(ts), dict(zip(sources, row)) |
fb48ba17ae3e
pvl.rrd: copy+update from old rrdweb
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
116 |