aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Crute <mcrute@gmail.com>2013-09-27 11:31:47 -0400
committerMike Crute <mcrute@gmail.com>2013-09-27 11:32:20 -0400
commitd64e26457e6c891304315a7de17db886493e8039 (patch)
tree4a4513ec443aa10fd05eaf37cce7bc7c56336ac6
parent07a941dd1f316a4facb97e2841764f5244225d95 (diff)
downloadubntmfi-d64e26457e6c891304315a7de17db886493e8039.tar.bz2
ubntmfi-d64e26457e6c891304315a7de17db886493e8039.tar.xz
ubntmfi-d64e26457e6c891304315a7de17db886493e8039.zip
Adding unifi stats collection
-rw-r--r--.gitignore1
-rwxr-xr-xcollect_ssh.py123
-rw-r--r--parse_dumped_bodies.py2
-rw-r--r--requirements.txt1
-rw-r--r--utils.py16
5 files changed, 142 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index e07a3b2..07469ec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
1*.pyc 1*.pyc
2.sandbox_name 2.sandbox_name
3keystore.py
diff --git a/collect_ssh.py b/collect_ssh.py
new file mode 100755
index 0000000..607b774
--- /dev/null
+++ b/collect_ssh.py
@@ -0,0 +1,123 @@
1#!/usr/bin/env python
2
3import os
4import json
5import time
6import paramiko
7import contextlib
8import subprocess
9
10from keystore import USERNAME, PASSWORD, HOSTS
11
12
13RRA_COMMON = [
14 "RRA:AVERAGE:0.5:1:800",
15 "RRA:AVERAGE:0.5:6:800",
16 "RRA:AVERAGE:0.5:24:800",
17 "RRA:AVERAGE:0.5:288:800",
18 "RRA:MAX:0.5:1:800",
19 "RRA:MAX:0.5:6:800",
20 "RRA:MAX:0.5:24:800",
21 "RRA:MAX:0.5:288:800",
22]
23
24RRD_TEMPLATES = {
25 "interface": [
26 "DS:packets_rx:COUNTER:600:0:U",
27 "DS:packets_tx:COUNTER:600:0:U",
28 "DS:bytes_rx:COUNTER:600:0:U",
29 "DS:bytes_tx:COUNTER:600:0:U",
30 "DS:errors_rx:COUNTER:600:0:U",
31 "DS:errors_tx:COUNTER:600:0:U",
32 "DS:dropped_rx:COUNTER:600:0:U",
33 "DS:dropped_tx:COUNTER:600:0:U",
34 ],
35 "network": [
36 "DS:packets_rx:COUNTER:600:0:U",
37 "DS:packets_tx:COUNTER:600:0:U",
38 "DS:bytes_rx:COUNTER:600:0:U",
39 "DS:bytes_tx:COUNTER:600:0:U",
40 "DS:retries_tx:COUNTER:600:0:U",
41 "DS:stations:GAUGE:600:0:U",
42 ],
43 "station": [
44 "DS:rssi:GAUGE:600:0:U",
45 "DS:noise:GAUGE:600:U:U",
46 "DS:signal:GAUGE:600:U:U",
47 "DS:power:GAUGE:600:0:U",
48 "DS:rate_rx:GAUGE:600:0:U",
49 "DS:rate_tx:GAUGE:600:0:U",
50 "DS:packets_rx:COUNTER:600:0:U",
51 "DS:packets_tx:COUNTER:600:0:U",
52 "DS:bytes_rx:COUNTER:600:0:U",
53 "DS:bytes_tx:COUNTER:600:0:U",
54 ],
55}
56
57
58@contextlib.contextmanager
59def get_mca_data(host):
60 client = paramiko.SSHClient()
61 client.set_missing_host_key_policy(paramiko.MissingHostKeyPolicy())
62 client.connect(host, username=USERNAME, password=PASSWORD)
63 _, stdout, _ = client.exec_command("mca-dump")
64
65 yield json.loads(stdout.read())
66
67 client.close()
68
69
70@contextlib.contextmanager
71def host_folder(host):
72 if not os.path.exists(host):
73 os.mkdir(host)
74
75 os.chdir(host)
76 yield
77 os.chdir(os.path.dirname(os.getcwd()))
78
79
80def rrd_update(kind, name, source, *stats):
81 stats = ":".join(["N"] + list(str(int(source[key])) for key in stats))
82 rrd_name = "{}-{}.rrd".format(kind, name)
83
84 if not os.path.exists(rrd_name):
85 command = ["rrdtool", "create", rrd_name]
86 command.extend(RRD_TEMPLATES[kind])
87 command.extend(RRA_COMMON)
88 subprocess.call(command)
89
90 subprocess.call(("rrdtool", "update", rrd_name, stats))
91
92
93def update_eth(data):
94 rrd_update("interface", "eth0", data, "rx_packets", "tx_packets",
95 "rx_bytes", "tx_bytes", "rx_errors", "tx_errors", "rx_errors",
96 "tx_errors")
97
98def update_network(data):
99 rrd_update("network", "{}_{}".format(data["essid"], data["radio"]), data,
100 "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "tx_retries",
101 "num_sta")
102
103
104def update_station(data):
105 rrd_update("station", data["mac"], data, "rssi", "noise", "signal",
106 "tx_power", "rx_rate", "tx_rate", "rx_packets", "tx_packets",
107 "rx_bytes", "tx_bytes")
108
109
110while True:
111 for host in HOSTS:
112 print "Updating {}".format(host)
113 with host_folder(host), get_mca_data(host) as data:
114 update_eth(data["if_table"][0])
115
116 for vap in data["vap_table"]:
117 update_network(vap)
118
119 for station in vap["sta_table"]:
120 update_station(station)
121
122 print "=" * 80
123 time.sleep(300)
diff --git a/parse_dumped_bodies.py b/parse_dumped_bodies.py
index 2bb16a2..4275e68 100644
--- a/parse_dumped_bodies.py
+++ b/parse_dumped_bodies.py
@@ -5,7 +5,7 @@ from cStringIO import StringIO
5from inform import InformSerializer, Cryptor 5from inform import InformSerializer, Cryptor
6 6
7 7
8PATH = "/Users/mcrute/Desktop/test" 8PATH = "/Users/mcrute/Desktop/test2"
9 9
10 10
11for file in os.listdir(PATH): 11for file in os.listdir(PATH):
diff --git a/requirements.txt b/requirements.txt
index 390e1fe..3c93d5c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,3 @@
1tornado==3.1 1tornado==3.1
2pycrypto==2.6 2pycrypto==2.6
3paramiko==1.11.1
diff --git a/utils.py b/utils.py
new file mode 100644
index 0000000..2226108
--- /dev/null
+++ b/utils.py
@@ -0,0 +1,16 @@
1def decode_station_band(sta):
2 tx = sta["tx_rate"] / 1000
3 rx = sta["rx_rate"] / 1000
4 is_a = sta.get("is_11a", None)
5 is_n = sta.get("is_11n", False)
6
7 if is_n:
8 return "N"
9
10 if is_a:
11 return "A"
12
13 if not is_n and any((rx > 11, rx > 11)):
14 return "G"
15 else:
16 return "B"