Issues (12)

scripts/kytos_zabbix.py (1 issue)

Severity
1
#!/usr/bin/python3
2
"""
3
   This code was created to integrate Kytos napps with Zabbix
4
5
   Created on: Dec/2020
6
   Author: Italo Valcy
7
8
   Changelog:
9
     - 2020/12/10 - Creating the script for monitoring items of Kytos similar to oess_zabbix.py
10
     - 2020/12/15 - adding option to export EVC statistics (bytes and packets)
11
     - 2022/11/30 - bug fixes and integration with kytos-ng/flow_stats rather than flow_manager
12
13
"""
14
15
import os
16
import sys
17
import json
18
import argparse
19
import requests
20
import time
21
22
url='http://192.168.0.1:8181/api'
23
24
CACHE_DIR='/var/cache/kytos_zabbix'
25
cache = {
26
 1: CACHE_DIR + '/nodes.json',
27
 2: CACHE_DIR + '/links.json',
28
 3: CACHE_DIR + '/evcs.json',
29
 4: CACHE_DIR + '/flows.json',
30
 5: CACHE_DIR + '/flows.json',
31
}
32
33
help_msg = "Kytos wrapper for Zabbix"
34
35
parser = argparse.ArgumentParser()
36
parser.add_argument("-l", "--url", dest="url", help="URL for your Kytos REST API", default=url)
37
parser.add_argument("-u", "--user", dest="username", help="Username to authenticate into Kytos API")
38
parser.add_argument("-p", "--pass", dest="password", help="Password to authenticate into Kytos API")
39
parser.add_argument("-f", "--authfile", dest="authfile", help="Authentication file containing username (first line) and password (second line) to authenticate into Kytos API")
40
parser.add_argument("-T", "--timeout", dest="timeout", type=int, help="You can tell Requests to stop waiting for a response after a given number of seconds", default=5)
41
parser.add_argument("-c", "--cache_policy", dest="cache_policy", default=60, help="Cache policy: never, always or X seconds (default to cache for 600 seconds)")
42
parser.add_argument("-o", "--monitoring_option", dest="option", type=int, default=1, choices=[1, 2, 3, 4, 5], help="Monitoring option: 1 - for monitor nodes, 2 - for monitor links, 3 - for monitor evcs (status), 4 - evc statistics, 5 - OpenFlow flows stats")
43
parser.add_argument("-t", "--target", dest="target", help="Item status (0-down/others, 1-disabled, 2-up/primary, 3-up/backup). Argument is the item id to be monitored (depending on the -o option).")
44
parser.add_argument("-z", "--zabbix_output", dest="count_output", type=int, choices=[1, 2], help="Zabbix LLD: (1) Count number of lines in each output or (2) list-only registers", default=None)
45
parser.add_argument("-s", "--stats", dest="stats", type=int, default=1, choices=[1, 2, 3, 4], help="EVC statistics type: 1 - bytes/UNI_A, 2 - bytes/UNI_Z , 3 - packets/UNI_A, 4 - packets/UNI_Z")
46
47
args = parser.parse_args()
48
49
if args.option == 4 and not args.target:
50
    sys.stderr.write('error: to print statistics it requires -t\n')
51
    parser.print_help()
52
    sys.exit(2)
53
54
if args.authfile:
55
    authdata = open(args.authfile).readlines()
56
    args.username = authdata[0].strip()
57
    args.password = authdata[1].strip()
58
59
args.url = os.environ.get("KYTOS_URL", args.url)
60
args.timeout = os.environ.get("KYTOS_TIMEOUT", args.timeout)
61
args.username = os.environ.get("KYTOS_USERNAME", args.username)
62
args.password = os.environ.get("KYTOS_PASSWORD", args.password)
63
64
def is_valid_cache(option):
65
    filename = cache[option]
66
    if not os.path.isfile(filename) or os.path.getsize(filename) == 0:
67
        return False
68
    if args.cache_policy == 'never':
69
        return False
70
    elif args.cache_policy == 'always':
71
        return True
72
    try:
73
        tmout = int(args.cache_policy)
74
    except:
75
        tmout = 600
76
    return os.stat(filename).st_mtime > time.time() - tmout
77
78
def get_data(option, url):
79
    if is_valid_cache(option):
80
        with open(cache[option], 'r') as file:
81
            return file.read()
82
83
    auth = None
84
    if args.username and args.password:
85
        auth = (args.username, args.password)  # assume HTTP Basic
86
87
    try:
88
        response = requests.get(url, auth=auth, timeout=args.timeout)
89
        assert response.status_code == 200, response.text
90
        data = response.text
91
    except Exception as e:
92
        print("ERROR: failed to get data from URL=%s: %s" % (url, e))
93
        sys.exit(2)
