diff options
Diffstat (limited to 'src')
221 files changed, 1640 insertions, 569 deletions
diff --git a/src/completion/list_dumpable_interfaces.py b/src/completion/list_dumpable_interfaces.py index 67bf6206b..f9748352f 100755 --- a/src/completion/list_dumpable_interfaces.py +++ b/src/completion/list_dumpable_interfaces.py @@ -4,7 +4,7 @@ import re -from vyos.util import cmd +from vyos.utils.process import cmd if __name__ == '__main__': out = cmd('tcpdump -D').split('\n') diff --git a/src/completion/list_ipoe.py b/src/completion/list_ipoe.py index c386b46a2..5a8f4b0c5 100755 --- a/src/completion/list_ipoe.py +++ b/src/completion/list_ipoe.py @@ -1,7 +1,21 @@ #!/usr/bin/env python3 +# Copyright 2020-2023 VyOS maintainers and contributors <maintainers@vyos.io> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library. If not, see <http://www.gnu.org/licenses/>. import argparse -from vyos.util import popen +from vyos.utils.process import popen if __name__ == '__main__': parser = argparse.ArgumentParser() diff --git a/src/completion/list_ipsec_profile_tunnels.py b/src/completion/list_ipsec_profile_tunnels.py index df6c52f6d..4a917dbd6 100644 --- a/src/completion/list_ipsec_profile_tunnels.py +++ b/src/completion/list_ipsec_profile_tunnels.py @@ -19,7 +19,7 @@ import sys import argparse from vyos.config import Config -from vyos.util import dict_search +from vyos.utils.dict import dict_search def get_tunnels_from_ipsecprofile(profile): config = Config() diff --git a/src/completion/list_openconnect_users.py b/src/completion/list_openconnect_users.py index a266fd893..db2f4b4da 100755 --- a/src/completion/list_openconnect_users.py +++ b/src/completion/list_openconnect_users.py @@ -15,7 +15,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. from vyos.config import Config -from vyos.util import dict_search +from vyos.utils.dict import dict_search def get_user_from_ocserv(): config = Config() diff --git a/src/completion/list_openvpn_users.py b/src/completion/list_openvpn_users.py index c472dbeab..b2b0149fc 100755 --- a/src/completion/list_openvpn_users.py +++ b/src/completion/list_openvpn_users.py @@ -19,7 +19,7 @@ import sys import argparse from vyos.config import Config -from vyos.util import dict_search +from vyos.utils.dict import dict_search def get_user_from_interface(interface): config = Config() diff --git a/src/conf_mode/arp.py b/src/conf_mode/arp.py index 7dc5206e0..b141f1141 100755 --- a/src/conf_mode/arp.py +++ b/src/conf_mode/arp.py @@ -18,7 +18,7 @@ from sys import exit from vyos.config import Config from vyos.configdict import node_changed -from vyos.util import call +from vyos.utils.process import call from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/bcast_relay.py b/src/conf_mode/bcast_relay.py index 7b93a31c0..ced5d212e 100755 --- a/src/conf_mode/bcast_relay.py +++ b/src/conf_mode/bcast_relay.py @@ -23,7 +23,7 @@ from sys import exit from vyos.config import Config from vyos.configverify import verify_interface_exists from vyos.template import render -from vyos.util import call +from vyos.utils.process import call from vyos.validate import is_afi_configured from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/conntrack.py b/src/conf_mode/conntrack.py index 82289526f..2a77540f7 100755 --- a/src/conf_mode/conntrack.py +++ b/src/conf_mode/conntrack.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-2023 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 @@ -23,10 +23,10 @@ from vyos.config import Config from vyos.configdict import dict_merge from vyos.firewall import find_nftables_rule from vyos.firewall import remove_nftables_rule -from vyos.util import cmd -from vyos.util import run -from vyos.util import process_named_running -from vyos.util import dict_search +from vyos.utils.process import process_named_running +from vyos.utils.dict import dict_search +from vyos.utils.process import cmd +from vyos.utils.process import run from vyos.template import render from vyos.xml import defaults from vyos import ConfigError diff --git a/src/conf_mode/conntrack_sync.py b/src/conf_mode/conntrack_sync.py index c4b2bb488..a83c2274d 100755 --- a/src/conf_mode/conntrack_sync.py +++ b/src/conf_mode/conntrack_sync.py @@ -20,11 +20,11 @@ from sys import exit from vyos.config import Config from vyos.configdict import dict_merge from vyos.configverify import verify_interface_exists -from vyos.util import call -from vyos.util import dict_search -from vyos.util import process_named_running -from vyos.util import read_file -from vyos.util import run +from vyos.utils.dict import dict_search +from vyos.utils.process import process_named_running +from vyos.utils.file import read_file +from vyos.utils.process import call +from vyos.utils.process import run from vyos.template import render from vyos.template import get_ipv4 from vyos.validate import is_addr_assigned diff --git a/src/conf_mode/container.py b/src/conf_mode/container.py index 6198bb65f..3378aac63 100755 --- a/src/conf_mode/container.py +++ b/src/conf_mode/container.py @@ -28,11 +28,11 @@ from vyos.configdict import node_changed from vyos.configdict import is_node_changed from vyos.configverify import verify_vrf from vyos.ifconfig import Interface -from vyos.util import call -from vyos.util import cmd -from vyos.util import run -from vyos.util import rc_cmd -from vyos.util import write_file +from vyos.utils.file import write_file +from vyos.utils.process import call +from vyos.utils.process import cmd +from vyos.utils.process import run +from vyos.utils.process import rc_cmd from vyos.template import inc_ip from vyos.template import is_ipv4 from vyos.template import is_ipv6 diff --git a/src/conf_mode/dhcp_relay.py b/src/conf_mode/dhcp_relay.py index 7e702a446..fd39bd9fe 100755 --- a/src/conf_mode/dhcp_relay.py +++ b/src/conf_mode/dhcp_relay.py @@ -23,8 +23,8 @@ from vyos.config import Config from vyos.configdict import dict_merge from vyos.template import render from vyos.base import Warning -from vyos.util import call -from vyos.util import dict_search +from vyos.utils.process import call +from vyos.utils.dict import dict_search from vyos.xml import defaults from vyos import ConfigError from vyos import airbag @@ -51,7 +51,7 @@ def get_config(config=None): def verify(relay): # bail out early - looks like removal from running config - if not relay: + if not relay or 'disable' in relay: return None if 'lo' in (dict_search('interface', relay) or []): @@ -78,7 +78,7 @@ def verify(relay): def generate(relay): # bail out early - looks like removal from running config - if not relay: + if not relay or 'disable' in relay: return None render(config_file, 'dhcp-relay/dhcrelay.conf.j2', relay) @@ -87,7 +87,7 @@ def generate(relay): def apply(relay): # bail out early - looks like removal from running config service_name = 'isc-dhcp-relay.service' - if not relay: + if not relay or 'disable' in relay: call(f'systemctl stop {service_name}') if os.path.exists(config_file): os.unlink(config_file) diff --git a/src/conf_mode/dhcp_server.py b/src/conf_mode/dhcp_server.py index 2b2af252d..c29270367 100755 --- a/src/conf_mode/dhcp_server.py +++ b/src/conf_mode/dhcp_server.py @@ -25,9 +25,9 @@ from sys import exit from vyos.config import Config from vyos.configdict import dict_merge from vyos.template import render -from vyos.util import call -from vyos.util import dict_search -from vyos.util import run +from vyos.utils.dict import dict_search +from vyos.utils.process import call +from vyos.utils.process import run from vyos.validate import is_subnet_connected from vyos.validate import is_addr_assigned from vyos.xml import defaults diff --git a/src/conf_mode/dhcpv6_relay.py b/src/conf_mode/dhcpv6_relay.py index c1bd51f62..0e7da6f89 100755 --- a/src/conf_mode/dhcpv6_relay.py +++ b/src/conf_mode/dhcpv6_relay.py @@ -22,8 +22,9 @@ from vyos.config import Config from vyos.configdict import dict_merge from vyos.ifconfig import Interface from vyos.template import render -from vyos.util import call -from vyos.util import dict_search +from vyos.template import is_ipv6 +from vyos.utils.process import call +from vyos.utils.dict import dict_search from vyos.validate import is_ipv6_link_local from vyos.xml import defaults from vyos import ConfigError @@ -51,7 +52,7 @@ def get_config(config=None): def verify(relay): # bail out early - looks like removal from running config - if not relay: + if not relay or 'disable' in relay: return None if 'upstream_interface' not in relay: @@ -69,7 +70,7 @@ def verify(relay): for interface in relay['listen_interface']: has_global = False for addr in Interface(interface).get_addr(): - if not is_ipv6_link_local(addr): + if is_ipv6(addr) and not is_ipv6_link_local(addr): has_global = True if not has_global: raise ConfigError(f'Interface {interface} does not have global '\ @@ -79,7 +80,7 @@ def verify(relay): def generate(relay): # bail out early - looks like removal from running config - if not relay: + if not relay or 'disable' in relay: return None render(config_file, 'dhcp-relay/dhcrelay6.conf.j2', relay) @@ -88,7 +89,7 @@ def generate(relay): def apply(relay): # bail out early - looks like removal from running config service_name = 'isc-dhcp-relay6.service' - if not relay: + if not relay or 'disable' in relay: # DHCPv6 relay support is removed in the commit call(f'systemctl stop {service_name}') if os.path.exists(config_file): diff --git a/src/conf_mode/dhcpv6_server.py b/src/conf_mode/dhcpv6_server.py index 078ff327c..f89ad5b9c 100755 --- a/src/conf_mode/dhcpv6_server.py +++ b/src/conf_mode/dhcpv6_server.py @@ -23,8 +23,8 @@ from sys import exit from vyos.config import Config from vyos.template import render from vyos.template import is_ipv6 -from vyos.util import call -from vyos.util import dict_search +from vyos.utils.process import call +from vyos.utils.dict import dict_search from vyos.validate import is_subnet_connected from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/dns_dynamic.py b/src/conf_mode/dns_dynamic.py index 67134e681..d78eb70bc 100755 --- a/src/conf_mode/dns_dynamic.py +++ b/src/conf_mode/dns_dynamic.py @@ -21,7 +21,7 @@ from sys import exit from vyos.config import Config from vyos.configdict import dict_merge from vyos.template import render -from vyos.util import call +from vyos.utils.process import call from vyos.xml import defaults from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/dns_forwarding.py b/src/conf_mode/dns_forwarding.py index 0d86c6a52..2d98bffe3 100755 --- a/src/conf_mode/dns_forwarding.py +++ b/src/conf_mode/dns_forwarding.py @@ -25,9 +25,9 @@ from vyos.configdict import dict_merge from vyos.hostsd_client import Client as hostsd_client from vyos.template import render from vyos.template import bracketize_ipv6 -from vyos.util import call -from vyos.util import chown -from vyos.util import dict_search +from vyos.utils.process import call +from vyos.utils.permission import chown +from vyos.utils.dict import dict_search from vyos.xml import defaults from vyos import ConfigError diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py index 190587980..07166d457 100755 --- a/src/conf_mode/firewall.py +++ b/src/conf_mode/firewall.py @@ -31,12 +31,12 @@ from vyos.configdep import set_dependents, call_dependents from vyos.firewall import fqdn_config_parse from vyos.firewall import geoip_update from vyos.template import render -from vyos.util import call -from vyos.util import cmd -from vyos.util import dict_search_args -from vyos.util import dict_search_recursive -from vyos.util import process_named_running -from vyos.util import rc_cmd +from vyos.utils.process import call +from vyos.utils.process import cmd +from vyos.utils.dict import dict_search_args +from vyos.utils.dict import dict_search_recursive +from vyos.utils.process import process_named_running +from vyos.utils.process import rc_cmd from vyos.xml import defaults from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/flow_accounting_conf.py b/src/conf_mode/flow_accounting_conf.py index c36d52e05..bfe906c87 100755 --- a/src/conf_mode/flow_accounting_conf.py +++ b/src/conf_mode/flow_accounting_conf.py @@ -26,8 +26,8 @@ from vyos.configdict import dict_merge from vyos.configverify import verify_vrf from vyos.ifconfig import Section from vyos.template import render -from vyos.util import call -from vyos.util import cmd +from vyos.utils.process import call +from vyos.utils.process import cmd from vyos.validate import is_addr_assigned from vyos.xml import defaults from vyos import ConfigError diff --git a/src/conf_mode/high-availability.py b/src/conf_mode/high-availability.py index e18b426b1..0cbd4c49c 100755 --- a/src/conf_mode/high-availability.py +++ b/src/conf_mode/high-availability.py @@ -28,8 +28,8 @@ from vyos.ifconfig.vrrp import VRRP from vyos.template import render from vyos.template import is_ipv4 from vyos.template import is_ipv6 -from vyos.util import call -from vyos.util import dict_search +from vyos.utils.process import call +from vyos.utils.dict import dict_search from vyos.xml import defaults from vyos import ConfigError from vyos import airbag @@ -175,6 +175,11 @@ def verify(ha): # Virtual-server if 'virtual_server' in ha: for vs, vs_config in ha['virtual_server'].items(): + + if 'address' not in vs_config and 'fwmark' not in vs_config: + raise ConfigError('Either address or fwmark is required ' + f'but not set for virtual-server "{vs}"') + if 'port' not in vs_config and 'fwmark' not in vs_config: raise ConfigError(f'Port or fwmark is required but not set for virtual-server "{vs}"') if 'port' in vs_config and 'fwmark' in vs_config: diff --git a/src/conf_mode/host_name.py b/src/conf_mode/host_name.py index 93f244f42..36d1f6493 100755 --- a/src/conf_mode/host_name.py +++ b/src/conf_mode/host_name.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2021 VyOS maintainers and contributors +# Copyright (C) 2018-2023 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 @@ -18,16 +18,15 @@ import re import sys import copy -import vyos.util import vyos.hostsd_client from vyos.base import Warning from vyos.config import Config from vyos.ifconfig import Section from vyos.template import is_ip -from vyos.util import cmd -from vyos.util import call -from vyos.util import process_named_running +from vyos.utils.process import cmd +from vyos.utils.process import call +from vyos.utils.process import process_named_running from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/http-api.py b/src/conf_mode/http-api.py index 7e801eb26..7bdf448a3 100755 --- a/src/conf_mode/http-api.py +++ b/src/conf_mode/http-api.py @@ -27,8 +27,8 @@ from vyos.config import Config from vyos.configdict import dict_merge from vyos.configdep import set_dependents, call_dependents from vyos.template import render -from vyos.util import cmd -from vyos.util import call +from vyos.utils.process import cmd +from vyos.utils.process import call from vyos.xml import defaults from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/https.py b/src/conf_mode/https.py index b0c38e8d3..010490c7e 100755 --- a/src/conf_mode/https.py +++ b/src/conf_mode/https.py @@ -28,10 +28,10 @@ from vyos import ConfigError from vyos.pki import wrap_certificate from vyos.pki import wrap_private_key from vyos.template import render -from vyos.util import call -from vyos.util import check_port_availability -from vyos.util import is_listen_port_bind_service -from vyos.util import write_file +from vyos.utils.process import call +from vyos.utils.network import check_port_availability +from vyos.utils.network import is_listen_port_bind_service +from vyos.utils.file import write_file from vyos import airbag airbag.enable() diff --git a/src/conf_mode/igmp_proxy.py b/src/conf_mode/igmp_proxy.py index de6a51c64..4ec2f1835 100755 --- a/src/conf_mode/igmp_proxy.py +++ b/src/conf_mode/igmp_proxy.py @@ -23,8 +23,8 @@ from vyos.base import Warning from vyos.config import Config from vyos.configdict import dict_merge from vyos.template import render -from vyos.util import call -from vyos.util import dict_search +from vyos.utils.process import call +from vyos.utils.dict import dict_search from vyos.xml import defaults from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/intel_qat.py b/src/conf_mode/intel_qat.py index dd04a002d..e4b248675 100755 --- a/src/conf_mode/intel_qat.py +++ b/src/conf_mode/intel_qat.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2020 VyOS maintainers and contributors +# Copyright (C) 2019-2023 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 @@ -20,7 +20,8 @@ import re from sys import exit from vyos.config import Config -from vyos.util import popen, run +from vyos.utils.process import popen +from vyos.utils.process import run from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/interfaces-bonding.py b/src/conf_mode/interfaces-bonding.py index 9936620c8..c2a569fa9 100755 --- a/src/conf_mode/interfaces-bonding.py +++ b/src/conf_mode/interfaces-bonding.py @@ -35,7 +35,7 @@ from vyos.configverify import verify_vlan_config from vyos.configverify import verify_vrf from vyos.ifconfig import BondIf from vyos.ifconfig import Section -from vyos.util import dict_search +from vyos.utils.dict import dict_search from vyos.validate import has_address_configured from vyos.validate import has_vrf_configured from vyos import ConfigError diff --git a/src/conf_mode/interfaces-bridge.py b/src/conf_mode/interfaces-bridge.py index 4da3b097f..087ead20a 100755 --- a/src/conf_mode/interfaces-bridge.py +++ b/src/conf_mode/interfaces-bridge.py @@ -34,8 +34,8 @@ from vyos.validate import has_address_configured from vyos.validate import has_vrf_configured from vyos.xml import defaults -from vyos.util import cmd -from vyos.util import dict_search +from vyos.utils.process import cmd +from vyos.utils.dict import dict_search from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/interfaces-ethernet.py b/src/conf_mode/interfaces-ethernet.py index 9d2ea2eeb..b015bba88 100755 --- a/src/conf_mode/interfaces-ethernet.py +++ b/src/conf_mode/interfaces-ethernet.py @@ -40,9 +40,9 @@ from vyos.pki import encode_certificate from vyos.pki import load_certificate from vyos.pki import wrap_private_key from vyos.template import render -from vyos.util import call -from vyos.util import dict_search -from vyos.util import write_file +from vyos.utils.process import call +from vyos.utils.dict import dict_search +from vyos.utils.file import write_file from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/interfaces-l2tpv3.py b/src/conf_mode/interfaces-l2tpv3.py index ca321e01d..6efeac302 100755 --- a/src/conf_mode/interfaces-l2tpv3.py +++ b/src/conf_mode/interfaces-l2tpv3.py @@ -28,7 +28,7 @@ from vyos.configverify import verify_mtu_ipv6 from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_bond_bridge_member from vyos.ifconfig import L2TPv3If -from vyos.util import check_kmod +from vyos.utils.kernel import check_kmod from vyos.validate import is_addr_assigned from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/interfaces-macsec.py b/src/conf_mode/interfaces-macsec.py index 649ea8d50..3f86e2638 100755 --- a/src/conf_mode/interfaces-macsec.py +++ b/src/conf_mode/interfaces-macsec.py @@ -33,9 +33,9 @@ from vyos.configverify import verify_bond_bridge_member from vyos.ifconfig import MACsecIf from vyos.ifconfig import Interface from vyos.template import render -from vyos.util import call -from vyos.util import dict_search -from vyos.util import is_systemd_service_running +from vyos.utils.process import call +from vyos.utils.dict import dict_search +from vyos.utils.process import is_systemd_service_running from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py index 6f227b0d1..607a19385 100755 --- a/src/conf_mode/interfaces-openvpn.py +++ b/src/conf_mode/interfaces-openvpn.py @@ -50,15 +50,15 @@ from vyos.pki import wrap_private_key from vyos.template import render from vyos.template import is_ipv4 from vyos.template import is_ipv6 -from vyos.util import call -from vyos.util import chown -from vyos.util import cmd -from vyos.util import dict_search -from vyos.util import dict_search_args -from vyos.util import is_list_equal -from vyos.util import makedir -from vyos.util import read_file -from vyos.util import write_file +from vyos.utils.dict import dict_search +from vyos.utils.dict import dict_search_args +from vyos.utils.list import is_list_equal +from vyos.utils.file import makedir +from vyos.utils.file import read_file +from vyos.utils.file import write_file +from vyos.utils.process import call +from vyos.utils.permission import chown +from vyos.utils.process import cmd from vyos.validate import is_addr_assigned from vyos import ConfigError diff --git a/src/conf_mode/interfaces-pppoe.py b/src/conf_mode/interfaces-pppoe.py index 5f0b76f90..fca91253c 100755 --- a/src/conf_mode/interfaces-pppoe.py +++ b/src/conf_mode/interfaces-pppoe.py @@ -32,8 +32,8 @@ from vyos.configverify import verify_mtu_ipv6 from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import PPPoEIf from vyos.template import render -from vyos.util import call -from vyos.util import is_systemd_service_running +from vyos.utils.process import call +from vyos.utils.process import is_systemd_service_running from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/interfaces-sstpc.py b/src/conf_mode/interfaces-sstpc.py index b5cc4cf4e..b588910dc 100755 --- a/src/conf_mode/interfaces-sstpc.py +++ b/src/conf_mode/interfaces-sstpc.py @@ -27,10 +27,10 @@ from vyos.pki import encode_certificate from vyos.pki import find_chain from vyos.pki import load_certificate from vyos.template import render -from vyos.util import call -from vyos.util import dict_search -from vyos.util import is_systemd_service_running -from vyos.util import write_file +from vyos.utils.process import call +from vyos.utils.dict import dict_search +from vyos.utils.process import is_systemd_service_running +from vyos.utils.file import write_file from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/interfaces-tunnel.py b/src/conf_mode/interfaces-tunnel.py index 0a3726e94..6a075970e 100755 --- a/src/conf_mode/interfaces-tunnel.py +++ b/src/conf_mode/interfaces-tunnel.py @@ -33,8 +33,8 @@ from vyos.configverify import verify_bond_bridge_member from vyos.ifconfig import Interface from vyos.ifconfig import Section from vyos.ifconfig import TunnelIf -from vyos.util import get_interface_config -from vyos.util import dict_search +from vyos.utils.network import get_interface_config +from vyos.utils.dict import dict_search from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/interfaces-vti.py b/src/conf_mode/interfaces-vti.py index f4b0436af..9871810ae 100755 --- a/src/conf_mode/interfaces-vti.py +++ b/src/conf_mode/interfaces-vti.py @@ -21,7 +21,7 @@ from vyos.config import Config from vyos.configdict import get_interface_dict from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import VTIIf -from vyos.util import dict_search +from vyos.utils.dict import dict_search from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/interfaces-wireguard.py b/src/conf_mode/interfaces-wireguard.py index 762bad94f..a02baba82 100755 --- a/src/conf_mode/interfaces-wireguard.py +++ b/src/conf_mode/interfaces-wireguard.py @@ -27,8 +27,8 @@ from vyos.configverify import verify_mtu_ipv6 from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_bond_bridge_member from vyos.ifconfig import WireGuardIf -from vyos.util import check_kmod -from vyos.util import check_port_availability +from vyos.utils.kernel import check_kmod +from vyos.utils.network import check_port_availability from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/interfaces-wireless.py b/src/conf_mode/interfaces-wireless.py index dd798b5a2..42326bea0 100755 --- a/src/conf_mode/interfaces-wireless.py +++ b/src/conf_mode/interfaces-wireless.py @@ -33,8 +33,8 @@ from vyos.configverify import verify_vrf from vyos.configverify import verify_bond_bridge_member from vyos.ifconfig import WiFiIf from vyos.template import render -from vyos.util import call -from vyos.util import dict_search +from vyos.utils.process import call +from vyos.utils.dict import dict_search from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/interfaces-wwan.py b/src/conf_mode/interfaces-wwan.py index 9ca495476..6658ca86a 100755 --- a/src/conf_mode/interfaces-wwan.py +++ b/src/conf_mode/interfaces-wwan.py @@ -27,12 +27,12 @@ from vyos.configverify import verify_interface_exists from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_vrf from vyos.ifconfig import WWANIf -from vyos.util import cmd -from vyos.util import call -from vyos.util import dict_search -from vyos.util import DEVNULL -from vyos.util import is_systemd_service_active -from vyos.util import write_file +from vyos.utils.dict import dict_search +from vyos.utils.process import cmd +from vyos.utils.process import call +from vyos.utils.process import DEVNULL +from vyos.utils.process import is_systemd_service_active +from vyos.utils.file import write_file from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/le_cert.py b/src/conf_mode/le_cert.py index 6e169a3d5..06c7e7b72 100755 --- a/src/conf_mode/le_cert.py +++ b/src/conf_mode/le_cert.py @@ -20,9 +20,9 @@ import os import vyos.defaults from vyos.config import Config from vyos import ConfigError -from vyos.util import cmd -from vyos.util import call -from vyos.util import is_systemd_service_running +from vyos.utils.process import cmd +from vyos.utils.process import call +from vyos.utils.process import is_systemd_service_running from vyos import airbag airbag.enable() diff --git a/src/conf_mode/lldp.py b/src/conf_mode/lldp.py index c703c1fe0..0e5fc29d3 100755 --- a/src/conf_mode/lldp.py +++ b/src/conf_mode/lldp.py @@ -24,8 +24,8 @@ from vyos.configdict import dict_merge from vyos.validate import is_addr_assigned from vyos.validate import is_loopback_addr from vyos.version import get_version_data -from vyos.util import call -from vyos.util import dict_search +from vyos.utils.process import call +from vyos.utils.dict import dict_search from vyos.xml import defaults from vyos.template import render from vyos import ConfigError diff --git a/src/conf_mode/load-balancing-haproxy.py b/src/conf_mode/load-balancing-haproxy.py index b29fdffc7..2fb0edf8e 100755 --- a/src/conf_mode/load-balancing-haproxy.py +++ b/src/conf_mode/load-balancing-haproxy.py @@ -21,9 +21,9 @@ from shutil import rmtree from vyos.config import Config from vyos.configdict import dict_merge -from vyos.util import call -from vyos.util import check_port_availability -from vyos.util import is_listen_port_bind_service +from vyos.utils.process import call +from vyos.utils.network import check_port_availability +from vyos.utils.network import is_listen_port_bind_service from vyos.pki import wrap_certificate from vyos.pki import wrap_private_key from vyos.template import render diff --git a/src/conf_mode/load-balancing-wan.py b/src/conf_mode/load-balancing-wan.py index 7086aaf8b..3533a5a04 100755 --- a/src/conf_mode/load-balancing-wan.py +++ b/src/conf_mode/load-balancing-wan.py @@ -22,7 +22,7 @@ from shutil import rmtree from vyos.base import Warning from vyos.config import Config from vyos.configdict import dict_merge -from vyos.util import cmd +from vyos.utils.process import cmd from vyos.template import render from vyos.xml import defaults from vyos import ConfigError diff --git a/src/conf_mode/nat.py b/src/conf_mode/nat.py index 9f8221514..e19b12937 100755 --- a/src/conf_mode/nat.py +++ b/src/conf_mode/nat.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2022 VyOS maintainers and contributors +# Copyright (C) 2020-2023 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 @@ -28,11 +28,11 @@ from vyos.config import Config from vyos.configdict import dict_merge from vyos.template import render from vyos.template import is_ip_network -from vyos.util import cmd -from vyos.util import run -from vyos.util import check_kmod -from vyos.util import dict_search -from vyos.util import dict_search_args +from vyos.utils.kernel import check_kmod +from vyos.utils.dict import dict_search +from vyos.utils.dict import dict_search_args +from vyos.utils.process import cmd +from vyos.utils.process import run from vyos.validate import is_addr_assigned from vyos.xml import defaults from vyos import ConfigError @@ -72,6 +72,7 @@ def verify_rule(config, err_msg, groups_dict): """ Common verify steps used for both source and destination NAT """ if (dict_search('translation.port', config) != None or + dict_search('translation.redirect.port', config) != None or dict_search('destination.port', config) != None or dict_search('source.port', config)): @@ -221,7 +222,7 @@ def verify(nat): elif config['inbound_interface'] not in 'any' and config['inbound_interface'] not in interfaces(): Warning(f'rule "{rule}" interface "{config["inbound_interface"]}" does not exist on this system') - if not dict_search('translation.address', config) and not dict_search('translation.port', config): + if not dict_search('translation.address', config) and not dict_search('translation.port', config) and not dict_search('translation.redirect.port', config): if 'exclude' not in config: raise ConfigError(f'{err_msg} translation requires address and/or port') diff --git a/src/conf_mode/nat66.py b/src/conf_mode/nat66.py index d8f913b0c..25f625b84 100755 --- a/src/conf_mode/nat66.py +++ b/src/conf_mode/nat66.py @@ -25,9 +25,9 @@ from vyos.base import Warning from vyos.config import Config from vyos.configdict import dict_merge from vyos.template import render -from vyos.util import cmd -from vyos.util import check_kmod -from vyos.util import dict_search +from vyos.utils.process import cmd +from vyos.utils.kernel import check_kmod +from vyos.utils.dict import dict_search from vyos.template import is_ipv6 from vyos.xml import defaults from vyos import ConfigError diff --git a/src/conf_mode/netns.py b/src/conf_mode/netns.py index 20129ce65..95ab83dbc 100755 --- a/src/conf_mode/netns.py +++ b/src/conf_mode/netns.py @@ -22,9 +22,9 @@ from tempfile import NamedTemporaryFile from vyos.config import Config from vyos.configdict import node_changed from vyos.ifconfig import Interface -from vyos.util import call -from vyos.util import dict_search -from vyos.util import get_interface_config +from vyos.utils.process import call +from vyos.utils.dict import dict_search +from vyos.utils.network import get_interface_config from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/ntp.py b/src/conf_mode/ntp.py index 95766c44c..1cc23a7df 100755 --- a/src/conf_mode/ntp.py +++ b/src/conf_mode/ntp.py @@ -20,9 +20,9 @@ from vyos.config import Config from vyos.configdict import is_node_changed from vyos.configverify import verify_vrf from vyos.configverify import verify_interface_exists -from vyos.util import call -from vyos.util import chmod_750 -from vyos.util import get_interface_config +from vyos.utils.process import call +from vyos.utils.permission import chmod_750 +from vyos.utils.network import get_interface_config from vyos.template import render from vyos.template import is_ipv4 from vyos import ConfigError diff --git a/src/conf_mode/pki.py b/src/conf_mode/pki.py index 54de467ca..eb8cb3940 100755 --- a/src/conf_mode/pki.py +++ b/src/conf_mode/pki.py @@ -26,8 +26,8 @@ from vyos.pki import load_public_key from vyos.pki import load_private_key from vyos.pki import load_crl from vyos.pki import load_dh_parameters -from vyos.util import dict_search_args -from vyos.util import dict_search_recursive +from vyos.utils.dict import dict_search_args +from vyos.utils.dict import dict_search_recursive from vyos.xml import defaults from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/policy-local-route.py b/src/conf_mode/policy-local-route.py index 3f834f55c..79526f82a 100755 --- a/src/conf_mode/policy-local-route.py +++ b/src/conf_mode/policy-local-route.py @@ -24,7 +24,7 @@ from vyos.configdict import dict_merge from vyos.configdict import node_changed from vyos.configdict import leaf_node_changed from vyos.template import render -from vyos.util import call +from vyos.utils.process import call from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/policy-route.py b/src/conf_mode/policy-route.py index 40a32efb3..adad012de 100755 --- a/src/conf_mode/policy-route.py +++ b/src/conf_mode/policy-route.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-2023 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 @@ -22,9 +22,9 @@ from sys import exit from vyos.base import Warning from vyos.config import Config from vyos.template import render -from vyos.util import cmd -from vyos.util import dict_search_args -from vyos.util import run +from vyos.utils.dict import dict_search_args +from vyos.utils.process import cmd +from vyos.utils.process import run from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/policy.py b/src/conf_mode/policy.py index 331194fec..4df893ebf 100755 --- a/src/conf_mode/policy.py +++ b/src/conf_mode/policy.py @@ -19,7 +19,7 @@ from sys import exit from vyos.config import Config from vyos.configdict import dict_merge from vyos.template import render_to_string -from vyos.util import dict_search +from vyos.utils.dict import dict_search from vyos import ConfigError from vyos import frr from vyos import airbag diff --git a/src/conf_mode/protocols_babel.py b/src/conf_mode/protocols_babel.py index 20821c7f2..f5ac56f65 100755 --- a/src/conf_mode/protocols_babel.py +++ b/src/conf_mode/protocols_babel.py @@ -24,7 +24,7 @@ from vyos.configdict import node_changed from vyos.configverify import verify_common_route_maps from vyos.configverify import verify_access_list from vyos.configverify import verify_prefix_list -from vyos.util import dict_search +from vyos.utils.dict import dict_search from vyos.xml import defaults from vyos.template import render_to_string from vyos import ConfigError diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py index b23584bdb..cec025fea 100755 --- a/src/conf_mode/protocols_bgp.py +++ b/src/conf_mode/protocols_bgp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2022 VyOS maintainers and contributors +# Copyright (C) 2020-2023 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 @@ -20,13 +20,15 @@ from sys import argv from vyos.base import Warning from vyos.config import Config from vyos.configdict import dict_merge +from vyos.configdict import node_changed from vyos.configverify import verify_prefix_list from vyos.configverify import verify_route_map from vyos.configverify import verify_vrf from vyos.template import is_ip from vyos.template import is_interface from vyos.template import render_to_string -from vyos.util import dict_search +from vyos.utils.dict import dict_search +from vyos.utils.network import get_interface_vrf from vyos.validate import is_addr_assigned from vyos import ConfigError from vyos import frr @@ -55,6 +57,12 @@ def get_config(config=None): get_first_key=True, no_tag_node_value_mangle=True) + # Remove per interface MPLS configuration - get a list if changed + # nodes under the interface tagNode + interfaces_removed = node_changed(conf, base + ['interface']) + if interfaces_removed: + bgp['interface_removed'] = list(interfaces_removed) + # Assign the name of our VRF context. This MUST be done before the return # statement below, else on deletion we will delete the default instance # instead of the VRF instance. @@ -195,14 +203,21 @@ def verify_remote_as(peer_config, bgp_config): return None def verify_afi(peer_config, bgp_config): + # If address_family configured under neighboor if 'address_family' in peer_config: return True + # If address_family configured under peer-group + # if neighbor interface configured + peer_group_name = '' + if dict_search('interface.peer_group', peer_config): + peer_group_name = peer_config['interface']['peer_group'] + # if neighbor IP configured. if 'peer_group' in peer_config: peer_group_name = peer_config['peer_group'] + if peer_group_name: tmp = dict_search(f'peer_group.{peer_group_name}.address_family', bgp_config) if tmp: return True - return False def verify(bgp): @@ -231,6 +246,18 @@ def verify(bgp): if 'system_as' not in bgp: raise ConfigError('BGP system-as number must be defined!') + # Verify vrf on interface and bgp section + if 'interface' in bgp: + for interface in bgp['interface']: + error_msg = f'Interface "{interface}" belongs to different VRF instance' + tmp = get_interface_vrf(interface) + if 'vrf' in bgp: + if bgp['vrf'] != tmp: + vrf = bgp['vrf'] + raise ConfigError(f'{error_msg} "{vrf}"!') + elif tmp != 'default': + raise ConfigError(f'{error_msg} "{tmp}"!') + # Common verification for both peer-group and neighbor statements for neighbor in ['neighbor', 'peer_group']: # bail out early if there is no neighbor or peer-group statement @@ -520,6 +547,14 @@ def apply(bgp): vrf = ' vrf ' + bgp['vrf'] frr_cfg.load_configuration(bgp_daemon) + + # Remove interface specific config + for key in ['interface', 'interface_removed']: + if key not in bgp: + continue + for interface in bgp[key]: + frr_cfg.modify_section(f'^interface {interface}', stop_pattern='^exit', remove_stop_mark=True) + frr_cfg.modify_section(f'^router bgp \d+{vrf}', stop_pattern='^exit', remove_stop_mark=True) if 'frr_bgpd_config' in bgp: frr_cfg.add_before(frr.default_add_before, bgp['frr_bgpd_config']) diff --git a/src/conf_mode/protocols_failover.py b/src/conf_mode/protocols_failover.py index 85e984afe..faf56d741 100755 --- a/src/conf_mode/protocols_failover.py +++ b/src/conf_mode/protocols_failover.py @@ -21,7 +21,7 @@ from pathlib import Path from vyos.config import Config from vyos.configdict import dict_merge from vyos.template import render -from vyos.util import call +from vyos.utils.process import call from vyos.xml import defaults from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/protocols_igmp.py b/src/conf_mode/protocols_igmp.py index 65cc2beba..f6097e282 100755 --- a/src/conf_mode/protocols_igmp.py +++ b/src/conf_mode/protocols_igmp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-2023 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 @@ -21,7 +21,8 @@ from sys import exit from vyos import ConfigError from vyos.config import Config -from vyos.util import call, process_named_running +from vyos.utils.process import process_named_running +from vyos.utils.process import call from vyos.template import render from signal import SIGTERM diff --git a/src/conf_mode/protocols_isis.py b/src/conf_mode/protocols_isis.py index ecca87db0..4c637a99f 100755 --- a/src/conf_mode/protocols_isis.py +++ b/src/conf_mode/protocols_isis.py @@ -25,8 +25,8 @@ from vyos.configdict import node_changed from vyos.configverify import verify_common_route_maps from vyos.configverify import verify_interface_exists from vyos.ifconfig import Interface -from vyos.util import dict_search -from vyos.util import get_interface_config +from vyos.utils.dict import dict_search +from vyos.utils.network import get_interface_config from vyos.template import render_to_string from vyos.xml import defaults from vyos import ConfigError diff --git a/src/conf_mode/protocols_mpls.py b/src/conf_mode/protocols_mpls.py index 73af6595b..177a43444 100755 --- a/src/conf_mode/protocols_mpls.py +++ b/src/conf_mode/protocols_mpls.py @@ -21,9 +21,9 @@ from sys import exit from glob import glob from vyos.config import Config from vyos.template import render_to_string -from vyos.util import dict_search -from vyos.util import read_file -from vyos.util import sysctl_write +from vyos.utils.dict import dict_search +from vyos.utils.file import read_file +from vyos.utils.system import sysctl_write from vyos.configverify import verify_interface_exists from vyos import ConfigError from vyos import frr diff --git a/src/conf_mode/protocols_nhrp.py b/src/conf_mode/protocols_nhrp.py index d28ced4fd..5ec0bc9e5 100755 --- a/src/conf_mode/protocols_nhrp.py +++ b/src/conf_mode/protocols_nhrp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-2023 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 @@ -19,8 +19,8 @@ import os from vyos.config import Config from vyos.configdict import node_changed from vyos.template import render -from vyos.util import process_named_running -from vyos.util import run +from vyos.utils.process import process_named_running +from vyos.utils.process import run from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/protocols_ospf.py b/src/conf_mode/protocols_ospf.py index 460c9f1a4..f2075d25b 100755 --- a/src/conf_mode/protocols_ospf.py +++ b/src/conf_mode/protocols_ospf.py @@ -27,8 +27,8 @@ from vyos.configverify import verify_route_map from vyos.configverify import verify_interface_exists from vyos.configverify import verify_access_list from vyos.template import render_to_string -from vyos.util import dict_search -from vyos.util import get_interface_config +from vyos.utils.dict import dict_search +from vyos.utils.network import get_interface_config from vyos.xml import defaults from vyos import ConfigError from vyos import frr @@ -88,6 +88,8 @@ def get_config(config=None): del default_values['area']['area_type']['nssa'] if 'mpls_te' not in ospf: del default_values['mpls_te'] + if 'graceful_restart' not in ospf: + del default_values['graceful_restart'] for protocol in ['babel', 'bgp', 'connected', 'isis', 'kernel', 'rip', 'static', 'table']: # table is a tagNode thus we need to clean out all occurances for the diff --git a/src/conf_mode/protocols_ospfv3.py b/src/conf_mode/protocols_ospfv3.py index cb21bd83c..fbea51f56 100755 --- a/src/conf_mode/protocols_ospfv3.py +++ b/src/conf_mode/protocols_ospfv3.py @@ -27,8 +27,8 @@ from vyos.configverify import verify_route_map from vyos.configverify import verify_interface_exists from vyos.template import render_to_string from vyos.ifconfig import Interface -from vyos.util import dict_search -from vyos.util import get_interface_config +from vyos.utils.dict import dict_search +from vyos.utils.network import get_interface_config from vyos.xml import defaults from vyos import ConfigError from vyos import frr @@ -83,6 +83,8 @@ def get_config(config=None): # need to check this first and probably drop that key. if dict_search('default_information.originate', ospfv3) is None: del default_values['default_information'] + if 'graceful_restart' not in ospfv3: + del default_values['graceful_restart'] # XXX: T2665: we currently have no nice way for defaults under tag nodes, # clean them out and add them manually :( diff --git a/src/conf_mode/protocols_pim.py b/src/conf_mode/protocols_pim.py index 78df9b6f8..0aaa0d2c6 100755 --- a/src/conf_mode/protocols_pim.py +++ b/src/conf_mode/protocols_pim.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-2023 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 @@ -21,7 +21,8 @@ from sys import exit from vyos.config import Config from vyos import ConfigError -from vyos.util import call, process_named_running +from vyos.utils.process import process_named_running +from vyos.utils.process import call from vyos.template import render from signal import SIGTERM diff --git a/src/conf_mode/protocols_rip.py b/src/conf_mode/protocols_rip.py index c78d90396..5661dc377 100755 --- a/src/conf_mode/protocols_rip.py +++ b/src/conf_mode/protocols_rip.py @@ -24,7 +24,7 @@ from vyos.configdict import node_changed from vyos.configverify import verify_common_route_maps from vyos.configverify import verify_access_list from vyos.configverify import verify_prefix_list -from vyos.util import dict_search +from vyos.utils.dict import dict_search from vyos.xml import defaults from vyos.template import render_to_string from vyos import ConfigError diff --git a/src/conf_mode/protocols_ripng.py b/src/conf_mode/protocols_ripng.py index 21ff710b3..e3c904e33 100755 --- a/src/conf_mode/protocols_ripng.py +++ b/src/conf_mode/protocols_ripng.py @@ -23,7 +23,7 @@ from vyos.configdict import dict_merge from vyos.configverify import verify_common_route_maps from vyos.configverify import verify_access_list from vyos.configverify import verify_prefix_list -from vyos.util import dict_search +from vyos.utils.dict import dict_search from vyos.xml import defaults from vyos.template import render_to_string from vyos import ConfigError diff --git a/src/conf_mode/protocols_rpki.py b/src/conf_mode/protocols_rpki.py index 62ea9c878..035b7db05 100755 --- a/src/conf_mode/protocols_rpki.py +++ b/src/conf_mode/protocols_rpki.py @@ -21,7 +21,7 @@ from sys import exit from vyos.config import Config from vyos.configdict import dict_merge from vyos.template import render_to_string -from vyos.util import dict_search +from vyos.utils.dict import dict_search from vyos.xml import defaults from vyos import ConfigError from vyos import frr diff --git a/src/conf_mode/protocols_static.py b/src/conf_mode/protocols_static.py index 7b6150696..5def8d645 100755 --- a/src/conf_mode/protocols_static.py +++ b/src/conf_mode/protocols_static.py @@ -47,7 +47,7 @@ def get_config(config=None): base_path = ['protocols', 'static'] # eqivalent of the C foo ? 'a' : 'b' statement base = vrf and ['vrf', 'name', vrf, 'protocols', 'static'] or base_path - static = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + static = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True) # Assign the name of our VRF context if vrf: static['vrf'] = vrf diff --git a/src/conf_mode/protocols_static_multicast.py b/src/conf_mode/protocols_static_multicast.py index 6afdf31f3..7f6ae3680 100755 --- a/src/conf_mode/protocols_static_multicast.py +++ b/src/conf_mode/protocols_static_multicast.py @@ -21,7 +21,7 @@ from sys import exit from vyos import ConfigError from vyos.config import Config -from vyos.util import call +from vyos.utils.process import call from vyos.template import render from vyos import airbag diff --git a/src/conf_mode/qos.py b/src/conf_mode/qos.py index 1be2c283f..53e9ff50d 100755 --- a/src/conf_mode/qos.py +++ b/src/conf_mode/qos.py @@ -36,8 +36,8 @@ from vyos.qos import RateLimiter from vyos.qos import RoundRobin from vyos.qos import TrafficShaper from vyos.qos import TrafficShaperHFSC -from vyos.util import call -from vyos.util import dict_search_recursive +from vyos.utils.process import call +from vyos.utils.dict import dict_search_recursive from vyos.xml import defaults from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/salt-minion.py b/src/conf_mode/salt-minion.py index 00b889a11..3ff7880b2 100755 --- a/src/conf_mode/salt-minion.py +++ b/src/conf_mode/salt-minion.py @@ -25,8 +25,8 @@ from vyos.config import Config from vyos.configdict import dict_merge from vyos.configverify import verify_interface_exists from vyos.template import render -from vyos.util import call -from vyos.util import chown +from vyos.utils.process import call +from vyos.utils.permission import chown from vyos.xml import defaults from vyos import ConfigError diff --git a/src/conf_mode/service_config_sync.py b/src/conf_mode/service_config_sync.py new file mode 100755 index 000000000..5cde735a1 --- /dev/null +++ b/src/conf_mode/service_config_sync.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2023 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 <http://www.gnu.org/licenses/>. + +import os +import json +from pathlib import Path + +from vyos.config import Config +from vyos.configdict import dict_merge +from vyos.xml import defaults +from vyos import ConfigError +from vyos import airbag + +airbag.enable() + + +service_conf = Path(f'/run/config_sync_conf.conf') +post_commit_dir = '/run/scripts/commit/post-hooks.d' +post_commit_file_src = '/usr/libexec/vyos/vyos_config_sync.py' +post_commit_file = f'{post_commit_dir}/vyos_config_sync' + + +def get_config(config=None): + if config: + conf = config + else: + conf = Config() + + base = ['service', 'config-sync'] + if not conf.exists(base): + return None + config = conf.get_config_dict(base, + get_first_key=True, + no_tag_node_value_mangle=True) + + default_values = defaults(base) + config = dict_merge(default_values, config) + + return config + + +def verify(config): + # bail out early - looks like removal from running config + if not config: + return None + + if 'mode' not in config: + raise ConfigError(f'config-sync mode is mandatory!') + + for option in ['secondary', 'section']: + if option not in config: + raise ConfigError(f"config-sync '{option}' is not configured!") + + if 'address' not in config['secondary']: + raise ConfigError(f'secondary address is mandatory!') + if 'key' not in config['secondary']: + raise ConfigError(f'secondary key is mandatory!') + + +def generate(config): + if not config: + + if os.path.exists(post_commit_file): + os.unlink(post_commit_file) + + if service_conf.exists(): + service_conf.unlink() + + return None + + # Write configuration file + conf_json = json.dumps(config, indent=4) + service_conf.write_text(conf_json) + + # Create post commit dir + if not os.path.isdir(post_commit_dir): + os.makedirs(post_commit_dir) + + # Symlink from helpers to post-commit + if not os.path.exists(post_commit_file): + os.symlink(post_commit_file_src, post_commit_file) + + return None + + +def apply(config): + return None + + +if __name__ == '__main__': + try: + c = get_config() + verify(c) + generate(c) + apply(c) + except ConfigError as e: + print(e) + exit(1) diff --git a/src/conf_mode/service_console-server.py b/src/conf_mode/service_console-server.py index 60eff6543..7eb41ea87 100755 --- a/src/conf_mode/service_console-server.py +++ b/src/conf_mode/service_console-server.py @@ -22,7 +22,7 @@ from psutil import process_iter from vyos.config import Config from vyos.configdict import dict_merge from vyos.template import render -from vyos.util import call +from vyos.utils.process import call from vyos.xml import defaults from vyos import ConfigError diff --git a/src/conf_mode/service_event_handler.py b/src/conf_mode/service_event_handler.py index 5440d1056..5028ef52f 100755 --- a/src/conf_mode/service_event_handler.py +++ b/src/conf_mode/service_event_handler.py @@ -18,7 +18,8 @@ import json from pathlib import Path from vyos.config import Config -from vyos.util import call, dict_search +from vyos.utils.dict import dict_search +from vyos.utils.process import call from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/service_ids_fastnetmon.py b/src/conf_mode/service_ids_fastnetmon.py index c58f8db9a..2e678cf0b 100755 --- a/src/conf_mode/service_ids_fastnetmon.py +++ b/src/conf_mode/service_ids_fastnetmon.py @@ -21,7 +21,7 @@ from sys import exit from vyos.config import Config from vyos.configdict import dict_merge from vyos.template import render -from vyos.util import call +from vyos.utils.process import call from vyos.xml import defaults from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/service_ipoe-server.py b/src/conf_mode/service_ipoe-server.py index 95c72df47..b70e32373 100755 --- a/src/conf_mode/service_ipoe-server.py +++ b/src/conf_mode/service_ipoe-server.py @@ -24,8 +24,8 @@ from vyos.configdict import get_accel_dict from vyos.configverify import verify_accel_ppp_base_service from vyos.configverify import verify_interface_exists from vyos.template import render -from vyos.util import call -from vyos.util import dict_search +from vyos.utils.process import call +from vyos.utils.dict import dict_search from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/service_mdns-repeater.py b/src/conf_mode/service_mdns-repeater.py index 2383a53fb..a2c90b537 100755 --- a/src/conf_mode/service_mdns-repeater.py +++ b/src/conf_mode/service_mdns-repeater.py @@ -23,7 +23,7 @@ from netifaces import ifaddresses, interfaces, AF_INET from vyos.config import Config from vyos.ifconfig.vrrp import VRRP from vyos.template import render -from vyos.util import call +from vyos.utils.process import call from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/service_monitoring_telegraf.py b/src/conf_mode/service_monitoring_telegraf.py index 47510ce80..0269bedd9 100755 --- a/src/conf_mode/service_monitoring_telegraf.py +++ b/src/conf_mode/service_monitoring_telegraf.py @@ -27,9 +27,9 @@ from vyos.configdict import is_node_changed from vyos.configverify import verify_vrf from vyos.ifconfig import Section from vyos.template import render -from vyos.util import call -from vyos.util import chown -from vyos.util import cmd +from vyos.utils.process import call +from vyos.utils.permission import chown +from vyos.utils.process import cmd from vyos.xml import defaults from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/service_pppoe-server.py b/src/conf_mode/service_pppoe-server.py index adeefaa37..aace267a7 100755 --- a/src/conf_mode/service_pppoe-server.py +++ b/src/conf_mode/service_pppoe-server.py @@ -24,8 +24,8 @@ from vyos.configdict import is_node_changed from vyos.configverify import verify_accel_ppp_base_service from vyos.configverify import verify_interface_exists from vyos.template import render -from vyos.util import call -from vyos.util import dict_search +from vyos.utils.process import call +from vyos.utils.dict import dict_search from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/service_router-advert.py b/src/conf_mode/service_router-advert.py index 1dd973d67..fe33c43ea 100755 --- a/src/conf_mode/service_router-advert.py +++ b/src/conf_mode/service_router-advert.py @@ -21,7 +21,7 @@ from vyos.base import Warning from vyos.config import Config from vyos.configdict import dict_merge from vyos.template import render -from vyos.util import call +from vyos.utils.process import call from vyos.xml import defaults from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/service_sla.py b/src/conf_mode/service_sla.py index b1e22f37b..54b72e029 100755 --- a/src/conf_mode/service_sla.py +++ b/src/conf_mode/service_sla.py @@ -21,7 +21,7 @@ from sys import exit from vyos.config import Config from vyos.configdict import dict_merge from vyos.template import render -from vyos.util import call +from vyos.utils.process import call from vyos.xml import defaults from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/service_upnp.py b/src/conf_mode/service_upnp.py index c798fd515..b37d502c2 100755 --- a/src/conf_mode/service_upnp.py +++ b/src/conf_mode/service_upnp.py @@ -24,7 +24,7 @@ from ipaddress import IPv6Network from vyos.config import Config from vyos.configdict import dict_merge -from vyos.util import call +from vyos.utils.process import call from vyos.template import render from vyos.template import is_ipv4 from vyos.template import is_ipv6 diff --git a/src/conf_mode/service_webproxy.py b/src/conf_mode/service_webproxy.py index 658e496a6..bbdb756bd 100755 --- a/src/conf_mode/service_webproxy.py +++ b/src/conf_mode/service_webproxy.py @@ -22,10 +22,10 @@ from sys import exit from vyos.config import Config from vyos.configdict import dict_merge from vyos.template import render -from vyos.util import call -from vyos.util import chmod_755 -from vyos.util import dict_search -from vyos.util import write_file +from vyos.utils.process import call +from vyos.utils.permission import chmod_755 +from vyos.utils.dict import dict_search +from vyos.utils.file import write_file from vyos.validate import is_addr_assigned from vyos.xml import defaults from vyos.base import Warning diff --git a/src/conf_mode/snmp.py b/src/conf_mode/snmp.py index 9b7c04eb0..0f0d97ac3 100755 --- a/src/conf_mode/snmp.py +++ b/src/conf_mode/snmp.py @@ -26,9 +26,9 @@ from vyos.snmpv3_hashgen import plaintext_to_md5 from vyos.snmpv3_hashgen import plaintext_to_sha1 from vyos.snmpv3_hashgen import random from vyos.template import render -from vyos.util import call -from vyos.util import chmod_755 -from vyos.util import dict_search +from vyos.utils.process import call +from vyos.utils.permission import chmod_755 +from vyos.utils.dict import dict_search from vyos.validate import is_addr_assigned from vyos.version import get_version_data from vyos.xml import defaults @@ -161,8 +161,12 @@ def verify(snmp): for address in snmp['listen_address']: # We only wan't to configure addresses that exist on the system. # Hint the user if they don't exist - if not is_addr_assigned(address): - Warning(f'SNMP listen address "{address}" not configured!') + if 'vrf' in snmp: + vrf_name = snmp['vrf'] + if not is_addr_assigned(address, vrf_name) and address not in ['::1','127.0.0.1']: + raise ConfigError(f'SNMP listen address "{address}" not configured in vrf "{vrf_name}"!') + elif not is_addr_assigned(address): + raise ConfigError(f'SNMP listen address "{address}" not configured in default vrf!') if 'trap_target' in snmp: for trap, trap_config in snmp['trap_target'].items(): diff --git a/src/conf_mode/ssh.py b/src/conf_mode/ssh.py index 8de0617af..3b63fcb7d 100755 --- a/src/conf_mode/ssh.py +++ b/src/conf_mode/ssh.py @@ -24,7 +24,7 @@ from vyos.config import Config from vyos.configdict import dict_merge from vyos.configdict import is_node_changed from vyos.configverify import verify_vrf -from vyos.util import call +from vyos.utils.process import call from vyos.template import render from vyos.xml import defaults from vyos import ConfigError diff --git a/src/conf_mode/system-ip.py b/src/conf_mode/system-ip.py index 95865c690..cca996e4f 100755 --- a/src/conf_mode/system-ip.py +++ b/src/conf_mode/system-ip.py @@ -20,10 +20,10 @@ from vyos.config import Config from vyos.configdict import dict_merge from vyos.configverify import verify_route_map from vyos.template import render_to_string -from vyos.util import call -from vyos.util import dict_search -from vyos.util import sysctl_write -from vyos.util import write_file +from vyos.utils.process import call +from vyos.utils.dict import dict_search +from vyos.utils.file import write_file +from vyos.utils.system import sysctl_write from vyos.xml import defaults from vyos import ConfigError from vyos import frr diff --git a/src/conf_mode/system-ipv6.py b/src/conf_mode/system-ipv6.py index b6d3a79c3..22210c27a 100755 --- a/src/conf_mode/system-ipv6.py +++ b/src/conf_mode/system-ipv6.py @@ -21,9 +21,9 @@ from vyos.config import Config from vyos.configdict import dict_merge from vyos.configverify import verify_route_map from vyos.template import render_to_string -from vyos.util import dict_search -from vyos.util import sysctl_write -from vyos.util import write_file +from vyos.utils.dict import dict_search +from vyos.utils.system import sysctl_write +from vyos.utils.file import write_file from vyos.xml import defaults from vyos import ConfigError from vyos import frr diff --git a/src/conf_mode/system-login-banner.py b/src/conf_mode/system-login-banner.py index a521c9834..65fa04417 100755 --- a/src/conf_mode/system-login-banner.py +++ b/src/conf_mode/system-login-banner.py @@ -18,7 +18,7 @@ from sys import exit from copy import deepcopy from vyos.config import Config -from vyos.util import write_file +from vyos.utils.file import write_file from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/system-login.py b/src/conf_mode/system-login.py index 24766a5b5..afd75913e 100755 --- a/src/conf_mode/system-login.py +++ b/src/conf_mode/system-login.py @@ -29,12 +29,12 @@ from vyos.configverify import verify_vrf from vyos.defaults import directories from vyos.template import render from vyos.template import is_ipv4 -from vyos.util import cmd -from vyos.util import call -from vyos.util import rc_cmd -from vyos.util import run -from vyos.util import DEVNULL -from vyos.util import dict_search +from vyos.utils.dict import dict_search +from vyos.utils.process import cmd +from vyos.utils.process import call +from vyos.utils.process import rc_cmd +from vyos.utils.process import run +from vyos.utils.process import DEVNULL from vyos.xml import defaults from vyos import ConfigError from vyos import airbag @@ -389,7 +389,7 @@ def apply(login): # command until user is removed - userdel might return 8 as # SSH sessions are not all yet properly cleaned away, thus we # simply re-run the command until the account wen't away - while run(f'userdel --remove {user}', stderr=DEVNULL): + while run(f'userdel {user}', stderr=DEVNULL): sleep(0.250) except Exception as e: diff --git a/src/conf_mode/system-logs.py b/src/conf_mode/system-logs.py index c71938a79..12145d641 100755 --- a/src/conf_mode/system-logs.py +++ b/src/conf_mode/system-logs.py @@ -22,7 +22,7 @@ from vyos.config import Config from vyos.configdict import dict_merge from vyos.logger import syslog from vyos.template import render -from vyos.util import dict_search +from vyos.utils.dict import dict_search from vyos.xml import defaults airbag.enable() diff --git a/src/conf_mode/system-option.py b/src/conf_mode/system-option.py index e6c7a0ed2..5172b492e 100755 --- a/src/conf_mode/system-option.py +++ b/src/conf_mode/system-option.py @@ -24,8 +24,8 @@ from vyos.config import Config from vyos.configdict import dict_merge from vyos.configverify import verify_source_interface from vyos.template import render -from vyos.util import cmd -from vyos.util import is_systemd_service_running +from vyos.utils.process import cmd +from vyos.utils.process import is_systemd_service_running from vyos.validate import is_addr_assigned from vyos.validate import is_intf_addr_assigned from vyos.xml import defaults diff --git a/src/conf_mode/system-syslog.py b/src/conf_mode/system-syslog.py index cf34bad2e..19c87bcee 100755 --- a/src/conf_mode/system-syslog.py +++ b/src/conf_mode/system-syslog.py @@ -22,7 +22,7 @@ from vyos.config import Config from vyos.configdict import dict_merge from vyos.configdict import is_node_changed from vyos.configverify import verify_vrf -from vyos.util import call +from vyos.utils.process import call from vyos.template import render from vyos.xml import defaults from vyos import ConfigError @@ -46,6 +46,7 @@ def get_config(config=None): get_first_key=True, no_tag_node_value_mangle=True) syslog.update({ 'logrotate' : logrotate_conf }) + tmp = is_node_changed(conf, base + ['vrf']) if tmp: syslog.update({'restart_required': {}}) @@ -70,35 +71,22 @@ def get_config(config=None): syslog['console']['facility'][facility]) # XXX: add defaults for "host" tree - if 'host' in syslog: - default_values_host = defaults(base + ['host']) + for syslog_type in ['host', 'user', 'file']: + # Bail out early if there is nothing to do + if syslog_type not in syslog: + continue + + default_values_host = defaults(base + [syslog_type]) if 'facility' in default_values_host: del default_values_host['facility'] - default_values_facility = defaults(base + ['host', 'facility']) - - for host, host_config in syslog['host'].items(): - syslog['host'][host] = dict_merge(default_values_host, syslog['host'][host]) - if 'facility' in host_config: - for facility in host_config['facility']: - syslog['host'][host]['facility'][facility] = dict_merge(default_values_facility, - syslog['host'][host]['facility'][facility]) - - # XXX: add defaults for "user" tree - if 'user' in syslog: - default_values = defaults(base + ['user', 'facility']) - for user, user_config in syslog['user'].items(): - if 'facility' in user_config: - for facility in user_config['facility']: - syslog['user'][user]['facility'][facility] = dict_merge(default_values, - syslog['user'][user]['facility'][facility]) - - # XXX: add defaults for "file" tree - if 'file' in syslog: - default_values = defaults(base + ['file']) - for file, file_config in syslog['file'].items(): - for facility in file_config['facility']: - syslog['file'][file]['facility'][facility] = dict_merge(default_values, - syslog['file'][file]['facility'][facility]) + + for tmp, tmp_config in syslog[syslog_type].items(): + syslog[syslog_type][tmp] = dict_merge(default_values_host, syslog[syslog_type][tmp]) + if 'facility' in tmp_config: + default_values_facility = defaults(base + [syslog_type, 'facility']) + for facility in tmp_config['facility']: + syslog[syslog_type][tmp]['facility'][facility] = dict_merge(default_values_facility, + syslog[syslog_type][tmp]['facility'][facility]) return syslog diff --git a/src/conf_mode/system-timezone.py b/src/conf_mode/system-timezone.py index 3d98ba774..cd3d4b229 100755 --- a/src/conf_mode/system-timezone.py +++ b/src/conf_mode/system-timezone.py @@ -20,7 +20,7 @@ import os from copy import deepcopy from vyos.config import Config from vyos import ConfigError -from vyos.util import call +from vyos.utils.process import call from vyos import airbag airbag.enable() diff --git a/src/conf_mode/system_console.py b/src/conf_mode/system_console.py index e922edc4e..87d587959 100755 --- a/src/conf_mode/system_console.py +++ b/src/conf_mode/system_console.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-2023 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 @@ -20,9 +20,9 @@ from pathlib import Path from vyos.config import Config from vyos.configdict import dict_merge -from vyos.util import call -from vyos.util import read_file -from vyos.util import write_file +from vyos.utils.process import call +from vyos.utils.file import read_file +from vyos.utils.file import write_file from vyos.template import render from vyos.xml import defaults from vyos import ConfigError diff --git a/src/conf_mode/system_frr.py b/src/conf_mode/system_frr.py index 1af0055f6..fb252238a 100755 --- a/src/conf_mode/system_frr.py +++ b/src/conf_mode/system_frr.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-2023 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 @@ -22,7 +22,9 @@ from vyos import airbag from vyos.config import Config from vyos.logger import syslog from vyos.template import render_to_string -from vyos.util import read_file, write_file, run +from vyos.utils.file import read_file +from vyos.utils.file import write_file +from vyos.utils.process import run airbag.enable() # path to daemons config and config status files diff --git a/src/conf_mode/system_lcd.py b/src/conf_mode/system_lcd.py index 3341dd738..eb88224d1 100755 --- a/src/conf_mode/system_lcd.py +++ b/src/conf_mode/system_lcd.py @@ -19,8 +19,8 @@ import os from sys import exit from vyos.config import Config -from vyos.util import call -from vyos.util import find_device_file +from vyos.utils.process import call +from vyos.utils.system import find_device_file from vyos.template import render from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/system_sflow.py b/src/conf_mode/system_sflow.py index a0c3fca7f..9e3d41100 100755 --- a/src/conf_mode/system_sflow.py +++ b/src/conf_mode/system_sflow.py @@ -21,7 +21,7 @@ from sys import exit from vyos.config import Config from vyos.configdict import dict_merge from vyos.template import render -from vyos.util import call +from vyos.utils.process import call from vyos.validate import is_addr_assigned from vyos.xml import defaults from vyos import ConfigError diff --git a/src/conf_mode/system_sysctl.py b/src/conf_mode/system_sysctl.py index 2e0004ffa..f6b02023d 100755 --- a/src/conf_mode/system_sysctl.py +++ b/src/conf_mode/system_sysctl.py @@ -20,7 +20,7 @@ from sys import exit from vyos.config import Config from vyos.template import render -from vyos.util import cmd +from vyos.utils.process import cmd from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/system_update_check.py b/src/conf_mode/system_update_check.py index 08ecfcb81..8d641a97d 100755 --- a/src/conf_mode/system_update_check.py +++ b/src/conf_mode/system_update_check.py @@ -22,7 +22,7 @@ from pathlib import Path from sys import exit from vyos.config import Config -from vyos.util import call +from vyos.utils.process import call from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/tftp_server.py b/src/conf_mode/tftp_server.py index c5daccb7f..2735772dc 100755 --- a/src/conf_mode/tftp_server.py +++ b/src/conf_mode/tftp_server.py @@ -28,8 +28,8 @@ from vyos.configdict import dict_merge from vyos.configverify import verify_vrf from vyos.template import render from vyos.template import is_ipv4 -from vyos.util import call -from vyos.util import chmod_755 +from vyos.utils.process import call +from vyos.utils.permission import chmod_755 from vyos.validate import is_addr_assigned from vyos.xml import defaults from vyos import ConfigError diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py index b82d90e4d..b0825d0ee 100755 --- a/src/conf_mode/vpn_ipsec.py +++ b/src/conf_mode/vpn_ipsec.py @@ -40,10 +40,10 @@ from vyos.template import is_ipv4 from vyos.template import is_ipv6 from vyos.template import render from vyos.validate import is_ipv6_link_local -from vyos.util import call -from vyos.util import dict_search -from vyos.util import dict_search_args -from vyos.util import run +from vyos.utils.dict import dict_search +from vyos.utils.dict import dict_search_args +from vyos.utils.process import call +from vyos.utils.process import run from vyos.xml import defaults from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/vpn_l2tp.py b/src/conf_mode/vpn_l2tp.py index ffac3b023..6232ce64a 100755 --- a/src/conf_mode/vpn_l2tp.py +++ b/src/conf_mode/vpn_l2tp.py @@ -26,10 +26,10 @@ from ipaddress import ip_network from vyos.config import Config from vyos.template import is_ipv4 from vyos.template import render -from vyos.util import call -from vyos.util import get_half_cpus -from vyos.util import check_port_availability -from vyos.util import is_listen_port_bind_service +from vyos.utils.process import call +from vyos.utils.system import get_half_cpus +from vyos.utils.network import check_port_availability +from vyos.utils.network import is_listen_port_bind_service from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/vpn_openconnect.py b/src/conf_mode/vpn_openconnect.py index 3d5dc12a4..e82862fa3 100755 --- a/src/conf_mode/vpn_openconnect.py +++ b/src/conf_mode/vpn_openconnect.py @@ -23,11 +23,11 @@ from vyos.configdict import dict_merge from vyos.pki import wrap_certificate from vyos.pki import wrap_private_key from vyos.template import render -from vyos.util import call -from vyos.util import check_port_availability -from vyos.util import is_systemd_service_running -from vyos.util import is_listen_port_bind_service -from vyos.util import dict_search +from vyos.utils.process import call +from vyos.utils.network import check_port_availability +from vyos.utils.process import is_systemd_service_running +from vyos.utils.network import is_listen_port_bind_service +from vyos.utils.dict import dict_search from vyos.xml import defaults from vyos import ConfigError from passlib.hash import sha512_crypt diff --git a/src/conf_mode/vpn_pptp.py b/src/conf_mode/vpn_pptp.py index b9d18110a..d542f57fe 100755 --- a/src/conf_mode/vpn_pptp.py +++ b/src/conf_mode/vpn_pptp.py @@ -23,7 +23,8 @@ from sys import exit from vyos.config import Config from vyos.template import render -from vyos.util import call, get_half_cpus +from vyos.utils.system import get_half_cpus +from vyos.utils.process import call from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/vpn_sstp.py b/src/conf_mode/vpn_sstp.py index 2949ab290..e98d8385b 100755 --- a/src/conf_mode/vpn_sstp.py +++ b/src/conf_mode/vpn_sstp.py @@ -25,11 +25,11 @@ from vyos.configverify import verify_accel_ppp_base_service from vyos.pki import wrap_certificate from vyos.pki import wrap_private_key from vyos.template import render -from vyos.util import call -from vyos.util import check_port_availability -from vyos.util import dict_search -from vyos.util import is_listen_port_bind_service -from vyos.util import write_file +from vyos.utils.process import call +from vyos.utils.network import check_port_availability +from vyos.utils.dict import dict_search +from vyos.utils.network import is_listen_port_bind_service +from vyos.utils.file import write_file from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/vpp.py b/src/conf_mode/vpp.py index dc13f4e60..80ce1e8e3 100755 --- a/src/conf_mode/vpp.py +++ b/src/conf_mode/vpp.py @@ -15,7 +15,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os -import psutil +from psutil import virtual_memory from pathlib import Path from re import search as re_search, MULTILINE as re_M @@ -25,7 +25,11 @@ from vyos.configdep import set_dependents, call_dependents from vyos.configdict import dict_merge from vyos.configdict import node_changed from vyos.ifconfig import Section -from vyos.util import call, rc_cmd, boot_configuration_complete +from vyos.utils.boot import boot_configuration_complete +from vyos.utils.process import call +from vyos.utils.process import rc_cmd +from vyos.utils.system import sysctl_read +from vyos.utils.system import sysctl_apply from vyos.template import render from vyos.xml import defaults @@ -39,10 +43,10 @@ airbag.enable() service_name = 'vpp' service_conf = Path(f'/run/vpp/{service_name}.conf') systemd_override = '/run/systemd/system/vpp.service.d/10-override.conf' -sysctl_vpp = '/etc/sysctl.d/80-vpp.conf' -# Min memory 6GB (2GB reserved for vpp) -MIN_TOTAL_MEMORY = 6 +# Free memory required for VPP +# 2 GB for hugepages + 1 GB for other services +MIN_AVAILABLE_MEMORY: int = 3 * 1024**3 def _get_pci_address_by_interface(iface) -> str: @@ -64,7 +68,6 @@ def _get_pci_address_by_interface(iface) -> str: raise ConfigError(f'Cannot find PCI address for interface {iface}') - def get_config(config=None): if config: conf = config @@ -131,32 +134,45 @@ def verify(config): return None if 'interface' not in config: - raise ConfigError(f'"interface" is required but not set!') + raise ConfigError('"interface" is required but not set!') if 'cpu' in config: - if 'corelist_workers' in config['cpu'] and 'main_core' not in config['cpu']: - raise ConfigError(f'"cpu main-core" is required but not set!') + if 'corelist_workers' in config['cpu'] and 'main_core' not in config[ + 'cpu']: + raise ConfigError('"cpu main-core" is required but not set!') - memory = psutil.virtual_memory() - memory_total = round(memory.total / (1024 ** 3), 2) - if memory_total < MIN_TOTAL_MEMORY: + memory_available: int = virtual_memory().available + if memory_available < MIN_AVAILABLE_MEMORY: raise ConfigError( - f'Not enough installed memory {memory_total}GB! ' - f'The minimum required memory is {MIN_TOTAL_MEMORY}GB.' - ) + 'Not enough free memory to start VPP:\n' + f'available: {round(memory_available / 1024**3, 1)}GB\n' + f'required: {round(MIN_AVAILABLE_MEMORY / 1024**3, 1)}GB') def generate(config): if not config or (len(config) == 1 and 'removed_ifaces' in config): # Remove old config and return service_conf.unlink(missing_ok=True) - if os.path.isfile(sysctl_vpp): - os.unlink(sysctl_vpp) return None render(service_conf, 'vpp/startup.conf.j2', config) render(systemd_override, 'vpp/override.conf.j2', config) - render(sysctl_vpp, 'vpp/sysctl.conf.j2', config) + + # apply default sysctl values from + # https://github.com/FDio/vpp/blob/v23.06/src/vpp/conf/80-vpp.conf + sysctl_config: dict[str, str] = { + 'vm.nr_hugepages': '1024', + 'vm.max_map_count': '3096', + 'vm.hugetlb_shm_group': '0', + 'kernel.shmmax': '2147483648' + } + # we do not want to reduce `kernel.shmmax` + kernel_shmnax_current: str = sysctl_read('kernel.shmmax') + if int(kernel_shmnax_current) > int(sysctl_config['kernel.shmmax']): + sysctl_config['kernel.shmmax'] = kernel_shmnax_current + + if not sysctl_apply(sysctl_config): + raise ConfigError('Cannot configure sysctl parameters for VPP') return None @@ -168,8 +184,6 @@ def apply(config): call('systemctl daemon-reload') call(f'systemctl restart {service_name}.service') - call(f'sysctl -qp {sysctl_vpp}') - # Initialize interfaces removed from VPP for iface in config.get('removed_ifaces', []): host_control = HostControl() diff --git a/src/conf_mode/vrf.py b/src/conf_mode/vrf.py index 0b983293e..be867b208 100755 --- a/src/conf_mode/vrf.py +++ b/src/conf_mode/vrf.py @@ -26,13 +26,13 @@ from vyos.configverify import verify_route_map from vyos.ifconfig import Interface from vyos.template import render from vyos.template import render_to_string -from vyos.util import call -from vyos.util import cmd -from vyos.util import dict_search -from vyos.util import get_interface_config -from vyos.util import popen -from vyos.util import run -from vyos.util import sysctl_write +from vyos.utils.dict import dict_search +from vyos.utils.network import get_interface_config +from vyos.utils.process import call +from vyos.utils.process import cmd +from vyos.utils.process import popen +from vyos.utils.process import run +from vyos.utils.system import sysctl_write from vyos import ConfigError from vyos import frr from vyos import airbag diff --git a/src/conf_mode/vrf_vni.py b/src/conf_mode/vrf_vni.py index 9f33536e5..23b341079 100644 --- a/src/conf_mode/vrf_vni.py +++ b/src/conf_mode/vrf_vni.py @@ -19,7 +19,7 @@ from sys import exit from vyos.config import Config from vyos.template import render_to_string -from vyos.util import dict_search +from vyos.utils.dict import dict_search from vyos import ConfigError from vyos import frr from vyos import airbag diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/99-ipsec-dhclient-hook b/src/etc/dhcp/dhclient-exit-hooks.d/99-ipsec-dhclient-hook index 1f1926e17..c7a92fe26 100755 --- a/src/etc/dhcp/dhclient-exit-hooks.d/99-ipsec-dhclient-hook +++ b/src/etc/dhcp/dhclient-exit-hooks.d/99-ipsec-dhclient-hook @@ -15,7 +15,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. if [ "$reason" == "REBOOT" ] || [ "$reason" == "EXPIRE" ]; then - exit 0 + return 0 fi DHCP_HOOK_IFLIST="/tmp/ipsec_dhcp_waiting" @@ -24,22 +24,22 @@ if [ -f $DHCP_HOOK_IFLIST ] && [ "$reason" == "BOUND" ]; then if grep -qw $interface $DHCP_HOOK_IFLIST; then sudo rm $DHCP_HOOK_IFLIST sudo /usr/libexec/vyos/conf_mode/vpn_ipsec.py - exit 0 + return 0 fi fi if [ "$old_ip_address" == "$new_ip_address" ] && [ "$reason" == "BOUND" ]; then - exit 0 + return 0 fi python3 - <<PYEND import os import re -from vyos.util import call -from vyos.util import cmd -from vyos.util import read_file -from vyos.util import write_file +from vyos.utils.process import call +from vyos.utils.process import cmd +from vyos.utils.file import read_file +from vyos.utils.file import write_file SWANCTL_CONF="/etc/swanctl/swanctl.conf" @@ -83,4 +83,4 @@ if __name__ == '__main__': call('sudo swanctl -q') exit(0) -PYEND
\ No newline at end of file +PYEND diff --git a/src/etc/ipsec.d/vti-up-down b/src/etc/ipsec.d/vti-up-down index 1ffb32955..9eb6fac48 100755 --- a/src/etc/ipsec.d/vti-up-down +++ b/src/etc/ipsec.d/vti-up-down @@ -25,9 +25,9 @@ from syslog import LOG_PID from syslog import LOG_INFO from vyos.configquery import ConfigTreeQuery -from vyos.util import call -from vyos.util import get_interface_config -from vyos.util import get_interface_address +from vyos.utils.process import call +from vyos.utils.network import get_interface_config +from vyos.utils.network import get_interface_address if __name__ == '__main__': verb = os.getenv('PLUTO_VERB') diff --git a/src/etc/opennhrp/opennhrp-script.py b/src/etc/opennhrp/opennhrp-script.py index 688c7af2a..f6f6d075c 100755 --- a/src/etc/opennhrp/opennhrp-script.py +++ b/src/etc/opennhrp/opennhrp-script.py @@ -23,8 +23,8 @@ from json import loads from pathlib import Path from vyos.logger import getLogger -from vyos.util import cmd -from vyos.util import process_named_running +from vyos.utils.process import cmd +from vyos.utils.process import process_named_running NHRP_CONFIG: str = '/run/opennhrp/opennhrp.conf' diff --git a/src/etc/systemd/system-generators/vyos-generator b/src/etc/systemd/system-generators/vyos-generator new file mode 100755 index 000000000..34faab6a2 --- /dev/null +++ b/src/etc/systemd/system-generators/vyos-generator @@ -0,0 +1,94 @@ +#!/bin/sh +set -f + +LOG="" +DEBUG_LEVEL=1 +LOG_D="/run/vyos-router" +ENABLE="enabled" +DISABLE="disabled" +FOUND="found" +NOTFOUND="notfound" +RUN_ENABLED_FILE="$LOG_D/$ENABLE" +VYOS_SYSTEM_TARGET="/lib/systemd/system/vyos.target" +VYOS_TARGET_NAME="vyos.target" + +debug() { + local lvl="$1" + shift + [ "$lvl" -gt "$DEBUG_LEVEL" ] && return + if [ -z "$LOG" ]; then + local log="$LOG_D/${0##*/}.log" + { [ -d "$LOG_D" ] || mkdir -p "$LOG_D"; } && + { : > "$log"; } >/dev/null 2>&1 && LOG="$log" || + LOG="/dev/kmsg" + fi + echo "$@" >> "$LOG" +} + +default() { + _RET="$ENABLE" +} + +main() { + local normal_d="$1" early_d="$2" late_d="$3" + local target_name="multi-user.target" gen_d="$early_d" + local link_path="$gen_d/${target_name}.wants/${VYOS_TARGET_NAME}" + local ds="$NOTFOUND" + + debug 1 "$0 normal=$normal_d early=$early_d late=$late_d" + debug 2 "$0 $*" + + local search result="error" ret="" + for search in default; do + if $search; then + debug 1 "$search found $_RET" + [ "$_RET" = "$ENABLE" -o "$_RET" = "$DISABLE" ] && + result=$_RET && break + else + ret=$? + debug 0 "search $search returned $ret" + fi + done + + # enable AND ds=found == enable + # enable AND ds=notfound == disable + # disable || <any> == disabled + if [ "$result" = "$ENABLE" ]; then + if [ -e "$link_path" ]; then + debug 1 "already enabled: no change needed" + else + [ -d "${link_path%/*}" ] || mkdir -p "${link_path%/*}" || + debug 0 "failed to make dir $link_path" + if ln -snf "$VYOS_SYSTEM_TARGET" "$link_path"; then + debug 1 "enabled via $link_path -> $VYOS_SYSTEM_TARGET" + else + ret=$? + debug 0 "[$ret] enable failed:" \ + "ln $VYOS_SYSTEM_TARGET $link_path" + fi + fi + : > "$RUN_ENABLED_FILE" + elif [ "$result" = "$DISABLE" ]; then + if [ -f "$link_path" ]; then + if rm -f "$link_path"; then + debug 1 "disabled. removed existing $link_path" + else + ret=$? + debug 0 "[$ret] disable failed, remove $link_path" + fi + else + debug 1 "already disabled: no change needed [no $link_path]" + fi + if [ -e "$RUN_ENABLED_FILE" ]; then + rm -f "$RUN_ENABLED_FILE" + fi + else + debug 0 "unexpected result '$result' 'ds=$ds'" + ret=3 + fi + return $ret +} + +main "$@" + +# vi: ts=4 expandtab diff --git a/src/etc/systemd/system/getty@.service.d/aftervyos.conf b/src/etc/systemd/system/getty@.service.d/aftervyos.conf new file mode 100644 index 000000000..c5753900e --- /dev/null +++ b/src/etc/systemd/system/getty@.service.d/aftervyos.conf @@ -0,0 +1,3 @@ +[Service] +ExecStartPre=-/usr/libexec/vyos/init/vyos-config +StandardOutput=journal+console diff --git a/src/etc/systemd/system/serial-getty@.service.d/aftervyos.conf b/src/etc/systemd/system/serial-getty@.service.d/aftervyos.conf new file mode 100644 index 000000000..8ba42778d --- /dev/null +++ b/src/etc/systemd/system/serial-getty@.service.d/aftervyos.conf @@ -0,0 +1,3 @@ +[Service] +ExecStartPre=-/usr/libexec/vyos/init/vyos-config SERIAL +StandardOutput=journal+console diff --git a/src/etc/telegraf/custom_scripts/show_firewall_input_filter.py b/src/etc/telegraf/custom_scripts/show_firewall_input_filter.py index d7eca5894..bb7515a90 100755 --- a/src/etc/telegraf/custom_scripts/show_firewall_input_filter.py +++ b/src/etc/telegraf/custom_scripts/show_firewall_input_filter.py @@ -4,7 +4,7 @@ import json import re import time -from vyos.util import cmd +from vyos.utils.process import cmd def get_nft_filter_chains(): diff --git a/src/etc/telegraf/custom_scripts/vyos_services_input_filter.py b/src/etc/telegraf/custom_scripts/vyos_services_input_filter.py index df4eed131..00f2f184c 100755 --- a/src/etc/telegraf/custom_scripts/vyos_services_input_filter.py +++ b/src/etc/telegraf/custom_scripts/vyos_services_input_filter.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-2023 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 @@ -17,7 +17,8 @@ import time from vyos.configquery import ConfigTreeQuery -from vyos.util import is_systemd_service_running, process_named_running +from vyos.utils.process import is_systemd_service_running +from vyos.utils.process import process_named_running # Availible services and prouceses # 1 - service diff --git a/src/etc/vmware-tools/scripts/resume-vm-default.d/ether-resume.py b/src/etc/vmware-tools/scripts/resume-vm-default.d/ether-resume.py index 4e7fb117c..7da57bca8 100755 --- a/src/etc/vmware-tools/scripts/resume-vm-default.d/ether-resume.py +++ b/src/etc/vmware-tools/scripts/resume-vm-default.d/ether-resume.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2021 VyOS maintainers and contributors +# Copyright (C) 2018-2023 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 @@ -17,9 +17,9 @@ import sys import syslog -from vyos.config import Config from vyos import ConfigError -from vyos.util import run +from vyos.config import Config +from vyos.utils.process import run def get_config(): c = Config() diff --git a/src/helpers/run-config-migration.py b/src/helpers/run-config-migration.py index cc7166c22..ce647ad0a 100755 --- a/src/helpers/run-config-migration.py +++ b/src/helpers/run-config-migration.py @@ -20,7 +20,7 @@ import sys import argparse import datetime -from vyos.util import cmd +from vyos.utils.process import cmd from vyos.migrator import Migrator, VirtualMigrator def main(): diff --git a/src/helpers/vyos-boot-config-loader.py b/src/helpers/vyos-boot-config-loader.py index b9cc87bfa..01b06526d 100755 --- a/src/helpers/vyos-boot-config-loader.py +++ b/src/helpers/vyos-boot-config-loader.py @@ -26,7 +26,7 @@ from datetime import datetime from vyos.defaults import directories, config_status from vyos.configsession import ConfigSession, ConfigSessionError from vyos.configtree import ConfigTree -from vyos.util import cmd +from vyos.utils.process import cmd STATUS_FILE = config_status TRACE_FILE = '/tmp/boot-config-trace' diff --git a/src/helpers/vyos-check-wwan.py b/src/helpers/vyos-check-wwan.py index 2ff9a574f..334f08dd3 100755 --- a/src/helpers/vyos-check-wwan.py +++ b/src/helpers/vyos-check-wwan.py @@ -17,7 +17,7 @@ from vyos.configquery import VbashOpRun from vyos.configquery import ConfigTreeQuery -from vyos.util import is_wwan_connected +from vyos.utils.network import is_wwan_connected conf = ConfigTreeQuery() dict = conf.get_config_dict(['interfaces', 'wwan'], key_mangling=('-', '_'), diff --git a/src/helpers/vyos-domain-resolver.py b/src/helpers/vyos-domain-resolver.py index e31d9238e..2036ca72e 100755 --- a/src/helpers/vyos-domain-resolver.py +++ b/src/helpers/vyos-domain-resolver.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2022 VyOS maintainers and contributors +# Copyright (C) 2022-2023 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 @@ -22,10 +22,10 @@ from vyos.configdict import dict_merge from vyos.configquery import ConfigTreeQuery from vyos.firewall import fqdn_config_parse from vyos.firewall import fqdn_resolve -from vyos.util import cmd -from vyos.util import commit_in_progress -from vyos.util import dict_search_args -from vyos.util import run +from vyos.utils.commit import commit_in_progress +from vyos.utils.dict import dict_search_args +from vyos.utils.process import cmd +from vyos.utils.process import run from vyos.xml import defaults base = ['firewall'] diff --git a/src/helpers/vyos-failover.py b/src/helpers/vyos-failover.py index ce4cf8fa4..cc7610370 100755 --- a/src/helpers/vyos-failover.py +++ b/src/helpers/vyos-failover.py @@ -20,7 +20,7 @@ import subprocess import socket import time -from vyos.util import rc_cmd +from vyos.utils.process import rc_cmd from pathlib import Path from systemd import journal diff --git a/src/helpers/vyos-interface-rescan.py b/src/helpers/vyos-interface-rescan.py index 1ac1810e0..012357259 100755 --- a/src/helpers/vyos-interface-rescan.py +++ b/src/helpers/vyos-interface-rescan.py @@ -24,7 +24,7 @@ import netaddr from vyos.configtree import ConfigTree from vyos.defaults import directories -from vyos.util import get_cfg_group_id +from vyos.utils.permission import get_cfg_group_id debug = False diff --git a/src/helpers/vyos-merge-config.py b/src/helpers/vyos-merge-config.py index 14df2734b..8997705fe 100755 --- a/src/helpers/vyos-merge-config.py +++ b/src/helpers/vyos-merge-config.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 -# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2019-2023 VyOS maintainers and contributors <maintainers@vyos.io> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -20,11 +20,12 @@ import os import tempfile import vyos.defaults import vyos.remote + from vyos.config import Config from vyos.configtree import ConfigTree from vyos.migrator import Migrator, VirtualMigrator -from vyos.util import cmd, DEVNULL - +from vyos.utils.process import cmd +from vyos.utils.process import DEVNULL if (len(sys.argv) < 2): print("Need config file name to merge.") diff --git a/src/helpers/vyos-sudo.py b/src/helpers/vyos-sudo.py index 3e4c196d9..75dd7f29d 100755 --- a/src/helpers/vyos-sudo.py +++ b/src/helpers/vyos-sudo.py @@ -18,7 +18,7 @@ import os import sys -from vyos.util import is_admin +from vyos.utils.permission import is_admin if __name__ == '__main__': diff --git a/src/helpers/vyos_config_sync.py b/src/helpers/vyos_config_sync.py new file mode 100755 index 000000000..7cfa8fe88 --- /dev/null +++ b/src/helpers/vyos_config_sync.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2023 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 <http://www.gnu.org/licenses/>. +# +# + +import os +import json +import requests +import urllib3 +import logging +from typing import Optional, List, Union, Dict, Any + +from vyos.config import Config +from vyos.template import bracketize_ipv6 + + +CONFIG_FILE = '/run/config_sync_conf.conf' + +# Logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) +logger.name = os.path.basename(__file__) + +# API +API_HEADERS = {'Content-Type': 'application/json'} + + +def post_request(url: str, + data: str, + headers: Dict[str, str]) -> requests.Response: + """Sends a POST request to the specified URL + + Args: + url (str): The URL to send the POST request to. + data (Dict[str, Any]): The data to send with the POST request. + headers (Dict[str, str]): The headers to include with the POST request. + + Returns: + requests.Response: The response object representing the server's response to the request + """ + + response = requests.post(url, + data=data, + headers=headers, + verify=False, + timeout=timeout) + return response + + +def retrieve_config(section: str = None) -> Optional[Dict[str, Any]]: + """Retrieves the configuration from the local server. + + Args: + section: str: The section of the configuration to retrieve. Default is None. + + Returns: + Optional[Dict[str, Any]]: The retrieved configuration as a dictionary, or None if an error occurred. + """ + if section is None: + section = [] + else: + section = section.split() + + conf = Config() + config = conf.get_config_dict(section, get_first_key=True) + if config: + return config + return None + + +def set_remote_config( + address: str, + key: str, + op: str, + path: str = None, + section: Optional[str] = None) -> Optional[Dict[str, Any]]: + """Loads the VyOS configuration in JSON format to a remote host. + + Args: + address (str): The address of the remote host. + key (str): The key to use for loading the configuration. + path (Optional[str]): The path of the configuration. Default is None. + section (Optional[str]): The section of the configuration to load. Default is None. + + Returns: + Optional[Dict[str, Any]]: The response from the remote host as a dictionary, or None if an error occurred. + """ + + if path is None: + path = [] + else: + path = path.split() + headers = {'Content-Type': 'application/json'} + + # Disable the InsecureRequestWarning + urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) + + url = f'https://{address}/configure-section' + data = json.dumps({ + 'op': mode, + 'path': path, + 'section': section, + 'key': key + }) + + try: + config = post_request(url, data, headers) + return config.json() + except requests.exceptions.RequestException as e: + print(f"An error occurred: {e}") + logger.error(f"An error occurred: {e}") + return None + + +def is_section_revised(section: str) -> bool: + from vyos.config_mgmt import is_node_revised + return is_node_revised([section]) + + +def config_sync(secondary_address: str, + secondary_key: str, + sections: List[str], + mode: str): + """Retrieve a config section from primary router in JSON format and send it to + secondary router + """ + # Config sync only if sections changed + if not any(map(is_section_revised, sections)): + return + + logger.info( + f"Config synchronization: Mode={mode}, Secondary={secondary_address}" + ) + + # Sync sections ("nat", "firewall", etc) + for section in sections: + config_json = retrieve_config(section=section) + # Check if config path deesn't exist, for example "set nat" + # we set empty value for config_json data + # As we cannot send to the remote host section "nat None" config + if not config_json: + config_json = "" + logger.debug( + f"Retrieved config for section '{section}': {config_json}") + set_config = set_remote_config(address=secondary_address, + key=secondary_key, + op=mode, + path=section, + section=config_json) + logger.debug(f"Set config for section '{section}': {set_config}") + + +if __name__ == '__main__': + # Read configuration from file + if not os.path.exists(CONFIG_FILE): + logger.error(f"Post-commit: No config file '{CONFIG_FILE}' exists") + exit(0) + + with open(CONFIG_FILE, 'r') as f: + config_data = f.read() + + config = json.loads(config_data) + + mode = config.get('mode') + secondary_address = config.get('secondary', {}).get('address') + secondary_address = bracketize_ipv6(secondary_address) + secondary_key = config.get('secondary', {}).get('key') + sections = config.get('section') + timeout = int(config.get('secondary', {}).get('timeout')) + + if not all([ + mode, secondary_address, secondary_key, sections + ]): + logger.error( + "Missing required configuration data for config synchronization.") + exit(0) + + config_sync(secondary_address, secondary_key, + sections, mode) diff --git a/src/helpers/vyos_net_name b/src/helpers/vyos_net_name index 1798e92db..8c0992414 100755 --- a/src/helpers/vyos_net_name +++ b/src/helpers/vyos_net_name @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-2023 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 @@ -13,8 +13,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# import os import re @@ -26,7 +24,8 @@ from sys import argv from vyos.configtree import ConfigTree from vyos.defaults import directories -from vyos.util import cmd, boot_configuration_complete +from vyos.utils.process import cmd +from vyos.utils.boot import boot_configuration_complete from vyos.migrator import VirtualMigrator vyos_udev_dir = directories['vyos_udev_dir'] diff --git a/src/init/vyos-config b/src/init/vyos-config new file mode 100755 index 000000000..356427024 --- /dev/null +++ b/src/init/vyos-config @@ -0,0 +1,16 @@ +#!/bin/bash + +while [ ! -f /tmp/vyos-config-status ] +do + sleep 1 +done + +status=$(cat /tmp/vyos-config-status) + +if [ -z "$1" ]; then + if [ $status -ne 0 ]; then + echo "Configuration error" + else + echo "Configuration success" + fi +fi diff --git a/src/init/vyos-router b/src/init/vyos-router new file mode 100755 index 000000000..7b752b84b --- /dev/null +++ b/src/init/vyos-router @@ -0,0 +1,421 @@ +#!/bin/bash +# 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 <http://www.gnu.org/licenses/>. + +. /lib/lsb/init-functions + +: ${vyatta_env:=/etc/default/vyatta} +source $vyatta_env + +declare progname=${0##*/} +declare action=$1; shift + +declare -x BOOTFILE=$vyatta_sysconfdir/config/config.boot + +# If vyos-config= boot option is present, use that file instead +for x in $(cat /proc/cmdline); do + [[ $x = vyos-config=* ]] || continue + VYOS_CONFIG="${x#vyos-config=}" +done + +if [ ! -z "$VYOS_CONFIG" ]; then + if [ -r "$VYOS_CONFIG" ]; then + echo "Config selected manually: $VYOS_CONFIG" + declare -x BOOTFILE="$VYOS_CONFIG" + else + echo "WARNING: Could not read selected config file, using default!" + fi +fi + +declare -a subinit +declare -a all_subinits=( firewall ) + +if [ $# -gt 0 ] ; then + for s in $@ ; do + [ -x ${vyatta_sbindir}/${s}.init ] && subinit[${#subinit}]=$s + done +else + for s in ${all_subinits[@]} ; do + [ -x ${vyatta_sbindir}/${s}.init ] && subinit[${#subinit}]=$s + done +fi + +GROUP=vyattacfg + +# easy way to make empty file without any command +empty() +{ + >$1 +} + +# check if bootup of this portion is disabled +disabled () { + grep -q -w no-vyos-$1 /proc/cmdline +} + +# if necessary, provide initial config +init_bootfile () { + if [ ! -r $BOOTFILE ] ; then + if [ -f $vyatta_sysconfdir/config.boot.default ]; then + cp $vyatta_sysconfdir/config.boot.default $BOOTFILE + else + $vyos_libexec_dir/system-versions-foot.py > $BOOTFILE + fi + chgrp ${GROUP} $BOOTFILE + chmod 660 $BOOTFILE + fi +} + +# if necessary, migrate initial config +migrate_bootfile () +{ + if [ -x $vyos_libexec_dir/run-config-migration.py ]; then + log_progress_msg migrate + sg ${GROUP} -c "$vyos_libexec_dir/run-config-migration.py $BOOTFILE" + fi +} + +# load the initial config +load_bootfile () +{ + log_progress_msg configure + ( + if [ -f /etc/default/vyatta-load-boot ]; then + # build-specific environment for boot-time config loading + source /etc/default/vyatta-load-boot + fi + if [ -x $vyos_libexec_dir/vyos-boot-config-loader.py ]; then + sg ${GROUP} -c "$vyos_libexec_dir/vyos-boot-config-loader.py $BOOTFILE" + fi + ) +} + +# execute the pre-config script +run_preconfig_script () +{ + if [ -x $vyatta_sysconfdir/config/scripts/vyos-preconfig-bootup.script ]; then + $vyatta_sysconfdir/config/scripts/vyos-preconfig-bootup.script + fi +} + +# execute the post-config scripts +run_postconfig_scripts () +{ + if [ -x $vyatta_sysconfdir/config/scripts/vyatta-postconfig-bootup.script ]; then + $vyatta_sysconfdir/config/scripts/vyatta-postconfig-bootup.script + fi + if [ -x $vyatta_sysconfdir/config/scripts/vyos-postconfig-bootup.script ]; then + $vyatta_sysconfdir/config/scripts/vyos-postconfig-bootup.script + fi +} + +run_postupgrade_script () +{ + if [ -f $vyatta_sysconfdir/config/.upgraded ]; then + # Run the system script + /usr/libexec/vyos/system/post-upgrade + + # Run user scripts + if [ -d $vyatta_sysconfdir/config/scripts/post-upgrade.d ]; then + run-parts $vyatta_sysconfdir/config/scripts/post-upgrade.d + fi + rm -f $vyatta_sysconfdir/config/.upgraded + fi +} + +# +# On image booted machines, we need to mount /boot from the image-specific +# boot directory so that kernel package installation will put the +# files in the right place. We also have to mount /boot/grub from the +# system-wide grub directory so that tools that edit the grub.cfg +# file will find it in the expected location. +# +bind_mount_boot () +{ + persist_path=$(/opt/vyatta/sbin/vyos-persistpath) + if [ $? == 0 ]; then + if [ -e $persist_path/boot ]; then + image_name=$(cat /proc/cmdline | sed -e s+^.*vyos-union=/boot/++ | sed -e 's/ .*$//') + + if [ -n "$image_name" ]; then + mount --bind $persist_path/boot/$image_name /boot + if [ $? -ne 0 ]; then + echo "Couldn't bind mount /boot" + fi + + if [ ! -d /boot/grub ]; then + mkdir /boot/grub + fi + + mount --bind $persist_path/boot/grub /boot/grub + if [ $? -ne 0 ]; then + echo "Couldn't bind mount /boot/grub" + fi + fi + fi + fi +} + +clear_or_override_config_files () +{ + for conf in snmp/snmpd.conf snmp/snmptrapd.conf snmp/snmp.conf \ + keepalived/keepalived.conf cron.d/vyos-crontab \ + ipvsadm.rules default/ipvsadm resolv.conf + do + if [ -s /etc/$conf ] ; then + empty /etc/$conf + chmod 0644 /etc/$conf + fi + done +} + +update_interface_config () +{ + if [ -d /run/udev/vyos ]; then + $vyos_libexec_dir/vyos-interface-rescan.py $BOOTFILE + fi +} + +cleanup_post_commit_hooks () { + # Remove links from the post-commit hooks directory. + # note that this approach only supports hooks that are "configured", + # i.e., it does not support hooks that need to always be present. + cpostdir=$(cli-shell-api getPostCommitHookDir) + # exclude commits hooks from vyatta-cfg + excluded="10vyatta-log-commit.pl 99vyos-user-postcommit-hooks" + if [ -d "$cpostdir" ]; then + for f in $cpostdir/*; do + if [[ ! $excluded =~ $(basename $f) ]]; then + rm -f $cpostdir/$(basename $f) + fi + done + fi +} + +# These are all the default security setting which are later +# overridden when configuration is read. These are the values the +# system defaults. +security_reset () +{ + # restore PAM back to virgin state (no radius/tacacs services) + pam-auth-update --package --remove radius + rm -f /etc/pam_radius_auth.conf + pam-auth-update --package --remove tacplus + rm -f /etc/tacplus_nss.conf /etc/tacplus_servers + + # Certain configuration files are re-generated by the configuration + # subsystem and must reside under /etc and can not easily be moved to /run. + # So on every boot we simply delete any remaining files and let the CLI + # regenearte them. + + # PPPoE + rm -f /etc/ppp/peers/pppoe* /etc/ppp/peers/wlm* + + # IPSec + rm -rf /etc/ipsec.conf /etc/ipsec.secrets + find /etc/swanctl -type f | xargs rm -f + + # limit cleanup + rm -f /etc/security/limits.d/10-vyos.conf + + # iproute2 cleanup + rm -f /etc/iproute2/rt_tables.d/vyos-*.conf + + # Container + rm -f /etc/containers/storage.conf /etc/containers/registries.conf /etc/containers/containers.conf + # Clean all networks and re-create them from our CLI + rm -f /etc/containers/networks/* + + # System Options (SSH/cURL) + rm -f /etc/ssh/ssh_config.d/*vyos*.conf + rm -f /etc/curlrc +} + +# XXX: T3885 - generate persistend DHCPv6 DUID (Type4 - UUID based) +gen_duid () +{ + DUID_FILE="/var/lib/dhcpv6/dhcp6c_duid" + UUID_FILE="/sys/class/dmi/id/product_uuid" + UUID_FILE_ALT="/sys/class/dmi/id/product_serial" + if [ ! -f ${UUID_FILE} ] && [ ! -f ${UUID_FILE_ALT} ]; then + return 1 + fi + + # DUID is based on the BIOS/EFI UUID. We omit additional - characters + if [ -f ${UUID_FILE} ]; then + UUID=$(cat ${UUID_FILE} | tr -d -) + fi + if [ -z ${UUID} ]; then + UUID=$(uuidgen --sha1 --namespace @dns --name $(cat ${UUID_FILE_ALT}) | tr -d -) + fi + # Add DUID type4 (UUID) information + DUID_TYPE="0004" + + # The length-information (as per RFC6355 UUID is 128 bits long) is in big-endian + # format - beware when porting to ARM64. The length field consists out of the + # UUID (128 bit + 16 bits DUID type) resulting in hex 12. + DUID_LEN="0012" + if [ "$(echo -n I | od -to2 | head -n1 | cut -f2 -d" " | cut -c6 )" -eq 1 ]; then + # true on little-endian (x86) systems + DUID_LEN="1200" + fi + + for i in $(echo -n ${DUID_LEN}${DUID_TYPE}${UUID} | sed 's/../& /g'); do + echo -ne "\x$i" + done > ${DUID_FILE} +} + +start () +{ + # reset and clean config files + security_reset || log_failure_msg "security reset failed" + + # some legacy directories migrated over from old rl-system.init + mkdir -p /var/run/vyatta /var/log/vyatta + chgrp vyattacfg /var/run/vyatta /var/log/vyatta + chmod 775 /var/run/vyatta /var/log/vyatta + + log_daemon_msg "Waiting for NICs to settle down" + # On boot time udev migth take a long time to reorder nic's, this will ensure that + # all udev activity is completed and all nics presented at boot-time will have their + # final name before continuing with vyos-router initialization. + SECONDS=0 + udevadm settle + STATUS=$? + log_progress_msg "settled in ${SECONDS}sec." + log_end_msg ${STATUS} + + # mountpoint for bpf maps required by xdp + mount -t bpf none /sys/fs/bpf + + # Clear out Debian APT source config file + empty /etc/apt/sources.list + + # Generate DHCPv6 DUID + gen_duid || log_failure_msg "could not generate DUID" + + # Mount a temporary filesystem for container networks. + # Configuration should be loaded from VyOS cli. + cni_dir="/etc/cni/net.d" + [ ! -d ${cni_dir} ] && mkdir -p ${cni_dir} + mount -t tmpfs none ${cni_dir} + + # Init firewall + nfct helper add rpc inet tcp + nfct helper add rpc inet udp + nfct helper add tns inet tcp + nft -f /usr/share/vyos/vyos-firewall-init.conf || log_failure_msg "could not initiate firewall rules" + + rm -f /etc/hostname + ${vyos_conf_scripts_dir}/host_name.py || log_failure_msg "could not reset host-name" + systemctl start frr.service + + # As VyOS does not execute commands that are not present in the CLI we call + # the script by hand to have a single source for the login banner and MOTD + ${vyos_conf_scripts_dir}/system_console.py || log_failure_msg "could not reset serial console" + ${vyos_conf_scripts_dir}/system-login.py || log_failure_msg "could not reset system login" + ${vyos_conf_scripts_dir}/system-login-banner.py || log_failure_msg "could not reset motd and issue files" + ${vyos_conf_scripts_dir}/system-option.py || log_failure_msg "could not reset system option files" + ${vyos_conf_scripts_dir}/conntrack.py || log_failure_msg "could not reset conntrack subsystem" + ${vyos_conf_scripts_dir}/container.py || log_failure_msg "could not reset container subsystem" + + clear_or_override_config_files || log_failure_msg "could not reset config files" + + # enable some debugging before loading the configuration + if grep -q vyos-debug /proc/cmdline; then + log_action_begin_msg "Enable runtime debugging options" + touch /tmp/vyos.container.debug + touch /tmp/vyos.ifconfig.debug + touch /tmp/vyos.frr.debug + touch /tmp/vyos.container.debug + fi + + log_action_begin_msg "Mounting VyOS Config" + # ensure the vyatta_configdir supports a large number of inodes since + # the config hierarchy is often inode-bound (instead of size). + # impose a minimum and then scale up dynamically with the actual size + # of the system memory. + local tmem=$(sed -n 's/^MemTotal: \+\([0-9]\+\) kB$/\1/p' /proc/meminfo) + local tpages + local tmpfs_opts="nosuid,nodev,mode=775,nr_inodes=0" #automatically allocate inodes + mount -o $tmpfs_opts -t tmpfs none ${vyatta_configdir} \ + && chgrp ${GROUP} ${vyatta_configdir} + log_action_end_msg $? + + disabled bootfile || init_bootfile + + cleanup_post_commit_hooks + + log_daemon_msg "Starting VyOS router" + disabled migrate || migrate_bootfile + + run_preconfig_script + + run_postupgrade_script + + update_interface_config + + for s in ${subinit[@]} ; do + if ! disabled $s; then + log_progress_msg $s + if ! ${vyatta_sbindir}/${s}.init start + then log_failure_msg + exit 1 + fi + fi + done + + bind_mount_boot + + disabled configure || load_bootfile + log_end_msg $? + + telinit q + chmod g-w,o-w / + + run_postconfig_scripts +} + +stop() +{ + local -i status=0 + log_daemon_msg "Stopping VyOS router" + for ((i=${#sub_inits[@]} - 1; i >= 0; i--)) ; do + s=${subinit[$i]} + log_progress_msg $s + ${vyatta_sbindir}/${s}.init stop + let status\|=$? + done + log_end_msg $status + log_action_begin_msg "Un-mounting VyOS Config" + umount ${vyatta_configdir} + log_action_end_msg $? + + systemctl stop frr.service +} + +case "$action" in + start) start ;; + stop) stop ;; + restart|force-reload) stop && start ;; + *) log_failure_msg "usage: $progname [ start|stop|restart ] [ subinit ... ]" ; + false ;; +esac + +exit $? + +# Local Variables: +# mode: shell-script +# sh-indentation: 4 +# End: diff --git a/src/migration-scripts/container/0-to-1 b/src/migration-scripts/container/0-to-1 index d0461389b..86f89ee04 100755 --- a/src/migration-scripts/container/0-to-1 +++ b/src/migration-scripts/container/0-to-1 @@ -21,7 +21,7 @@ import shutil import sys from vyos.configtree import ConfigTree -from vyos.util import call +from vyos.utils.process import call if (len(sys.argv) < 1): print("Must specify file name!") @@ -39,12 +39,12 @@ config = ConfigTree(config_file) if config.exists(base): for container in config.list_nodes(base): # Stop any given container first - call(f'systemctl stop vyos-container-{container}.service') + call(f'sudo systemctl stop vyos-container-{container}.service') # Export container image for later re-import to new filesystem. We store # the backup on a real disk as a tmpfs (like /tmp) could probably lack # memory if a host has too many containers stored. image_name = config.return_value(base + [container, 'image']) - call(f'podman image save --quiet --output /root/{container}.tar --format oci-archive {image_name}') + call(f'sudo podman image save --quiet --output /root/{container}.tar --format oci-archive {image_name}') # No need to adjust the strage driver online (this is only used for testing and # debugging on a live system) - it is already overlay2 when the migration script @@ -66,10 +66,10 @@ if config.exists(base): # Export container image for later re-import to new filesystem image_name = config.return_value(base + [container, 'image']) image_path = f'/root/{container}.tar' - call(f'podman image load --quiet --input {image_path}') + call(f'sudo podman image load --quiet --input {image_path}') # Start any given container first - call(f'systemctl start vyos-container-{container}.service') + call(f'sudo systemctl start vyos-container-{container}.service') # Delete temporary container image if os.path.exists(image_path): diff --git a/src/migration-scripts/interfaces/24-to-25 b/src/migration-scripts/interfaces/24-to-25 index 4095f2a3e..f3a1dc464 100755 --- a/src/migration-scripts/interfaces/24-to-25 +++ b/src/migration-scripts/interfaces/24-to-25 @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-2023 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 @@ -19,6 +19,7 @@ import os import sys + from vyos.configtree import ConfigTree from vyos.pki import CERT_BEGIN from vyos.pki import load_certificate @@ -29,7 +30,7 @@ from vyos.pki import encode_certificate from vyos.pki import encode_dh_parameters from vyos.pki import encode_private_key from vyos.pki import verify_crl -from vyos.util import run +from vyos.utils.process import run def wrapped_pem_to_config_value(pem): out = [] @@ -241,7 +242,7 @@ if config.exists(base): config.set(pki_base + ['certificate', pki_name, 'private', 'key'], value=wrapped_pem_to_config_value(key_pem)) else: print(f'Failed to migrate private key on openvpn interface {interface}') - + config.delete(x509_base + ['key-file']) if config.exists(x509_base + ['dh-file']): @@ -276,7 +277,7 @@ base = ['interfaces', 'wireguard'] if config.exists(base): for interface in config.list_nodes(base): private_key_path = base + [interface, 'private-key'] - + key_file = 'default' if config.exists(private_key_path): key_file = config.return_value(private_key_path) @@ -375,7 +376,7 @@ if config.exists(base): config.set(pki_base + ['certificate', pki_name, 'private', 'key'], value=wrapped_pem_to_config_value(key_pem)) else: print(f'Failed to migrate private key on eapol config for interface {interface}') - + config.delete(x509_base + ['key-file']) try: diff --git a/src/migration-scripts/interfaces/7-to-8 b/src/migration-scripts/interfaces/7-to-8 index a4051301f..9845098a7 100755 --- a/src/migration-scripts/interfaces/7-to-8 +++ b/src/migration-scripts/interfaces/7-to-8 @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-2023 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 @@ -21,7 +21,8 @@ import os from sys import exit, argv from vyos.configtree import ConfigTree -from vyos.util import chown, chmod_750 +from vyos.utils.permission import chown +from vyos.utils.permission import chmod_750 def migrate_default_keys(): kdir = r'/config/auth/wireguard' diff --git a/src/migration-scripts/ipsec/6-to-7 b/src/migration-scripts/ipsec/6-to-7 index 788a87095..649a18cb3 100755 --- a/src/migration-scripts/ipsec/6-to-7 +++ b/src/migration-scripts/ipsec/6-to-7 @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-2023 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 @@ -27,7 +27,7 @@ from vyos.pki import load_crl from vyos.pki import load_private_key from vyos.pki import encode_certificate from vyos.pki import encode_private_key -from vyos.util import run +from vyos.utils.process import run if (len(argv) < 1): print("Must specify file name!") @@ -127,7 +127,7 @@ if config.exists(ipsec_site_base): config.set(pki_base + ['ca', pki_name, 'crl'], value=wrapped_pem_to_config_value(crl_pem)) else: print(f'Failed to migrate CRL on peer "{peer}"') - + config.delete(peer_x509_base + ['crl-file']) if config.exists(peer_x509_base + ['key', 'file']): @@ -157,7 +157,7 @@ if config.exists(ipsec_site_base): config.set(peer_x509_base + ['private-key-passphrase'], value=key_passphrase) else: print(f'Failed to migrate private key on peer "{peer}"') - + config.delete(peer_x509_base + ['key']) if changes_made: diff --git a/src/migration-scripts/l2tp/3-to-4 b/src/migration-scripts/l2tp/3-to-4 index 18eabadec..ee6079864 100755 --- a/src/migration-scripts/l2tp/3-to-4 +++ b/src/migration-scripts/l2tp/3-to-4 @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-2023 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 @@ -27,7 +27,7 @@ from vyos.pki import load_crl from vyos.pki import load_private_key from vyos.pki import encode_certificate from vyos.pki import encode_private_key -from vyos.util import run +from vyos.utils.process import run if (len(argv) < 1): print("Must specify file name!") @@ -156,7 +156,7 @@ if config.exists(x509_base + ['server-key-file']): config.set(x509_base + ['private-key-passphrase'], value=key_passphrase) else: print(f'Failed to migrate private key on l2tp remote-access config') - + config.delete(x509_base + ['server-key-file']) if config.exists(x509_base + ['server-key-password']): config.delete(x509_base + ['server-key-password']) diff --git a/src/migration-scripts/openconnect/0-to-1 b/src/migration-scripts/openconnect/0-to-1 index 83cd09143..b26023a5b 100755 --- a/src/migration-scripts/openconnect/0-to-1 +++ b/src/migration-scripts/openconnect/0-to-1 @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-2023 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 @@ -26,7 +26,7 @@ from vyos.pki import load_crl from vyos.pki import load_private_key from vyos.pki import encode_certificate from vyos.pki import encode_private_key -from vyos.util import run +from vyos.utils.process import run if (len(argv) < 1): print("Must specify file name!") @@ -125,7 +125,7 @@ if config.exists(x509_base + ['key-file']): config.set(pki_base + ['certificate', pki_name, 'private', 'key'], value=wrapped_pem_to_config_value(key_pem)) else: print(f'Failed to migrate private key on openconnect config') - + config.delete(x509_base + ['key-file']) try: diff --git a/src/migration-scripts/policy/3-to-4 b/src/migration-scripts/policy/3-to-4 index bae30cffc..49e0b4c38 100755 --- a/src/migration-scripts/policy/3-to-4 +++ b/src/migration-scripts/policy/3-to-4 @@ -51,7 +51,7 @@ def community_migrate(config: ConfigTree, rule: list[str]) -> bool: :rtype: bool """ community_list = list((config.return_value(rule)).split(" ")) - config.delete(rule) + if 'none' in community_list: config.set(rule + ['none']) return False @@ -61,8 +61,10 @@ def community_migrate(config: ConfigTree, rule: list[str]) -> bool: community_action = 'add' community_list.remove('additive') for community in community_list: - config.set(rule + [community_action], value=community, - replace=False) + if len(community): + config.set(rule + [community_action], value=community, + replace=False) + config.delete(rule) if community_action == 'replace': return False else: diff --git a/src/migration-scripts/qos/1-to-2 b/src/migration-scripts/qos/1-to-2 index 14d3a6e0a..a689bacc5 100755 --- a/src/migration-scripts/qos/1-to-2 +++ b/src/migration-scripts/qos/1-to-2 @@ -18,7 +18,7 @@ from sys import argv,exit from vyos.base import Warning from vyos.configtree import ConfigTree -from vyos.util import read_file +from vyos.utils.file import read_file def bandwidth_percent_to_val(interface, percent) -> int: speed = read_file(f'/sys/class/net/{interface}/speed') diff --git a/src/migration-scripts/sstp/3-to-4 b/src/migration-scripts/sstp/3-to-4 index 0568f043f..ea814fdc5 100755 --- a/src/migration-scripts/sstp/3-to-4 +++ b/src/migration-scripts/sstp/3-to-4 @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-2023 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 @@ -26,7 +26,7 @@ from vyos.pki import load_crl from vyos.pki import load_private_key from vyos.pki import encode_certificate from vyos.pki import encode_private_key -from vyos.util import run +from vyos.utils.process import run if (len(argv) < 1): print("Must specify file name!") @@ -125,7 +125,7 @@ if config.exists(x509_base + ['key-file']): config.set(pki_base + ['certificate', pki_name, 'private', 'key'], value=wrapped_pem_to_config_value(key_pem)) else: print(f'Failed to migrate private key on sstp config') - + config.delete(x509_base + ['key-file']) try: diff --git a/src/migration-scripts/system/13-to-14 b/src/migration-scripts/system/13-to-14 index 5b068f4fc..1751f1865 100755 --- a/src/migration-scripts/system/13-to-14 +++ b/src/migration-scripts/system/13-to-14 @@ -12,7 +12,7 @@ import re import sys from vyos.configtree import ConfigTree -from vyos.util import cmd +from vyos.utils.process import cmd if (len(sys.argv) < 1): diff --git a/src/migration-scripts/vrrp/3-to-4 b/src/migration-scripts/vrrp/3-to-4 new file mode 100755 index 000000000..b0a6975c2 --- /dev/null +++ b/src/migration-scripts/vrrp/3-to-4 @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2023 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 <http://www.gnu.org/licenses/>. + +from sys import argv +from vyos.configtree import ConfigTree + +if (len(argv) < 1): + print('Must specify file name!') + exit(1) + +file_name = argv[1] + +with open(file_name, 'r') as f: + config_file = f.read() + +base = ['high-availability', 'virtual-server'] +config = ConfigTree(config_file) + +if not config.exists(base): + # Nothing to do + exit(0) + +if config.exists(base): + for vs in config.list_nodes(base): + vs_base = base + [vs] + + # If the fwmark is used, the address is not required + if not config.exists(vs_base + ['fwmark']): + # add option: 'virtual-server <tag> address x.x.x.x' + config.set(vs_base + ['address'], value=vs) + + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print(f'Failed to save the modified config: {e}') + exit(1) diff --git a/src/op_mode/accelppp.py b/src/op_mode/accelppp.py index 00de45fc8..67ce786d0 100755 --- a/src/op_mode/accelppp.py +++ b/src/op_mode/accelppp.py @@ -21,7 +21,7 @@ import vyos.accel_ppp import vyos.opmode from vyos.configquery import ConfigTreeQuery -from vyos.util import rc_cmd +from vyos.utils.process import rc_cmd accel_dict = { diff --git a/src/op_mode/bgp.py b/src/op_mode/bgp.py index af9ea788b..096113cb4 100755 --- a/src/op_mode/bgp.py +++ b/src/op_mode/bgp.py @@ -81,7 +81,7 @@ ArgFamily = typing.Literal['inet', 'inet6', 'l2vpn'] ArgFamilyModifier = typing.Literal['unicast', 'labeled_unicast', 'multicast', 'vpn', 'flowspec'] def show_summary(raw: bool): - from vyos.util import cmd + from vyos.utils.process import cmd if raw: from json import loads @@ -96,7 +96,7 @@ def show_summary(raw: bool): return output def show_neighbors(raw: bool): - from vyos.util import cmd + from vyos.utils.process import cmd from vyos.utils.dict import dict_to_list if raw: @@ -129,7 +129,7 @@ def show(raw: bool, frr_command = frr_command_template.render(kwargs) frr_command = re.sub(r'\s+', ' ', frr_command) - from vyos.util import cmd + from vyos.utils.process import cmd output = cmd(f"vtysh -c '{frr_command}'") if raw: diff --git a/src/op_mode/bridge.py b/src/op_mode/bridge.py index d6098c158..1834b9cc9 100755 --- a/src/op_mode/bridge.py +++ b/src/op_mode/bridge.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2022 VyOS maintainers and contributors +# Copyright (C) 2022-2023 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 @@ -22,8 +22,10 @@ import typing from sys import exit from tabulate import tabulate -from vyos.util import cmd, rc_cmd -from vyos.util import dict_search +from vyos.utils.process import cmd +from vyos.utils.process import rc_cmd +from vyos.utils.process import call +from vyos.utils.dict import dict_search import vyos.opmode @@ -128,7 +130,8 @@ def _get_formatted_output_vlan(data): if vlan_entry.get('vlanEnd'): vlan_end = vlan_entry.get('vlanEnd') vlan = f'{vlan}-{vlan_end}' - flags = ', '.join(vlan_entry.get('flags')).lower() + flags_raw = vlan_entry.get('flags') + flags = ', '.join(flags_raw if isinstance(flags_raw,list) else "").lower() data_entries.append([interface, vlan, flags]) headers = ["Interface", "Vlan", "Flags"] @@ -163,6 +166,23 @@ def _get_formatted_output_mdb(data): output = tabulate(data_entries, headers) return output +def _get_bridge_detail(iface): + """Get interface detail statistics""" + return call(f'vtysh -c "show interface {iface}"') + +def _get_bridge_detail_nexthop_group(iface): + """Get interface detail nexthop_group statistics""" + return call(f'vtysh -c "show interface {iface} nexthop-group"') + +def _get_bridge_detail_nexthop_group_raw(iface): + out = cmd(f'vtysh -c "show interface {iface} nexthop-group"') + return out + +def _get_bridge_detail_raw(iface): + """Get interface detail json statistics""" + data = cmd(f'vtysh -c "show interface {iface} json"') + data_dict = json.loads(data) + return data_dict def show(raw: bool): bridge_data = _get_raw_data_summary() @@ -195,6 +215,17 @@ def show_mdb(raw: bool, interface: str): else: return _get_formatted_output_mdb(mdb_data) +def show_detail(raw: bool, nexthop_group: typing.Optional[bool], interface: str): + if raw: + if nexthop_group: + return _get_bridge_detail_nexthop_group_raw(interface) + else: + return _get_bridge_detail_raw(interface) + else: + if nexthop_group: + return _get_bridge_detail_nexthop_group(interface) + else: + return _get_bridge_detail(interface) if __name__ == '__main__': try: diff --git a/src/op_mode/clear_conntrack.py b/src/op_mode/clear_conntrack.py index 423694187..fec7cf144 100755 --- a/src/op_mode/clear_conntrack.py +++ b/src/op_mode/clear_conntrack.py @@ -16,8 +16,9 @@ import sys -from vyos.util import ask_yes_no -from vyos.util import cmd, DEVNULL +from vyos.utils.io import ask_yes_no +from vyos.utils.process import cmd +from vyos.utils.process import DEVNULL if not ask_yes_no("This will clear all currently tracked and expected connections. Continue?"): sys.exit(1) diff --git a/src/op_mode/clear_dhcp_lease.py b/src/op_mode/clear_dhcp_lease.py index 250dbcce1..f372d3af0 100755 --- a/src/op_mode/clear_dhcp_lease.py +++ b/src/op_mode/clear_dhcp_lease.py @@ -7,9 +7,9 @@ from isc_dhcp_leases import Lease from isc_dhcp_leases import IscDhcpLeases from vyos.configquery import ConfigTreeQuery -from vyos.util import ask_yes_no -from vyos.util import call -from vyos.util import commit_in_progress +from vyos.utils.io import ask_yes_no +from vyos.utils.process import call +from vyos.utils.commit import commit_in_progress config = ConfigTreeQuery() diff --git a/src/op_mode/connect_disconnect.py b/src/op_mode/connect_disconnect.py index d39e88bf3..89f929be7 100755 --- a/src/op_mode/connect_disconnect.py +++ b/src/op_mode/connect_disconnect.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-2023 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 @@ -19,10 +19,10 @@ import argparse from psutil import process_iter -from vyos.util import call -from vyos.util import commit_in_progress -from vyos.util import DEVNULL -from vyos.util import is_wwan_connected +from vyos.utils.process import call +from vyos.utils.commit import commit_in_progress +from vyos.utils.network import is_wwan_connected +from vyos.utils.process import DEVNULL def check_ppp_interface(interface): if not os.path.isfile(f'/etc/ppp/peers/{interface}'): diff --git a/src/op_mode/conntrack.py b/src/op_mode/conntrack.py index ea7c4c208..cf8adf795 100755 --- a/src/op_mode/conntrack.py +++ b/src/op_mode/conntrack.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2022 VyOS maintainers and contributors +# Copyright (C) 2022-2023 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 @@ -19,8 +19,8 @@ import typing import xmltodict from tabulate import tabulate -from vyos.util import cmd -from vyos.util import run +from vyos.utils.process import cmd +from vyos.utils.process import run import vyos.opmode diff --git a/src/op_mode/conntrack_sync.py b/src/op_mode/conntrack_sync.py index c3345a936..a38688e45 100755 --- a/src/op_mode/conntrack_sync.py +++ b/src/op_mode/conntrack_sync.py @@ -24,10 +24,10 @@ import vyos.opmode from argparse import ArgumentParser from vyos.configquery import CliShellApiConfigQuery from vyos.configquery import ConfigTreeQuery -from vyos.util import call -from vyos.util import commit_in_progress -from vyos.util import cmd -from vyos.util import run +from vyos.utils.commit import commit_in_progress +from vyos.utils.process import call +from vyos.utils.process import cmd +from vyos.utils.process import run from vyos.template import render_to_string conntrackd_bin = '/usr/sbin/conntrackd' diff --git a/src/op_mode/container.py b/src/op_mode/container.py index 7f726f076..5a022d0c0 100755 --- a/src/op_mode/container.py +++ b/src/op_mode/container.py @@ -19,7 +19,7 @@ import sys from sys import exit -from vyos.util import cmd +from vyos.utils.process import cmd import vyos.opmode @@ -36,14 +36,14 @@ def _get_raw_data(command: str) -> list: return data def add_image(name: str): - from vyos.util import rc_cmd + from vyos.utils.process import rc_cmd rc, output = rc_cmd(f'podman image pull {name}') if rc != 0: raise vyos.opmode.InternalError(output) def delete_image(name: str): - from vyos.util import rc_cmd + from vyos.utils.process import rc_cmd rc, output = rc_cmd(f'podman image rm --force {name}') if rc != 0: @@ -77,7 +77,7 @@ def show_network(raw: bool): def restart(name: str): - from vyos.util import rc_cmd + from vyos.utils.process import rc_cmd rc, output = rc_cmd(f'systemctl restart vyos-container-{name}.service') if rc != 0: diff --git a/src/op_mode/dhcp.py b/src/op_mode/dhcp.py index fe7f252ba..3e51e990b 100755 --- a/src/op_mode/dhcp.py +++ b/src/op_mode/dhcp.py @@ -27,9 +27,9 @@ import vyos.opmode from vyos.base import Warning from vyos.configquery import ConfigTreeQuery -from vyos.util import cmd -from vyos.util import dict_search -from vyos.util import is_systemd_service_running +from vyos.utils.process import cmd +from vyos.utils.dict import dict_search +from vyos.utils.process import is_systemd_service_running config = ConfigTreeQuery() lease_valid_states = ['all', 'active', 'free', 'expired', 'released', 'abandoned', 'reset', 'backup'] diff --git a/src/op_mode/dns.py b/src/op_mode/dns.py index f8863c530..2168aef89 100755 --- a/src/op_mode/dns.py +++ b/src/op_mode/dns.py @@ -20,7 +20,7 @@ import sys from tabulate import tabulate from vyos.configquery import ConfigTreeQuery -from vyos.util import cmd +from vyos.utils.process import cmd import vyos.opmode diff --git a/src/op_mode/dns_dynamic.py b/src/op_mode/dns_dynamic.py index 76ca5249b..12aa5494a 100755 --- a/src/op_mode/dns_dynamic.py +++ b/src/op_mode/dns_dynamic.py @@ -22,7 +22,7 @@ from tabulate import tabulate from vyos.config import Config from vyos.template import is_ipv4, is_ipv6 -from vyos.util import call +from vyos.utils.process import call cache_file = r'/run/ddclient/ddclient.cache' diff --git a/src/op_mode/dns_forwarding_reset.py b/src/op_mode/dns_forwarding_reset.py index bfc640a26..55e20918f 100755 --- a/src/op_mode/dns_forwarding_reset.py +++ b/src/op_mode/dns_forwarding_reset.py @@ -25,7 +25,7 @@ import argparse from sys import exit from vyos.config import Config -from vyos.util import call +from vyos.utils.process import call PDNS_CMD='/usr/bin/rec_control --socket-dir=/run/powerdns' diff --git a/src/op_mode/dns_forwarding_statistics.py b/src/op_mode/dns_forwarding_statistics.py index d79b6c024..32b5c76a7 100755 --- a/src/op_mode/dns_forwarding_statistics.py +++ b/src/op_mode/dns_forwarding_statistics.py @@ -4,7 +4,7 @@ import jinja2 from sys import exit from vyos.config import Config -from vyos.util import cmd +from vyos.utils.process import cmd PDNS_CMD='/usr/bin/rec_control --socket-dir=/run/powerdns' diff --git a/src/op_mode/firewall.py b/src/op_mode/firewall.py index 46bda5f7e..8260bbb77 100755 --- a/src/op_mode/firewall.py +++ b/src/op_mode/firewall.py @@ -21,8 +21,8 @@ import re import tabulate from vyos.config import Config -from vyos.util import cmd -from vyos.util import dict_search_args +from vyos.utils.process import cmd +from vyos.utils.dict import dict_search_args def get_firewall_interfaces(firewall, name=None, ipv6=False): directions = ['in', 'out', 'local'] diff --git a/src/op_mode/flow_accounting_op.py b/src/op_mode/flow_accounting_op.py index 514143cd7..497ccafdf 100755 --- a/src/op_mode/flow_accounting_op.py +++ b/src/op_mode/flow_accounting_op.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018 VyOS maintainers and contributors +# Copyright (C) 2018-2023 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 @@ -13,18 +13,18 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -# import sys import argparse import re import ipaddress import os.path + from tabulate import tabulate from json import loads -from vyos.util import cmd -from vyos.util import commit_in_progress -from vyos.util import run +from vyos.utils.commit import commit_in_progress +from vyos.utils.process import cmd +from vyos.utils.process import run from vyos.logger import syslog # some default values diff --git a/src/op_mode/format_disk.py b/src/op_mode/format_disk.py index b3ba44e87..31ceb196a 100755 --- a/src/op_mode/format_disk.py +++ b/src/op_mode/format_disk.py @@ -20,10 +20,10 @@ import re from datetime import datetime -from vyos.util import ask_yes_no -from vyos.util import call -from vyos.util import cmd -from vyos.util import DEVNULL +from vyos.utils.io import ask_yes_no +from vyos.utils.process import call +from vyos.utils.process import cmd +from vyos.utils.process import DEVNULL def list_disks(): disks = set() diff --git a/src/op_mode/generate_interfaces_debug_archive.py b/src/op_mode/generate_interfaces_debug_archive.py index f5767080a..3059aad23 100755 --- a/src/op_mode/generate_interfaces_debug_archive.py +++ b/src/op_mode/generate_interfaces_debug_archive.py @@ -20,7 +20,7 @@ from shutil import rmtree from socket import gethostname from sys import exit from tarfile import open as tar_open -from vyos.util import rc_cmd +from vyos.utils.process import rc_cmd import os # define a list of commands that needs to be executed diff --git a/src/op_mode/generate_ipsec_debug_archive.py b/src/op_mode/generate_ipsec_debug_archive.py index 1422559a8..60195d48b 100755 --- a/src/op_mode/generate_ipsec_debug_archive.py +++ b/src/op_mode/generate_ipsec_debug_archive.py @@ -20,7 +20,7 @@ from shutil import rmtree from socket import gethostname from sys import exit from tarfile import open as tar_open -from vyos.util import rc_cmd +from vyos.utils.process import rc_cmd # define a list of commands that needs to be executed CMD_LIST: list[str] = [ diff --git a/src/op_mode/generate_openconnect_otp_key.py b/src/op_mode/generate_openconnect_otp_key.py index 363bcf3ea..99b67d261 100755 --- a/src/op_mode/generate_openconnect_otp_key.py +++ b/src/op_mode/generate_openconnect_otp_key.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2022 VyOS maintainers and contributors +# Copyright (C) 2022-2023 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 @@ -17,7 +17,7 @@ import argparse import os -from vyos.util import popen +from vyos.utils.process import popen from secrets import token_hex from base64 import b32encode diff --git a/src/op_mode/generate_ovpn_client_file.py b/src/op_mode/generate_ovpn_client_file.py index 0628e6135..cec370a07 100755 --- a/src/op_mode/generate_ovpn_client_file.py +++ b/src/op_mode/generate_ovpn_client_file.py @@ -22,7 +22,7 @@ from textwrap import fill from vyos.configquery import ConfigTreeQuery from vyos.ifconfig import Section -from vyos.util import cmd +from vyos.utils.process import cmd client_config = """ diff --git a/src/op_mode/generate_ssh_server_key.py b/src/op_mode/generate_ssh_server_key.py index 43e94048d..d6063c43c 100755 --- a/src/op_mode/generate_ssh_server_key.py +++ b/src/op_mode/generate_ssh_server_key.py @@ -15,9 +15,9 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. from sys import exit -from vyos.util import ask_yes_no -from vyos.util import cmd -from vyos.util import commit_in_progress +from vyos.utils.io import ask_yes_no +from vyos.utils.process import cmd +from vyos.utils.commit import commit_in_progress if not ask_yes_no('Do you really want to remove the existing SSH host keys?'): exit(0) diff --git a/src/op_mode/generate_system_login_user.py b/src/op_mode/generate_system_login_user.py index 8f8827b1b..1b328eae0 100755 --- a/src/op_mode/generate_system_login_user.py +++ b/src/op_mode/generate_system_login_user.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2022 VyOS maintainers and contributors +# Copyright (C) 2022-2023 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 @@ -17,7 +17,7 @@ import argparse import os -from vyos.util import popen +from vyos.utils.process import popen from secrets import token_hex from base64 import b32encode diff --git a/src/op_mode/igmp-proxy.py b/src/op_mode/igmp-proxy.py index 0086c9aa6..709e25915 100755 --- a/src/op_mode/igmp-proxy.py +++ b/src/op_mode/igmp-proxy.py @@ -28,16 +28,14 @@ import tabulate import vyos.config import vyos.opmode -from vyos.util import bytes_to_human, print_error +from vyos.utils.convert import bytes_to_human +from vyos.utils.io import print_error +from vyos.utils.process import process_named_running def _is_configured(): """Check if IGMP proxy is configured""" return vyos.config.Config().exists_effective('protocols igmp-proxy') -def _is_running(): - """Check if IGMP proxy is currently running""" - return not vyos.util.run('ps -C igmpproxy') - def _kernel_to_ip(addr): """ Convert any given address from Linux kernel to a proper, IPv4 address @@ -84,7 +82,7 @@ def show_interface(raw: bool): if not _is_configured(): print_error('IGMP proxy is not configured.') sys.exit(0) -if not _is_running(): +if not process_named_running('igmpproxy'): print_error('IGMP proxy is not running.') sys.exit(0) diff --git a/src/op_mode/ikev2_profile_generator.py b/src/op_mode/ikev2_profile_generator.py index a22f04c45..5454cc0ce 100755 --- a/src/op_mode/ikev2_profile_generator.py +++ b/src/op_mode/ikev2_profile_generator.py @@ -24,7 +24,7 @@ from cryptography.x509.oid import NameOID from vyos.configquery import ConfigTreeQuery from vyos.pki import load_certificate from vyos.template import render_to_string -from vyos.util import ask_input +from vyos.utils.io import ask_input # Apple profiles only support one IKE/ESP encryption cipher and hash, whereas # VyOS comes with a multitude of different proposals for a connection. diff --git a/src/op_mode/interfaces.py b/src/op_mode/interfaces.py index f38b95a71..782e178c6 100755 --- a/src/op_mode/interfaces.py +++ b/src/op_mode/interfaces.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2022 VyOS maintainers and contributors +# Copyright (C) 2022-2023 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 @@ -28,7 +28,9 @@ import vyos.opmode from vyos.ifconfig import Section from vyos.ifconfig import Interface from vyos.ifconfig import VRRP -from vyos.util import cmd, rc_cmd, call +from vyos.utils.process import cmd +from vyos.utils.process import rc_cmd +from vyos.utils.process import call def catch_broken_pipe(func): def wrapped(*args, **kwargs): @@ -384,7 +386,7 @@ def _format_show_counters(data: list): rx_errors = entry.get('rx_over_errors') tx_errors = entry.get('tx_carrier_errors') data_entries.append([interface, rx_packets, rx_bytes, tx_packets, tx_bytes, rx_dropped, tx_dropped, rx_errors, tx_errors]) - + headers = ['Interface', 'Rx Packets', 'Rx Bytes', 'Tx Packets', 'Tx Bytes', 'Rx Dropped', 'Tx Dropped', 'Rx Errors', 'Tx Errors'] output = tabulate(data_entries, headers, numalign="left") print (output) diff --git a/src/op_mode/ipoe-control.py b/src/op_mode/ipoe-control.py index 7111498b2..0f33beca7 100755 --- a/src/op_mode/ipoe-control.py +++ b/src/op_mode/ipoe-control.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-2023 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 @@ -18,7 +18,8 @@ import sys import argparse from vyos.config import Config -from vyos.util import popen, run +from vyos.utils.process import popen +from vyos.utils.process import run cmd_dict = { 'cmd_base' : '/usr/bin/accel-cmd -p 2002 ', diff --git a/src/op_mode/ipsec.py b/src/op_mode/ipsec.py index 823bd039d..57d3cfed9 100755 --- a/src/op_mode/ipsec.py +++ b/src/op_mode/ipsec.py @@ -21,9 +21,9 @@ from hurry import filesize from re import split as re_split from tabulate import tabulate -from vyos.util import convert_data -from vyos.util import seconds_to_human -from vyos.util import cmd +from vyos.utils.convert import convert_data +from vyos.utils.convert import seconds_to_human +from vyos.utils.process import cmd from vyos.configquery import ConfigTreeQuery import vyos.opmode diff --git a/src/op_mode/lldp.py b/src/op_mode/lldp.py index 1a1b94783..c287b8fa6 100755 --- a/src/op_mode/lldp.py +++ b/src/op_mode/lldp.py @@ -22,8 +22,8 @@ import typing from tabulate import tabulate from vyos.configquery import ConfigTreeQuery -from vyos.util import cmd -from vyos.util import dict_search +from vyos.utils.process import cmd +from vyos.utils.dict import dict_search import vyos.opmode unconf_message = 'LLDP is not configured' diff --git a/src/op_mode/log.py b/src/op_mode/log.py index b0abd6191..797ba5a88 100755 --- a/src/op_mode/log.py +++ b/src/op_mode/log.py @@ -21,7 +21,7 @@ import typing from jinja2 import Template -from vyos.util import rc_cmd +from vyos.utils.process import rc_cmd import vyos.opmode diff --git a/src/op_mode/memory.py b/src/op_mode/memory.py index 7666de646..eb530035b 100755 --- a/src/op_mode/memory.py +++ b/src/op_mode/memory.py @@ -54,7 +54,7 @@ def _get_raw_data(): return mem_data def _get_formatted_output(mem): - from vyos.util import bytes_to_human + from vyos.utils.convert import bytes_to_human # For human-readable outputs, we convert bytes to more convenient units # (100M, 1.3G...) diff --git a/src/op_mode/nat.py b/src/op_mode/nat.py index c92795745..71a40c0e1 100755 --- a/src/op_mode/nat.py +++ b/src/op_mode/nat.py @@ -25,8 +25,8 @@ from tabulate import tabulate import vyos.opmode from vyos.configquery import ConfigTreeQuery -from vyos.util import cmd -from vyos.util import dict_search +from vyos.utils.process import cmd +from vyos.utils.dict import dict_search base = 'nat' unconf_message = 'NAT is not configured' diff --git a/src/op_mode/neighbor.py b/src/op_mode/neighbor.py index b329ea280..1edeb0045 100755 --- a/src/op_mode/neighbor.py +++ b/src/op_mode/neighbor.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2022 VyOS maintainers and contributors +# Copyright (C) 2022-2023 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 @@ -41,7 +41,7 @@ def interface_exists(interface): def get_raw_data(family, interface=None, state=None): from json import loads - from vyos.util import cmd + from vyos.utils.process import cmd if interface: if not interface_exists(interface): @@ -102,7 +102,7 @@ def show(raw: bool, family: ArgFamily, interface: typing.Optional[str], return format_neighbors(data, interface) def reset(family: ArgFamily, interface: typing.Optional[str], address: typing.Optional[str]): - from vyos.util import run + from vyos.utils.process import run if address and interface: raise ValueError("interface and address parameters are mutually exclusive") @@ -114,7 +114,6 @@ def reset(family: ArgFamily, interface: typing.Optional[str], address: typing.Op # Flush an entire neighbor table run(f"""ip --family {family} neighbor flush""") - if __name__ == '__main__': try: res = vyos.opmode.run(sys.modules[__name__]) diff --git a/src/op_mode/nhrp.py b/src/op_mode/nhrp.py index 5ff91a59c..e66f33079 100755 --- a/src/op_mode/nhrp.py +++ b/src/op_mode/nhrp.py @@ -18,9 +18,9 @@ import sys import tabulate import vyos.opmode -from vyos.util import cmd -from vyos.util import process_named_running -from vyos.util import colon_separated_to_dict +from vyos.utils.process import cmd +from vyos.utils.process import process_named_running +from vyos.utils.dict import colon_separated_to_dict def _get_formatted_output(output_dict: dict) -> str: diff --git a/src/op_mode/openconnect-control.py b/src/op_mode/openconnect-control.py index 20c50e779..b70d4fa16 100755 --- a/src/op_mode/openconnect-control.py +++ b/src/op_mode/openconnect-control.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-2023 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 @@ -18,12 +18,13 @@ import sys import argparse import json -from vyos.config import Config -from vyos.util import popen -from vyos.util import run -from vyos.util import DEVNULL from tabulate import tabulate +from vyos.config import Config +from vyos.utils.process import popen +from vyos.utils.process import run +from vyos.utils.process import DEVNULL + occtl = '/usr/bin/occtl' occtl_socket = '/run/ocserv/occtl.socket' diff --git a/src/op_mode/openconnect.py b/src/op_mode/openconnect.py index b21890728..cfa0678a7 100755 --- a/src/op_mode/openconnect.py +++ b/src/op_mode/openconnect.py @@ -19,7 +19,7 @@ import json from tabulate import tabulate from vyos.configquery import ConfigTreeQuery -from vyos.util import rc_cmd +from vyos.utils.process import rc_cmd import vyos.opmode diff --git a/src/op_mode/openvpn.py b/src/op_mode/openvpn.py index d9ae965c5..fd9d2db92 100755 --- a/src/op_mode/openvpn.py +++ b/src/op_mode/openvpn.py @@ -23,10 +23,10 @@ import typing from tabulate import tabulate import vyos.opmode -from vyos.util import bytes_to_human -from vyos.util import commit_in_progress -from vyos.util import call -from vyos.util import rc_cmd +from vyos.utils.convert import bytes_to_human +from vyos.utils.commit import commit_in_progress +from vyos.utils.process import call +from vyos.utils.process import rc_cmd from vyos.config import Config ArgMode = typing.Literal['client', 'server', 'site_to_site'] diff --git a/src/op_mode/ping.py b/src/op_mode/ping.py index 610e63cb3..f1d87a118 100755 --- a/src/op_mode/ping.py +++ b/src/op_mode/ping.py @@ -18,7 +18,7 @@ import os import sys import socket import ipaddress -from vyos.util import get_all_vrfs +from vyos.utils.network import get_all_vrfs from vyos.ifconfig import Section @@ -90,6 +90,16 @@ options = { 'type': '<seconds>', 'help': 'Number of seconds to wait between requests' }, + 'ipv4': { + 'ping': '{command} -4', + 'type': 'noarg', + 'help': 'Use IPv4 only' + }, + 'ipv6': { + 'ping': '{command} -6', + 'type': 'noarg', + 'help': 'Use IPv6 only' + }, 'mark': { 'ping': '{command} -m {value}', 'type': '<fwmark>', diff --git a/src/op_mode/pki.py b/src/op_mode/pki.py index b054690b0..4c31291ad 100755 --- a/src/op_mode/pki.py +++ b/src/op_mode/pki.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-2023 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 @@ -34,10 +34,11 @@ from vyos.pki import create_dh_parameters from vyos.pki import load_certificate, load_certificate_request, load_private_key from vyos.pki import load_crl, load_dh_parameters, load_public_key from vyos.pki import verify_certificate +from vyos.utils.io import ask_input +from vyos.utils.io import ask_yes_no +from vyos.utils.misc import install_into_config +from vyos.utils.process import cmd from vyos.xml import defaults -from vyos.util import ask_input, ask_yes_no -from vyos.util import cmd -from vyos.util import install_into_config CERT_REQ_END = '-----END CERTIFICATE REQUEST-----' auth_dir = '/config/auth' @@ -190,7 +191,7 @@ def install_ssh_key(name, public_key, private_key, passphrase=None): def install_keypair(name, key_type, private_key=None, public_key=None, passphrase=None, prompt=True): # Show/install conf commands for key-pair - + config_paths = [] if public_key: @@ -840,7 +841,7 @@ def import_openvpn_secret(name, path): install_openvpn_key(name, key_data, key_version) # Show functions -def show_certificate_authority(name=None): +def show_certificate_authority(name=None, pem=False): headers = ['Name', 'Subject', 'Issuer CN', 'Issued', 'Expiry', 'Private Key', 'Parent'] data = [] certs = get_config_ca_certificate() @@ -852,6 +853,11 @@ def show_certificate_authority(name=None): continue cert = load_certificate(cert_dict['certificate']) + + if name and pem: + print(encode_certificate(cert)) + return + parent_ca_name = get_certificate_ca(cert, certs) cert_issuer_cn = cert.issuer.rfc4514_string().split(",")[0] @@ -867,7 +873,7 @@ def show_certificate_authority(name=None): print("Certificate Authorities:") print(tabulate.tabulate(data, headers)) -def show_certificate(name=None): +def show_certificate(name=None, pem=False): headers = ['Name', 'Type', 'Subject CN', 'Issuer CN', 'Issued', 'Expiry', 'Revoked', 'Private Key', 'CA Present'] data = [] certs = get_config_certificate() @@ -885,6 +891,10 @@ def show_certificate(name=None): if not cert: continue + if name and pem: + print(encode_certificate(cert)) + return + ca_name = get_certificate_ca(cert, ca_certs) cert_subject_cn = cert.subject.rfc4514_string().split(",")[0] cert_issuer_cn = cert.issuer.rfc4514_string().split(",")[0] @@ -906,7 +916,7 @@ def show_certificate(name=None): print("Certificates:") print(tabulate.tabulate(data, headers)) -def show_crl(name=None): +def show_crl(name=None, pem=False): headers = ['CA Name', 'Updated', 'Revokes'] data = [] certs = get_config_ca_certificate() @@ -927,9 +937,16 @@ def show_crl(name=None): if not crl: continue + if name and pem: + print(encode_certificate(crl)) + continue + certs = get_revoked_by_serial_numbers([revoked.serial_number for revoked in crl]) data.append([cert_name, crl.last_update, ", ".join(certs)]) + if name and pem: + return + print("Certificate Revocation Lists:") print(tabulate.tabulate(data, headers)) @@ -943,6 +960,7 @@ if __name__ == '__main__': parser.add_argument('--crl', help='Certificate Revocation List', required=False) parser.add_argument('--sign', help='Sign certificate with specified CA', required=False) parser.add_argument('--self-sign', help='Self-sign the certificate', action='store_true') + parser.add_argument('--pem', help='Output using PEM encoding', action='store_true') # SSH parser.add_argument('--ssh', help='SSH Key', required=False) @@ -1032,16 +1050,16 @@ if __name__ == '__main__': if not conf.exists(['pki', 'ca', ca_name]): print(f'CA "{ca_name}" does not exist!') exit(1) - show_certificate_authority(ca_name) + show_certificate_authority(ca_name, args.pem) elif args.certificate: cert_name = None if args.certificate == 'all' else args.certificate if cert_name: if not conf.exists(['pki', 'certificate', cert_name]): print(f'Certificate "{cert_name}" does not exist!') exit(1) - show_certificate(None if args.certificate == 'all' else args.certificate) + show_certificate(None if args.certificate == 'all' else args.certificate, args.pem) elif args.crl: - show_crl(None if args.crl == 'all' else args.crl) + show_crl(None if args.crl == 'all' else args.crl, args.pem) else: show_certificate_authority() show_certificate() diff --git a/src/op_mode/policy_route.py b/src/op_mode/policy_route.py index fae47adec..eff99de7f 100755 --- a/src/op_mode/policy_route.py +++ b/src/op_mode/policy_route.py @@ -19,8 +19,8 @@ import re import tabulate from vyos.config import Config -from vyos.util import cmd -from vyos.util import dict_search_args +from vyos.utils.process import cmd +from vyos.utils.dict import dict_search_args def get_config_policy(conf, name=None, ipv6=False): config_path = ['policy'] diff --git a/src/op_mode/powerctrl.py b/src/op_mode/powerctrl.py index dfacd45c2..3ac5991b4 100755 --- a/src/op_mode/powerctrl.py +++ b/src/op_mode/powerctrl.py @@ -22,7 +22,11 @@ from datetime import datetime, timedelta, time as type_time, date as type_date from sys import exit from time import time -from vyos.util import ask_yes_no, cmd, call, run, STDOUT +from vyos.utils.io import ask_yes_no +from vyos.utils.process import call +from vyos.utils.process import cmd +from vyos.utils.process import run +from vyos.utils.process import STDOUT systemd_sched_file = "/run/systemd/shutdown/scheduled" @@ -104,7 +108,7 @@ def cancel_shutdown(): def check_unsaved_config(): from vyos.config_mgmt import unsaved_commits - from vyos.util import boot_configuration_success + from vyos.utils.boot import boot_configuration_success if unsaved_commits() and boot_configuration_success(): print("Warning: there are unsaved configuration changes!") diff --git a/src/op_mode/ppp-server-ctrl.py b/src/op_mode/ppp-server-ctrl.py index e93963fdd..2bae5b32a 100755 --- a/src/op_mode/ppp-server-ctrl.py +++ b/src/op_mode/ppp-server-ctrl.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019 VyOS maintainers and contributors +# Copyright (C) 2019-2023 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 @@ -18,7 +18,8 @@ import sys import argparse from vyos.config import Config -from vyos.util import popen, DEVNULL +from vyos.utils.process import popen +from vyos.utils.process import DEVNULL cmd_dict = { 'cmd_base' : '/usr/bin/accel-cmd -p {} ', diff --git a/src/op_mode/reset_openvpn.py b/src/op_mode/reset_openvpn.py index efbf65083..cef5299da 100755 --- a/src/op_mode/reset_openvpn.py +++ b/src/op_mode/reset_openvpn.py @@ -16,8 +16,8 @@ import os from sys import argv, exit -from vyos.util import call -from vyos.util import commit_in_progress +from vyos.utils.process import call +from vyos.utils.commit import commit_in_progress if __name__ == '__main__': if (len(argv) < 1): diff --git a/src/op_mode/reset_vpn.py b/src/op_mode/reset_vpn.py index 46195d6cd..61d7c8c81 100755 --- a/src/op_mode/reset_vpn.py +++ b/src/op_mode/reset_vpn.py @@ -13,10 +13,11 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. + import sys import typing -from vyos.util import run +from vyos.utils.process import run import vyos.opmode @@ -29,7 +30,6 @@ cmd_dict = { } } - def reset_conn(protocol: str, username: typing.Optional[str] = None, interface: typing.Optional[str] = None): if protocol in cmd_dict['vpn_types']: diff --git a/src/op_mode/restart_dhcp_relay.py b/src/op_mode/restart_dhcp_relay.py index 9203c009f..3ead97f4c 100755 --- a/src/op_mode/restart_dhcp_relay.py +++ b/src/op_mode/restart_dhcp_relay.py @@ -23,8 +23,8 @@ import argparse import os import vyos.config -from vyos.util import call -from vyos.util import commit_in_progress +from vyos.utils.process import call +from vyos.utils.commit import commit_in_progress parser = argparse.ArgumentParser() diff --git a/src/op_mode/restart_frr.py b/src/op_mode/restart_frr.py index 680d9f8cc..5cce377eb 100755 --- a/src/op_mode/restart_frr.py +++ b/src/op_mode/restart_frr.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2021 VyOS maintainers and contributors +# Copyright (C) 2019-2023 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 @@ -23,10 +23,10 @@ from logging.handlers import SysLogHandler from shutil import rmtree from vyos.base import Warning -from vyos.util import call -from vyos.util import ask_yes_no -from vyos.util import process_named_running -from vyos.util import makedir +from vyos.utils.io import ask_yes_no +from vyos.utils.file import makedir +from vyos.utils.process import call +from vyos.utils.process import process_named_running # some default values watchfrr = '/usr/lib/frr/watchfrr.sh' diff --git a/src/op_mode/route.py b/src/op_mode/route.py index d6d6b7d6f..4aa57dbf4 100755 --- a/src/op_mode/route.py +++ b/src/op_mode/route.py @@ -57,7 +57,7 @@ frr_command_template = Template(""" ArgFamily = typing.Literal['inet', 'inet6'] def show_summary(raw: bool, family: ArgFamily, table: typing.Optional[int], vrf: typing.Optional[str]): - from vyos.util import cmd + from vyos.utils.process import cmd if family == 'inet': family_cmd = 'ip' @@ -119,7 +119,7 @@ def show(raw: bool, frr_command = frr_command_template.render(kwargs) frr_command = re.sub(r'\s+', ' ', frr_command) - from vyos.util import cmd + from vyos.utils.process import cmd output = cmd(f"vtysh -c '{frr_command}'") if raw: diff --git a/src/op_mode/sflow.py b/src/op_mode/sflow.py index 88f70d6bd..dca7f44cb 100755 --- a/src/op_mode/sflow.py +++ b/src/op_mode/sflow.py @@ -20,7 +20,7 @@ import sys from tabulate import tabulate from vyos.configquery import ConfigTreeQuery -from vyos.util import cmd +from vyos.utils.process import cmd import vyos.opmode diff --git a/src/op_mode/show-bond.py b/src/op_mode/show-bond.py index edf7847fc..f676e0841 100755 --- a/src/op_mode/show-bond.py +++ b/src/op_mode/show-bond.py @@ -19,7 +19,7 @@ import jinja2 from argparse import ArgumentParser from vyos.ifconfig import Section from vyos.ifconfig import BondIf -from vyos.util import read_file +from vyos.utils.file import read_file from sys import exit diff --git a/src/op_mode/show_acceleration.py b/src/op_mode/show_acceleration.py index 48c31d4d9..1c4831f1d 100755 --- a/src/op_mode/show_acceleration.py +++ b/src/op_mode/show_acceleration.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2022 VyOS maintainers and contributors +# Copyright (C) 2019-2023 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 @@ -20,8 +20,8 @@ import re import argparse from vyos.config import Config -from vyos.util import popen -from vyos.util import call +from vyos.utils.process import call +from vyos.utils.process import popen def detect_qat_dev(): output, err = popen('lspci -nn', decode='utf-8') diff --git a/src/op_mode/show_ntp.sh b/src/op_mode/show_ntp.sh index 85f8eda15..4b59b801e 100755 --- a/src/op_mode/show_ntp.sh +++ b/src/op_mode/show_ntp.sh @@ -18,7 +18,7 @@ if ! ps -C chronyd &>/dev/null; then fi PID=$(pgrep chronyd | head -n1) -VRF_NAME=$(ip vrf identify ) +VRF_NAME=$(ip vrf identify ${PID}) if [ ! -z ${VRF_NAME} ]; then VRF_CMD="sudo ip vrf exec ${VRF_NAME}" diff --git a/src/op_mode/show_openconnect_otp.py b/src/op_mode/show_openconnect_otp.py index 88982c50b..415a5f72c 100755 --- a/src/op_mode/show_openconnect_otp.py +++ b/src/op_mode/show_openconnect_otp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright 2017, 2022 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2017-2023 VyOS maintainers and contributors <maintainers@vyos.io> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -21,7 +21,7 @@ import os from vyos.config import Config from vyos.xml import defaults from vyos.configdict import dict_merge -from vyos.util import popen +from vyos.utils.process import popen from base64 import b32encode otp_file = '/run/ocserv/users.oath' diff --git a/src/op_mode/show_openvpn_mfa.py b/src/op_mode/show_openvpn_mfa.py index 1ab54600c..100c42154 100755 --- a/src/op_mode/show_openvpn_mfa.py +++ b/src/op_mode/show_openvpn_mfa.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 - -# Copyright 2017, 2021 VyOS maintainers and contributors <maintainers@vyos.io> +# +# Copyright 2017-2023 VyOS maintainers and contributors <maintainers@vyos.io> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -20,7 +20,7 @@ import socket import urllib.parse import argparse -from vyos.util import popen +from vyos.utils.process import popen otp_file = '/config/auth/openvpn/{interface}-otp-secrets' diff --git a/src/op_mode/show_sensors.py b/src/op_mode/show_sensors.py index 6ae477647..5e3084fe9 100755 --- a/src/op_mode/show_sensors.py +++ b/src/op_mode/show_sensors.py @@ -1,9 +1,25 @@ #!/usr/bin/env python3 +# +# Copyright 2017-2023 VyOS maintainers and contributors <maintainers@vyos.io> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library. If not, see <http://www.gnu.org/licenses/>. import re import sys -from vyos.util import popen -from vyos.util import DEVNULL +from vyos.utils.process import popen +from vyos.utils.process import DEVNULL + output,retcode = popen("sensors --no-adapter", stderr=DEVNULL) if retcode == 0: print (output) @@ -23,5 +39,3 @@ else: print ("No sensors found") sys.exit(1) - - diff --git a/src/op_mode/show_techsupport_report.py b/src/op_mode/show_techsupport_report.py index 782004144..d27221e54 100644 --- a/src/op_mode/show_techsupport_report.py +++ b/src/op_mode/show_techsupport_report.py @@ -17,7 +17,7 @@ import os from typing import List -from vyos.util import rc_cmd +from vyos.utils.process import rc_cmd from vyos.ifconfig import Section from vyos.ifconfig import Interface diff --git a/src/op_mode/show_virtual_server.py b/src/op_mode/show_virtual_server.py index 377180dec..7880edc97 100755 --- a/src/op_mode/show_virtual_server.py +++ b/src/op_mode/show_virtual_server.py @@ -15,7 +15,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. from vyos.configquery import ConfigTreeQuery -from vyos.util import call +from vyos.utils.process import call def is_configured(): """ Check if high-availability virtual-server is configured """ diff --git a/src/op_mode/show_wireless.py b/src/op_mode/show_wireless.py index 19ab6771c..340163057 100755 --- a/src/op_mode/show_wireless.py +++ b/src/op_mode/show_wireless.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019 VyOS maintainers and contributors +# Copyright (C) 2019-2023 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 @@ -21,7 +21,7 @@ from sys import exit from copy import deepcopy from vyos.config import Config -from vyos.util import popen +from vyos.utils.process import popen parser = argparse.ArgumentParser() parser.add_argument("-s", "--scan", help="Scan for Wireless APs on given interface, e.g. 'wlan0'") diff --git a/src/op_mode/show_wwan.py b/src/op_mode/show_wwan.py index eb601a456..bd97bb0e5 100755 --- a/src/op_mode/show_wwan.py +++ b/src/op_mode/show_wwan.py @@ -18,7 +18,7 @@ import argparse from sys import exit from vyos.configquery import ConfigTreeQuery -from vyos.util import cmd +from vyos.utils.process import cmd parser = argparse.ArgumentParser() parser.add_argument("--model", help="Get module model", action="store_true") diff --git a/src/op_mode/snmp.py b/src/op_mode/snmp.py index 5fae67881..43f5d9e0a 100755 --- a/src/op_mode/snmp.py +++ b/src/op_mode/snmp.py @@ -24,7 +24,7 @@ import sys import argparse from vyos.config import Config -from vyos.util import call +from vyos.utils.process import call config_file_daemon = r'/etc/snmp/snmpd.conf' diff --git a/src/op_mode/snmp_ifmib.py b/src/op_mode/snmp_ifmib.py index 2479936bd..c71febac9 100755 --- a/src/op_mode/snmp_ifmib.py +++ b/src/op_mode/snmp_ifmib.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018 VyOS maintainers and contributors +# Copyright (C) 2018-2023 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 @@ -24,7 +24,7 @@ import argparse import netifaces from vyos.config import Config -from vyos.util import popen +from vyos.utils.process import popen parser = argparse.ArgumentParser(description='Retrieve SNMP interfaces information') parser.add_argument('--ifindex', action='store', nargs='?', const='all', help='Show interface index') diff --git a/src/op_mode/storage.py b/src/op_mode/storage.py index d16e271bd..6bc3d3a2d 100755 --- a/src/op_mode/storage.py +++ b/src/op_mode/storage.py @@ -18,7 +18,7 @@ import sys import vyos.opmode -from vyos.util import cmd +from vyos.utils.process import cmd # FIY: As of coreutils from Debian Buster and Bullseye, # the outpt looks like this: @@ -43,7 +43,7 @@ def _get_system_storage(only_persistent=False): def _get_raw_data(): from re import sub as re_sub - from vyos.util import human_to_bytes + from vyos.utils.convert import human_to_bytes out = _get_system_storage(only_persistent=True) lines = out.splitlines() diff --git a/src/op_mode/traceroute.py b/src/op_mode/traceroute.py index 6c7030ea0..2f0edf53a 100755 --- a/src/op_mode/traceroute.py +++ b/src/op_mode/traceroute.py @@ -18,7 +18,7 @@ import os import sys import socket import ipaddress -from vyos.util import get_all_vrfs +from vyos.utils.network import get_all_vrfs from vyos.ifconfig import Section diff --git a/src/op_mode/uptime.py b/src/op_mode/uptime.py index 2ebe6783b..d6adf6f4d 100755 --- a/src/op_mode/uptime.py +++ b/src/op_mode/uptime.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021-2022 VyOS maintainers and contributors +# Copyright (C) 2021-2023 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 as @@ -20,7 +20,7 @@ import vyos.opmode def _get_uptime_seconds(): from re import search - from vyos.util import read_file + from vyos.utils.file import read_file data = read_file("/proc/uptime") seconds = search("([0-9\.]+)\s", data).group(1) @@ -29,7 +29,7 @@ def _get_uptime_seconds(): def _get_load_averages(): from re import search - from vyos.util import cmd + from vyos.utils.process import cmd from vyos.cpu import get_core_count data = cmd("uptime") @@ -45,7 +45,7 @@ def _get_load_averages(): return res def _get_raw_data(): - from vyos.util import seconds_to_human + from vyos.utils.convert import seconds_to_human res = {} res["uptime_seconds"] = _get_uptime_seconds() diff --git a/src/op_mode/vpn_ike_sa.py b/src/op_mode/vpn_ike_sa.py index 4b44c5c15..069c12069 100755 --- a/src/op_mode/vpn_ike_sa.py +++ b/src/op_mode/vpn_ike_sa.py @@ -19,7 +19,7 @@ import re import sys import vici -from vyos.util import process_named_running +from vyos.utils.process import process_named_running ike_sa_peer_prefix = """\ Peer ID / IP Local ID / IP @@ -39,8 +39,6 @@ def ike_sa(peer, nat): peers = [] for conn in sas: for name, sa in conn.items(): - if peer and not name.startswith('peer_' + peer): - continue if name.startswith('peer_') and name in peers: continue if nat and 'nat-local' not in sa: @@ -70,7 +68,7 @@ if __name__ == '__main__': args = parser.parse_args() - if not process_named_running('charon'): + if not process_named_running('charon-systemd'): print("IPsec Process NOT Running") sys.exit(0) diff --git a/src/op_mode/vpn_ipsec.py b/src/op_mode/vpn_ipsec.py index b81d1693e..ef89e605f 100755 --- a/src/op_mode/vpn_ipsec.py +++ b/src/op_mode/vpn_ipsec.py @@ -17,7 +17,7 @@ import re import argparse -from vyos.util import call +from vyos.utils.process import call SWANCTL_CONF = '/etc/swanctl/swanctl.conf' diff --git a/src/op_mode/vrf.py b/src/op_mode/vrf.py index a9a416761..1f0bbbaeb 100755 --- a/src/op_mode/vrf.py +++ b/src/op_mode/vrf.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2022 VyOS maintainers and contributors +# Copyright (C) 2022-2023 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 @@ -20,7 +20,7 @@ import sys import typing from tabulate import tabulate -from vyos.util import cmd +from vyos.utils.process import cmd import vyos.opmode diff --git a/src/op_mode/vrrp.py b/src/op_mode/vrrp.py index dab146d28..b3ab55cc3 100755 --- a/src/op_mode/vrrp.py +++ b/src/op_mode/vrrp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2022 VyOS maintainers and contributors +# Copyright (C) 2018-2023 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 @@ -13,7 +13,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -# import sys import time @@ -21,12 +20,10 @@ import argparse import json import tabulate -import vyos.util - from vyos.configquery import ConfigTreeQuery from vyos.ifconfig.vrrp import VRRP -from vyos.ifconfig.vrrp import VRRPError, VRRPNoData - +from vyos.ifconfig.vrrp import VRRPError +from vyos.ifconfig.vrrp import VRRPNoData parser = argparse.ArgumentParser() group = parser.add_mutually_exclusive_group() @@ -44,7 +41,7 @@ def is_configured(): return True # Exit early if VRRP is dead or not configured -if is_configured() == False: +if is_configured() == False: print('VRRP not configured!') exit(0) if not VRRP.is_running(): diff --git a/src/op_mode/wireguard_client.py b/src/op_mode/wireguard_client.py index 76c1ff7d1..04d8ce28c 100755 --- a/src/op_mode/wireguard_client.py +++ b/src/op_mode/wireguard_client.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-2023 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 @@ -23,8 +23,8 @@ from ipaddress import ip_interface from vyos.ifconfig import Section from vyos.template import is_ipv4 from vyos.template import is_ipv6 -from vyos.util import cmd -from vyos.util import popen +from vyos.utils.process import cmd +from vyos.utils.process import popen if os.geteuid() != 0: exit("You need to have root privileges to run this script.\nPlease try again, this time using 'sudo'. Exiting.") diff --git a/src/op_mode/zone.py b/src/op_mode/zone.py index f326215b1..17ce90396 100755 --- a/src/op_mode/zone.py +++ b/src/op_mode/zone.py @@ -19,8 +19,8 @@ import vyos.opmode import tabulate from vyos.configquery import ConfigTreeQuery -from vyos.util import dict_search_args -from vyos.util import dict_search +from vyos.utils.dict import dict_search_args +from vyos.utils.dict import dict_search def get_config_zone(conf, name=None): diff --git a/src/services/api/graphql/generate/schema_from_op_mode.py b/src/services/api/graphql/generate/schema_from_op_mode.py index 229ccf90f..ab7cb691f 100755 --- a/src/services/api/graphql/generate/schema_from_op_mode.py +++ b/src/services/api/graphql/generate/schema_from_op_mode.py @@ -27,7 +27,7 @@ from jinja2 import Template from vyos.defaults import directories from vyos.opmode import _is_op_mode_function_name as is_op_mode_function_name from vyos.opmode import _get_literal_values as get_literal_values -from vyos.util import load_as_module +from vyos.utils.system import load_as_module if __package__ is None or __package__ == '': sys.path.append(os.path.join(directories['services'], 'api')) from graphql.libs.op_mode import is_show_function_name diff --git a/src/services/api/graphql/libs/op_mode.py b/src/services/api/graphql/libs/op_mode.py index e91d8bd0f..5022f7d4e 100644 --- a/src/services/api/graphql/libs/op_mode.py +++ b/src/services/api/graphql/libs/op_mode.py @@ -20,7 +20,7 @@ from typing import Union, Tuple, Optional from humps import decamelize from vyos.defaults import directories -from vyos.util import load_as_module +from vyos.utils.system import load_as_module from vyos.opmode import _normalize_field_names from vyos.opmode import _is_literal_type, _get_literal_values diff --git a/src/services/vyos-configd b/src/services/vyos-configd index 48c9135e2..355182b26 100755 --- a/src/services/vyos-configd +++ b/src/services/vyos-configd @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-2023 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 @@ -13,8 +13,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# import os import sys @@ -28,8 +26,9 @@ import zmq from contextlib import contextmanager from vyos.defaults import directories -from vyos.util import boot_configuration_complete -from vyos.configsource import ConfigSourceString, ConfigSourceError +from vyos.utils.boot import boot_configuration_complete +from vyos.configsource import ConfigSourceString +from vyos.configsource import ConfigSourceError from vyos.config import Config from vyos import ConfigError diff --git a/src/services/vyos-hostsd b/src/services/vyos-hostsd index 894f9e24d..e34a4b740 100755 --- a/src/services/vyos-hostsd +++ b/src/services/vyos-hostsd @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2020 VyOS maintainers and contributors +# Copyright (C) 2019-2023 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 @@ -241,9 +241,14 @@ import traceback import re import logging import zmq + from voluptuous import Schema, MultipleInvalid, Required, Any from collections import OrderedDict -from vyos.util import popen, chown, chmod_755, makedir, process_named_running +from vyos.utils.file import makedir +from vyos.utils.permission import chown +from vyos.utils.permission import chmod_755 +from vyos.utils.process import popen +from vyos.utils.process import process_named_running from vyos.template import render debug = True diff --git a/src/system/keepalived-fifo.py b/src/system/keepalived-fifo.py index 864ee8419..5e19bdbad 100755 --- a/src/system/keepalived-fifo.py +++ b/src/system/keepalived-fifo.py @@ -28,9 +28,9 @@ from logging.handlers import SysLogHandler from vyos.ifconfig.vrrp import VRRP from vyos.configquery import ConfigTreeQuery -from vyos.util import cmd -from vyos.util import dict_search -from vyos.util import commit_in_progress +from vyos.utils.process import cmd +from vyos.utils.dict import dict_search +from vyos.utils.commit import commit_in_progress # configure logging logger = logging.getLogger(__name__) diff --git a/src/system/vyos-event-handler.py b/src/system/vyos-event-handler.py index 1c85380bc..74112ec91 100755 --- a/src/system/vyos-event-handler.py +++ b/src/system/vyos-event-handler.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2022 VyOS maintainers and contributors +# Copyright (C) 2022-2023 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 @@ -18,6 +18,7 @@ import argparse import json import re import select + from copy import deepcopy from os import getpid, environ from pathlib import Path @@ -25,13 +26,13 @@ from signal import signal, SIGTERM, SIGINT from sys import exit from systemd import journal -from vyos.util import run, dict_search +from vyos.utils.dict import dict_search +from vyos.utils.process import run # Identify this script my_pid = getpid() my_name = Path(__file__).stem - # handle termination signal def handle_signal(signal_type, frame): if signal_type == SIGTERM: diff --git a/src/system/vyos-system-update-check.py b/src/system/vyos-system-update-check.py index c9597721b..c874f1e2c 100755 --- a/src/system/vyos-system-update-check.py +++ b/src/system/vyos-system-update-check.py @@ -22,7 +22,7 @@ from pathlib import Path from sys import exit from time import sleep -from vyos.util import call +from vyos.utils.process import call import vyos.version diff --git a/src/systemd/vyos-router.service b/src/systemd/vyos-router.service new file mode 100644 index 000000000..6f683cebb --- /dev/null +++ b/src/systemd/vyos-router.service @@ -0,0 +1,19 @@ +[Unit] +Description=VyOS Router +After=systemd-journald-dev-log.socket time-sync.target local-fs.target cloud-config.service +Requires=frr.service +Conflicts=shutdown.target +Before=systemd-user-sessions.service + +[Service] +Type=simple +Restart=no +TimeoutSec=20min +KillMode=process +RemainAfterExit=yes +ExecStart=/usr/libexec/vyos/init/vyos-router start +ExecStop=/usr/libexec/vyos/init/vyos-router stop +StandardOutput=journal+console + +[Install] +WantedBy=vyos.target diff --git a/src/systemd/vyos.target b/src/systemd/vyos.target new file mode 100644 index 000000000..47c91c1cc --- /dev/null +++ b/src/systemd/vyos.target @@ -0,0 +1,3 @@ +[Unit] +Description=VyOS target +After=multi-user.target diff --git a/src/tests/test_configverify.py b/src/tests/test_configverify.py index 6fb43ece2..15ccdf13d 100644 --- a/src/tests/test_configverify.py +++ b/src/tests/test_configverify.py @@ -16,7 +16,7 @@ from unittest import TestCase from vyos.configverify import verify_diffie_hellman_length -from vyos.util import cmd +from vyos.utils.process import cmd dh_file = '/tmp/dh.pem' diff --git a/src/tests/test_dict_search.py b/src/tests/test_dict_search.py index 1028437b2..2435d89c7 100644 --- a/src/tests/test_dict_search.py +++ b/src/tests/test_dict_search.py @@ -15,8 +15,8 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. from unittest import TestCase -from vyos.util import dict_search -from vyos.util import dict_search_recursive +from vyos.utils.dict import dict_search +from vyos.utils.dict import dict_search_recursive data = { 'string': 'fooo', diff --git a/src/tests/test_find_device_file.py b/src/tests/test_find_device_file.py index 43c80dc76..f18043d65 100755 --- a/src/tests/test_find_device_file.py +++ b/src/tests/test_find_device_file.py @@ -15,7 +15,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. from unittest import TestCase -from vyos.util import find_device_file +from vyos.utils.system import find_device_file class TestDeviceFile(TestCase): """ used to find USB devices on target """ diff --git a/src/tests/test_util.py b/src/tests/test_util.py index 473052bef..27ee648d4 100644 --- a/src/tests/test_util.py +++ b/src/tests/test_util.py @@ -15,14 +15,15 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. from unittest import TestCase -from vyos.util import * class TestVyOSUtil(TestCase): - def test_key_mangline(self): + def test_key_mangling(self): + from vyos.utils.dict import mangle_dict_keys data = {"foo-bar": {"baz-quux": None}} expected_data = {"foo_bar": {"baz_quux": None}} new_data = mangle_dict_keys(data, '-', '_') self.assertEqual(new_data, expected_data) def test_sysctl_read(self): + from vyos.utils.system import sysctl_read self.assertEqual(sysctl_read('net.ipv4.conf.lo.forwarding'), '1') diff --git a/src/validators/port-multi b/src/validators/port-multi index bd6f0ef60..ed6ff6849 100755 --- a/src/validators/port-multi +++ b/src/validators/port-multi @@ -4,7 +4,7 @@ from sys import argv from sys import exit import re -from vyos.util import read_file +from vyos.utils.file import read_file services_file = '/etc/services' diff --git a/src/validators/port-range b/src/validators/port-range index 5468000a7..526c639ad 100755 --- a/src/validators/port-range +++ b/src/validators/port-range @@ -3,7 +3,7 @@ import sys import re -from vyos.util import read_file +from vyos.utils.file import read_file services_file = '/etc/services' diff --git a/src/validators/script b/src/validators/script index 4ffdeb2a0..eb176d23b 100755 --- a/src/validators/script +++ b/src/validators/script @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2021 VyOS maintainers and contributors +# Copyright (C) 2018-2023 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 @@ -19,7 +19,7 @@ import os import sys import shlex -import vyos.util +from vyos.utils.file import file_is_persistent if __name__ == '__main__': if len(sys.argv) < 2: @@ -35,7 +35,7 @@ if __name__ == '__main__': sys.exit(f'File {script} is not an executable file') # File outside the config dir is just a warning - if not vyos.util.file_is_persistent(script): + if not file_is_persistent(script): sys.exit(0)( f'Warning: file {script} is outside the "/config" directory\n' 'It will not be automatically migrated to a new image on system update' diff --git a/src/validators/timezone b/src/validators/timezone index 107571181..e55af8d2a 100755 --- a/src/validators/timezone +++ b/src/validators/timezone @@ -17,7 +17,7 @@ import argparse import sys -from vyos.util import cmd +from vyos.utils.process import cmd if __name__ == '__main__': |