def get_config(): tz = deepcopy(default_config_data) conf = Config() if conf.exists('system time-zone'): tz['name'] = conf.return_value('system time-zone') return tz
def get_config(): conf = Config() conf.set_level("service broadcast-relay id") relay_id = conf.list_nodes("") relays = [] for id in relay_id: interface_list = [] address = conf.return_value("{0} address".format(id)) description = conf.return_value("{0} description".format(id)) port = conf.return_value("{0} port".format(id)) # split the interface name listing and form a list if conf.exists("{0} interface".format(id)): intfs_names = conf.return_values("{0} interface".format(id)) intfs_names = intfs_names.replace("'", "") intfs_names = intfs_names.split() for name in intfs_names: interface_list.append(name) relay = { "id": id, "address": address, "description": description, "interfaces": interface_list, "port": port } relays.append(relay) return relays
def get_config(): lldp = deepcopy(default_config_data) conf = Config() if not conf.exists(base): return None else: lldp['options'] = get_options(conf) lldp['interface_list'] = get_interface_list(conf) lldp['location'] = get_location(conf) return lldp
def get_config(): nat = deepcopy(default_config_data) conf = Config() # read in current nftable (once) for further processing tmp = cmd('nft -j list table raw') nftable_json = json.loads(tmp) # condense the full JSON table into a list with only relevand informations pattern = 'nftables[?rule].rule[?expr[].jump].{chain: chain, handle: handle, target: expr[].jump.target | [0]}' condensed_json = jmespath.search(pattern, nftable_json) if not conf.exists(['nat']): nat['helper_functions'] = 'remove' # Retrieve current table handler positions nat['pre_ct_ignore'] = get_handler(condensed_json, 'PREROUTING', 'VYATTA_CT_HELPER') nat['pre_ct_conntrack'] = get_handler(condensed_json, 'PREROUTING', 'NAT_CONNTRACK') nat['out_ct_ignore'] = get_handler(condensed_json, 'OUTPUT', 'VYATTA_CT_HELPER') nat['out_ct_conntrack'] = get_handler(condensed_json, 'OUTPUT', 'NAT_CONNTRACK') nat['deleted'] = True return nat # check if NAT connection tracking helpers need to be set up - this has to # be done only once if not get_handler(condensed_json, 'PREROUTING', 'NAT_CONNTRACK'): nat['helper_functions'] = 'add' # Retrieve current table handler positions nat['pre_ct_ignore'] = get_handler(condensed_json, 'PREROUTING', 'VYATTA_CT_IGNORE') nat['pre_ct_conntrack'] = get_handler(condensed_json, 'PREROUTING', 'VYATTA_CT_PREROUTING_HOOK') nat['out_ct_ignore'] = get_handler(condensed_json, 'OUTPUT', 'VYATTA_CT_IGNORE') nat['out_ct_conntrack'] = get_handler(condensed_json, 'OUTPUT', 'VYATTA_CT_OUTPUT_HOOK') # set config level for parsing in NAT configuration conf.set_level(['nat']) # use a common wrapper function to read in the source / destination # tree from the config - thus we do not need to replicate almost the # same code :-) for tgt in ['source', 'destination', 'nptv6']: nat[tgt] = parse_source_destination(conf, tgt) return nat
def get_config(): regdom = deepcopy(default_config_data) conf = Config() base = ['system', 'wifi-regulatory-domain'] # Check if interface has been removed if not conf.exists(base): regdom['deleted'] = True return regdom else: regdom['regdom'] = conf.return_value(base) return regdom
def verify(bridge): if bridge['dhcpv6_prm_only'] and bridge['dhcpv6_temporary']: raise ConfigError( 'DHCPv6 temporary and parameters-only options are mutually exclusive!' ) vrf_name = bridge['vrf'] if vrf_name and vrf_name not in interfaces(): raise ConfigError(f'VRF "{vrf_name}" does not exist') conf = Config() for intf in bridge['member']: # the interface must exist prior adding it to a bridge if intf['name'] not in interfaces(): raise ConfigError( (f'Cannot add nonexistent interface "{intf["name"]}" ' f'to bridge "{bridge["intf"]}"')) if intf['name'] == 'lo': raise ConfigError( 'Loopback interface "lo" can not be added to a bridge') # bridge members aren't allowed to be members of another bridge for br in conf.list_nodes('interfaces bridge'): # it makes no sense to verify ourself in this case if br == bridge['intf']: continue tmp = conf.list_nodes(f'interfaces bridge {br} member interface') if intf['name'] in tmp: raise ConfigError(( f'Cannot add interface "{intf["name"]}" to bridge ' f'"{bridge["intf"]}", it is already a member of bridge "{br}"!' )) # bridge members are not allowed to be bond members tmp = is_member(conf, intf['name'], 'bonding') if tmp: raise ConfigError( (f'Cannot add interface "{intf["name"]}" to bridge ' f'"{bridge["intf"]}", it is already a member of bond "{tmp}"!' )) # bridge members must not have an assigned address if has_address_configured(conf, intf['name']): raise ConfigError( (f'Cannot add interface "{intf["name"]}" to bridge ' f'"{bridge["intf"]}", it has an address assigned!')) return None
def get_config(): c = Config() interfaces = dict() for intf in c.list_effective_nodes('interfaces ethernet'): # skip interfaces that are disabled or is configured for dhcp check_disable = "interfaces ethernet {} disable".format(intf) check_dhcp = "interfaces ethernet {} address dhcp".format(intf) if c.exists_effective(check_disable): continue # get addresses configured on the interface intf_addresses = c.return_effective_values( "interfaces ethernet {} address".format(intf)) interfaces[intf] = [addr.strip("'") for addr in intf_addresses] return interfaces
def get_config(): opt = deepcopy(default_config_data) conf = Config() conf.set_level('system options') if conf.exists(''): if conf.exists('ctrl-alt-del-action'): opt['ctrl_alt_del'] = conf.return_value('ctrl-alt-del-action') opt['beep_if_fully_booted'] = conf.exists('beep-if-fully-booted') opt['reboot_on_panic'] = conf.exists('reboot-on-panic') return opt
def show_status(): # Do nothing if service is not configured c = Config() if not c.exists_effective('service dns dynamic'): print("Dynamic DNS not configured") sys.exit(0) data = { 'hosts': [] } with open(cache_file, 'r') as f: for line in f: if line.startswith('#'): continue outp = { 'host': '', 'ip': '', 'time': '' } if 'host=' in line: host = line.split('host=')[1] if host: outp['host'] = host.split(',')[0] if 'ip=' in line: ip = line.split('ip=')[1] if ip: outp['ip'] = ip.split(',')[0] if 'atime=' in line: atime = line.split('atime=')[1] if atime: tmp = atime.split(',')[0] outp['time'] = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(int(tmp, base=10))) if 'status=' in line: status = line.split('status=')[1] if status: outp['status'] = status.split(',')[0] data['hosts'].append(outp) tmpl = jinja2.Template(OUT_TMPL_SRC) print(tmpl.render(data))
def get_config(): """Get configuration""" conf = Config() hostname = conf.return_value("system host-name") domain = conf.return_value("system domain-name") # No one likes fixups, but we really don't want VyOS fail to boot # if hostname is not in the config if not hostname: hostname = "vyos" if domain: fqdn = "{0}.{1}".format(hostname, domain) else: fqdn = hostname return {"hostname": hostname, "domain": domain, "fqdn": fqdn}
def get_config(): ip_opt = deepcopy(default_config_data) conf = Config() conf.set_level('system ip') if conf.exists(''): if conf.exists('arp table-size'): ip_opt['arp_table'] = int(conf.return_value('arp table-size')) if conf.exists('disable-forwarding'): ip_opt['ipv4_forward'] = '0' if conf.exists('multipath ignore-unreachable-nexthops'): ip_opt['mp_unreach_nexthop'] = '1' if conf.exists('multipath layer4-hashing'): ip_opt['mp_layer4_hashing'] = '1' return ip_opt
def get_config(): c = Config() config_data = { 'qat_conf' : None, 'ipsec_conf' : None, 'openvpn_conf' : None, } if c.exists('system acceleration qat'): config_data['qat_conf'] = True if c.exists('vpn ipsec '): gl_ipsec_conf = True config_data['ipsec_conf'] = True if c.exists('interfaces openvpn'): config_data['openvpn_conf'] = True return config_data
def list_users(): cfg = Config() vyos_users = cfg.list_effective_nodes('system login user') users = [] with open('/var/log/lastlog', 'rb') as lastlog_file: for (name, _, uid, _, _, _, _) in pwd.getpwall(): lastlog_info = decode_lastlog(lastlog_file, uid) if lastlog_info is None: continue user_info = UserInfo( uid, name, user_type='vyos' if name in vyos_users else 'other', is_locked=is_locked(name), login_time=lastlog_info[0], tty=lastlog_info[1], host=lastlog_info[2]) users.append(user_info) return users
def get_config(): conf = Config() if not conf.exists('service https certificates certbot'): return None else: conf.set_level('service https certificates certbot') cert = {} if conf.exists('domain-name'): cert['domains'] = conf.return_values('domain-name') if conf.exists('email'): cert['email'] = conf.return_value('email') return cert
def get_config(): bgp = deepcopy(default_config_data) conf = Config() # this lives in the "nbgp" tree until we switch over base = ['protocols', 'nbgp'] if not conf.exists(base): return None bgp = deepcopy(default_config_data) # Get full BGP configuration as dictionary - output the configuration for development # # vyos@vyos# commit # [ protocols nbgp 65000 ] # {'nbgp': {'65000': {'address-family': {'ipv4-unicast': {'aggregate-address': {'1.1.0.0/16': {}, # '2.2.2.0/24': {}}}, # 'ipv6-unicast': {'aggregate-address': {'2001:db8::/32': {}}}}, # 'neighbor': {'192.0.2.1': {'password': '******', # 'remote-as': '100'}}}}} # tmp = conf.get_config_dict(base) # extract base key from dict as this is our AS number bgp['as_number'] = jmespath.search('nbgp | keys(@) [0]', tmp) # adjust level of dictionary returned by get_config_dict() # by using jmesgpath and update dictionary bgp.update(jmespath.search('nbgp.* | [0]', tmp)) from pprint import pprint pprint(bgp) # resulting in e.g. # vyos@vyos# commit # [ protocols nbgp 65000 ] # {'address-family': {'ipv4-unicast': {'aggregate-address': {'1.1.0.0/16': {}, # '2.2.2.0/24': {}}}, # 'ipv6-unicast': {'aggregate-address': {'2001:db8::/32': {}}}}, # 'as_number': '65000', # 'neighbor': {'192.0.2.1': {'password': '******', 'remote-as': '100'}}, # 'timers': {'holdtime': '5'}} return bgp
def get_config(): conf = Config() options = get_options(conf) interface_list = get_interface_list(conf) location = get_location(conf) lldp = { "options": options, "interface_list": interface_list, "location": location } return lldp
def verify(eth): if eth['deleted']: return None if eth['intf'] not in interfaces(): raise ConfigError(f"Interface ethernet {eth['intf']} does not exist") if eth['speed'] == 'auto': if eth['duplex'] != 'auto': raise ConfigError( 'If speed is hardcoded, duplex must be hardcoded, too') if eth['duplex'] == 'auto': if eth['speed'] != 'auto': raise ConfigError( 'If duplex is hardcoded, speed must be hardcoded, too') if eth['dhcpv6_prm_only'] and eth['dhcpv6_temporary']: raise ConfigError( 'DHCPv6 temporary and parameters-only options are mutually exclusive!' ) vrf_name = eth['vrf'] if vrf_name and vrf_name not in interfaces(): raise ConfigError(f'VRF "{vrf_name}" does not exist') conf = Config() # some options can not be changed when interface is enslaved to a bond for bond in conf.list_nodes('interfaces bonding'): if conf.exists('interfaces bonding ' + bond + ' member interface'): bond_member = conf.return_values('interfaces bonding ' + bond + ' member interface') if eth['intf'] in bond_member: if eth['address']: raise ConfigError( f"Can not assign address to interface {eth['intf']} which is a member of {bond}" ) # use common function to verify VLAN configuration verify_vlan_config(eth) return None
def generate(c): c_eff = Config() c_eff.set_level('protocols static') c_eff_cnf = {} for ip_addr in c_eff.list_effective_nodes('arp'): c_eff_cnf.update({ ip_addr: c_eff.return_effective_value('arp ' + ip_addr + ' hwaddr') }) config_data = {'remove': [], 'update': {}} ### removal if c == None: for ip_addr in c_eff_cnf: config_data['remove'].append(ip_addr) else: for ip_addr in c_eff_cnf: if not ip_addr in c or c[ip_addr] == None: config_data['remove'].append(ip_addr) ### add/update if c != None: for ip_addr in c: if not ip_addr in c_eff_cnf: config_data['update'][ip_addr] = c[ip_addr] if ip_addr in c_eff_cnf: if c[ip_addr] != c_eff_cnf[ip_addr] and c[ip_addr] != None: config_data['update'][ip_addr] = c[ip_addr] return config_data
def get_config(): c = Config() if not c.exists('protocols static arp'): return None c.set_level('protocols static') config_data = {} for ip_addr in c.list_nodes('arp'): config_data.update( {ip_addr: c.return_value('arp ' + ip_addr + ' hwaddr')}) return config_data
def get_config(): bfd = deepcopy(default_config_data) conf = Config() if not (conf.exists('protocols bfd') or conf.exists_effective('protocols bfd')): return None else: conf.set_level('protocols bfd') # as we have to use vtysh to talk to FRR we also need to know # which peers are gone due to a config removal - thus we read in # all peers (active or to delete) for peer in conf.list_effective_nodes('peer'): bfd['old_peers'].append(get_bfd_peer_config(peer, "effective")) for peer in conf.list_nodes('peer'): bfd['new_peers'].append(get_bfd_peer_config(peer)) # find deleted peers set_new_peers = set(conf.list_nodes('peer')) set_old_peers = set(conf.list_effective_nodes('peer')) bfd['deleted_peers'] = set_old_peers - set_new_peers return bfd
def show_brief(): config = Config() if len(config.list_effective_nodes('interfaces wireless')) == 0: print("No Wireless interfaces configured") exit(0) interfaces = [] for intf in config.list_effective_nodes('interfaces wireless'): config.set_level('interfaces wireless {}'.format(intf)) data = {'name': intf, 'type': '', 'ssid': '', 'channel': ''} data['type'] = config.return_effective_value('type') data['ssid'] = config.return_effective_value('ssid') data['channel'] = config.return_effective_value('channel') interfaces.append(data) return interfaces
def get_config(): conf = Config() conf.set_level("system task-scheduler task") task_names = conf.list_nodes("") tasks = [] for name in task_names: interval = conf.return_value("{0} interval".format(name)) spec = conf.return_value("{0} crontab-spec".format(name)) executable = conf.return_value("{0} executable path".format(name)) args = conf.return_value("{0} executable arguments".format(name)) task = { "name": name, "interval": interval, "spec": spec, "executable": executable, "args": args } tasks.append(task) return tasks
def get_config(): banner = default_config_data conf = Config() base_level = ['system', 'login', 'banner'] if not conf.exists(base_level): return banner else: conf.set_level(base_level) # Post-Login banner if conf.exists(['post-login']): tmp = conf.return_value(['post-login']) # post-login banner can be empty as well if tmp: tmp = tmp.replace('\\n', '\n') tmp = tmp.replace('\\t', '\t') # always add newline character tmp += '\n' else: tmp = '' banner['motd'] = tmp # Pre-Login banner if conf.exists(['pre-login']): tmp = conf.return_value(['pre-login']) # pre-login banner can be empty as well if tmp: tmp = tmp.replace('\\n', '\n') tmp = tmp.replace('\\t', '\t') # always add newline character tmp += '\n' else: tmp = '' banner['issue'] = banner['issue_net'] = tmp return banner
def get_config(): mdns = deepcopy(default_config_data) conf = Config() base = ['service', 'mdns', 'repeater'] if not conf.exists(base): return None else: conf.set_level(base) # Service can be disabled by user if conf.exists(['disable']): mdns['disabled'] = True return mdns # Interface to repeat mDNS advertisements if conf.exists(['interface']): mdns['interfaces'] = conf.return_values(['interface']) return mdns
def get_config(): interface_list = [] conf = Config() conf.set_level('service mdns repeater') if not conf.exists(''): return interface_list if conf.exists('interface'): intfs_names = [] intfs_names = conf.return_values('interface') for name in intfs_names: interface_list.append(name) return interface_list
def get_config(): vyos_cert = vyos.defaults.vyos_cert_data conf = Config() if not conf.exists( 'service https certificates system-generated-certificate'): return None else: conf.set_level( 'service https certificates system-generated-certificate') if conf.exists('lifetime'): lifetime = conf.return_value('lifetime') vyos_cert['lifetime'] = lifetime return vyos_cert
def verify(bridge): if bridge['dhcpv6_prm_only'] and bridge['dhcpv6_temporary']: raise ConfigError( 'DHCPv6 temporary and parameters-only options are mutually exclusive!' ) vrf_name = bridge['vrf'] if vrf_name and vrf_name not in interfaces(): raise ConfigError(f'VRF "{vrf_name}" does not exist') conf = Config() for br in conf.list_nodes('interfaces bridge'): # it makes no sense to verify ourself in this case if br == bridge['intf']: continue for intf in bridge['member']: tmp = conf.list_nodes( 'interfaces bridge {} member interface'.format(br)) if intf['name'] in tmp: raise ConfigError( 'Interface "{}" belongs to bridge "{}" and can not be enslaved.' .format(intf['name'], bridge['intf'])) # the interface must exist prior adding it to a bridge for intf in bridge['member']: if intf['name'] not in interfaces(): raise ConfigError( 'Can not add non existing interface "{}" to bridge "{}"'. format(intf['name'], bridge['intf'])) if intf['name'] == 'lo': raise ConfigError( 'Loopback interface "lo" can not be added to a bridge') # bridge members are not allowed to be bond members, too for intf in bridge['member']: for bond in conf.list_nodes('interfaces bonding'): if conf.exists('interfaces bonding ' + bond + ' member interface'): if intf['name'] in conf.return_values('interfaces bonding ' + bond + ' member interface'): raise ConfigError( 'Interface {} belongs to bond {}, can not add it to {}' .format(intf['name'], bond, bridge['intf'])) return None
def get_config(): c = Config() if not c.exists_effective('interfaces ethernet'): return None interfaces = {} for intf in c.list_effective_nodes('interfaces ethernet'): if not c.exists_effective('interfaces ethernet ' + intf + ' disable') and c.exists_effective( 'interfaces ethernet ' + intf + ' address'): interfaces[intf] = re.sub( "\'", "", c.return_effective_values('interfaces ethernet ' + intf + ' address')).split() return interfaces
def get_config(): http_api = deepcopy(vyos.defaults.api_data) x = http_api.get('api_keys') if x is None: default_key = None else: default_key = x[0] keys_added = False conf = Config() if not conf.exists('service https api'): return None else: conf.set_level('service https api') if conf.exists('strict'): http_api['strict'] = 'true' if conf.exists('debug'): http_api['debug'] = 'true' if conf.exists('port'): port = conf.return_value('port') http_api['port'] = port if conf.exists('keys'): for name in conf.list_nodes('keys id'): if conf.exists('keys id {0} key'.format(name)): key = conf.return_value('keys id {0} key'.format(name)) new_key = {'id': name, 'key': key} http_api['api_keys'].append(new_key) keys_added = True if keys_added and default_key: if default_key in http_api['api_keys']: http_api['api_keys'].remove(default_key) return http_api
{% endfor %}{% endif %} """ VIEW_OUTP_TMPL_SRC = """ SNMPv3 Views: {% if view -%}{% for v in view %} View : {{ v.name }} OIDs : .{{ v.oids | join("\n .")}} {% endfor %}{% endif %} """ if __name__ == '__main__': args = parser.parse_args() # Do nothing if service is not configured c = Config() if not c.exists_effective('service snmp v3'): print("SNMP v3 is not configured") sys.exit(0) data = { 'group': [], 'trap': [], 'user': [], 'view': [] } if c.exists_effective('service snmp v3 group'): for g in c.list_effective_nodes('service snmp v3 group'): group = { 'name': g,