94
95
    if args.cache_policy != 'never':
96
        with open(cache[option], 'w') as file:
97
            file.write(data)
0 ignored issues
show
The variable data does not seem to be defined for all execution paths.
Loading history...
98
    return data
99
100
def get_kytos_data(url, option):
101
    API_ENDPOINT = ""
102
    if option == 1:
103
        API_ENDPOINT="/kytos/topology/v3/switches"
104
    elif option == 2:
105
        API_ENDPOINT="/kytos/topology/v3/links"
106
    elif option == 3:
107
        API_ENDPOINT="/kytos/mef_eline/v2/evc"
108
    elif option in [4,5]:
109
        API_ENDPOINT="/amlight/flow_stats/v1/flow/stats"
110
111
    data = get_data(option, url + API_ENDPOINT)
112
    try:
113
        data = json.loads(data)
114
        if option == 1:
115
            data = data["switches"]
116
        elif option == 2:
117
            data = data["links"]
118
    except Exception as e:
119
        print("ERROR: failed to get data from URL=%s: %s" % (url + API_ENDPOINT, e))
120
        sys.exit(2)
121
122
    return data
123
124
def convert_status(active, enabled):
125
    if active:
126
        return "2"
127
    elif not enabled:
128
        return "1"
129
    else:
130
        return "0"
131
132
def print_target_results(data, option, target):
133
    if target not in data:
134
        print("Unknown target=%s" % (target))
135
        return
136
137
    if option == 1:
138
        sw = data[target]
139
        print(convert_status(sw["active"], sw["enabled"]))
140
    elif option == 2:
141
        link = data[target]
142
        print(convert_status(link["active"], link["enabled"]))
143
    elif option == 3:
144
        evc = data[target]
145
        status = convert_status(evc["active"], evc["enabled"])
146
        if status != "2" or evc.get("dynamic_backup_path", False):
147
            print(status)
148
            return
149
        if evc["current_path"] == evc["primary_path"]:
150
            print("2")
151
        elif evc["current_path"] == evc["backup_path"]:
152
            print("3")
153
        else:
154
            print("0")
155
156
def print_flow_stats(data, target):
157
    if target:
158
        print(len(data.get(target, [])))
159
    else:
160
        l = 0
161
        for s in data:
162
            l+= len(data[s])
163
        print(l)
164
165
def print_stats(flows, target, stats_type):
166
    evcs = get_kytos_data(args.url, 3)
167
    if target not in evcs:
168
        print("Unknown target=%s" % (target))
169
        return
170
171
    uni_field = 'uni_a'
172
    if stats_type in [2,4]:
173
        uni_field = 'uni_z'
174
    stats_field = 'byte_count'
175
    if stats_type in [3, 4]:
176
        stats_field = 'packet_count'
177
178
    uni = evcs[target][uni_field]['interface_id'].split(':')
179
    sw = ':'.join(uni[:-1])
180
    iface = int(uni[-1])
181
    try:
182
        tag = evcs[target][uni_field]['tag']['value']
183
    except:
184
        tag = None
185
186
    result = 0
187
    for flow_id, flow in flows.get(sw, {}).items():
188
        if format(flow['cookie'], 'x')[2:] == target and flow['match']['in_port'] == iface and flow['match'].get('dl_vlan') == tag:
189
            result += flow[stats_field]
190
191
    print(result)
192
193
def list_items(data, option):
194
    result = {"data":[]}
195
    if option == 1:
196
        for sw in data:
197
            name = data[sw]["metadata"].get("name", None)
198
            if not name:
199
                name = data[sw]["name"]
200
            result["data"].append({"{#OFSWID}": sw, "{#OFSWNAME}": name})
201
    elif option == 2:
202
        for l in data:
203
            link = data[l]
204
            name = link.get("name", None)
205
            if not name:
206
                name = link["endpoint_a"]["name"] + "_" +  link["endpoint_b"]["name"]
207
            result["data"].append({"{#LINKID}": l, "{#LINKNAME}": name})
208
    elif option == 3:
209
        for evc in data:
210
            result["data"].append({"{#EVCID}": evc, "{#EVCNAME}": data[evc]["name"]})
211
    print(json.dumps(result))
212
213
data = get_kytos_data(args.url, args.option)
214
215
if args.option == 4:
216
    print_stats(data, args.target, args.stats)
217
elif args.option == 5:
218
    print_flow_stats(data, args.target)
219
elif args.target:
220
    print_target_results(data, args.option, args.target)
221
elif args.count_output == 1:
222
    # Count amount of items
223
    print(len(data))
224
elif args.count_output == 2:
225
    # List in JSON format. Don't show status!
226
    list_items(data, args.option)
227
else:
228
    parser.print_help()
229