1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
#!/usr/bin/env python
import os
import json
import time
import paramiko
import contextlib
import subprocess
from keystore import USERNAME, PASSWORD, HOSTS
RRA_COMMON = [
"RRA:AVERAGE:0.5:1:800",
"RRA:AVERAGE:0.5:6:800",
"RRA:AVERAGE:0.5:24:800",
"RRA:AVERAGE:0.5:288:800",
"RRA:MAX:0.5:1:800",
"RRA:MAX:0.5:6:800",
"RRA:MAX:0.5:24:800",
"RRA:MAX:0.5:288:800",
]
RRD_TEMPLATES = {
"interface": [
"DS:packets_rx:COUNTER:600:0:U",
"DS:packets_tx:COUNTER:600:0:U",
"DS:bytes_rx:COUNTER:600:0:U",
"DS:bytes_tx:COUNTER:600:0:U",
"DS:errors_rx:COUNTER:600:0:U",
"DS:errors_tx:COUNTER:600:0:U",
"DS:dropped_rx:COUNTER:600:0:U",
"DS:dropped_tx:COUNTER:600:0:U",
],
"network": [
"DS:packets_rx:COUNTER:600:0:U",
"DS:packets_tx:COUNTER:600:0:U",
"DS:bytes_rx:COUNTER:600:0:U",
"DS:bytes_tx:COUNTER:600:0:U",
"DS:retries_tx:COUNTER:600:0:U",
"DS:stations:GAUGE:600:0:U",
],
"station": [
"DS:rssi:GAUGE:600:0:U",
"DS:noise:GAUGE:600:U:U",
"DS:signal:GAUGE:600:U:U",
"DS:power:GAUGE:600:0:U",
"DS:rate_rx:GAUGE:600:0:U",
"DS:rate_tx:GAUGE:600:0:U",
"DS:packets_rx:COUNTER:600:0:U",
"DS:packets_tx:COUNTER:600:0:U",
"DS:bytes_rx:COUNTER:600:0:U",
"DS:bytes_tx:COUNTER:600:0:U",
],
}
@contextlib.contextmanager
def get_mca_data(host):
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.MissingHostKeyPolicy())
client.connect(host, username=USERNAME, password=PASSWORD)
_, stdout, _ = client.exec_command("mca-dump")
yield json.loads(stdout.read())
client.close()
@contextlib.contextmanager
def host_folder(host):
if not os.path.exists(host):
os.mkdir(host)
os.chdir(host)
yield
os.chdir(os.path.dirname(os.getcwd()))
def rrd_update(kind, name, source, *stats):
stats = ":".join(["N"] + list(str(int(source[key])) for key in stats))
rrd_name = "{}-{}.rrd".format(kind, name)
if not os.path.exists(rrd_name):
command = ["rrdtool", "create", rrd_name]
command.extend(RRD_TEMPLATES[kind])
command.extend(RRA_COMMON)
subprocess.call(command)
subprocess.call(("rrdtool", "update", rrd_name, stats))
def update_eth(data):
rrd_update("interface", "eth0", data, "rx_packets", "tx_packets",
"rx_bytes", "tx_bytes", "rx_errors", "tx_errors", "rx_errors",
"tx_errors")
def update_network(data):
rrd_update("network", "{}_{}".format(data["essid"], data["radio"]), data,
"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "tx_retries",
"num_sta")
def update_station(data):
rrd_update("station", data["mac"], data, "rssi", "noise", "signal",
"tx_power", "rx_rate", "tx_rate", "rx_packets", "tx_packets",
"rx_bytes", "tx_bytes")
while True:
for host in HOSTS:
print "Updating {}".format(host)
with host_folder(host), get_mca_data(host) as data:
update_eth(data["if_table"][0])
for vap in data["vap_table"]:
update_network(vap)
for station in vap["sta_table"]:
update_station(station)
print "=" * 80
time.sleep(300)
|