aboutsummaryrefslogtreecommitdiff
path: root/collect_ssh.py
blob: 607b7745b50339bb5393bb0085f4b13eeb12aaff (plain)
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)