#!/usr/bin/env python3 # # Copyright (C) 2018 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 sys import os import jinja2 import vyos.version import ipaddress from vyos.config import Config from vyos import ConfigError config_file_client = r'/etc/snmp/snmp.conf' config_file_daemon = r'/etc/snmp/snmpd.conf' # SNMPS template - be careful if you edit the template. client_config_tmpl = """ ### Autogenerated by snmp.py ### {% if trap_source -%} clientaddr {{ trap_source }} {% endif %} """ # SNMPS template - be careful if you edit the template. daemon_config_tmpl = """ ### Autogenerated by snmp.py ### # non configurable defaults sysObjectID 1.3.6.1.4.1.44641 sysServices 14 # maybe needed by lldpd master agentx agentXPerms 0755 0755 # add hook to read IF-MIB::ifAlias from sysfs pass .1.3.6.1.2.1.31.1.1.1.18 /opt/vyatta/sbin/if-mib-alias # ospfd smuxpeer .1.3.6.1.4.1.3317.1.2.2 # bgpd smuxpeer .1.3.6.1.4.1.3317.1.2.5 # ripd smuxpeer .1.3.6.1.4.1.3317.1.2.3 # mribd smuxpeer .1.3.6.1.4.1.3317.1.2.9 # mribd smuxpeer .1.3.6.1.2.1.83 # pimd smuxpeer .1.3.6.1.4.1.3317.1.2.8 # pimd smuxpeer .1.3.6.1.2.1.157 smuxsocket localhost # linkUp/Down configure the Event MIB tables to monitor # the ifTable for network interfaces being taken up or down # for making internal queries to retrieve any necessary information # create an internal snmpv3 user of the form 'vyattaxxxxxxxxxxxxxxxx' ## TODO!!!! iquerySecName vyatta3392514e4189da84 # Modified from the default linkUpDownNotification # to include more OIDs and poll more frequently notificationEvent linkUpTrap linkUp ifIndex ifDescr ifType ifAdminStatus ifOperStatus notificationEvent linkDownTrap linkDown ifIndex ifDescr ifType ifAdminStatus ifOperStatus monitor -r 10 -e linkUpTrap "Generate linkUp" ifOperStatus != 2 monitor -r 10 -e linkDownTrap "Generate linkDown" ifOperStatus == 2 ######################## # configurable section # ######################## # Version sysDescr VyOS {{ version }} {% if description -%} # Description SysDescr {{ description }} {% endif %} # Listen agentaddress unix:/run/snmpd.socket{% for li in listen_on %},{{ li }}{% endfor %} # SNMP communities {% if communities -%} {% for c in communities %} {% if c.network -%} {% for network in c.network %} {{ c.authorization }}community {{ c.name }} {{ network }} {% endfor %} {% else %} {{ c.authorization }}community {{ c.name }} {% endif %} {% endfor %} {% endif %} {% if contact -%} # system contact information SysContact {{ contact }} {% endif %} {% if location -%} # system location information SysLocation {{ location }} {% endif %} {% if smux_peers -%} # additional smux peers {% for sp in smux_peers %} smuxpeer {{ sp }} {% endfor %} {% endif %} """ default_config_data = { 'listen_on': [], 'location' : '', 'description' : '', 'contact' : '', 'communities': [], 'trap_source': '', 'smux_peers': [] } def get_config(): snmp = default_config_data conf = Config() if not conf.exists('service snmp'): return None else: conf.set_level('service snmp') version_data = vyos.version.get_version_data() snmp.setdefault('version', version_data['version']) if conf.exists('community'): for name in conf.list_nodes('community'): community = { 'name': name, 'authorization': 'ro', 'network': [] } if conf.exists('community {0} authorization'.format(name)): community['authorization'] = conf.return_value('community {0} authorization'.format(name)) if conf.exists('community {0} network'.format(name)): community['network'] = conf.return_values('community {0} network'.format(name)) snmp['communities'].append(community) if conf.exists('contact'): snmp['contact'] = conf.return_value('contact') if conf.exists('description'): snmp['description'] = conf.return_value('description') if conf.exists('listen-address'): for addr in conf.list_nodes('listen-address'): listen = '' port = '161' if conf.exists('listen-address {0} port'.format(addr)): port = conf.return_value('listen-address {0} port'.format(addr)) if ipaddress.ip_address(addr).version == 4: # udp:127.0.0.1:161 listen = 'udp:' + addr + ':' + port elif ipaddress.ip_address(addr).version == 6: # udp6:[::1]:161 listen = 'udp6:' + '[' + addr + ']' + ':' + port else: raise ConfigError('Invalid IP address version') snmp['listen_on'].append(listen) if conf.exists('location'): snmp['location'] = conf.return_value('location') if conf.exists('smux-peer'): snmp['smux_peers'] = conf.return_values('smux-peer') if conf.exists('trap-source'): snmp['trap_source'] = conf.return_value('trap-source') return snmp def verify(snmp): return None def generate(snmp): if snmp is None: return None tmpl = jinja2.Template(client_config_tmpl, trim_blocks=True) config_text = tmpl.render(snmp) with open(config_file_client, 'w') as f: f.write(config_text) tmpl = jinja2.Template(daemon_config_tmpl, trim_blocks=True) config_text = tmpl.render(snmp) with open(config_file_daemon, 'w') as f: f.write(config_text) return None def apply(snmp): if snmp is not None: os.system("sudo systemctl restart snmpd.service") else: # SNMP is removed in the commit os.system("sudo systemctl stop snmpd.service") os.unlink(config_file_client) os.unlink(config_file_daemon) return None if __name__ == '__main__': try: c = get_config() verify(c) generate(c) apply(c) except ConfigError as e: print(e) sys.exit(1)