From 10d67313d320c97b48fe4fa2236f25ada94ae98c Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Tue, 8 Feb 2022 15:14:03 +0000 Subject: monitoring: T3872: Add new feature service monitoring telegraf --- .../custom_scripts/show_firewall_input_filter.py | 73 ++++++++++++++++++ .../custom_scripts/show_interfaces_input_filter.py | 88 ++++++++++++++++++++++ .../custom_scripts/vyos_services_input_filter.py | 61 +++++++++++++++ 3 files changed, 222 insertions(+) create mode 100755 src/etc/telegraf/custom_scripts/show_firewall_input_filter.py create mode 100755 src/etc/telegraf/custom_scripts/show_interfaces_input_filter.py create mode 100755 src/etc/telegraf/custom_scripts/vyos_services_input_filter.py (limited to 'src/etc') diff --git a/src/etc/telegraf/custom_scripts/show_firewall_input_filter.py b/src/etc/telegraf/custom_scripts/show_firewall_input_filter.py new file mode 100755 index 000000000..bf4bfd05d --- /dev/null +++ b/src/etc/telegraf/custom_scripts/show_firewall_input_filter.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 + +import json +import re +import time + +from vyos.util import cmd + + +def get_nft_filter_chains(): + """ + Get list of nft chains for table filter + """ + nft = cmd('/usr/sbin/nft --json list table ip filter') + nft = json.loads(nft) + chain_list = [] + + for output in nft['nftables']: + if 'chain' in output: + chain = output['chain']['name'] + chain_list.append(chain) + + return chain_list + + +def get_nftables_details(name): + """ + Get dict, counters packets and bytes for chain + """ + command = f'/usr/sbin/nft list chain ip filter {name}' + try: + results = cmd(command) + except: + return {} + + # Trick to remove 'NAME_' from chain name in the comment + # It was added to any chain T4218 + # counter packets 0 bytes 0 return comment "FOO default-action accept" + comment_name = name.replace("NAME_", "") + out = {} + for line in results.split('\n'): + comment_search = re.search(rf'{comment_name}[\- ](\d+|default-action)', line) + if not comment_search: + continue + + rule = {} + rule_id = comment_search[1] + counter_search = re.search(r'counter packets (\d+) bytes (\d+)', line) + if counter_search: + rule['packets'] = counter_search[1] + rule['bytes'] = counter_search[2] + + rule['conditions'] = re.sub(r'(\b(counter packets \d+ bytes \d+|drop|reject|return|log)\b|comment "[\w\-]+")', '', line).strip() + out[rule_id] = rule + return out + + +def get_nft_telegraf(name): + """ + Get data for telegraf in influxDB format + """ + for rule, rule_config in get_nftables_details(name).items(): + print(f'nftables,table=filter,chain={name},' + f'ruleid={rule} ' + f'pkts={rule_config["packets"]}i,' + f'bytes={rule_config["bytes"]}i ' + f'{str(int(time.time()))}000000000') + + +chains = get_nft_filter_chains() + +for chain in chains: + get_nft_telegraf(chain) diff --git a/src/etc/telegraf/custom_scripts/show_interfaces_input_filter.py b/src/etc/telegraf/custom_scripts/show_interfaces_input_filter.py new file mode 100755 index 000000000..0c7474156 --- /dev/null +++ b/src/etc/telegraf/custom_scripts/show_interfaces_input_filter.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 + +from vyos.ifconfig import Section +from vyos.ifconfig import Interface + +import time + +def get_interfaces(type='', vlan=True): + """ + Get interfaces: + ['dum0', 'eth0', 'eth1', 'eth1.5', 'lo', 'tun0'] + """ + interfaces = [] + ifaces = Section.interfaces(type) + for iface in ifaces: + if vlan == False and '.' in iface: + continue + interfaces.append(iface) + + return interfaces + +def get_interface_addresses(iface, link_local_v6=False): + """ + Get IP and IPv6 addresses from interface in one string + By default don't get IPv6 link-local addresses + If interface doesn't have address, return "-" + """ + addresses = [] + addrs = Interface(iface).get_addr() + + for addr in addrs: + if link_local_v6 == False: + if addr.startswith('fe80::'): + continue + addresses.append(addr) + + if not addresses: + return "-" + + return (" ".join(addresses)) + +def get_interface_description(iface): + """ + Get interface description + If none return "empty" + """ + description = Interface(iface).get_alias() + + if not description: + return "empty" + + return description + +def get_interface_admin_state(iface): + """ + Interface administrative state + up => 0, down => 2 + """ + state = Interface(iface).get_admin_state() + if state == 'up': + admin_state = 0 + if state == 'down': + admin_state = 2 + + return admin_state + +def get_interface_oper_state(iface): + """ + Interface operational state + up => 0, down => 1 + """ + state = Interface(iface).operational.get_state() + if state == 'down': + oper_state = 1 + else: + oper_state = 0 + + return oper_state + +interfaces = get_interfaces() + +for iface in interfaces: + print(f'show_interfaces,interface={iface} ' + f'ip_addresses="{get_interface_addresses(iface)}",' + f'state={get_interface_admin_state(iface)}i,' + f'link={get_interface_oper_state(iface)}i,' + f'description="{get_interface_description(iface)}" ' + f'{str(int(time.time()))}000000000') diff --git a/src/etc/telegraf/custom_scripts/vyos_services_input_filter.py b/src/etc/telegraf/custom_scripts/vyos_services_input_filter.py new file mode 100755 index 000000000..df4eed131 --- /dev/null +++ b/src/etc/telegraf/custom_scripts/vyos_services_input_filter.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +import time +from vyos.configquery import ConfigTreeQuery +from vyos.util import is_systemd_service_running, process_named_running + +# Availible services and prouceses +# 1 - service +# 2 - process +services = { + "protocols bgp" : "bgpd", + "protocols ospf" : "ospfd", + "protocols ospfv3" : "ospf6d", + "protocols rip" : "ripd", + "protocols ripng" : "ripngd", + "protocols isis" : "isisd", + "service pppoe" : "accel-ppp@pppoe.service", + "vpn l2tp remote-access" : "accel-ppp@l2tp.service", + "vpn pptp remote-access" : "accel-ppp@pptp.service", + "vpn sstp" : "accel-ppp@sstp.service", + "vpn ipsec" : "charon" +} + +# Configured services +conf_services = { + 'zebra' : 0, + 'staticd' : 0, +} +# Get configured service and create list to check if process running +config = ConfigTreeQuery() +for service in services: + if config.exists(service): + conf_services[services[service]] = 0 + +for conf_service in conf_services: + status = 0 + if ".service" in conf_service: + # Check systemd service + if is_systemd_service_running(conf_service): + status = 1 + else: + # Check process + if process_named_running(conf_service): + status = 1 + print(f'vyos_services,service="{conf_service}" ' + f'status={str(status)}i {str(int(time.time()))}000000000') -- cgit v1.2.3