diff options
240 files changed, 1183 insertions, 846 deletions
diff --git a/.gitignore b/.gitignore index d781beead..7707e94ca 100644 --- a/.gitignore +++ b/.gitignore @@ -109,7 +109,6 @@ ENV/ templates-cfg/* templates-op/* tests/templates/* -xml_cache/* # Debian packaging debian/files diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3ff00df88..48cdbd5a7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,7 +21,7 @@ file(s) history by invoking git log path/to/file.txt. In a big system, such as VyOS, that is comprised of multiple components, it’s impossible to keep track of all the changes and bugs/feature requests in one’s -head. We use a bugtracker known as Phabricator for it (“issue tracker” would +head. We use a bugtracker named Phorge (formerly known Phabricator) for it (“issue tracker” would be a better term, but this one stuck). The information is used in three ways: @@ -35,14 +35,14 @@ The information is used in three ways: To make this approach work, every change must be associated with a task number (prefixed with **T**) and a component. If there is no bug report/feature -request for the changes you are going to make, you have to create a Phabricator -task first. Once there is an entry in Phabricator, you should reference its id +request for the changes you are going to make, you have to create a development portal +task first. Once there is an entry in the development portal, you should reference its id in your commit message, as shown below: * `ddclient: T1030: auto create runtime directories` * `Jenkins: add current Git commit ID to build description` -If there is no [Phabricator](https://vyos.dev) reference in the +If there is no [development portal](https://vyos.dev) reference in the commits of your pull request, we have to ask you to amend the commit message. Otherwise we will have to reject it. @@ -57,7 +57,7 @@ development environments. * A single, short, summary of the commit (recommended 50 characters or less, not exceeding 80 characters) containing a prefix of the changed component - and the corresponding Phabricator reference e.g. `snmp: T1111:` or + and the corresponding development portal reference e.g. `snmp: T1111:` or `ethernet: T2222:` - multiple components could be concatenated as in `snmp: ethernet: T3333` * In some contexts, the first line is treated as the subject of an email and @@ -126,7 +126,7 @@ also contain information that is helpful for the development team. ### Reporting In order to open up a bug-report/feature request you need to create yourself -an account on [Phabricator](https://vyos.dev). On the left +an account in the [development portal](https://vyos.dev). On the left side of the specific project (VyOS 1.2 or VyOS 1.3) you will find quick-links for opening a bug-report/feature request. @@ -141,7 +141,7 @@ for opening a bug-report/feature request. You have an idea of how to make VyOS better or you are in need of a specific feature which all users of VyOS would benefit from? To send a feature request -please search [Phabricator](https://vyos.dev) if there is already a +please search the [development portal](https://vyos.dev) if there is already a request pending. You can enhance it or if you don't find one, create a new one by use the quick link in the left side under the specific project. @@ -3,7 +3,6 @@ OP_TMPL_DIR := templates-op BUILD_DIR := build DATA_DIR := data SHIM_DIR := src/shim -CACHE_DIR := xml_cache LIBS := -lzmq CFLAGS := BUILD_ARCH := $(shell dpkg-architecture -q DEB_BUILD_ARCH) @@ -24,11 +23,10 @@ op_xml_obj = $(op_xml_src:.xml.in=.xml) .ONESHELL: interface_definitions: $(config_xml_obj) mkdir -p $(TMPL_DIR) - mkdir -p $(CACHE_DIR) $(CURDIR)/scripts/override-default $(BUILD_DIR)/interface-definitions - $(CURDIR)/python/vyos/xml_ref/generate_cache.py --xml-dir $(BUILD_DIR)/interface-definitions --package-name vyos-1x --output-path $(CACHE_DIR) + $(CURDIR)/python/vyos/xml_ref/generate_cache.py --xml-dir $(BUILD_DIR)/interface-definitions find $(BUILD_DIR)/interface-definitions -type f -name "*.xml" | xargs -I {} $(CURDIR)/scripts/build-command-templates {} $(CURDIR)/schema/interface_definition.rng $(TMPL_DIR) || exit 1 @@ -98,7 +96,6 @@ clean: rm -rf $(BUILD_DIR) rm -rf $(TMPL_DIR) rm -rf $(OP_TMPL_DIR) - rm -rf $(CACHE_DIR) $(MAKE) -C $(SHIM_DIR) clean .PHONY: test @@ -1,8 +1,5 @@ # vyos-1x: VyOS command definitions, configuration scripts, and data -[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=vyos_vyos-1x&metric=coverage)](https://sonarcloud.io/component_measures?id=vyos_vyos-1x&metric=coverage) -[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fvyos%2Fvyos-1x.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fvyos%2Fvyos-1x?ref=badge_shield) - VyOS 1.1.x had its codebase split into way too many submodules for no good reason, which made it hard to navigate or write meaningful changelogs. As the code undergoes rewrite in the new style in VyOS 1.2.0+, we consolidate the @@ -56,7 +53,7 @@ The guidelines in a nutshell: for the common structure * Use the `get_config_dict()` API as much as possible when retrieving values from the CLI * Use a template processor when the format is more complex than just one line - (Jinja2 and pystache are acceptable options) + (our standard is Jinja2) ## Tests @@ -74,5 +71,3 @@ Runtime tests are executed by the CI system on a running VyOS instance inside QEMU. The testcases can be found inside the smoketest subdirectory which will be placed into the vyos-1x-smoketest package. -## License -[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fvyos%2Fvyos-1x.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fvyos%2Fvyos-1x?ref=badge_large) diff --git a/data/templates/dhcp-client/daemon-options.j2 b/data/templates/dhcp-client/daemon-options.j2 deleted file mode 100644 index b21ad08ab..000000000 --- a/data/templates/dhcp-client/daemon-options.j2 +++ /dev/null @@ -1,4 +0,0 @@ -### Autogenerated by interface.py ### -{% set if_metric = '-e IF_METRIC=' ~ dhcp_options.default_route_distance if dhcp_options.default_route_distance is vyos_defined else '' %} -DHCLIENT_OPTS="-nw -cf /var/lib/dhcp/dhclient_{{ ifname }}.conf -pf /var/lib/dhcp/dhclient_{{ ifname }}.pid -lf /var/lib/dhcp/dhclient_{{ ifname }}.leases {{ if_metric }} {{ ifname }}" - diff --git a/data/templates/dhcp-client/dhcp6c_daemon-options.j2 b/data/templates/dhcp-client/dhcp6c_daemon-options.j2 deleted file mode 100644 index d33d418fc..000000000 --- a/data/templates/dhcp-client/dhcp6c_daemon-options.j2 +++ /dev/null @@ -1,2 +0,0 @@ -{% set no_release = '-n' if dhcpv6_options.no_release is vyos_defined else '' %} -DHCP6C_OPTS="-D -k /run/dhcp6c/dhcp6c.{{ ifname }}.sock -c /run/dhcp6c/dhcp6c.{{ ifname }}.conf -p /run/dhcp6c/dhcp6c.{{ ifname }}.pid {{ no_release }} {{ ifname }}" diff --git a/data/templates/dhcp-client/ipv6.override.conf.j2 b/data/templates/dhcp-client/ipv6.override.conf.j2 new file mode 100644 index 000000000..b0c0e0544 --- /dev/null +++ b/data/templates/dhcp-client/ipv6.override.conf.j2 @@ -0,0 +1,12 @@ +{% set vrf_command = 'ip vrf exec ' ~ vrf ~ ' ' if vrf is vyos_defined else '' %} +{% set no_release = '-n' if dhcpv6_options.no_release is vyos_defined else '' %} +{% set dhcp6c_options = '-D -k ' ~ dhcp6_client_dir ~ '/dhcp6c.' ~ ifname ~ '.sock -c ' ~ dhcp6_client_dir ~ '/dhcp6c.' ~ ifname ~ '.conf -p ' ~ dhcp6_client_dir ~ '/dhcp6c.' ~ ifname ~ '.pid ' ~ no_release %} + +[Unit] +ConditionPathExists={{ dhcp6_client_dir }}/dhcp6c.%i.conf + +[Service] +ExecStart= +ExecStart={{ vrf_command }}/usr/sbin/dhcp6c {{ dhcp6c_options }} {{ ifname }} +WorkingDirectory={{ dhcp6_client_dir }} +PIDFile={{ dhcp6_client_dir }}/dhcp6c.%i.pid diff --git a/data/templates/dhcp-client/override.conf.j2 b/data/templates/dhcp-client/override.conf.j2 new file mode 100644 index 000000000..03fd71bf1 --- /dev/null +++ b/data/templates/dhcp-client/override.conf.j2 @@ -0,0 +1,15 @@ +### Autogenerated by interface.py ### +{% set vrf_command = 'ip vrf exec ' ~ vrf ~ ' ' if vrf is vyos_defined else '' %} +{% set if_metric = '-e IF_METRIC=' ~ dhcp_options.default_route_distance if dhcp_options.default_route_distance is vyos_defined else '' %} +{% set dhclient_options = '-d -nw -cf ' ~ isc_dhclient_dir ~ '/dhclient_' ~ ifname ~ '.conf -pf ' ~ isc_dhclient_dir ~ '/dhclient_' ~ ifname ~ '.pid -lf ' ~ isc_dhclient_dir ~ '/dhclient_' ~ ifname ~ '.leases ' ~ if_metric %} + +[Unit] +ConditionPathExists={{ isc_dhclient_dir }}/dhclient_%i.conf + +[Service] +ExecStart= +ExecStart={{ vrf_command }}/sbin/dhclient -4 {{ dhclient_options }} {{ ifname }} +ExecStop= +ExecStop=/sbin/dhclient -4 -r {{ dhclient_options }} {{ ifname }} +WorkingDirectory={{ isc_dhclient_dir }} +PIDFile={{ isc_dhclient_dir }}/dhclient_%i.pid diff --git a/data/templates/dns-dynamic/ddclient.conf.j2 b/data/templates/dns-dynamic/ddclient.conf.j2 index 4da7153c7..3446a9d1b 100644 --- a/data/templates/dns-dynamic/ddclient.conf.j2 +++ b/data/templates/dns-dynamic/ddclient.conf.j2 @@ -23,7 +23,7 @@ if{{ ipv }}={{ address }}, \ {{ host }} {% endmacro %} ### Autogenerated by dns_dynamic.py ### -daemon=1m +daemon={{ timeout }} syslog=yes ssl=yes pid={{ config_file | replace('.conf', '.pid') }} diff --git a/data/templates/frr/bgpd.frr.j2 b/data/templates/frr/bgpd.frr.j2 index ddfba2306..4535758da 100644 --- a/data/templates/frr/bgpd.frr.j2 +++ b/data/templates/frr/bgpd.frr.j2 @@ -481,7 +481,7 @@ router bgp {{ system_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }} bgp bestpath compare-routerid {% endif %} {% if parameters.bestpath.med is vyos_defined %} - bgp bestpath med {{ 'confed' if parameters.bestpath.med.confed is vyos_defined }} {{ 'missing-as-worst' if parameters.bestpath.med.missing_as_worst is vyos_defined }} + bgp bestpath med {{ parameters.bestpath.med | join(' ') | replace('_', '-') }} {% endif %} {% if parameters.bestpath.peer_type is vyos_defined %} bgp bestpath peer-type {{ 'multipath-relax' if parameters.bestpath.peer_type.multipath_relax is vyos_defined }} diff --git a/data/templates/frr/daemons.frr.tmpl b/data/templates/frr/daemons.frr.tmpl index fdff9772a..3aad8e8dd 100644 --- a/data/templates/frr/daemons.frr.tmpl +++ b/data/templates/frr/daemons.frr.tmpl @@ -41,6 +41,7 @@ pimd_options=" --daemon -A 127.0.0.1" ldpd_options=" --daemon -A 127.0.0.1 {%- if snmp is defined and snmp.ldpd is defined %} -M snmp{% endif -%} " +mgmtd_options=" --daemon -A 127.0.0.1" nhrpd_options=" --daemon -A 127.0.0.1" eigrpd_options=" --daemon -A 127.0.0.1" babeld_options=" --daemon -A 127.0.0.1" diff --git a/debian/rules b/debian/rules index 39185f1e6..9ada2bf87 100755 --- a/debian/rules +++ b/debian/rules @@ -9,7 +9,6 @@ VYOS_CFG_TMPL_DIR := opt/vyatta/share/vyatta-cfg/templates VYOS_OP_TMPL_DIR := opt/vyatta/share/vyatta-op/templates VYOS_MIBS_DIR := usr/share/snmp/mibs VYOS_LOCALUI_DIR := srv/localui -VYOS_XML_CACHE_DIR := python/vyos/xml_ref/pkg_cache MIGRATION_SCRIPTS_DIR := opt/vyatta/etc/config-migrate/migrate SYSTEM_SCRIPTS_DIR := usr/libexec/vyos/system @@ -36,8 +35,6 @@ override_dh_auto_install: # convert the XML to dictionaries env PYTHONPATH=python python3 python/vyos/xml/generate.py - cp xml_cache/vyos_1x_cache.py python/vyos/xml_ref/pkg_cache - cd python; python3 setup.py install --install-layout=deb --root ../$(DIR); cd .. # Install scripts diff --git a/debian/vyos-1x.postinst b/debian/vyos-1x.postinst index b1bd23ff2..f3dc00b46 100644 --- a/debian/vyos-1x.postinst +++ b/debian/vyos-1x.postinst @@ -120,9 +120,24 @@ if ! grep -q '^dhcpd' /etc/passwd; then adduser --quiet dhcpd hostsd fi -# ensure hte proxy user has a proper shell +# ensure the proxy user has a proper shell chsh -s /bin/sh proxy +# create /opt/vyatta/etc/config/scripts/vyos-preconfig-bootup.script +PRECONFIG_SCRIPT=/opt/vyatta/etc/config/scripts/vyos-preconfig-bootup.script +if [ ! -x $PRECONFIG_SCRIPT ]; then + mkdir -p $(dirname $PRECONFIG_SCRIPT) + touch $PRECONFIG_SCRIPT + chmod 755 $PRECONFIG_SCRIPT + cat <<EOF >>$PRECONFIG_SCRIPT +#!/bin/sh +# This script is executed at boot time before VyOS configuration is applied. +# Any modifications required to work around unfixed bugs or use +# services not available through the VyOS CLI system can be placed here. + +EOF +fi + # create /opt/vyatta/etc/config/scripts/vyos-postconfig-bootup.script POSTCONFIG_SCRIPT=/opt/vyatta/etc/config/scripts/vyos-postconfig-bootup.script if [ ! -x $POSTCONFIG_SCRIPT ]; then diff --git a/interface-definitions/container.xml.in b/interface-definitions/container.xml.in index d36b34941..6d2eb18d0 100644 --- a/interface-definitions/container.xml.in +++ b/interface-definitions/container.xml.in @@ -3,7 +3,7 @@ <node name="container" owner="${vyos_conf_scripts_dir}/container.py"> <properties> <help>Container applications</help> - <priority>1280</priority> + <priority>450</priority> </properties> <children> <tagNode name="name"> diff --git a/interface-definitions/dhcp-server.xml.in b/interface-definitions/dhcp-server.xml.in index 1830cc1ad..583de7ba9 100644 --- a/interface-definitions/dhcp-server.xml.in +++ b/interface-definitions/dhcp-server.xml.in @@ -129,7 +129,7 @@ <properties> <help>Bootstrap file name</help> <constraint> - <regex>[-_a-zA-Z0-9./]+</regex> + <regex>[[:ascii:]]{1,253}</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/dns-dynamic.xml.in b/interface-definitions/dns-dynamic.xml.in index c7b45b8f7..a0720f3aa 100644 --- a/interface-definitions/dns-dynamic.xml.in +++ b/interface-definitions/dns-dynamic.xml.in @@ -150,6 +150,20 @@ </tagNode> </children> </tagNode> + <leafNode name="timeout"> + <properties> + <help>Time in seconds to wait between DNS updates</help> + <valueHelp> + <format>u32:60-3600</format> + <description>Time in seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 60-3600"/> + </constraint> + <constraintErrorMessage>Timeout must be between 60 and 3600 seconds</constraintErrorMessage> + </properties> + <defaultValue>300</defaultValue> + </leafNode> </children> </node> </children> diff --git a/interface-definitions/include/bgp/protocol-common-config.xml.i b/interface-definitions/include/bgp/protocol-common-config.xml.i index 12024ed8b..504385b53 100644 --- a/interface-definitions/include/bgp/protocol-common-config.xml.i +++ b/interface-definitions/include/bgp/protocol-common-config.xml.i @@ -1123,25 +1123,26 @@ <valueless/> </properties> </leafNode> - <node name="med"> + <leafNode name="med"> <properties> <help>MED attribute comparison parameters</help> + <completionHelp> + <list>confed missing-as-worst</list> + </completionHelp> + <valueHelp> + <format>confed</format> + <description>Compare MEDs among confederation paths</description> + </valueHelp> + <valueHelp> + <format>missing-as-worst</format> + <description>Treat missing route as a MED as the least preferred one</description> + </valueHelp> + <constraint> + <regex>(confed|missing-as-worst)</regex> + </constraint> + <multi/> </properties> - <children> - <leafNode name="confed"> - <properties> - <help>Compare MEDs among confederation paths</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="missing-as-worst"> - <properties> - <help>Treat missing route as a MED as the least preferred one</help> - <valueless/> - </properties> - </leafNode> - </children> - </node> + </leafNode> <node name="peer-type"> <properties> <help>Peer type</help> diff --git a/interface-definitions/include/version/interfaces-version.xml.i b/interface-definitions/include/version/interfaces-version.xml.i index 4a2b3f9ab..3d11ce888 100644 --- a/interface-definitions/include/version/interfaces-version.xml.i +++ b/interface-definitions/include/version/interfaces-version.xml.i @@ -1,3 +1,3 @@ <!-- include start from include/version/interfaces-version.xml.i --> -<syntaxVersion component='interfaces' version='29'></syntaxVersion> +<syntaxVersion component='interfaces' version='30'></syntaxVersion> <!-- include end --> diff --git a/interface-definitions/system-option.xml.in b/interface-definitions/system-option.xml.in index efab50a66..b1b5f7fae 100644 --- a/interface-definitions/system-option.xml.in +++ b/interface-definitions/system-option.xml.in @@ -144,6 +144,26 @@ <valueless/> </properties> </leafNode> + <leafNode name="time-format"> + <properties> + <help>System time-format</help> + <completionHelp> + <list>12-hour 24-hour</list> + </completionHelp> + <valueHelp> + <format>12-hour</format> + <description>12 hour time format</description> + </valueHelp> + <valueHelp> + <format>24-hour</format> + <description>24 hour time format</description> + </valueHelp> + <constraint> + <regex>(12-hour|24-hour)</regex> + </constraint> + </properties> + <defaultValue>12-hour</defaultValue> + </leafNode> </children> </node> </children> diff --git a/op-mode-definitions/clear-dhcp-server-lease.xml.in b/op-mode-definitions/clear-dhcp-server-lease.xml.in index b1241588c..aef0eb22a 100644 --- a/op-mode-definitions/clear-dhcp-server-lease.xml.in +++ b/op-mode-definitions/clear-dhcp-server-lease.xml.in @@ -4,7 +4,7 @@ <children> <node name="dhcp-server"> <properties> - <help>clear DHCP server lease</help> + <help>Clear DHCP server lease</help> </properties> <children> <tagNode name="lease"> diff --git a/op-mode-definitions/dns-dynamic.xml.in b/op-mode-definitions/dns-dynamic.xml.in index 8f32f63f9..79478f392 100644 --- a/op-mode-definitions/dns-dynamic.xml.in +++ b/op-mode-definitions/dns-dynamic.xml.in @@ -1,5 +1,29 @@ <?xml version="1.0"?> <interfaceDefinition> + <node name="clear"> + <children> + <node name="dns"> + <properties> + <help>Clear Domain Name System</help> + </properties> + <children> + <node name="dynamic"> + <properties> + <help>Clear Dynamic DNS information</help> + </properties> + <children> + <leafNode name="cache"> + <properties> + <help>Clear Dynamic DNS information cache (ddclient)</help> + </properties> + <command>sudo rm -f /run/ddclient/ddclient.cache</command> + </leafNode> + </children> + </node> + </children> + </node> + </children> + </node> <node name="monitor"> <children> <node name="log"> diff --git a/op-mode-definitions/include/ospfv3/detail.xml.i b/op-mode-definitions/include/frr-detail.xml.i index 4e3c91268..4edf82eab 100644 --- a/op-mode-definitions/include/ospfv3/detail.xml.i +++ b/op-mode-definitions/include/frr-detail.xml.i @@ -1,8 +1,8 @@ -<!-- included start from ospfv3/detail.xml.i --> -<node name="detail"> +<!-- included start from frr-detail.xml.i --> +<leafNode name="detail"> <properties> <help>Show detailed information</help> </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> -</node> +</leafNode> <!-- included end --> diff --git a/op-mode-definitions/include/ospf/common.xml.i b/op-mode-definitions/include/ospf/common.xml.i index c8341bd3e..684073cc5 100644 --- a/op-mode-definitions/include/ospf/common.xml.i +++ b/op-mode-definitions/include/ospf/common.xml.i @@ -524,12 +524,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - <node name="detail"> - <properties> - <help>Show detailed IPv4 OSPF neighbor information</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - </node> + #include <include/frr-detail.xml.i> </children> </node> <tagNode name="neighbor"> diff --git a/op-mode-definitions/include/ospfv3/adv-router-id-node-tag.xml.i b/op-mode-definitions/include/ospfv3/adv-router-id-node-tag.xml.i index a1bd67a90..806366444 100644 --- a/op-mode-definitions/include/ospfv3/adv-router-id-node-tag.xml.i +++ b/op-mode-definitions/include/ospfv3/adv-router-id-node-tag.xml.i @@ -8,7 +8,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> </children> diff --git a/op-mode-definitions/include/ospfv3/adv-router.xml.i b/op-mode-definitions/include/ospfv3/adv-router.xml.i index a14fc39db..238242d11 100644 --- a/op-mode-definitions/include/ospfv3/adv-router.xml.i +++ b/op-mode-definitions/include/ospfv3/adv-router.xml.i @@ -7,7 +7,7 @@ </completionHelp> </properties> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> diff --git a/op-mode-definitions/include/ospfv3/border-routers.xml.i b/op-mode-definitions/include/ospfv3/border-routers.xml.i index b6fac6785..e8827a2c4 100644 --- a/op-mode-definitions/include/ospfv3/border-routers.xml.i +++ b/op-mode-definitions/include/ospfv3/border-routers.xml.i @@ -5,7 +5,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> </children> </node> <tagNode name="border-routers"> diff --git a/op-mode-definitions/include/ospfv3/database.xml.i b/op-mode-definitions/include/ospfv3/database.xml.i index e98f9e35b..fdc45f184 100644 --- a/op-mode-definitions/include/ospfv3/database.xml.i +++ b/op-mode-definitions/include/ospfv3/database.xml.i @@ -29,7 +29,7 @@ </completionHelp> </properties> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> </children> @@ -45,7 +45,7 @@ </properties> <command>vtysh -c "show ipv6 ospf6 database * $6"</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/adv-router-id-node-tag.xml.i> @@ -67,12 +67,12 @@ </properties> <command>vtysh -c "show ipv6 ospf6 database as-external * $7"</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> </children> </tagNode> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> @@ -87,14 +87,14 @@ </completionHelp> </properties> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/self-originated.xml.i> #include <include/ospfv3/adv-router-id-node-tag.xml.i> </children> </tagNode> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> #include <include/ospfv3/self-originated.xml.i> @@ -105,7 +105,7 @@ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> @@ -120,7 +120,7 @@ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> @@ -135,7 +135,7 @@ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> @@ -150,7 +150,7 @@ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> @@ -165,7 +165,7 @@ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> @@ -180,7 +180,7 @@ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> @@ -195,7 +195,7 @@ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> @@ -210,7 +210,7 @@ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> @@ -225,7 +225,7 @@ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> diff --git a/op-mode-definitions/include/ospfv3/interface.xml.i b/op-mode-definitions/include/ospfv3/interface.xml.i index 7a0b8ea48..45d5dbd45 100644 --- a/op-mode-definitions/include/ospfv3/interface.xml.i +++ b/op-mode-definitions/include/ospfv3/interface.xml.i @@ -11,7 +11,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> </children> </node> <tagNode name="prefix"> @@ -23,7 +23,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> <node name="match"> <properties> <help>Matched interface prefix information</help> @@ -49,7 +49,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> </children> </node> <tagNode name="prefix"> @@ -61,7 +61,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> <node name="match"> <properties> <help>Matched interface prefix information</help> diff --git a/op-mode-definitions/include/ospfv3/linkstate-id-node-tag.xml.i b/op-mode-definitions/include/ospfv3/linkstate-id-node-tag.xml.i index ee3863b35..66674e754 100644 --- a/op-mode-definitions/include/ospfv3/linkstate-id-node-tag.xml.i +++ b/op-mode-definitions/include/ospfv3/linkstate-id-node-tag.xml.i @@ -8,7 +8,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/self-originated.xml.i> diff --git a/op-mode-definitions/include/ospfv3/linkstate-id.xml.i b/op-mode-definitions/include/ospfv3/linkstate-id.xml.i index 9ead17c20..aa226c988 100644 --- a/op-mode-definitions/include/ospfv3/linkstate-id.xml.i +++ b/op-mode-definitions/include/ospfv3/linkstate-id.xml.i @@ -7,7 +7,7 @@ </completionHelp> </properties> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> </children> diff --git a/op-mode-definitions/include/ospfv3/linkstate.xml.i b/op-mode-definitions/include/ospfv3/linkstate.xml.i index 78ef3efa1..030dc7923 100644 --- a/op-mode-definitions/include/ospfv3/linkstate.xml.i +++ b/op-mode-definitions/include/ospfv3/linkstate.xml.i @@ -4,7 +4,7 @@ <help>Show OSPFv3 linkstate routing information</help> </properties> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> <tagNode name="network"> <properties> <help>Show linkstate Network information</help> diff --git a/op-mode-definitions/include/ospfv3/neighbor.xml.i b/op-mode-definitions/include/ospfv3/neighbor.xml.i index 37859f815..b736270be 100644 --- a/op-mode-definitions/include/ospfv3/neighbor.xml.i +++ b/op-mode-definitions/include/ospfv3/neighbor.xml.i @@ -5,7 +5,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> <node name="drchoice"> <properties> <help>Show neighbor DR choice information</help> diff --git a/op-mode-definitions/include/ospfv3/route.xml.i b/op-mode-definitions/include/ospfv3/route.xml.i index 9271c9c3a..a5b97cd05 100644 --- a/op-mode-definitions/include/ospfv3/route.xml.i +++ b/op-mode-definitions/include/ospfv3/route.xml.i @@ -11,7 +11,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> </children> </node> <node name="external-2"> @@ -20,7 +20,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> </children> </node> <node name="inter-area"> @@ -29,7 +29,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> </children> </node> <node name="intra-area"> @@ -38,10 +38,10 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> </children> </node> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> <node name="summary"> <properties> <help>Show route table summary</help> @@ -71,7 +71,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> </children> </node> </children> diff --git a/op-mode-definitions/include/ospfv3/self-originated.xml.i b/op-mode-definitions/include/ospfv3/self-originated.xml.i index 734f3f8ad..7549ccb2c 100644 --- a/op-mode-definitions/include/ospfv3/self-originated.xml.i +++ b/op-mode-definitions/include/ospfv3/self-originated.xml.i @@ -5,7 +5,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> </children> diff --git a/op-mode-definitions/show-rpki.xml.in b/op-mode-definitions/rpki.xml.in index c1902ccec..72d378b88 100644 --- a/op-mode-definitions/show-rpki.xml.in +++ b/op-mode-definitions/rpki.xml.in @@ -29,4 +29,14 @@ </node> </children> </node> + <node name="reset"> + <children> + <leafNode name="rpki"> + <properties> + <help>Reset RPKI</help> + </properties> + <command>vtysh -c "rpki reset"</command> + </leafNode> + </children> + </node> </interfaceDefinition> diff --git a/op-mode-definitions/show-bridge.xml.in b/op-mode-definitions/show-bridge.xml.in index a272ea204..fad3f3418 100644 --- a/op-mode-definitions/show-bridge.xml.in +++ b/op-mode-definitions/show-bridge.xml.in @@ -7,12 +7,20 @@ <help>Show bridging information</help> </properties> <children> - <leafNode name="vlan"> + <node name="vlan"> <properties> <help>View the VLAN filter settings of the bridge</help> </properties> <command>${vyos_op_scripts_dir}/bridge.py show_vlan</command> - </leafNode> + <children> + <leafNode name="tunnel"> + <properties> + <help>Show bridge VLAN tunnel mapping</help> + </properties> + <command>${vyos_op_scripts_dir}/bridge.py show_vlan --tunnel</command> + </leafNode> + </children> + </node> </children> </node> <leafNode name="bridge"> diff --git a/op-mode-definitions/show-evpn.xml.in b/op-mode-definitions/show-evpn.xml.in index 0bdb41e7a..a005cbc30 100644 --- a/op-mode-definitions/show-evpn.xml.in +++ b/op-mode-definitions/show-evpn.xml.in @@ -7,6 +7,34 @@ <help>Show Ethernet VPN (EVPN) information</help> </properties> <children> + <node name="access-vlan"> + <properties> + <help>Access VLANs</help> + </properties> + <children> + #include <include/frr-detail.xml.i> + </children> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + </node> + <tagNode name="access-vlan"> + <properties> + <help>Access VLANs interface name</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces --bridgeable --no-vlan-subinterfaces</script> + </completionHelp> + </properties> + <children> + <node name="node.tag"> + <properties> + <help>VLAN ID</help> + <completionHelp> + <list><1-4094></list> + </completionHelp> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + </node> + </children> + </tagNode> <node name="arp-cache"> <properties> <help>ARP and ND cache</help> diff --git a/python/vyos/configdict.py b/python/vyos/configdict.py index f642d38f2..2a47e88f9 100644 --- a/python/vyos/configdict.py +++ b/python/vyos/configdict.py @@ -177,24 +177,6 @@ def get_removed_vlans(conf, path, dict): return dict -def T2665_set_dhcpv6pd_defaults(config_dict): - """ Properly configure DHCPv6 default options in the dictionary. If there is - no DHCPv6 configured at all, it is safe to remove the entire configuration. - """ - # As this is the same for every interface type it is safe to assume this - # for ethernet - pd_defaults = defaults(['interfaces', 'ethernet', 'dhcpv6-options', 'pd']) - - # Implant default dictionary for DHCPv6-PD instances - if dict_search('dhcpv6_options.pd.length', config_dict): - del config_dict['dhcpv6_options']['pd']['length'] - - for pd in (dict_search('dhcpv6_options.pd', config_dict) or []): - config_dict['dhcpv6_options']['pd'][pd] = dict_merge(pd_defaults, - config_dict['dhcpv6_options']['pd'][pd]) - - return config_dict - def is_member(conf, interface, intftype=None): """ Checks if passed interface is member of other interface of specified type. @@ -263,6 +245,48 @@ def is_mirror_intf(conf, interface, direction=None): return ret_val +def has_address_configured(conf, intf): + """ + Checks if interface has an address configured. + Checks the following config nodes: + 'address', 'ipv6 address eui64', 'ipv6 address autoconf' + + Returns True if interface has address configured, False if it doesn't. + """ + from vyos.ifconfig import Section + ret = False + + old_level = conf.get_level() + conf.set_level([]) + + intfpath = 'interfaces ' + Section.get_config_path(intf) + if ( conf.exists(f'{intfpath} address') or + conf.exists(f'{intfpath} ipv6 address autoconf') or + conf.exists(f'{intfpath} ipv6 address eui64') ): + ret = True + + conf.set_level(old_level) + return ret + +def has_vrf_configured(conf, intf): + """ + Checks if interface has a VRF configured. + + Returns True if interface has VRF configured, False if it doesn't. + """ + from vyos.ifconfig import Section + ret = False + + old_level = conf.get_level() + conf.set_level([]) + + tmp = ['interfaces', Section.get_config_path(intf), 'vrf'] + if conf.exists(tmp): + ret = True + + conf.set_level(old_level) + return ret + def has_vlan_subinterface_configured(conf, intf): """ Checks if interface has an VLAN subinterface configured. @@ -455,6 +479,10 @@ def get_interface_dict(config, base, ifname='', recursive_defaults=True): dhcp = is_node_changed(config, base + [ifname, 'dhcp-options']) if dhcp: dict.update({'dhcp_options_changed' : {}}) + # Changine interface VRF assignemnts require a DHCP restart, too + dhcp = is_node_changed(config, base + [ifname, 'vrf']) + if dhcp: dict.update({'dhcp_options_changed' : {}}) + # Some interfaces come with a source_interface which must also not be part # of any other bond or bridge interface as it is exclusivly assigned as the # Kernels "lower" interface to this new "virtual/upper" interface. diff --git a/python/vyos/defaults.py b/python/vyos/defaults.py index d4ffc249e..a5314790d 100644 --- a/python/vyos/defaults.py +++ b/python/vyos/defaults.py @@ -32,7 +32,9 @@ directories = { 'api_schema': f'{base_dir}/services/api/graphql/graphql/schema/', 'api_client_op': f'{base_dir}/services/api/graphql/graphql/client_op/', 'api_templates': f'{base_dir}/services/api/graphql/session/templates/', - 'vyos_udev_dir' : '/run/udev/vyos' + 'vyos_udev_dir' : '/run/udev/vyos', + 'isc_dhclient_dir' : '/run/dhclient', + 'dhcp6_client_dir' : '/run/dhcp6c', } config_status = '/tmp/vyos-config-status' diff --git a/python/vyos/ifconfig/bond.py b/python/vyos/ifconfig/bond.py index e88f860be..d1d7d48c4 100644 --- a/python/vyos/ifconfig/bond.py +++ b/python/vyos/ifconfig/bond.py @@ -18,8 +18,8 @@ import os from vyos.ifconfig.interface import Interface from vyos.utils.process import cmd from vyos.utils.dict import dict_search -from vyos.validate import assert_list -from vyos.validate import assert_positive +from vyos.utils.assertion import assert_list +from vyos.utils.assertion import assert_positive @Interface.register class BondIf(Interface): diff --git a/python/vyos/ifconfig/bridge.py b/python/vyos/ifconfig/bridge.py index b103b49d8..b29e71394 100644 --- a/python/vyos/ifconfig/bridge.py +++ b/python/vyos/ifconfig/bridge.py @@ -17,8 +17,8 @@ from netifaces import interfaces import json from vyos.ifconfig.interface import Interface -from vyos.validate import assert_boolean -from vyos.validate import assert_positive +from vyos.utils.assertion import assert_boolean +from vyos.utils.assertion import assert_positive from vyos.utils.process import cmd from vyos.utils.dict import dict_search from vyos.configdict import get_vlan_ids diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py index 4ff044c23..24ce3a803 100644 --- a/python/vyos/ifconfig/ethernet.py +++ b/python/vyos/ifconfig/ethernet.py @@ -23,7 +23,7 @@ from vyos.ifconfig.interface import Interface from vyos.utils.dict import dict_search from vyos.utils.file import read_file from vyos.utils.process import run -from vyos.validate import assert_list +from vyos.utils.assertion import assert_list @Interface.register class EthernetIf(Interface): diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 99ddb2021..75c5f27a9 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -31,6 +31,7 @@ from vyos import ConfigError from vyos.configdict import list_diff from vyos.configdict import dict_merge from vyos.configdict import get_vlan_ids +from vyos.defaults import directories from vyos.template import render from vyos.utils.network import mac2eui64 from vyos.utils.dict import dict_search @@ -40,14 +41,14 @@ from vyos.utils.network import get_interface_namespace from vyos.utils.process import is_systemd_service_active from vyos.template import is_ipv4 from vyos.template import is_ipv6 -from vyos.validate import is_intf_addr_assigned -from vyos.validate import is_ipv6_link_local -from vyos.validate import assert_boolean -from vyos.validate import assert_list -from vyos.validate import assert_mac -from vyos.validate import assert_mtu -from vyos.validate import assert_positive -from vyos.validate import assert_range +from vyos.utils.network import is_intf_addr_assigned +from vyos.utils.network import is_ipv6_link_local +from vyos.utils.assertion import assert_boolean +from vyos.utils.assertion import assert_list +from vyos.utils.assertion import assert_mac +from vyos.utils.assertion import assert_mtu +from vyos.utils.assertion import assert_positive +from vyos.utils.assertion import assert_range from vyos.ifconfig.control import Control from vyos.ifconfig.vrrp import VRRP @@ -1240,44 +1241,49 @@ class Interface(Control): raise ValueError() ifname = self.ifname - config_base = r'/var/lib/dhcp/dhclient' - config_file = f'{config_base}_{ifname}.conf' - options_file = f'{config_base}_{ifname}.options' - pid_file = f'{config_base}_{ifname}.pid' - lease_file = f'{config_base}_{ifname}.leases' + config_base = directories['isc_dhclient_dir'] + '/dhclient' + dhclient_config_file = f'{config_base}_{ifname}.conf' + dhclient_lease_file = f'{config_base}_{ifname}.leases' + systemd_override_file = f'/run/systemd/system/dhclient@{ifname}.service.d/10-override.conf' systemd_service = f'dhclient@{ifname}.service' + # Rendered client configuration files require the apsolute config path + self.config['isc_dhclient_dir'] = directories['isc_dhclient_dir'] + # 'up' check is mandatory b/c even if the interface is A/D, as soon as # the DHCP client is started the interface will be placed in u/u state. # This is not what we intended to do when disabling an interface. - if enable and 'disable' not in self._config: - if dict_search('dhcp_options.host_name', self._config) == None: + if enable and 'disable' not in self.config: + if dict_search('dhcp_options.host_name', self.config) == None: # read configured system hostname. # maybe change to vyos hostd client ??? hostname = 'vyos' with open('/etc/hostname', 'r') as f: hostname = f.read().rstrip('\n') tmp = {'dhcp_options' : { 'host_name' : hostname}} - self._config = dict_merge(tmp, self._config) + self.config = dict_merge(tmp, self.config) + + render(systemd_override_file, 'dhcp-client/override.conf.j2', self.config) + render(dhclient_config_file, 'dhcp-client/ipv4.j2', self.config) - render(options_file, 'dhcp-client/daemon-options.j2', self._config) - render(config_file, 'dhcp-client/ipv4.j2', self._config) + # Reload systemd unit definitons as some options are dynamically generated + self._cmd('systemctl daemon-reload') # When the DHCP client is restarted a brief outage will occur, as # the old lease is released a new one is acquired (T4203). We will # only restart DHCP client if it's option changed, or if it's not # running, but it should be running (e.g. on system startup) - if 'dhcp_options_changed' in self._config or not is_systemd_service_active(systemd_service): + if 'dhcp_options_changed' in self.config or not is_systemd_service_active(systemd_service): return self._cmd(f'systemctl restart {systemd_service}') - return None else: if is_systemd_service_active(systemd_service): self._cmd(f'systemctl stop {systemd_service}') # cleanup old config files - for file in [config_file, options_file, pid_file, lease_file]: + for file in [dhclient_config_file, systemd_override_file, dhclient_lease_file]: if os.path.isfile(file): os.remove(file) + return None def set_dhcpv6(self, enable): """ @@ -1287,13 +1293,20 @@ class Interface(Control): raise ValueError() ifname = self.ifname - config_file = f'/run/dhcp6c/dhcp6c.{ifname}.conf' - options_file = f'/run/dhcp6c/dhcp6c.{ifname}.options' + config_base = directories['dhcp6_client_dir'] + config_file = f'{config_base}/dhcp6c.{ifname}.conf' + systemd_override_file = f'/run/systemd/system/dhcp6c@{ifname}.service.d/10-override.conf' systemd_service = f'dhcp6c@{ifname}.service' - if enable and 'disable' not in self._config: - render(options_file, 'dhcp-client/dhcp6c_daemon-options.j2', self._config) - render(config_file, 'dhcp-client/ipv6.j2', self._config) + # Rendered client configuration files require the apsolute config path + self.config['dhcp6_client_dir'] = directories['dhcp6_client_dir'] + + if enable and 'disable' not in self.config: + render(systemd_override_file, 'dhcp-client/ipv6.override.conf.j2', self.config) + render(config_file, 'dhcp-client/ipv6.j2', self.config) + + # Reload systemd unit definitons as some options are dynamically generated + self._cmd('systemctl daemon-reload') # We must ignore any return codes. This is required to enable # DHCPv6-PD for interfaces which are yet not up and running. @@ -1304,26 +1317,28 @@ class Interface(Control): if os.path.isfile(config_file): os.remove(config_file) + return None + def set_mirror_redirect(self): # Please refer to the document for details # - https://man7.org/linux/man-pages/man8/tc.8.html # - https://man7.org/linux/man-pages/man8/tc-mirred.8.html # Depening if we are the source or the target interface of the port # mirror we need to setup some variables. - source_if = self._config['ifname'] + source_if = self.config['ifname'] mirror_config = None - if 'mirror' in self._config: - mirror_config = self._config['mirror'] - if 'is_mirror_intf' in self._config: - source_if = next(iter(self._config['is_mirror_intf'])) - mirror_config = self._config['is_mirror_intf'][source_if].get('mirror', None) + if 'mirror' in self.config: + mirror_config = self.config['mirror'] + if 'is_mirror_intf' in self.config: + source_if = next(iter(self.config['is_mirror_intf'])) + mirror_config = self.config['is_mirror_intf'][source_if].get('mirror', None) redirect_config = None # clear existing ingess - ignore errors (e.g. "Error: Cannot find specified # qdisc on specified device") - we simply cleanup all stuff here - if not 'traffic_policy' in self._config: + if not 'traffic_policy' in self.config: self._popen(f'tc qdisc del dev {source_if} parent ffff: 2>/dev/null'); self._popen(f'tc qdisc del dev {source_if} parent 1: 2>/dev/null'); @@ -1347,11 +1362,11 @@ class Interface(Control): if err: print('tc qdisc(filter for mirror port failed') # Apply interface traffic redirection policy - elif 'redirect' in self._config: + elif 'redirect' in self.config: _, err = self._popen(f'tc qdisc add dev {source_if} handle ffff: ingress') if err: print(f'tc qdisc add for redirect failed!') - target_if = self._config['redirect'] + target_if = self.config['redirect'] _, err = self._popen(f'tc filter add dev {source_if} parent ffff: protocol '\ f'all prio 10 u32 match u32 0 0 flowid 1:1 action mirred '\ f'egress redirect dev {target_if}') @@ -1370,7 +1385,7 @@ class Interface(Control): # Cache the configuration - it will be reused inside e.g. DHCP handler # XXX: maybe pass the option via __init__ in the future and rename this # method to apply()? - self._config = config + self.config = config # Change interface MAC address - re-set to real hardware address (hw-id) # if custom mac is removed. Skip if bond member. diff --git a/python/vyos/ifconfig/pppoe.py b/python/vyos/ifconfig/pppoe.py index fd4590beb..febf1452d 100644 --- a/python/vyos/ifconfig/pppoe.py +++ b/python/vyos/ifconfig/pppoe.py @@ -14,7 +14,7 @@ # License along with this library. If not, see <http://www.gnu.org/licenses/>. from vyos.ifconfig.interface import Interface -from vyos.validate import assert_range +from vyos.utils.assertion import assert_range from vyos.utils.network import get_interface_config @Interface.register diff --git a/python/vyos/ifconfig/tunnel.py b/python/vyos/ifconfig/tunnel.py index fb2f38e2b..9ba7b31a6 100644 --- a/python/vyos/ifconfig/tunnel.py +++ b/python/vyos/ifconfig/tunnel.py @@ -18,7 +18,7 @@ from vyos.ifconfig.interface import Interface from vyos.utils.dict import dict_search -from vyos.validate import assert_list +from vyos.utils.assertion import assert_list def enable_to_on(value): if value == 'enable': diff --git a/python/vyos/ipsec.py b/python/vyos/ipsec.py index bb5611025..4603aab22 100644 --- a/python/vyos/ipsec.py +++ b/python/vyos/ipsec.py @@ -33,9 +33,11 @@ def get_vici_sas(): session = vici_session() except Exception: raise ViciInitiateError("IPsec not initialized") - sas = list(session.list_sas()) - return sas - + try: + sas = list(session.list_sas()) + return sas + except Exception: + raise ViciCommandError(f'Failed to get SAs') def get_vici_connections(): from vici import Session as vici_session @@ -44,9 +46,11 @@ def get_vici_connections(): session = vici_session() except Exception: raise ViciInitiateError("IPsec not initialized") - connections = list(session.list_conns()) - return connections - + try: + connections = list(session.list_conns()) + return connections + except Exception: + raise ViciCommandError(f'Failed to get connections') def get_vici_sas_by_name(ike_name: str, tunnel: str) -> list: """ diff --git a/python/vyos/qos/base.py b/python/vyos/qos/base.py index 6c5a3d79c..1eac0d1ee 100644 --- a/python/vyos/qos/base.py +++ b/python/vyos/qos/base.py @@ -107,7 +107,8 @@ class QoSBase: queue_limit = dict_search('queue_limit', config) for ii in range(1, 4): - tmp = f'tc qdisc replace dev {self._interface} parent {handle:x}:{ii:x} pfifo limit {queue_limit}' + tmp = f'tc qdisc replace dev {self._interface} parent {handle:x}:{ii:x} pfifo' + if queue_limit: tmp += f' limit {queue_limit}' self._cmd(tmp) elif queue_type == 'fair-queue': diff --git a/python/vyos/template.py b/python/vyos/template.py index 7d1c3970f..6469623fd 100644 --- a/python/vyos/template.py +++ b/python/vyos/template.py @@ -420,7 +420,7 @@ def get_dhcp_router(interface): Returns False of no router is found, returns the IP address as string if a router is found. """ - lease_file = f'/var/lib/dhcp/dhclient_{interface}.leases' + lease_file = directories['isc_dhclient_dir'] + f'/dhclient_{interface}.leases' if not os.path.exists(lease_file): return None diff --git a/python/vyos/utils/__init__.py b/python/vyos/utils/__init__.py index f2783113a..12ef2d3b8 100644 --- a/python/vyos/utils/__init__.py +++ b/python/vyos/utils/__init__.py @@ -13,6 +13,7 @@ # 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/>. +from vyos.utils import assertion from vyos.utils import auth from vyos.utils import boot from vyos.utils import commit diff --git a/python/vyos/utils/assertion.py b/python/vyos/utils/assertion.py new file mode 100644 index 000000000..1aaa54dff --- /dev/null +++ b/python/vyos/utils/assertion.py @@ -0,0 +1,81 @@ +# Copyright 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/>. + +def assert_boolean(b): + if int(b) not in (0, 1): + raise ValueError(f'Value {b} out of range') + +def assert_range(value, lower=0, count=3): + if int(value, 16) not in range(lower, lower+count): + raise ValueError("Value out of range") + +def assert_list(s, l): + if s not in l: + o = ' or '.join([f'"{n}"' for n in l]) + raise ValueError(f'state must be {o}, got {s}') + +def assert_number(n): + if not str(n).isnumeric(): + raise ValueError(f'{n} must be a number') + +def assert_positive(n, smaller=0): + assert_number(n) + if int(n) < smaller: + raise ValueError(f'{n} is smaller than {smaller}') + +def assert_mtu(mtu, ifname): + assert_number(mtu) + + import json + from vyos.utils.process import cmd + out = cmd(f'ip -j -d link show dev {ifname}') + # [{"ifindex":2,"ifname":"eth0","flags":["BROADCAST","MULTICAST","UP","LOWER_UP"],"mtu":1500,"qdisc":"pfifo_fast","operstate":"UP","linkmode":"DEFAULT","group":"default","txqlen":1000,"link_type":"ether","address":"08:00:27:d9:5b:04","broadcast":"ff:ff:ff:ff:ff:ff","promiscuity":0,"min_mtu":46,"max_mtu":16110,"inet6_addr_gen_mode":"none","num_tx_queues":1,"num_rx_queues":1,"gso_max_size":65536,"gso_max_segs":65535}] + parsed = json.loads(out)[0] + min_mtu = int(parsed.get('min_mtu', '0')) + # cur_mtu = parsed.get('mtu',0), + max_mtu = int(parsed.get('max_mtu', '0')) + cur_mtu = int(mtu) + + if (min_mtu and cur_mtu < min_mtu) or cur_mtu < 68: + raise ValueError(f'MTU is too small for interface "{ifname}": {mtu} < {min_mtu}') + if (max_mtu and cur_mtu > max_mtu) or cur_mtu > 65536: + raise ValueError(f'MTU is too small for interface "{ifname}": {mtu} > {max_mtu}') + +def assert_mac(m): + split = m.split(':') + size = len(split) + + # a mac address consits out of 6 octets + if size != 6: + raise ValueError(f'wrong number of MAC octets ({size}): {m}') + + octets = [] + try: + for octet in split: + octets.append(int(octet, 16)) + except ValueError: + raise ValueError(f'invalid hex number "{octet}" in : {m}') + + # validate against the first mac address byte if it's a multicast + # address + if octets[0] & 1: + raise ValueError(f'{m} is a multicast MAC address') + + # overall mac address is not allowed to be 00:00:00:00:00:00 + if sum(octets) == 0: + raise ValueError('00:00:00:00:00:00 is not a valid MAC address') + + if octets[:5] == (0, 0, 94, 0, 1): + raise ValueError(f'{m} is a VRRP MAC address') diff --git a/python/vyos/utils/network.py b/python/vyos/utils/network.py index 3786caf26..3f9a3ef4b 100644 --- a/python/vyos/utils/network.py +++ b/python/vyos/utils/network.py @@ -13,7 +13,15 @@ # 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 os +def _are_same_ip(one, two): + from socket import AF_INET + from socket import AF_INET6 + from socket import inet_pton + from vyos.template import is_ipv4 + # compare the binary representation of the IP + f_one = AF_INET if is_ipv4(one) else AF_INET6 + s_two = AF_INET if is_ipv4(two) else AF_INET6 + return inet_pton(f_one, one) == inet_pton(f_one, two) def get_protocol_by_name(protocol_name): """Get protocol number by protocol name @@ -48,6 +56,7 @@ def get_interface_config(interface): """ Returns the used encapsulation protocol for given interface. If interface does not exist, None is returned. """ + import os if not os.path.exists(f'/sys/class/net/{interface}'): return None from json import loads @@ -59,6 +68,7 @@ def get_interface_address(interface): """ Returns the used encapsulation protocol for given interface. If interface does not exist, None is returned. """ + import os if not os.path.exists(f'/sys/class/net/{interface}'): return None from json import loads @@ -85,7 +95,6 @@ def get_interface_namespace(iface): if iface == tmp["ifname"]: return netns - def is_wwan_connected(interface): """ Determine if a given WWAN interface, e.g. wwan0 is connected to the carrier network or not """ @@ -110,6 +119,7 @@ def is_wwan_connected(interface): def get_bridge_fdb(interface): """ Returns the forwarding database entries for a given interface """ + import os if not os.path.exists(f'/sys/class/net/{interface}'): return None from json import loads @@ -211,3 +221,175 @@ def is_listen_port_bind_service(port: int, service: str) -> bool: if service == pid_name and port == pid_port: return True return False + +def is_ipv6_link_local(addr): + """ Check if addrsss is an IPv6 link-local address. Returns True/False """ + from ipaddress import ip_interface + from vyos.template import is_ipv6 + addr = addr.split('%')[0] + if is_ipv6(addr): + if ip_interface(addr).is_link_local: + return True + + return False + +def is_addr_assigned(ip_address, vrf=None) -> bool: + """ Verify if the given IPv4/IPv6 address is assigned to any interface """ + from netifaces import interfaces + from vyos.utils.network import get_interface_config + from vyos.utils.dict import dict_search + + for interface in interfaces(): + # Check if interface belongs to the requested VRF, if this is not the + # case there is no need to proceed with this data set - continue loop + # with next element + tmp = get_interface_config(interface) + if dict_search('master', tmp) != vrf: + continue + + if is_intf_addr_assigned(interface, ip_address): + return True + + return False + +def is_intf_addr_assigned(intf, address) -> bool: + """ + Verify if the given IPv4/IPv6 address is assigned to specific interface. + It can check both a single IP address (e.g. 192.0.2.1 or a assigned CIDR + address 192.0.2.1/24. + """ + from vyos.template import is_ipv4 + + from netifaces import ifaddresses + from netifaces import AF_INET + from netifaces import AF_INET6 + + # check if the requested address type is configured at all + # { + # 17: [{'addr': '08:00:27:d9:5b:04', 'broadcast': 'ff:ff:ff:ff:ff:ff'}], + # 2: [{'addr': '10.0.2.15', 'netmask': '255.255.255.0', 'broadcast': '10.0.2.255'}], + # 10: [{'addr': 'fe80::a00:27ff:fed9:5b04%eth0', 'netmask': 'ffff:ffff:ffff:ffff::'}] + # } + try: + addresses = ifaddresses(intf) + except ValueError as e: + print(e) + return False + + # determine IP version (AF_INET or AF_INET6) depending on passed address + addr_type = AF_INET if is_ipv4(address) else AF_INET6 + + # Check every IP address on this interface for a match + netmask = None + if '/' in address: + address, netmask = address.split('/') + for ip in addresses.get(addr_type, []): + # ip can have the interface name in the 'addr' field, we need to remove it + # {'addr': 'fe80::a00:27ff:fec5:f821%eth2', 'netmask': 'ffff:ffff:ffff:ffff::'} + ip_addr = ip['addr'].split('%')[0] + + if not _are_same_ip(address, ip_addr): + continue + + # we do not have a netmask to compare against, they are the same + if not netmask: + return True + + prefixlen = '' + if is_ipv4(ip_addr): + prefixlen = sum([bin(int(_)).count('1') for _ in ip['netmask'].split('.')]) + else: + prefixlen = sum([bin(int(_,16)).count('1') for _ in ip['netmask'].split('/')[0].split(':') if _]) + + if str(prefixlen) == netmask: + return True + + return False + +def is_loopback_addr(addr): + """ Check if supplied IPv4/IPv6 address is a loopback address """ + from ipaddress import ip_address + return ip_address(addr).is_loopback + +def is_wireguard_key_pair(private_key: str, public_key:str) -> bool: + """ + Checks if public/private keys are keypair + :param private_key: Wireguard private key + :type private_key: str + :param public_key: Wireguard public key + :type public_key: str + :return: If public/private keys are keypair returns True else False + :rtype: bool + """ + from vyos.utils.process import cmd + gen_public_key = cmd('wg pubkey', input=private_key) + if gen_public_key == public_key: + return True + else: + return False + +def is_subnet_connected(subnet, primary=False): + """ + Verify is the given IPv4/IPv6 subnet is connected to any interface on this + system. + + primary check if the subnet is reachable via the primary IP address of this + interface, or in other words has a broadcast address configured. ISC DHCP + for instance will complain if it should listen on non broadcast interfaces. + + Return True/False + """ + from ipaddress import ip_address + from ipaddress import ip_network + + from netifaces import ifaddresses + from netifaces import interfaces + from netifaces import AF_INET + from netifaces import AF_INET6 + + from vyos.template import is_ipv6 + + # determine IP version (AF_INET or AF_INET6) depending on passed address + addr_type = AF_INET + if is_ipv6(subnet): + addr_type = AF_INET6 + + for interface in interfaces(): + # check if the requested address type is configured at all + if addr_type not in ifaddresses(interface).keys(): + continue + + # An interface can have multiple addresses, but some software components + # only support the primary address :( + if primary: + ip = ifaddresses(interface)[addr_type][0]['addr'] + if ip_address(ip) in ip_network(subnet): + return True + else: + # Check every assigned IP address if it is connected to the subnet + # in question + for ip in ifaddresses(interface)[addr_type]: + # remove interface extension (e.g. %eth0) that gets thrown on the end of _some_ addrs + addr = ip['addr'].split('%')[0] + if ip_address(addr) in ip_network(subnet): + return True + + return False + +def is_afi_configured(interface, afi): + """ Check if given address family is configured, or in other words - an IP + address is assigned to the interface. """ + from netifaces import ifaddresses + from netifaces import AF_INET + from netifaces import AF_INET6 + + if afi not in [AF_INET, AF_INET6]: + raise ValueError('Address family must be in [AF_INET, AF_INET6]') + + try: + addresses = ifaddresses(interface) + except ValueError as e: + print(e) + return False + + return afi in addresses diff --git a/python/vyos/validate.py b/python/vyos/validate.py deleted file mode 100644 index 567f4c972..000000000 --- a/python/vyos/validate.py +++ /dev/null @@ -1,304 +0,0 @@ -# Copyright 2018-2021 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/>. - -# Important note when you are adding new validation functions: -# -# The Control class will analyse the signature of the function in this file -# and will build the parameters to be passed to it. -# -# The parameter names "ifname" and "self" will get the Interface name and class -# parameters with default will be left unset -# all other paramters will receive the value to check - -def is_ipv6_link_local(addr): - """ Check if addrsss is an IPv6 link-local address. Returns True/False """ - from ipaddress import ip_interface - from vyos.template import is_ipv6 - addr = addr.split('%')[0] - if is_ipv6(addr): - if ip_interface(addr).is_link_local: - return True - - return False - -def _are_same_ip(one, two): - from socket import AF_INET - from socket import AF_INET6 - from socket import inet_pton - from vyos.template import is_ipv4 - # compare the binary representation of the IP - f_one = AF_INET if is_ipv4(one) else AF_INET6 - s_two = AF_INET if is_ipv4(two) else AF_INET6 - return inet_pton(f_one, one) == inet_pton(f_one, two) - -def is_intf_addr_assigned(intf, address) -> bool: - """ - Verify if the given IPv4/IPv6 address is assigned to specific interface. - It can check both a single IP address (e.g. 192.0.2.1 or a assigned CIDR - address 192.0.2.1/24. - """ - from vyos.template import is_ipv4 - - from netifaces import ifaddresses - from netifaces import AF_INET - from netifaces import AF_INET6 - - # check if the requested address type is configured at all - # { - # 17: [{'addr': '08:00:27:d9:5b:04', 'broadcast': 'ff:ff:ff:ff:ff:ff'}], - # 2: [{'addr': '10.0.2.15', 'netmask': '255.255.255.0', 'broadcast': '10.0.2.255'}], - # 10: [{'addr': 'fe80::a00:27ff:fed9:5b04%eth0', 'netmask': 'ffff:ffff:ffff:ffff::'}] - # } - try: - addresses = ifaddresses(intf) - except ValueError as e: - print(e) - return False - - # determine IP version (AF_INET or AF_INET6) depending on passed address - addr_type = AF_INET if is_ipv4(address) else AF_INET6 - - # Check every IP address on this interface for a match - netmask = None - if '/' in address: - address, netmask = address.split('/') - for ip in addresses.get(addr_type, []): - # ip can have the interface name in the 'addr' field, we need to remove it - # {'addr': 'fe80::a00:27ff:fec5:f821%eth2', 'netmask': 'ffff:ffff:ffff:ffff::'} - ip_addr = ip['addr'].split('%')[0] - - if not _are_same_ip(address, ip_addr): - continue - - # we do not have a netmask to compare against, they are the same - if not netmask: - return True - - prefixlen = '' - if is_ipv4(ip_addr): - prefixlen = sum([bin(int(_)).count('1') for _ in ip['netmask'].split('.')]) - else: - prefixlen = sum([bin(int(_,16)).count('1') for _ in ip['netmask'].split('/')[0].split(':') if _]) - - if str(prefixlen) == netmask: - return True - - return False - -def is_addr_assigned(ip_address, vrf=None) -> bool: - """ Verify if the given IPv4/IPv6 address is assigned to any interface """ - from netifaces import interfaces - from vyos.utils.network import get_interface_config - from vyos.utils.dict import dict_search - - for interface in interfaces(): - # Check if interface belongs to the requested VRF, if this is not the - # case there is no need to proceed with this data set - continue loop - # with next element - tmp = get_interface_config(interface) - if dict_search('master', tmp) != vrf: - continue - - if is_intf_addr_assigned(interface, ip_address): - return True - - return False - -def is_afi_configured(interface, afi): - """ Check if given address family is configured, or in other words - an IP - address is assigned to the interface. """ - from netifaces import ifaddresses - from netifaces import AF_INET - from netifaces import AF_INET6 - - if afi not in [AF_INET, AF_INET6]: - raise ValueError('Address family must be in [AF_INET, AF_INET6]') - - try: - addresses = ifaddresses(interface) - except ValueError as e: - print(e) - return False - - return afi in addresses - -def is_loopback_addr(addr): - """ Check if supplied IPv4/IPv6 address is a loopback address """ - from ipaddress import ip_address - return ip_address(addr).is_loopback - -def is_subnet_connected(subnet, primary=False): - """ - Verify is the given IPv4/IPv6 subnet is connected to any interface on this - system. - - primary check if the subnet is reachable via the primary IP address of this - interface, or in other words has a broadcast address configured. ISC DHCP - for instance will complain if it should listen on non broadcast interfaces. - - Return True/False - """ - from ipaddress import ip_address - from ipaddress import ip_network - - from netifaces import ifaddresses - from netifaces import interfaces - from netifaces import AF_INET - from netifaces import AF_INET6 - - from vyos.template import is_ipv6 - - # determine IP version (AF_INET or AF_INET6) depending on passed address - addr_type = AF_INET - if is_ipv6(subnet): - addr_type = AF_INET6 - - for interface in interfaces(): - # check if the requested address type is configured at all - if addr_type not in ifaddresses(interface).keys(): - continue - - # An interface can have multiple addresses, but some software components - # only support the primary address :( - if primary: - ip = ifaddresses(interface)[addr_type][0]['addr'] - if ip_address(ip) in ip_network(subnet): - return True - else: - # Check every assigned IP address if it is connected to the subnet - # in question - for ip in ifaddresses(interface)[addr_type]: - # remove interface extension (e.g. %eth0) that gets thrown on the end of _some_ addrs - addr = ip['addr'].split('%')[0] - if ip_address(addr) in ip_network(subnet): - return True - - return False - - -def assert_boolean(b): - if int(b) not in (0, 1): - raise ValueError(f'Value {b} out of range') - - -def assert_range(value, lower=0, count=3): - if int(value, 16) not in range(lower, lower+count): - raise ValueError("Value out of range") - - -def assert_list(s, l): - if s not in l: - o = ' or '.join([f'"{n}"' for n in l]) - raise ValueError(f'state must be {o}, got {s}') - - -def assert_number(n): - if not str(n).isnumeric(): - raise ValueError(f'{n} must be a number') - - -def assert_positive(n, smaller=0): - assert_number(n) - if int(n) < smaller: - raise ValueError(f'{n} is smaller than {smaller}') - - -def assert_mtu(mtu, ifname): - assert_number(mtu) - - import json - from vyos.utils.process import cmd - out = cmd(f'ip -j -d link show dev {ifname}') - # [{"ifindex":2,"ifname":"eth0","flags":["BROADCAST","MULTICAST","UP","LOWER_UP"],"mtu":1500,"qdisc":"pfifo_fast","operstate":"UP","linkmode":"DEFAULT","group":"default","txqlen":1000,"link_type":"ether","address":"08:00:27:d9:5b:04","broadcast":"ff:ff:ff:ff:ff:ff","promiscuity":0,"min_mtu":46,"max_mtu":16110,"inet6_addr_gen_mode":"none","num_tx_queues":1,"num_rx_queues":1,"gso_max_size":65536,"gso_max_segs":65535}] - parsed = json.loads(out)[0] - min_mtu = int(parsed.get('min_mtu', '0')) - # cur_mtu = parsed.get('mtu',0), - max_mtu = int(parsed.get('max_mtu', '0')) - cur_mtu = int(mtu) - - if (min_mtu and cur_mtu < min_mtu) or cur_mtu < 68: - raise ValueError(f'MTU is too small for interface "{ifname}": {mtu} < {min_mtu}') - if (max_mtu and cur_mtu > max_mtu) or cur_mtu > 65536: - raise ValueError(f'MTU is too small for interface "{ifname}": {mtu} > {max_mtu}') - - -def assert_mac(m): - split = m.split(':') - size = len(split) - - # a mac address consits out of 6 octets - if size != 6: - raise ValueError(f'wrong number of MAC octets ({size}): {m}') - - octets = [] - try: - for octet in split: - octets.append(int(octet, 16)) - except ValueError: - raise ValueError(f'invalid hex number "{octet}" in : {m}') - - # validate against the first mac address byte if it's a multicast - # address - if octets[0] & 1: - raise ValueError(f'{m} is a multicast MAC address') - - # overall mac address is not allowed to be 00:00:00:00:00:00 - if sum(octets) == 0: - raise ValueError('00:00:00:00:00:00 is not a valid MAC address') - - if octets[:5] == (0, 0, 94, 0, 1): - raise ValueError(f'{m} is a VRRP MAC address') - -def has_address_configured(conf, intf): - """ - Checks if interface has an address configured. - Checks the following config nodes: - 'address', 'ipv6 address eui64', 'ipv6 address autoconf' - - Returns True if interface has address configured, False if it doesn't. - """ - from vyos.ifconfig import Section - ret = False - - old_level = conf.get_level() - conf.set_level([]) - - intfpath = 'interfaces ' + Section.get_config_path(intf) - if ( conf.exists(f'{intfpath} address') or - conf.exists(f'{intfpath} ipv6 address autoconf') or - conf.exists(f'{intfpath} ipv6 address eui64') ): - ret = True - - conf.set_level(old_level) - return ret - -def has_vrf_configured(conf, intf): - """ - Checks if interface has a VRF configured. - - Returns True if interface has VRF configured, False if it doesn't. - """ - from vyos.ifconfig import Section - ret = False - - old_level = conf.get_level() - conf.set_level([]) - - tmp = ['interfaces', Section.get_config_path(intf), 'vrf'] - if conf.exists(tmp): - ret = True - - conf.set_level(old_level) - return ret diff --git a/smoketest/scripts/cli/base_interfaces_test.py b/smoketest/scripts/cli/base_interfaces_test.py index a3868fa70..cef61e42b 100644 --- a/smoketest/scripts/cli/base_interfaces_test.py +++ b/smoketest/scripts/cli/base_interfaces_test.py @@ -26,17 +26,24 @@ from base_vyostest_shim import VyOSUnitTestSHIM from vyos.configsession import ConfigSession from vyos.configsession import ConfigSessionError +from vyos.defaults import directories from vyos.ifconfig import Interface from vyos.ifconfig import Section from vyos.utils.file import read_file from vyos.utils.dict import dict_search from vyos.utils.process import process_named_running from vyos.utils.network import get_interface_config +from vyos.utils.network import get_interface_vrf from vyos.utils.process import cmd -from vyos.validate import is_intf_addr_assigned -from vyos.validate import is_ipv6_link_local +from vyos.utils.network import is_intf_addr_assigned +from vyos.utils.network import is_ipv6_link_local from vyos.xml_ref import cli_defined +dhclient_base_dir = directories['isc_dhclient_dir'] +dhclient_process_name = 'dhclient' +dhcp6c_base_dir = directories['dhcp6_client_dir'] +dhcp6c_process_name = 'dhcp6c' + def is_mirrored_to(interface, mirror_if, qdisc): """ Ask TC if we are mirroring traffic to a discrete interface. @@ -66,6 +73,7 @@ class BasicInterfaceTest: _test_ipv6_pd = False _test_ipv6_dhcpc6 = False _test_mirror = False + _test_vrf = False _base_path = [] _options = {} @@ -93,6 +101,7 @@ class BasicInterfaceTest: cls._test_ipv6_dhcpc6 = cli_defined(cls._base_path, 'dhcpv6-options') cls._test_ipv6_pd = cli_defined(cls._base_path + ['dhcpv6-options'], 'pd') cls._test_mtu = cli_defined(cls._base_path, 'mtu') + cls._test_vrf = cli_defined(cls._base_path, 'vrf') # Setup mirror interfaces for SPAN (Switch Port Analyzer) for span in cls._mirror_interfaces: @@ -137,8 +146,6 @@ class BasicInterfaceTest: for option in self._options.get(interface, []): self.cli_set(self._base_path + [interface] + option.split()) - self.cli_set(self._base_path + [interface, 'disable']) - # Also enable DHCP (ISC DHCP always places interface in admin up # state so we check that we do not start DHCP client. # https://vyos.dev/T2767 @@ -151,6 +158,99 @@ class BasicInterfaceTest: flags = read_file(f'/sys/class/net/{interface}/flags') self.assertEqual(int(flags, 16) & 1, 0) + def test_dhcp_client_options(self): + if not self._test_dhcp or not self._test_vrf: + self.skipTest('not supported') + + distance = '100' + + for interface in self._interfaces: + for option in self._options.get(interface, []): + self.cli_set(self._base_path + [interface] + option.split()) + + self.cli_set(self._base_path + [interface, 'address', 'dhcp']) + self.cli_set(self._base_path + [interface, 'dhcp-options', 'default-route-distance', distance]) + + self.cli_commit() + + for interface in self._interfaces: + # Check if dhclient process runs + dhclient_pid = process_named_running(dhclient_process_name, cmdline=interface) + self.assertTrue(dhclient_pid) + + dhclient_config = read_file(f'{dhclient_base_dir}/dhclient_{interface}.conf') + self.assertIn('request subnet-mask, broadcast-address, routers, domain-name-servers', dhclient_config) + self.assertIn('require subnet-mask;', dhclient_config) + + # and the commandline has the appropriate options + cmdline = read_file(f'/proc/{dhclient_pid}/cmdline') + self.assertIn(f'-e\x00IF_METRIC={distance}', cmdline) + + def test_dhcp_vrf(self): + if not self._test_dhcp or not self._test_vrf: + self.skipTest('not supported') + + vrf_name = 'purple4' + self.cli_set(['vrf', 'name', vrf_name, 'table', '65000']) + + for interface in self._interfaces: + for option in self._options.get(interface, []): + self.cli_set(self._base_path + [interface] + option.split()) + + self.cli_set(self._base_path + [interface, 'address', 'dhcp']) + self.cli_set(self._base_path + [interface, 'vrf', vrf_name]) + + self.cli_commit() + + # Validate interface state + for interface in self._interfaces: + tmp = get_interface_vrf(interface) + self.assertEqual(tmp, vrf_name) + + # Check if dhclient process runs + dhclient_pid = process_named_running(dhclient_process_name, cmdline=interface) + self.assertTrue(dhclient_pid) + # .. inside the appropriate VRF instance + vrf_pids = cmd(f'ip vrf pids {vrf_name}') + self.assertIn(str(dhclient_pid), vrf_pids) + # and the commandline has the appropriate options + cmdline = read_file(f'/proc/{dhclient_pid}/cmdline') + self.assertIn('-e\x00IF_METRIC=210', cmdline) # 210 is the default value + + self.cli_delete(['vrf', 'name', vrf_name]) + + def test_dhcpv6_vrf(self): + if not self._test_ipv6_dhcpc6 or not self._test_vrf: + self.skipTest('not supported') + + vrf_name = 'purple6' + self.cli_set(['vrf', 'name', vrf_name, 'table', '65001']) + + # When interface is configured as admin down, it must be admin down + # even when dhcpc starts on the given interface + for interface in self._interfaces: + for option in self._options.get(interface, []): + self.cli_set(self._base_path + [interface] + option.split()) + + self.cli_set(self._base_path + [interface, 'address', 'dhcpv6']) + self.cli_set(self._base_path + [interface, 'vrf', vrf_name]) + + self.cli_commit() + + # Validate interface state + for interface in self._interfaces: + tmp = get_interface_vrf(interface) + self.assertEqual(tmp, vrf_name) + + # Check if dhclient process runs + tmp = process_named_running(dhcp6c_process_name, cmdline=interface) + self.assertTrue(tmp) + # .. inside the appropriate VRF instance + vrf_pids = cmd(f'ip vrf pids {vrf_name}') + self.assertIn(str(tmp), vrf_pids) + + self.cli_delete(['vrf', 'name', vrf_name]) + def test_span_mirror(self): if not self._mirror_interfaces: self.skipTest('not supported') @@ -799,13 +899,10 @@ class BasicInterfaceTest: self.cli_commit() - dhcp6c_options = read_file(f'/run/dhcp6c/dhcp6c.{interface}.options') - self.assertIn(f'-n', dhcp6c_options) - duid_base = 10 for interface in self._interfaces: duid = '00:01:00:01:27:71:db:f0:00:50:00:00:00:{}'.format(duid_base) - dhcpc6_config = read_file(f'/run/dhcp6c/dhcp6c.{interface}.conf') + dhcpc6_config = read_file(f'{dhcp6c_base_dir}/dhcp6c.{interface}.conf') self.assertIn(f'interface {interface} ' + '{', dhcpc6_config) self.assertIn(f' request domain-name-servers;', dhcpc6_config) self.assertIn(f' request domain-name;', dhcpc6_config) @@ -816,8 +913,12 @@ class BasicInterfaceTest: self.assertIn('};', dhcpc6_config) duid_base += 1 - # Check for running process - self.assertTrue(process_named_running('dhcp6c')) + # Better ask the process about it's commandline in the future + pid = process_named_running(dhcp6c_process_name, cmdline=interface) + self.assertTrue(pid) + + dhcp6c_options = read_file(f'/proc/{pid}/cmdline') + self.assertIn('-n', dhcp6c_options) def test_dhcpv6pd_auto_sla_id(self): if not self._test_ipv6_pd: @@ -853,7 +954,7 @@ class BasicInterfaceTest: self.cli_commit() for interface in self._interfaces: - dhcpc6_config = read_file(f'/run/dhcp6c/dhcp6c.{interface}.conf') + dhcpc6_config = read_file(f'{dhcp6c_base_dir}/dhcp6c.{interface}.conf') # verify DHCPv6 prefix delegation self.assertIn(f'prefix ::/{prefix_len} infinity;', dhcpc6_config) @@ -871,8 +972,8 @@ class BasicInterfaceTest: # increment interface address address = str(int(address) + 1) - # Check for running process - self.assertTrue(process_named_running('dhcp6c')) + # Check for running process + self.assertTrue(process_named_running(dhcp6c_process_name, cmdline=interface)) for delegatee in delegatees: # we can already cleanup the test delegatee interface here @@ -921,7 +1022,7 @@ class BasicInterfaceTest: for interface in self._interfaces: address = '1' sla_id = '1' - dhcpc6_config = read_file(f'/run/dhcp6c/dhcp6c.{interface}.conf') + dhcpc6_config = read_file(f'{dhcp6c_base_dir}/dhcp6c.{interface}.conf') # verify DHCPv6 prefix delegation self.assertIn(f'prefix ::/{prefix_len} infinity;', dhcpc6_config) @@ -938,7 +1039,7 @@ class BasicInterfaceTest: address = str(int(address) + 1) # Check for running process - self.assertTrue(process_named_running('dhcp6c', interface)) + self.assertTrue(process_named_running(dhcp6c_process_name, cmdline=interface)) for delegatee in delegatees: # we can already cleanup the test delegatee interface here diff --git a/smoketest/scripts/cli/test_interfaces_bonding.py b/smoketest/scripts/cli/test_interfaces_bonding.py index d8e6bde5c..8867cb427 100755 --- a/smoketest/scripts/cli/test_interfaces_bonding.py +++ b/smoketest/scripts/cli/test_interfaces_bonding.py @@ -37,9 +37,8 @@ class BondingInterfaceTest(BasicInterfaceTest.TestCase): if 'TEST_ETH' in os.environ: cls._members = os.environ['TEST_ETH'].split() else: - for tmp in Section.interfaces('ethernet'): - if not '.' in tmp: - cls._members.append(tmp) + for tmp in Section.interfaces('ethernet', vlan=False): + cls._members.append(tmp) cls._options = {'bond0' : []} for member in cls._members: diff --git a/smoketest/scripts/cli/test_interfaces_bridge.py b/smoketest/scripts/cli/test_interfaces_bridge.py index 674b0535a..cdff49f4b 100755 --- a/smoketest/scripts/cli/test_interfaces_bridge.py +++ b/smoketest/scripts/cli/test_interfaces_bridge.py @@ -27,7 +27,7 @@ from vyos.ifconfig import Section from vyos.utils.process import cmd from vyos.utils.file import read_file from vyos.utils.network import get_interface_config -from vyos.validate import is_intf_addr_assigned +from vyos.utils.network import is_intf_addr_assigned class BridgeInterfaceTest(BasicInterfaceTest.TestCase): @classmethod @@ -41,9 +41,8 @@ class BridgeInterfaceTest(BasicInterfaceTest.TestCase): if 'TEST_ETH' in os.environ: cls._members = os.environ['TEST_ETH'].split() else: - for tmp in Section.interfaces('ethernet'): - if not '.' in tmp: - cls._members.append(tmp) + for tmp in Section.interfaces('ethernet', vlan=False): + cls._members.append(tmp) cls._options['br0'] = [] for member in cls._members: diff --git a/smoketest/scripts/cli/test_interfaces_ethernet.py b/smoketest/scripts/cli/test_interfaces_ethernet.py index eec3ddbe8..5ea21fea8 100755 --- a/smoketest/scripts/cli/test_interfaces_ethernet.py +++ b/smoketest/scripts/cli/test_interfaces_ethernet.py @@ -31,7 +31,7 @@ from vyos.template import is_ipv6 from vyos.utils.process import cmd from vyos.utils.process import process_named_running from vyos.utils.file import read_file -from vyos.validate import is_ipv6_link_local +from vyos.utils.network import is_ipv6_link_local server_ca_root_cert_data = """ MIIBcTCCARagAwIBAgIUDcAf1oIQV+6WRaW7NPcSnECQ/lUwCgYIKoZIzj0EAwIw diff --git a/smoketest/scripts/cli/test_interfaces_loopback.py b/smoketest/scripts/cli/test_interfaces_loopback.py index cde90189b..0454dc658 100755 --- a/smoketest/scripts/cli/test_interfaces_loopback.py +++ b/smoketest/scripts/cli/test_interfaces_loopback.py @@ -19,7 +19,7 @@ import unittest from base_interfaces_test import BasicInterfaceTest from netifaces import interfaces -from vyos.validate import is_intf_addr_assigned +from vyos.utils.network import is_intf_addr_assigned loopbacks = ['127.0.0.1', '::1'] diff --git a/smoketest/scripts/cli/test_interfaces_wireguard.py b/smoketest/scripts/cli/test_interfaces_wireguard.py index 14fc8d109..f84ce159d 100755 --- a/smoketest/scripts/cli/test_interfaces_wireguard.py +++ b/smoketest/scripts/cli/test_interfaces_wireguard.py @@ -100,5 +100,34 @@ class WireGuardInterfaceTest(VyOSUnitTestSHIM.TestCase): self.cli_delete(base_path + [interface, 'peer', 'PEER01']) self.cli_commit() + def test_wireguard_same_public_key(self): + # T2939: Create WireGuard interfaces with associated peers. + # Remove one of the configured peers. + # T4774: Test prevention of duplicate peer public keys + interface = 'wg0' + port = '12345' + privkey = 'OOjcXGfgQlAuM6q8Z9aAYduCua7pxf7UKYvIqoUPoGQ=' + pubkey_fail = 'eiVeYKq66mqKLbrZLzlckSP9voaw8jSFyVNiNTdZDjU=' + pubkey_ok = 'ebFx/1G0ti8tvuZd94sEIosAZZIznX+dBAKG/8DFm0I=' + + self.cli_set(base_path + [interface, 'address', '172.16.0.1/24']) + self.cli_set(base_path + [interface, 'private-key', privkey]) + + self.cli_set(base_path + [interface, 'peer', 'PEER01', 'public-key', pubkey_fail]) + self.cli_set(base_path + [interface, 'peer', 'PEER01', 'port', port]) + self.cli_set(base_path + [interface, 'peer', 'PEER01', 'allowed-ips', '10.205.212.10/32']) + self.cli_set(base_path + [interface, 'peer', 'PEER01', 'address', '192.0.2.1']) + + # The same pubkey as the interface wg0 + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + self.cli_set(base_path + [interface, 'peer', 'PEER01', 'public-key', pubkey_ok]) + + # Commit peers + self.cli_commit() + + self.assertTrue(os.path.isdir(f'/sys/class/net/{interface}')) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_service_dns_dynamic.py b/smoketest/scripts/cli/test_service_dns_dynamic.py index f6c42e8c9..ee8a07b37 100755 --- a/smoketest/scripts/cli/test_service_dns_dynamic.py +++ b/smoketest/scripts/cli/test_service_dns_dynamic.py @@ -14,7 +14,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 re import os import unittest import tempfile @@ -34,13 +33,6 @@ zone = 'vyos.io' password = 'paSS_@4ord' interface = 'eth0' - -def get_config_value(key): - tmp = cmd(f'sudo cat {DDCLIENT_CONF}') - vals = re.findall(r'\n?{}=([.-@_A-Za-z0-9]+),? \\'.format(key), tmp) - return vals[0] if vals else '' - - class TestServiceDDNS(VyOSUnitTestSHIM.TestCase): def tearDown(self): # Check for running process @@ -54,45 +46,54 @@ class TestServiceDDNS(VyOSUnitTestSHIM.TestCase): self.assertFalse(os.path.exists(DDCLIENT_PID)) # IPv4 standard DDNS service configuration - def test_dyndns_service_standard(self): + def test_01_dyndns_service_standard(self): ddns = ['address', interface, 'service'] services = {'cloudflare': {'protocol': 'cloudflare'}, 'freedns': {'protocol': 'freedns', 'username': 'vyos_user'}, 'zoneedit': {'protocol': 'zoneedit1', 'username': 'vyos_user'}} for svc, details in services.items(): + # Always start with a clean CLI instance self.cli_delete(base_path) + self.cli_set(base_path + ddns + [svc, 'host-name', hostname]) - for opt, value in details.items(): - self.cli_set(base_path + ddns + [svc, opt, value]) self.cli_set(base_path + ddns + [svc, 'password', password]) self.cli_set(base_path + ddns + [svc, 'zone', zone]) + for opt, value in details.items(): + self.cli_set(base_path + ddns + [svc, opt, value]) # commit changes if details['protocol'] == 'cloudflare': - self.cli_commit() + pass else: # zone option does not work on all protocols, an exception is # raised for all others with self.assertRaises(ConfigSessionError): self.cli_commit() self.cli_delete(base_path + ddns + [svc, 'zone', zone]) - # commit changes again - now it should work - self.cli_commit() + + # commit changes + self.cli_commit() # Check the generating config parameters - self.assertEqual(get_config_value('use'), 'if') - self.assertEqual(get_config_value('if'), interface) - self.assertEqual(get_config_value('password'), password) + ddclient_conf = cmd(f'sudo cat {DDCLIENT_CONF}') + # default value 300 seconds + self.assertIn(f'daemon=300', ddclient_conf) + self.assertIn(f'use=if', ddclient_conf) + self.assertIn(f'if={interface}', ddclient_conf) + self.assertIn(f'password={password}', ddclient_conf) for opt in details.keys(): if opt == 'username': - self.assertEqual(get_config_value('login'), details[opt]) + login = details[opt] + self.assertIn(f'login={login}', ddclient_conf) else: - self.assertEqual(get_config_value(opt), details[opt]) + tmp = details[opt] + self.assertIn(f'{opt}={tmp}', ddclient_conf) # IPv6 only DDNS service configuration - def test_dyndns_service_ipv6(self): + def test_02_dyndns_service_ipv6(self): + timeout = '60' ddns = ['address', interface, 'service', 'dynv6'] proto = 'dyndns2' user = 'none' @@ -100,6 +101,7 @@ class TestServiceDDNS(VyOSUnitTestSHIM.TestCase): srv = 'ddns.vyos.io' ip_version = 'ipv6' + self.cli_set(base_path + ['timeout', timeout]) self.cli_set(base_path + ddns + ['ip-version', ip_version]) self.cli_set(base_path + ddns + ['protocol', proto]) self.cli_set(base_path + ddns + ['server', srv]) @@ -111,15 +113,17 @@ class TestServiceDDNS(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Check the generating config parameters - self.assertEqual(get_config_value('usev6'), 'ifv6') - self.assertEqual(get_config_value('ifv6'), interface) - self.assertEqual(get_config_value('protocol'), proto) - self.assertEqual(get_config_value('server'), srv) - self.assertEqual(get_config_value('login'), user) - self.assertEqual(get_config_value('password'), password) + ddclient_conf = cmd(f'sudo cat {DDCLIENT_CONF}') + self.assertIn(f'daemon={timeout}', ddclient_conf) + self.assertIn(f'usev6=ifv6', ddclient_conf) + self.assertIn(f'ifv6={interface}', ddclient_conf) + self.assertIn(f'protocol={proto}', ddclient_conf) + self.assertIn(f'server={srv}', ddclient_conf) + self.assertIn(f'login={user}', ddclient_conf) + self.assertIn(f'password={password}', ddclient_conf) # IPv4+IPv6 dual DDNS service configuration - def test_dyndns_service_dual_stack(self): + def test_03_dyndns_service_dual_stack(self): ddns = ['address', interface, 'service'] services = {'cloudflare': {'protocol': 'cloudflare', 'zone': 'vyos.io'}, 'freedns': {'protocol': 'freedns', 'username': 'vyos_user'}} @@ -127,30 +131,35 @@ class TestServiceDDNS(VyOSUnitTestSHIM.TestCase): ip_version = 'both' for svc, details in services.items(): + # Always start with a clean CLI instance self.cli_delete(base_path) + self.cli_set(base_path + ddns + [svc, 'host-name', hostname]) - for opt, value in details.items(): - self.cli_set(base_path + ddns + [svc, opt, value]) self.cli_set(base_path + ddns + [svc, 'password', password]) self.cli_set(base_path + ddns + [svc, 'ip-version', ip_version]) + for opt, value in details.items(): + self.cli_set(base_path + ddns + [svc, opt, value]) # commit changes self.cli_commit() # Check the generating config parameters - self.assertEqual(get_config_value('usev4'), 'ifv4') - self.assertEqual(get_config_value('usev6'), 'ifv6') - self.assertEqual(get_config_value('ifv4'), interface) - self.assertEqual(get_config_value('ifv6'), interface) - self.assertEqual(get_config_value('password'), password) + ddclient_conf = cmd(f'sudo cat {DDCLIENT_CONF}') + self.assertIn(f'usev4=ifv4', ddclient_conf) + self.assertIn(f'usev6=ifv6', ddclient_conf) + self.assertIn(f'ifv4={interface}', ddclient_conf) + self.assertIn(f'ifv6={interface}', ddclient_conf) + self.assertIn(f'password={password}', ddclient_conf) for opt in details.keys(): if opt == 'username': - self.assertEqual(get_config_value('login'), details[opt]) + login = details[opt] + self.assertIn(f'login={login}', ddclient_conf) else: - self.assertEqual(get_config_value(opt), details[opt]) + tmp = details[opt] + self.assertIn(f'{opt}={tmp}', ddclient_conf) - def test_dyndns_rfc2136(self): + def test_04_dyndns_rfc2136(self): # Check if DDNS service can be configured and runs ddns = ['address', interface, 'rfc2136', 'vyos'] srv = 'ns1.vyos.io' @@ -170,14 +179,14 @@ class TestServiceDDNS(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Check some generating config parameters - self.assertEqual(get_config_value('use'), 'if') - self.assertEqual(get_config_value('if'), interface) - self.assertEqual(get_config_value('protocol'), 'nsupdate') - self.assertEqual(get_config_value('server'), srv) - self.assertEqual(get_config_value('zone'), zone) - self.assertEqual(get_config_value('password'), key_file.name) - self.assertEqual(get_config_value('ttl'), ttl) - + ddclient_conf = cmd(f'sudo cat {DDCLIENT_CONF}') + self.assertIn(f'use=if', ddclient_conf) + self.assertIn(f'if={interface}', ddclient_conf) + self.assertIn(f'protocol=nsupdate', ddclient_conf) + self.assertIn(f'server={srv}', ddclient_conf) + self.assertIn(f'zone={zone}', ddclient_conf) + self.assertIn(f'password={key_file.name}', ddclient_conf) + self.assertIn(f'ttl={ttl}', ddclient_conf) if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_system_ipv6.py b/smoketest/scripts/cli/test_system_ipv6.py index b540be9ff..978af3766 100755 --- a/smoketest/scripts/cli/test_system_ipv6.py +++ b/smoketest/scripts/cli/test_system_ipv6.py @@ -22,7 +22,7 @@ from vyos.configsession import ConfigSessionError from vyos.template import is_ipv4 from vyos.utils.file import read_file from vyos.utils.network import get_interface_config -from vyos.validate import is_intf_addr_assigned +from vyos.utils.network import is_intf_addr_assigned base_path = ['system', 'ipv6'] diff --git a/smoketest/scripts/cli/test_vrf.py b/smoketest/scripts/cli/test_vrf.py index 932f7b4f1..5fb599a87 100755 --- a/smoketest/scripts/cli/test_vrf.py +++ b/smoketest/scripts/cli/test_vrf.py @@ -29,7 +29,7 @@ from vyos.template import is_ipv4 from vyos.utils.process import cmd from vyos.utils.file import read_file from vyos.utils.network import get_interface_config -from vyos.validate import is_intf_addr_assigned +from vyos.utils.network import is_intf_addr_assigned base_path = ['vrf'] vrfs = ['red', 'green', 'blue', 'foo-bar', 'baz_foo'] @@ -47,9 +47,8 @@ class VRFTest(VyOSUnitTestSHIM.TestCase): tmp = os.environ['TEST_ETH'].split() cls._interfaces = tmp else: - for tmp in Section.interfaces('ethernet'): - if not '.' in tmp: - cls._interfaces.append(tmp) + for tmp in Section.interfaces('ethernet', vlan=False): + cls._interfaces.append(tmp) # call base-classes classmethod super(VRFTest, cls).setUpClass() diff --git a/src/conf_mode/bcast_relay.py b/src/conf_mode/bcast_relay.py index ced5d212e..31c552f5a 100755 --- a/src/conf_mode/bcast_relay.py +++ b/src/conf_mode/bcast_relay.py @@ -24,7 +24,7 @@ from vyos.config import Config from vyos.configverify import verify_interface_exists from vyos.template import render from vyos.utils.process import call -from vyos.validate import is_afi_configured +from vyos.utils.network import is_afi_configured from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/conntrack_sync.py b/src/conf_mode/conntrack_sync.py index a83c2274d..6a4d102f7 100755 --- a/src/conf_mode/conntrack_sync.py +++ b/src/conf_mode/conntrack_sync.py @@ -27,7 +27,7 @@ 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 +from vyos.utils.network import is_addr_assigned from vyos.xml import defaults from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/dhcp_server.py b/src/conf_mode/dhcp_server.py index c29270367..3ea708902 100755 --- a/src/conf_mode/dhcp_server.py +++ b/src/conf_mode/dhcp_server.py @@ -28,8 +28,8 @@ from vyos.template import render 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.utils.network import is_subnet_connected +from vyos.utils.network import is_addr_assigned from vyos.xml import defaults from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/dhcpv6_relay.py b/src/conf_mode/dhcpv6_relay.py index 0e7da6f89..d912611b3 100755 --- a/src/conf_mode/dhcpv6_relay.py +++ b/src/conf_mode/dhcpv6_relay.py @@ -25,7 +25,7 @@ from vyos.template import render 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.utils.network import is_ipv6_link_local from vyos.xml import defaults from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/dhcpv6_server.py b/src/conf_mode/dhcpv6_server.py index f89ad5b9c..427001609 100755 --- a/src/conf_mode/dhcpv6_server.py +++ b/src/conf_mode/dhcpv6_server.py @@ -25,7 +25,7 @@ from vyos.template import render from vyos.template import is_ipv6 from vyos.utils.process import call from vyos.utils.dict import dict_search -from vyos.validate import is_subnet_connected +from vyos.utils.network import is_subnet_connected from vyos import ConfigError from vyos import airbag airbag.enable() diff --git a/src/conf_mode/dns_dynamic.py b/src/conf_mode/dns_dynamic.py index d78eb70bc..97d46148a 100755 --- a/src/conf_mode/dns_dynamic.py +++ b/src/conf_mode/dns_dynamic.py @@ -49,16 +49,9 @@ def get_config(config=None): if not conf.exists(base_level): return None - dyndns = conf.get_config_dict(base_level, key_mangling=('-', '_'), get_first_key=True) - - if 'address' in dyndns: - for address in dyndns['address']: - # Apply service specific defaults (svc_type = ['rfc2136', 'service']) - for svc_type in dyndns['address'][address]: - default_values = defaults(base_level + ['address', svc_type]) - for svc_cfg in dyndns['address'][address][svc_type]: - dyndns['address'][address][svc_type][svc_cfg] = dict_merge( - default_values, dyndns['address'][address][svc_type][svc_cfg]) + dyndns = conf.get_config_dict(base_level, key_mangling=('-', '_'), + get_first_key=True, no_tag_node_value_mangle=True, + with_defaults=True, with_recursive_defaults=True) dyndns['config_file'] = config_file return dyndns diff --git a/src/conf_mode/flow_accounting_conf.py b/src/conf_mode/flow_accounting_conf.py index bfe906c87..372bb0da7 100755 --- a/src/conf_mode/flow_accounting_conf.py +++ b/src/conf_mode/flow_accounting_conf.py @@ -28,7 +28,7 @@ from vyos.ifconfig import Section from vyos.template import render from vyos.utils.process import call from vyos.utils.process import cmd -from vyos.validate import is_addr_assigned +from vyos.utils.network import is_addr_assigned from vyos.xml import defaults from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/high-availability.py b/src/conf_mode/high-availability.py index 0cbd4c49c..626a3757e 100755 --- a/src/conf_mode/high-availability.py +++ b/src/conf_mode/high-availability.py @@ -14,7 +14,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 from sys import exit from ipaddress import ip_interface @@ -23,14 +22,11 @@ from ipaddress import IPv6Interface from vyos.base import Warning from vyos.config import Config -from vyos.configdict import dict_merge 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.utils.process import call -from vyos.utils.dict import dict_search -from vyos.xml import defaults from vyos import ConfigError from vyos import airbag airbag.enable() @@ -42,42 +38,12 @@ def get_config(config=None): conf = Config() base = ['high-availability'] - base_vrrp = ['high-availability', 'vrrp'] if not conf.exists(base): return None ha = conf.get_config_dict(base, key_mangling=('-', '_'), - get_first_key=True, no_tag_node_value_mangle=True) - # We have gathered the dict representation of the CLI, but there are default - # options which we need to update into the dictionary retrived. - if 'vrrp' in ha: - if dict_search('vrrp.global_parameters.garp', ha) != None: - default_values = defaults(base_vrrp + ['global-parameters', 'garp']) - ha['vrrp']['global_parameters']['garp'] = dict_merge( - default_values, ha['vrrp']['global_parameters']['garp']) - - if 'group' in ha['vrrp']: - default_values = defaults(base_vrrp + ['group']) - default_values_garp = defaults(base_vrrp + ['group', 'garp']) - - # XXX: T2665: we can not safely rely on the defaults() when there are - # tagNodes in place, it is better to blend in the defaults manually. - if 'garp' in default_values: - del default_values['garp'] - for group in ha['vrrp']['group']: - ha['vrrp']['group'][group] = dict_merge(default_values, ha['vrrp']['group'][group]) - - # XXX: T2665: we can not safely rely on the defaults() when there are - # tagNodes in place, it is better to blend in the defaults manually. - if 'garp' in ha['vrrp']['group'][group]: - ha['vrrp']['group'][group]['garp'] = dict_merge( - default_values_garp, ha['vrrp']['group'][group]['garp']) - - # Merge per virtual-server default values - if 'virtual_server' in ha: - default_values = defaults(base + ['virtual-server']) - for vs in ha['virtual_server']: - ha['virtual_server'][vs] = dict_merge(default_values, ha['virtual_server'][vs]) + no_tag_node_value_mangle=True, + get_first_key=True, with_defaults=True) ## Get the sync group used for conntrack-sync conntrack_path = ['service', 'conntrack-sync', 'failover-mechanism', 'vrrp', 'sync-group'] @@ -112,7 +78,7 @@ def verify(ha): from vyos.utils.dict import check_mutually_exclusive_options try: check_mutually_exclusive_options(group_config["health_check"], health_check_types, required=True) - except ValueError as e: + except ValueError: Warning(f'Health check configuration for VRRP group "{group}" will remain unused ' \ f'until it has one of the following options: {health_check_types}') # XXX: health check has default options so we need to remove it diff --git a/src/conf_mode/interfaces-bonding.py b/src/conf_mode/interfaces-bonding.py index c2a569fa9..0bd306ed0 100755 --- a/src/conf_mode/interfaces-bonding.py +++ b/src/conf_mode/interfaces-bonding.py @@ -36,8 +36,8 @@ from vyos.configverify import verify_vrf from vyos.ifconfig import BondIf from vyos.ifconfig import Section from vyos.utils.dict import dict_search -from vyos.validate import has_address_configured -from vyos.validate import has_vrf_configured +from vyos.configdict import has_address_configured +from vyos.configdict import has_vrf_configured from vyos import ConfigError from vyos import airbag airbag.enable() @@ -195,11 +195,11 @@ def verify(bond): raise ConfigError(error_msg + 'it does not exist!') if 'is_bridge_member' in interface_config: - tmp = interface_config['is_bridge_member'] + tmp = next(iter(interface_config['is_bridge_member'])) raise ConfigError(error_msg + f'it is already a member of bridge "{tmp}"!') if 'is_bond_member' in interface_config: - tmp = interface_config['is_bond_member'] + tmp = next(iter(interface_config['is_bond_member'])) raise ConfigError(error_msg + f'it is already a member of bond "{tmp}"!') if 'is_source_interface' in interface_config: diff --git a/src/conf_mode/interfaces-bridge.py b/src/conf_mode/interfaces-bridge.py index 087ead20a..1bdd61eca 100755 --- a/src/conf_mode/interfaces-bridge.py +++ b/src/conf_mode/interfaces-bridge.py @@ -30,8 +30,8 @@ from vyos.configverify import verify_dhcpv6 from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_vrf from vyos.ifconfig import BridgeIf -from vyos.validate import has_address_configured -from vyos.validate import has_vrf_configured +from vyos.configdict import has_address_configured +from vyos.configdict import has_vrf_configured from vyos.xml import defaults from vyos.utils.process import cmd diff --git a/src/conf_mode/interfaces-l2tpv3.py b/src/conf_mode/interfaces-l2tpv3.py index 6efeac302..e1db3206e 100755 --- a/src/conf_mode/interfaces-l2tpv3.py +++ b/src/conf_mode/interfaces-l2tpv3.py @@ -29,7 +29,7 @@ from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_bond_bridge_member from vyos.ifconfig import L2TPv3If from vyos.utils.kernel import check_kmod -from vyos.validate import is_addr_assigned +from vyos.utils.network import is_addr_assigned 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 3bef9b8f6..2a9b43f9b 100755 --- a/src/conf_mode/interfaces-openvpn.py +++ b/src/conf_mode/interfaces-openvpn.py @@ -61,7 +61,7 @@ from vyos.utils.kernel import unload_kmod 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.utils.network import is_addr_assigned from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/interfaces-vxlan.py b/src/conf_mode/interfaces-vxlan.py index b1536148c..a3b0867e0 100755 --- a/src/conf_mode/interfaces-vxlan.py +++ b/src/conf_mode/interfaces-vxlan.py @@ -87,8 +87,8 @@ def verify(vxlan): raise ConfigError('Multicast VXLAN requires an underlaying interface') verify_source_interface(vxlan) - if not any(tmp in ['group', 'remote', 'source_address'] for tmp in vxlan): - raise ConfigError('Group, remote or source-address must be configured') + if not any(tmp in ['group', 'remote', 'source_address', 'source_interface'] for tmp in vxlan): + raise ConfigError('Group, remote, source-address or source-interface must be configured') if 'vni' not in vxlan and 'external' not in vxlan: raise ConfigError( diff --git a/src/conf_mode/interfaces-wireguard.py b/src/conf_mode/interfaces-wireguard.py index a02baba82..446399255 100755 --- a/src/conf_mode/interfaces-wireguard.py +++ b/src/conf_mode/interfaces-wireguard.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 @@ -29,10 +29,12 @@ from vyos.configverify import verify_bond_bridge_member from vyos.ifconfig import WireGuardIf from vyos.utils.kernel import check_kmod from vyos.utils.network import check_port_availability +from vyos.utils.network import is_wireguard_key_pair from vyos import ConfigError from vyos import airbag airbag.enable() + def get_config(config=None): """ Retrive CLI config as dictionary. Dictionary can never be empty, as at least the @@ -105,6 +107,9 @@ def verify(wireguard): if peer['public_key'] in public_keys: raise ConfigError(f'Duplicate public-key defined on peer "{tmp}"') + if 'disable' not in peer and is_wireguard_key_pair(wireguard['private_key'], peer['public_key']): + raise ConfigError(f'Peer "{tmp}" has the same public key as the interface "{wireguard["ifname"]}"') + public_keys.append(peer['public_key']) def apply(wireguard): diff --git a/src/conf_mode/lldp.py b/src/conf_mode/lldp.py index 0e5fc29d3..c8f341327 100755 --- a/src/conf_mode/lldp.py +++ b/src/conf_mode/lldp.py @@ -21,8 +21,8 @@ from sys import exit from vyos.base import Warning from vyos.config import Config from vyos.configdict import dict_merge -from vyos.validate import is_addr_assigned -from vyos.validate import is_loopback_addr +from vyos.utils.network import is_addr_assigned +from vyos.utils.network import is_loopback_addr from vyos.version import get_version_data from vyos.utils.process import call from vyos.utils.dict import dict_search diff --git a/src/conf_mode/nat.py b/src/conf_mode/nat.py index 5af06ed16..8e3a11ff4 100755 --- a/src/conf_mode/nat.py +++ b/src/conf_mode/nat.py @@ -33,7 +33,7 @@ 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.utils.network import is_addr_assigned from vyos.xml import defaults from vyos import ConfigError diff --git a/src/conf_mode/protocols_bfd.py b/src/conf_mode/protocols_bfd.py index 0436abaf9..b8d2d65ee 100755 --- a/src/conf_mode/protocols_bfd.py +++ b/src/conf_mode/protocols_bfd.py @@ -21,7 +21,7 @@ from vyos.configdict import dict_merge from vyos.configverify import verify_vrf from vyos.template import is_ipv6 from vyos.template import render_to_string -from vyos.validate import is_ipv6_link_local +from vyos.utils.network import is_ipv6_link_local from vyos.xml import defaults from vyos import ConfigError from vyos import frr diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py index 7b9f15505..00015023c 100755 --- a/src/conf_mode/protocols_bgp.py +++ b/src/conf_mode/protocols_bgp.py @@ -29,7 +29,7 @@ from vyos.template import is_interface from vyos.template import render_to_string from vyos.utils.dict import dict_search from vyos.utils.network import get_interface_vrf -from vyos.validate import is_addr_assigned +from vyos.utils.network import is_addr_assigned from vyos import ConfigError from vyos import frr from vyos import airbag diff --git a/src/conf_mode/service_webproxy.py b/src/conf_mode/service_webproxy.py index bbdb756bd..db4066572 100755 --- a/src/conf_mode/service_webproxy.py +++ b/src/conf_mode/service_webproxy.py @@ -26,7 +26,7 @@ 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.utils.network import is_addr_assigned from vyos.xml import defaults from vyos.base import Warning from vyos import ConfigError diff --git a/src/conf_mode/snmp.py b/src/conf_mode/snmp.py index 0f0d97ac3..4bf67f079 100755 --- a/src/conf_mode/snmp.py +++ b/src/conf_mode/snmp.py @@ -29,7 +29,7 @@ from vyos.template import render 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.utils.network import is_addr_assigned from vyos.version import get_version_data from vyos.xml import defaults from vyos import ConfigError diff --git a/src/conf_mode/system-option.py b/src/conf_mode/system-option.py index 5172b492e..917013651 100755 --- a/src/conf_mode/system-option.py +++ b/src/conf_mode/system-option.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 @@ -26,8 +26,8 @@ from vyos.configverify import verify_source_interface from vyos.template import render 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.utils.network import is_addr_assigned +from vyos.utils.network import is_intf_addr_assigned from vyos.xml import defaults from vyos import ConfigError from vyos import airbag @@ -36,6 +36,11 @@ airbag.enable() curlrc_config = r'/etc/curlrc' ssh_config = r'/etc/ssh/ssh_config.d/91-vyos-ssh-client-options.conf' systemd_action_file = '/lib/systemd/system/ctrl-alt-del.target' +time_format_to_locale = { + '12-hour': 'en_US.UTF-8', + '24-hour': 'en_GB.UTF-8' +} + def get_config(config=None): if config: @@ -143,6 +148,11 @@ def apply(options): else: cmd('systemctl disable root-partition-auto-resize.service') + # Time format 12|24-hour + if 'time_format' in options: + time_format = time_format_to_locale.get(options['time_format']) + cmd(f'localectl set-locale LC_TIME={time_format}') + if __name__ == '__main__': try: c = get_config() diff --git a/src/conf_mode/system_sflow.py b/src/conf_mode/system_sflow.py index 9e3d41100..eae869a6d 100755 --- a/src/conf_mode/system_sflow.py +++ b/src/conf_mode/system_sflow.py @@ -22,7 +22,7 @@ from vyos.config import Config from vyos.configdict import dict_merge from vyos.template import render from vyos.utils.process import call -from vyos.validate import is_addr_assigned +from vyos.utils.network import is_addr_assigned from vyos.xml import defaults from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/tftp_server.py b/src/conf_mode/tftp_server.py index 2735772dc..32882fc12 100755 --- a/src/conf_mode/tftp_server.py +++ b/src/conf_mode/tftp_server.py @@ -30,7 +30,7 @@ from vyos.template import render from vyos.template import is_ipv4 from vyos.utils.process import call from vyos.utils.permission import chmod_755 -from vyos.validate import is_addr_assigned +from vyos.utils.network import is_addr_assigned from vyos.xml import defaults from vyos import ConfigError from vyos import airbag diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py index b0825d0ee..9a27a44bf 100755 --- a/src/conf_mode/vpn_ipsec.py +++ b/src/conf_mode/vpn_ipsec.py @@ -28,6 +28,7 @@ from vyos.config import Config from vyos.configdict import leaf_node_changed from vyos.configverify import verify_interface_exists from vyos.configdict import dict_merge +from vyos.defaults import directories from vyos.ifconfig import Interface from vyos.pki import encode_public_key from vyos.pki import load_private_key @@ -39,7 +40,7 @@ from vyos.template import ip_from_cidr 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.utils.network import is_ipv6_link_local from vyos.utils.dict import dict_search from vyos.utils.dict import dict_search_args from vyos.utils.process import call @@ -69,7 +70,6 @@ KEY_PATH = f'{swanctl_dir}/private/' CA_PATH = f'{swanctl_dir}/x509ca/' CRL_PATH = f'{swanctl_dir}/x509crl/' -DHCP_BASE = '/var/lib/dhcp/dhclient' DHCP_HOOK_IFLIST = '/tmp/ipsec_dhcp_waiting' def get_config(config=None): @@ -433,8 +433,9 @@ def verify(ipsec): dhcp_interface = peer_conf['dhcp_interface'] verify_interface_exists(dhcp_interface) + dhcp_base = directories['isc_dhclient_dir'] - if not os.path.exists(f'{DHCP_BASE}_{dhcp_interface}.conf'): + if not os.path.exists(f'{dhcp_base}/dhclient_{dhcp_interface}.conf'): raise ConfigError(f"Invalid dhcp-interface on site-to-site peer {peer}") address = get_dhcp_address(dhcp_interface) diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/03-vyatta-dhclient-hook b/src/etc/dhcp/dhclient-exit-hooks.d/03-vyos-dhclient-hook index 49bb18372..35721d009 100644 --- a/src/etc/dhcp/dhclient-exit-hooks.d/03-vyatta-dhclient-hook +++ b/src/etc/dhcp/dhclient-exit-hooks.d/03-vyos-dhclient-hook @@ -28,7 +28,8 @@ if [[ $reason =~ ^(REBOOT6|INIT6|EXPIRE6|RELEASE6|STOP6|INFORM6|BOUND6|REBIND6|D fi if [ "$RUN" = "yes" ]; then - LOG=/var/lib/dhcp/dhclient_"$interface"."$proto"lease + BASE_PATH=$(python3 -c "from vyos.defaults import directories; print(directories['isc_dhclient_dir'])") + LOG=${BASE_PATH}/dhclient_"$interface"."$proto"lease echo `date` > $LOG for i in reason interface new_expiry new_dhcp_lease_time medium \ diff --git a/src/migration-scripts/bgp/0-to-1 b/src/migration-scripts/bgp/0-to-1 index 5e9dffe1f..03c45107b 100755 --- a/src/migration-scripts/bgp/0-to-1 +++ b/src/migration-scripts/bgp/0-to-1 @@ -21,7 +21,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/bgp/1-to-2 b/src/migration-scripts/bgp/1-to-2 index e2d3fcd33..96b939b47 100755 --- a/src/migration-scripts/bgp/1-to-2 +++ b/src/migration-scripts/bgp/1-to-2 @@ -21,7 +21,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/bgp/2-to-3 b/src/migration-scripts/bgp/2-to-3 index 7ced0a3b0..34d321a96 100755 --- a/src/migration-scripts/bgp/2-to-3 +++ b/src/migration-scripts/bgp/2-to-3 @@ -21,7 +21,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/bgp/3-to-4 b/src/migration-scripts/bgp/3-to-4 index 0df2fbec4..894cdda2b 100755 --- a/src/migration-scripts/bgp/3-to-4 +++ b/src/migration-scripts/bgp/3-to-4 @@ -22,7 +22,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/config-management/0-to-1 b/src/migration-scripts/config-management/0-to-1 index 344359110..6528fd136 100755 --- a/src/migration-scripts/config-management/0-to-1 +++ b/src/migration-scripts/config-management/0-to-1 @@ -6,7 +6,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/conntrack-sync/1-to-2 b/src/migration-scripts/conntrack-sync/1-to-2 index ebbd8c35a..a8e1007f3 100755 --- a/src/migration-scripts/conntrack-sync/1-to-2 +++ b/src/migration-scripts/conntrack-sync/1-to-2 @@ -23,7 +23,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/conntrack/1-to-2 b/src/migration-scripts/conntrack/1-to-2 index 4fc88a1ed..c4fe667fc 100755 --- a/src/migration-scripts/conntrack/1-to-2 +++ b/src/migration-scripts/conntrack/1-to-2 @@ -6,7 +6,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/conntrack/2-to-3 b/src/migration-scripts/conntrack/2-to-3 index 8a8b43279..6fb457b7f 100755 --- a/src/migration-scripts/conntrack/2-to-3 +++ b/src/migration-scripts/conntrack/2-to-3 @@ -8,7 +8,7 @@ import sys from vyos.configtree import ConfigTree from vyos.version import get_version -if len(sys.argv) < 1: +if len(sys.argv) < 2: print('Must specify file name!') sys.exit(1) diff --git a/src/migration-scripts/container/0-to-1 b/src/migration-scripts/container/0-to-1 index 86f89ee04..6b282e082 100755 --- a/src/migration-scripts/container/0-to-1 +++ b/src/migration-scripts/container/0-to-1 @@ -23,7 +23,7 @@ import sys from vyos.configtree import ConfigTree from vyos.utils.process import call -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/dhcp-relay/1-to-2 b/src/migration-scripts/dhcp-relay/1-to-2 index b72da1028..508bac6be 100755 --- a/src/migration-scripts/dhcp-relay/1-to-2 +++ b/src/migration-scripts/dhcp-relay/1-to-2 @@ -7,7 +7,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/dhcp-server/4-to-5 b/src/migration-scripts/dhcp-server/4-to-5 index 313b5279a..d15e0baf5 100755 --- a/src/migration-scripts/dhcp-server/4-to-5 +++ b/src/migration-scripts/dhcp-server/4-to-5 @@ -9,7 +9,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/dhcp-server/5-to-6 b/src/migration-scripts/dhcp-server/5-to-6 index aefe84737..f5c766a09 100755 --- a/src/migration-scripts/dhcp-server/5-to-6 +++ b/src/migration-scripts/dhcp-server/5-to-6 @@ -20,7 +20,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/dhcpv6-server/0-to-1 b/src/migration-scripts/dhcpv6-server/0-to-1 index 6f1150da1..deae1ca29 100755 --- a/src/migration-scripts/dhcpv6-server/0-to-1 +++ b/src/migration-scripts/dhcpv6-server/0-to-1 @@ -19,7 +19,7 @@ from sys import argv, exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/dns-dynamic/0-to-1 b/src/migration-scripts/dns-dynamic/0-to-1 index cf0983b01..d80e8d44a 100755 --- a/src/migration-scripts/dns-dynamic/0-to-1 +++ b/src/migration-scripts/dns-dynamic/0-to-1 @@ -43,7 +43,7 @@ service_protocol_mapping = { 'zoneedit': 'zoneedit1' } -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/dns-forwarding/0-to-1 b/src/migration-scripts/dns-forwarding/0-to-1 index 6e8720eef..7f4343652 100755 --- a/src/migration-scripts/dns-forwarding/0-to-1 +++ b/src/migration-scripts/dns-forwarding/0-to-1 @@ -22,7 +22,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/dns-forwarding/1-to-2 b/src/migration-scripts/dns-forwarding/1-to-2 index a8c930be7..7df2d47e2 100755 --- a/src/migration-scripts/dns-forwarding/1-to-2 +++ b/src/migration-scripts/dns-forwarding/1-to-2 @@ -25,7 +25,7 @@ from sys import argv, exit from vyos.ifconfig import Interface from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/dns-forwarding/2-to-3 b/src/migration-scripts/dns-forwarding/2-to-3 index 01e445b22..d7ff9e260 100755 --- a/src/migration-scripts/dns-forwarding/2-to-3 +++ b/src/migration-scripts/dns-forwarding/2-to-3 @@ -21,7 +21,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/dns-forwarding/3-to-4 b/src/migration-scripts/dns-forwarding/3-to-4 index 55165c2c5..3d5316ed4 100755 --- a/src/migration-scripts/dns-forwarding/3-to-4 +++ b/src/migration-scripts/dns-forwarding/3-to-4 @@ -20,7 +20,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/firewall/5-to-6 b/src/migration-scripts/firewall/5-to-6 index ccb86830a..3fa07a0a1 100755 --- a/src/migration-scripts/firewall/5-to-6 +++ b/src/migration-scripts/firewall/5-to-6 @@ -23,7 +23,7 @@ from sys import exit from vyos.configtree import ConfigTree from vyos.ifconfig import Section -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/firewall/6-to-7 b/src/migration-scripts/firewall/6-to-7 index 626d6849f..9ad887acc 100755 --- a/src/migration-scripts/firewall/6-to-7 +++ b/src/migration-scripts/firewall/6-to-7 @@ -28,7 +28,7 @@ from sys import exit from vyos.configtree import ConfigTree from vyos.ifconfig import Section -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/firewall/7-to-8 b/src/migration-scripts/firewall/7-to-8 index ce527acf5..d06c3150a 100755 --- a/src/migration-scripts/firewall/7-to-8 +++ b/src/migration-scripts/firewall/7-to-8 @@ -25,7 +25,7 @@ from sys import exit from vyos.configtree import ConfigTree from vyos.ifconfig import Section -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/firewall/8-to-9 b/src/migration-scripts/firewall/8-to-9 index f7c1bb90d..d7647354a 100755 --- a/src/migration-scripts/firewall/8-to-9 +++ b/src/migration-scripts/firewall/8-to-9 @@ -28,7 +28,7 @@ from sys import exit from vyos.configtree import ConfigTree from vyos.ifconfig import Section -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/firewall/9-to-10 b/src/migration-scripts/firewall/9-to-10 index 6f67cc512..a70460718 100755 --- a/src/migration-scripts/firewall/9-to-10 +++ b/src/migration-scripts/firewall/9-to-10 @@ -28,7 +28,7 @@ from sys import exit from vyos.configtree import ConfigTree from vyos.ifconfig import Section -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/flow-accounting/0-to-1 b/src/migration-scripts/flow-accounting/0-to-1 index 72cce77b0..0f790fd9c 100755 --- a/src/migration-scripts/flow-accounting/0-to-1 +++ b/src/migration-scripts/flow-accounting/0-to-1 @@ -21,7 +21,7 @@ from sys import argv from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/https/2-to-3 b/src/migration-scripts/https/2-to-3 index fa29fdd18..2beba6d2b 100755 --- a/src/migration-scripts/https/2-to-3 +++ b/src/migration-scripts/https/2-to-3 @@ -25,7 +25,7 @@ from vyos.pki import create_private_key from vyos.pki import encode_certificate from vyos.pki import encode_private_key -if (len(sys.argv) < 2): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/https/3-to-4 b/src/migration-scripts/https/3-to-4 index 5ee528b31..b3cfca201 100755 --- a/src/migration-scripts/https/3-to-4 +++ b/src/migration-scripts/https/3-to-4 @@ -20,7 +20,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 2): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/ids/0-to-1 b/src/migration-scripts/ids/0-to-1 index 9f08f7dc7..8b7850a1a 100755 --- a/src/migration-scripts/ids/0-to-1 +++ b/src/migration-scripts/ids/0-to-1 @@ -19,7 +19,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/0-to-1 b/src/migration-scripts/interfaces/0-to-1 index c7f324661..25f6842eb 100755 --- a/src/migration-scripts/interfaces/0-to-1 +++ b/src/migration-scripts/interfaces/0-to-1 @@ -37,7 +37,7 @@ def migrate_bridge(config, tree, intf): if __name__ == '__main__': - if (len(sys.argv) < 1): + if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/interfaces/1-to-2 b/src/migration-scripts/interfaces/1-to-2 index c75404d85..c95623c2b 100755 --- a/src/migration-scripts/interfaces/1-to-2 +++ b/src/migration-scripts/interfaces/1-to-2 @@ -7,7 +7,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/interfaces/10-to-11 b/src/migration-scripts/interfaces/10-to-11 index 6b8e49ed9..cafaa3fa4 100755 --- a/src/migration-scripts/interfaces/10-to-11 +++ b/src/migration-scripts/interfaces/10-to-11 @@ -23,7 +23,7 @@ from sys import exit, argv from vyos.configtree import ConfigTree if __name__ == '__main__': - if (len(argv) < 1): + if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/11-to-12 b/src/migration-scripts/interfaces/11-to-12 index 0dad24642..e9eb7f939 100755 --- a/src/migration-scripts/interfaces/11-to-12 +++ b/src/migration-scripts/interfaces/11-to-12 @@ -22,7 +22,7 @@ from sys import exit, argv from vyos.configtree import ConfigTree if __name__ == '__main__': - if (len(argv) < 1): + if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/12-to-13 b/src/migration-scripts/interfaces/12-to-13 index f866ca9a6..ef1d93903 100755 --- a/src/migration-scripts/interfaces/12-to-13 +++ b/src/migration-scripts/interfaces/12-to-13 @@ -24,7 +24,7 @@ from sys import exit, argv from vyos.configtree import ConfigTree if __name__ == '__main__': - if (len(argv) < 1): + if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/13-to-14 b/src/migration-scripts/interfaces/13-to-14 index 6e6439c36..b20d8b4db 100755 --- a/src/migration-scripts/interfaces/13-to-14 +++ b/src/migration-scripts/interfaces/13-to-14 @@ -21,7 +21,7 @@ from sys import exit, argv from vyos.configtree import ConfigTree if __name__ == '__main__': - if (len(argv) < 1): + if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/14-to-15 b/src/migration-scripts/interfaces/14-to-15 index c38db0bf8..e21251f86 100755 --- a/src/migration-scripts/interfaces/14-to-15 +++ b/src/migration-scripts/interfaces/14-to-15 @@ -20,7 +20,7 @@ from sys import exit, argv from vyos.configtree import ConfigTree if __name__ == '__main__': - if (len(argv) < 1): + if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/15-to-16 b/src/migration-scripts/interfaces/15-to-16 index 804c48be0..ae3441b9f 100755 --- a/src/migration-scripts/interfaces/15-to-16 +++ b/src/migration-scripts/interfaces/15-to-16 @@ -20,7 +20,7 @@ from sys import exit, argv from vyos.configtree import ConfigTree if __name__ == '__main__': - if (len(argv) < 1): + if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/16-to-17 b/src/migration-scripts/interfaces/16-to-17 index d123be06f..75f160686 100755 --- a/src/migration-scripts/interfaces/16-to-17 +++ b/src/migration-scripts/interfaces/16-to-17 @@ -21,7 +21,7 @@ import sys from vyos.configtree import ConfigTree if __name__ == '__main__': - if (len(sys.argv) < 1): + if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) @@ -35,7 +35,7 @@ if __name__ == '__main__': if not config.exists(base): # Nothing to do sys.exit(0) - + for interface in config.list_nodes(base): mirror_old_base = base + [interface, 'mirror'] if config.exists(mirror_old_base): @@ -43,7 +43,7 @@ if __name__ == '__main__': if config.exists(mirror_old_base): config.delete(mirror_old_base) config.set(mirror_old_base + ['ingress'],intf[0]) - + try: with open(file_name, 'w') as f: f.write(config.to_string()) diff --git a/src/migration-scripts/interfaces/17-to-18 b/src/migration-scripts/interfaces/17-to-18 index b8cb8c119..51486ac37 100755 --- a/src/migration-scripts/interfaces/17-to-18 +++ b/src/migration-scripts/interfaces/17-to-18 @@ -22,7 +22,7 @@ from sys import exit, argv from vyos.configtree import ConfigTree if __name__ == '__main__': - if (len(argv) < 1): + if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/18-to-19 b/src/migration-scripts/interfaces/18-to-19 index a12c4a6cd..c3209f250 100755 --- a/src/migration-scripts/interfaces/18-to-19 +++ b/src/migration-scripts/interfaces/18-to-19 @@ -41,7 +41,7 @@ def replace_nat_interfaces(config, old, new): if __name__ == '__main__': - if (len(argv) < 1): + if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/19-to-20 b/src/migration-scripts/interfaces/19-to-20 index e96663e54..05abae898 100755 --- a/src/migration-scripts/interfaces/19-to-20 +++ b/src/migration-scripts/interfaces/19-to-20 @@ -19,7 +19,7 @@ from sys import exit from vyos.configtree import ConfigTree if __name__ == '__main__': - if (len(argv) < 1): + if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/2-to-3 b/src/migration-scripts/interfaces/2-to-3 index 68d41de39..15c3bc8be 100755 --- a/src/migration-scripts/interfaces/2-to-3 +++ b/src/migration-scripts/interfaces/2-to-3 @@ -7,7 +7,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/interfaces/20-to-21 b/src/migration-scripts/interfaces/20-to-21 index cb1c36882..14ad0fe4d 100755 --- a/src/migration-scripts/interfaces/20-to-21 +++ b/src/migration-scripts/interfaces/20-to-21 @@ -23,7 +23,7 @@ from sys import argv from vyos.ethtool import Ethtool from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/21-to-22 b/src/migration-scripts/interfaces/21-to-22 index 098102102..1838eb1c0 100755 --- a/src/migration-scripts/interfaces/21-to-22 +++ b/src/migration-scripts/interfaces/21-to-22 @@ -17,7 +17,7 @@ from sys import argv from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/22-to-23 b/src/migration-scripts/interfaces/22-to-23 index 06e07572f..8b21fce51 100755 --- a/src/migration-scripts/interfaces/22-to-23 +++ b/src/migration-scripts/interfaces/22-to-23 @@ -75,7 +75,7 @@ def migrate_ripng(config, path, interface): config.delete(path[:-1]) if __name__ == '__main__': - if (len(argv) < 1): + if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/23-to-24 b/src/migration-scripts/interfaces/23-to-24 index d1ec2ad3e..8fd79ecc6 100755 --- a/src/migration-scripts/interfaces/23-to-24 +++ b/src/migration-scripts/interfaces/23-to-24 @@ -22,7 +22,7 @@ import sys from vyos.configtree import ConfigTree if __name__ == '__main__': - if (len(sys.argv) < 1): + if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/interfaces/24-to-25 b/src/migration-scripts/interfaces/24-to-25 index f3a1dc464..9aa6ea5e3 100755 --- a/src/migration-scripts/interfaces/24-to-25 +++ b/src/migration-scripts/interfaces/24-to-25 @@ -53,7 +53,7 @@ def read_file_for_pki(config_auth_path): return output -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/interfaces/25-to-26 b/src/migration-scripts/interfaces/25-to-26 index a8936235e..4967a29fa 100755 --- a/src/migration-scripts/interfaces/25-to-26 +++ b/src/migration-scripts/interfaces/25-to-26 @@ -22,7 +22,7 @@ from sys import argv from vyos.ethtool import Ethtool from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/26-to-27 b/src/migration-scripts/interfaces/26-to-27 index 949cc55b6..a0d043d11 100755 --- a/src/migration-scripts/interfaces/26-to-27 +++ b/src/migration-scripts/interfaces/26-to-27 @@ -22,7 +22,7 @@ from sys import argv from vyos.ethtool import Ethtool from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/27-to-28 b/src/migration-scripts/interfaces/27-to-28 index e36c95cc9..ad5bfa653 100755 --- a/src/migration-scripts/interfaces/27-to-28 +++ b/src/migration-scripts/interfaces/27-to-28 @@ -22,7 +22,7 @@ from sys import argv from vyos.ethtool import Ethtool from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/28-to-29 b/src/migration-scripts/interfaces/28-to-29 index 64c649b02..acb6ee1fb 100755 --- a/src/migration-scripts/interfaces/28-to-29 +++ b/src/migration-scripts/interfaces/28-to-29 @@ -21,7 +21,7 @@ from sys import argv from vyos.ethtool import Ethtool from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/29-to-30 b/src/migration-scripts/interfaces/29-to-30 new file mode 100755 index 000000000..97e1b329c --- /dev/null +++ b/src/migration-scripts/interfaces/29-to-30 @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +# +# 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 +# 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/>. +# +# Deletes Wireguard peers if they have the same public key as the router has. +import sys +from vyos.configtree import ConfigTree +from vyos.utils.network import is_wireguard_key_pair + +if __name__ == '__main__': + if len(sys.argv) < 2: + print("Must specify file name!") + sys.exit(1) + + file_name = sys.argv[1] + + with open(file_name, 'r') as f: + config_file = f.read() + + config = ConfigTree(config_file) + base = ['interfaces', 'wireguard'] + if not config.exists(base): + # Nothing to do + sys.exit(0) + for interface in config.list_nodes(base): + private_key = config.return_value(base + [interface, 'private-key']) + interface_base = base + [interface] + if config.exists(interface_base + ['peer']): + for peer in config.list_nodes(interface_base + ['peer']): + peer_base = interface_base + ['peer', peer] + peer_public_key = config.return_value(peer_base + ['public-key']) + if config.exists(peer_base + ['public-key']): + if not config.exists(peer_base + ['disable']) \ + and is_wireguard_key_pair(private_key, peer_public_key): + config.set(peer_base + ['disable']) + + try: + with open(file_name, 'w') as f: + f.write(config.to_string()) + except OSError as e: + print("Failed to save the modified config: {}".format(e)) + sys.exit(1) diff --git a/src/migration-scripts/interfaces/3-to-4 b/src/migration-scripts/interfaces/3-to-4 index e3bd25a68..c7fd7d01d 100755 --- a/src/migration-scripts/interfaces/3-to-4 +++ b/src/migration-scripts/interfaces/3-to-4 @@ -6,7 +6,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/interfaces/4-to-5 b/src/migration-scripts/interfaces/4-to-5 index f645c5aeb..68d81e846 100755 --- a/src/migration-scripts/interfaces/4-to-5 +++ b/src/migration-scripts/interfaces/4-to-5 @@ -57,7 +57,7 @@ def migrate_dialer(config, tree, intf): if __name__ == '__main__': - if (len(sys.argv) < 1): + if len(sys.argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/5-to-6 b/src/migration-scripts/interfaces/5-to-6 index ae79c1d1b..9d9a49c2d 100755 --- a/src/migration-scripts/interfaces/5-to-6 +++ b/src/migration-scripts/interfaces/5-to-6 @@ -98,7 +98,7 @@ def copy_rtradv(c, old_base, interface): c.delete(new_base + ['link-mtu']) if __name__ == '__main__': - if (len(sys.argv) < 1): + if len(sys.argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/6-to-7 b/src/migration-scripts/interfaces/6-to-7 index 220c7e601..49b853d90 100755 --- a/src/migration-scripts/interfaces/6-to-7 +++ b/src/migration-scripts/interfaces/6-to-7 @@ -20,7 +20,7 @@ import sys from vyos.configtree import ConfigTree if __name__ == '__main__': - if (len(sys.argv) < 1): + if len(sys.argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/7-to-8 b/src/migration-scripts/interfaces/7-to-8 index 9845098a7..9343a48a8 100755 --- a/src/migration-scripts/interfaces/7-to-8 +++ b/src/migration-scripts/interfaces/7-to-8 @@ -37,7 +37,7 @@ def migrate_default_keys(): os.rename(f'{kdir}/public.key', f'{location}/public.key') if __name__ == '__main__': - if (len(argv) < 1): + if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/8-to-9 b/src/migration-scripts/interfaces/8-to-9 index 2d1efd418..960962be7 100755 --- a/src/migration-scripts/interfaces/8-to-9 +++ b/src/migration-scripts/interfaces/8-to-9 @@ -22,7 +22,7 @@ from sys import exit, argv from vyos.configtree import ConfigTree if __name__ == '__main__': - if (len(argv) < 1): + if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/interfaces/9-to-10 b/src/migration-scripts/interfaces/9-to-10 index 4aa2c42b5..e9b8cb784 100755 --- a/src/migration-scripts/interfaces/9-to-10 +++ b/src/migration-scripts/interfaces/9-to-10 @@ -23,7 +23,7 @@ from sys import exit, argv from vyos.configtree import ConfigTree if __name__ == '__main__': - if (len(argv) < 1): + if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/ipoe-server/0-to-1 b/src/migration-scripts/ipoe-server/0-to-1 index d768758ba..ac9d13abc 100755 --- a/src/migration-scripts/ipoe-server/0-to-1 +++ b/src/migration-scripts/ipoe-server/0-to-1 @@ -26,7 +26,7 @@ import sys from sys import argv, exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/ipsec/10-to-11 b/src/migration-scripts/ipsec/10-to-11 index 0707a5e3c..509216267 100755 --- a/src/migration-scripts/ipsec/10-to-11 +++ b/src/migration-scripts/ipsec/10-to-11 @@ -20,7 +20,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/ipsec/11-to-12 b/src/migration-scripts/ipsec/11-to-12 index 8bbde5efa..e34882c23 100755 --- a/src/migration-scripts/ipsec/11-to-12 +++ b/src/migration-scripts/ipsec/11-to-12 @@ -23,7 +23,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/ipsec/4-to-5 b/src/migration-scripts/ipsec/4-to-5 index 4e959a7bf..772d05787 100755 --- a/src/migration-scripts/ipsec/4-to-5 +++ b/src/migration-scripts/ipsec/4-to-5 @@ -20,7 +20,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/ipsec/5-to-6 b/src/migration-scripts/ipsec/5-to-6 index 3a8b3926d..7d7c777c6 100755 --- a/src/migration-scripts/ipsec/5-to-6 +++ b/src/migration-scripts/ipsec/5-to-6 @@ -23,7 +23,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/ipsec/6-to-7 b/src/migration-scripts/ipsec/6-to-7 index 649a18cb3..71fbbe8a1 100755 --- a/src/migration-scripts/ipsec/6-to-7 +++ b/src/migration-scripts/ipsec/6-to-7 @@ -29,7 +29,7 @@ from vyos.pki import encode_certificate from vyos.pki import encode_private_key from vyos.utils.process import run -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/ipsec/7-to-8 b/src/migration-scripts/ipsec/7-to-8 index 5d48b2875..e002db0b1 100755 --- a/src/migration-scripts/ipsec/7-to-8 +++ b/src/migration-scripts/ipsec/7-to-8 @@ -31,7 +31,7 @@ from vyos.pki import load_private_key from vyos.pki import encode_public_key from vyos.pki import encode_private_key -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/ipsec/8-to-9 b/src/migration-scripts/ipsec/8-to-9 index eb44b6216..c08411f83 100755 --- a/src/migration-scripts/ipsec/8-to-9 +++ b/src/migration-scripts/ipsec/8-to-9 @@ -19,7 +19,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/ipsec/9-to-10 b/src/migration-scripts/ipsec/9-to-10 index de366ef3b..a4a71d38e 100755 --- a/src/migration-scripts/ipsec/9-to-10 +++ b/src/migration-scripts/ipsec/9-to-10 @@ -24,7 +24,7 @@ from vyos.template import is_ipv4 from vyos.template import is_ipv6 -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/isis/0-to-1 b/src/migration-scripts/isis/0-to-1 index b75a7f72c..0149c0c1f 100755 --- a/src/migration-scripts/isis/0-to-1 +++ b/src/migration-scripts/isis/0-to-1 @@ -21,7 +21,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/isis/1-to-2 b/src/migration-scripts/isis/1-to-2 index f914ea995..9c110bf2a 100755 --- a/src/migration-scripts/isis/1-to-2 +++ b/src/migration-scripts/isis/1-to-2 @@ -21,7 +21,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/isis/2-to-3 b/src/migration-scripts/isis/2-to-3 index 4490feb0a..78e3c1715 100755 --- a/src/migration-scripts/isis/2-to-3 +++ b/src/migration-scripts/isis/2-to-3 @@ -22,7 +22,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/l2tp/0-to-1 b/src/migration-scripts/l2tp/0-to-1 index 686ebc655..15d229822 100755 --- a/src/migration-scripts/l2tp/0-to-1 +++ b/src/migration-scripts/l2tp/0-to-1 @@ -8,7 +8,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/l2tp/1-to-2 b/src/migration-scripts/l2tp/1-to-2 index c46eba8f8..2ffb91c53 100755 --- a/src/migration-scripts/l2tp/1-to-2 +++ b/src/migration-scripts/l2tp/1-to-2 @@ -6,7 +6,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/l2tp/2-to-3 b/src/migration-scripts/l2tp/2-to-3 index 3472ee3ed..b46b0f22e 100755 --- a/src/migration-scripts/l2tp/2-to-3 +++ b/src/migration-scripts/l2tp/2-to-3 @@ -23,7 +23,7 @@ import sys from sys import argv, exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/l2tp/3-to-4 b/src/migration-scripts/l2tp/3-to-4 index ee6079864..8c2b909b7 100755 --- a/src/migration-scripts/l2tp/3-to-4 +++ b/src/migration-scripts/l2tp/3-to-4 @@ -29,7 +29,7 @@ from vyos.pki import encode_certificate from vyos.pki import encode_private_key from vyos.utils.process import run -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/lldp/0-to-1 b/src/migration-scripts/lldp/0-to-1 index 5f66570e7..a936cbdfc 100755 --- a/src/migration-scripts/lldp/0-to-1 +++ b/src/migration-scripts/lldp/0-to-1 @@ -7,7 +7,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/monitoring/0-to-1 b/src/migration-scripts/monitoring/0-to-1 index 803cdb49c..384d22f8c 100755 --- a/src/migration-scripts/monitoring/0-to-1 +++ b/src/migration-scripts/monitoring/0-to-1 @@ -21,7 +21,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/nat/4-to-5 b/src/migration-scripts/nat/4-to-5 index b791996e2..ce215d455 100755 --- a/src/migration-scripts/nat/4-to-5 +++ b/src/migration-scripts/nat/4-to-5 @@ -20,7 +20,7 @@ from sys import argv,exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/nat66/0-to-1 b/src/migration-scripts/nat66/0-to-1 index 83b421926..444b2315f 100755 --- a/src/migration-scripts/nat66/0-to-1 +++ b/src/migration-scripts/nat66/0-to-1 @@ -17,7 +17,7 @@ from sys import argv,exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/ntp/0-to-1 b/src/migration-scripts/ntp/0-to-1 index 294964580..cbce45b9b 100755 --- a/src/migration-scripts/ntp/0-to-1 +++ b/src/migration-scripts/ntp/0-to-1 @@ -6,7 +6,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/ntp/1-to-2 b/src/migration-scripts/ntp/1-to-2 index d1e510e4c..fd1f15d91 100755 --- a/src/migration-scripts/ntp/1-to-2 +++ b/src/migration-scripts/ntp/1-to-2 @@ -20,7 +20,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/ntp/2-to-3 b/src/migration-scripts/ntp/2-to-3 index 7d4e0bd83..a4351845e 100755 --- a/src/migration-scripts/ntp/2-to-3 +++ b/src/migration-scripts/ntp/2-to-3 @@ -24,7 +24,7 @@ from vyos.configtree import ConfigTree from vyos.template import is_ipv4 from vyos.template import is_ipv6 -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/openconnect/0-to-1 b/src/migration-scripts/openconnect/0-to-1 index b26023a5b..8be15fad1 100755 --- a/src/migration-scripts/openconnect/0-to-1 +++ b/src/migration-scripts/openconnect/0-to-1 @@ -28,7 +28,7 @@ from vyos.pki import encode_certificate from vyos.pki import encode_private_key from vyos.utils.process import run -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/openconnect/1-to-2 b/src/migration-scripts/openconnect/1-to-2 index 51cd6bc37..7978aa56e 100755 --- a/src/migration-scripts/openconnect/1-to-2 +++ b/src/migration-scripts/openconnect/1-to-2 @@ -20,7 +20,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/ospf/0-to-1 b/src/migration-scripts/ospf/0-to-1 index 678569d9e..8f02acada 100755 --- a/src/migration-scripts/ospf/0-to-1 +++ b/src/migration-scripts/ospf/0-to-1 @@ -37,7 +37,7 @@ def ospf_passive_migration(config, ospf_base): config.set(ospf_base + ['interface', interface, 'passive', 'disable']) config.delete(ospf_base + ['passive-interface-exclude']) -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/ospf/1-to-2 b/src/migration-scripts/ospf/1-to-2 index a6beaf04e..ba9499c60 100755 --- a/src/migration-scripts/ospf/1-to-2 +++ b/src/migration-scripts/ospf/1-to-2 @@ -22,7 +22,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/policy/0-to-1 b/src/migration-scripts/policy/0-to-1 index 7134920ad..8508b734a 100755 --- a/src/migration-scripts/policy/0-to-1 +++ b/src/migration-scripts/policy/0-to-1 @@ -23,7 +23,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/policy/1-to-2 b/src/migration-scripts/policy/1-to-2 index eebbf9d41..c70490ce9 100755 --- a/src/migration-scripts/policy/1-to-2 +++ b/src/migration-scripts/policy/1-to-2 @@ -23,7 +23,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/policy/2-to-3 b/src/migration-scripts/policy/2-to-3 index 84cb1ff4a..8a62c8e6f 100755 --- a/src/migration-scripts/policy/2-to-3 +++ b/src/migration-scripts/policy/2-to-3 @@ -23,7 +23,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/policy/3-to-4 b/src/migration-scripts/policy/3-to-4 index 49e0b4c38..1ebb248b0 100755 --- a/src/migration-scripts/policy/3-to-4 +++ b/src/migration-scripts/policy/3-to-4 @@ -98,7 +98,7 @@ def extcommunity_migrate(config: ConfigTree, rule: list[str]) -> None: config.set(rule + ['soo'], value=community, replace=False) -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/policy/4-to-5 b/src/migration-scripts/policy/4-to-5 index 33c9e6ade..f6f889c35 100755 --- a/src/migration-scripts/policy/4-to-5 +++ b/src/migration-scripts/policy/4-to-5 @@ -24,7 +24,7 @@ from sys import exit from vyos.configtree import ConfigTree from vyos.ifconfig import Section -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/pppoe-server/0-to-1 b/src/migration-scripts/pppoe-server/0-to-1 index 063c7eb56..4d36f8545 100755 --- a/src/migration-scripts/pppoe-server/0-to-1 +++ b/src/migration-scripts/pppoe-server/0-to-1 @@ -20,7 +20,7 @@ from sys import argv, exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/pppoe-server/1-to-2 b/src/migration-scripts/pppoe-server/1-to-2 index 902efb86b..c73899ca1 100755 --- a/src/migration-scripts/pppoe-server/1-to-2 +++ b/src/migration-scripts/pppoe-server/1-to-2 @@ -21,7 +21,7 @@ import os from sys import argv, exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/pppoe-server/2-to-3 b/src/migration-scripts/pppoe-server/2-to-3 index 7cae3b5bc..a7be060df 100755 --- a/src/migration-scripts/pppoe-server/2-to-3 +++ b/src/migration-scripts/pppoe-server/2-to-3 @@ -19,7 +19,7 @@ from sys import argv, exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/pppoe-server/3-to-4 b/src/migration-scripts/pppoe-server/3-to-4 index 5f9730a41..c07bbb1df 100755 --- a/src/migration-scripts/pppoe-server/3-to-4 +++ b/src/migration-scripts/pppoe-server/3-to-4 @@ -21,7 +21,7 @@ import os from sys import argv, exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/pppoe-server/4-to-5 b/src/migration-scripts/pppoe-server/4-to-5 index 05e9c17d6..5850db673 100755 --- a/src/migration-scripts/pppoe-server/4-to-5 +++ b/src/migration-scripts/pppoe-server/4-to-5 @@ -20,7 +20,7 @@ from vyos.configtree import ConfigTree from sys import argv from sys import exit -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/pppoe-server/5-to-6 b/src/migration-scripts/pppoe-server/5-to-6 index e4888f4db..e079ae684 100755 --- a/src/migration-scripts/pppoe-server/5-to-6 +++ b/src/migration-scripts/pppoe-server/5-to-6 @@ -20,7 +20,7 @@ from vyos.configtree import ConfigTree from sys import argv from sys import exit -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/pptp/0-to-1 b/src/migration-scripts/pptp/0-to-1 index d0c7a83b5..1b7697c11 100755 --- a/src/migration-scripts/pptp/0-to-1 +++ b/src/migration-scripts/pptp/0-to-1 @@ -8,7 +8,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/pptp/1-to-2 b/src/migration-scripts/pptp/1-to-2 index a13cc3a4f..99624dceb 100755 --- a/src/migration-scripts/pptp/1-to-2 +++ b/src/migration-scripts/pptp/1-to-2 @@ -21,7 +21,7 @@ from sys import argv, exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/qos/1-to-2 b/src/migration-scripts/qos/1-to-2 index a689bacc5..cca32d06e 100755 --- a/src/migration-scripts/qos/1-to-2 +++ b/src/migration-scripts/qos/1-to-2 @@ -28,7 +28,7 @@ def bandwidth_percent_to_val(interface, percent) -> int: speed = int(speed) *1000000 # convert to MBit/s return speed * int(percent) // 100 # integer division -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/quagga/10-to-11 b/src/migration-scripts/quagga/10-to-11 index 04fc16f79..0ed4f5df6 100755 --- a/src/migration-scripts/quagga/10-to-11 +++ b/src/migration-scripts/quagga/10-to-11 @@ -22,7 +22,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/quagga/2-to-3 b/src/migration-scripts/quagga/2-to-3 index 4c1cd86a3..96b56da70 100755 --- a/src/migration-scripts/quagga/2-to-3 +++ b/src/migration-scripts/quagga/2-to-3 @@ -21,7 +21,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/quagga/3-to-4 b/src/migration-scripts/quagga/3-to-4 index be3528391..1e8c8e2f2 100755 --- a/src/migration-scripts/quagga/3-to-4 +++ b/src/migration-scripts/quagga/3-to-4 @@ -28,7 +28,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/quagga/4-to-5 b/src/migration-scripts/quagga/4-to-5 index f8c87ce8c..fcb496a9c 100755 --- a/src/migration-scripts/quagga/4-to-5 +++ b/src/migration-scripts/quagga/4-to-5 @@ -21,7 +21,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/quagga/5-to-6 b/src/migration-scripts/quagga/5-to-6 index a71851942..f075fc2e7 100755 --- a/src/migration-scripts/quagga/5-to-6 +++ b/src/migration-scripts/quagga/5-to-6 @@ -22,7 +22,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 2): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/quagga/6-to-7 b/src/migration-scripts/quagga/6-to-7 index 25cf5eebd..ed295a95c 100755 --- a/src/migration-scripts/quagga/6-to-7 +++ b/src/migration-scripts/quagga/6-to-7 @@ -23,7 +23,7 @@ from vyos.configtree import ConfigTree from vyos.template import is_ipv4 from vyos.template import is_ipv6 -if (len(argv) < 2): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/quagga/7-to-8 b/src/migration-scripts/quagga/7-to-8 index 15c44924f..8f11bf390 100755 --- a/src/migration-scripts/quagga/7-to-8 +++ b/src/migration-scripts/quagga/7-to-8 @@ -22,7 +22,7 @@ from sys import argv from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 2): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/quagga/8-to-9 b/src/migration-scripts/quagga/8-to-9 index 38507bd3d..0f683d5a1 100755 --- a/src/migration-scripts/quagga/8-to-9 +++ b/src/migration-scripts/quagga/8-to-9 @@ -84,7 +84,7 @@ def migrate_route(config, base, path, route_route6): config.rename(vrf_path, 'vrf') -if (len(argv) < 2): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/quagga/9-to-10 b/src/migration-scripts/quagga/9-to-10 index 249738822..3731762f7 100755 --- a/src/migration-scripts/quagga/9-to-10 +++ b/src/migration-scripts/quagga/9-to-10 @@ -21,7 +21,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 2): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/rip/0-to-1 b/src/migration-scripts/rip/0-to-1 index 60d510001..08a866374 100755 --- a/src/migration-scripts/rip/0-to-1 +++ b/src/migration-scripts/rip/0-to-1 @@ -22,7 +22,7 @@ from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/rpki/0-to-1 b/src/migration-scripts/rpki/0-to-1 index 5b4893205..a7b5d07d5 100755 --- a/src/migration-scripts/rpki/0-to-1 +++ b/src/migration-scripts/rpki/0-to-1 @@ -18,7 +18,7 @@ from sys import exit from sys import argv from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/salt/0-to-1 b/src/migration-scripts/salt/0-to-1 index 79053c056..481d9de8f 100755 --- a/src/migration-scripts/salt/0-to-1 +++ b/src/migration-scripts/salt/0-to-1 @@ -22,7 +22,7 @@ from sys import argv,exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/snmp/0-to-1 b/src/migration-scripts/snmp/0-to-1 index 096ba779d..b1e61b958 100755 --- a/src/migration-scripts/snmp/0-to-1 +++ b/src/migration-scripts/snmp/0-to-1 @@ -17,7 +17,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/snmp/1-to-2 b/src/migration-scripts/snmp/1-to-2 index 466a624e6..e02cd1aa1 100755 --- a/src/migration-scripts/snmp/1-to-2 +++ b/src/migration-scripts/snmp/1-to-2 @@ -43,7 +43,7 @@ def migrate_keys(config, path): config.set(config_path_priv, value=tmp) if __name__ == '__main__': - if (len(argv) < 1): + if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/snmp/2-to-3 b/src/migration-scripts/snmp/2-to-3 index 5f8d9c88d..30911aa27 100755 --- a/src/migration-scripts/snmp/2-to-3 +++ b/src/migration-scripts/snmp/2-to-3 @@ -28,7 +28,7 @@ from sys import exit from vyos.configtree import ConfigTree from vyos.ifconfig import Section -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/ssh/0-to-1 b/src/migration-scripts/ssh/0-to-1 index 91b832276..2595599ac 100755 --- a/src/migration-scripts/ssh/0-to-1 +++ b/src/migration-scripts/ssh/0-to-1 @@ -6,7 +6,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/ssh/1-to-2 b/src/migration-scripts/ssh/1-to-2 index 31c40df16..79d65d7d4 100755 --- a/src/migration-scripts/ssh/1-to-2 +++ b/src/migration-scripts/ssh/1-to-2 @@ -21,7 +21,7 @@ from sys import argv,exit from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/sstp/0-to-1 b/src/migration-scripts/sstp/0-to-1 index dc65bdeab..e2fe1ea8f 100755 --- a/src/migration-scripts/sstp/0-to-1 +++ b/src/migration-scripts/sstp/0-to-1 @@ -28,7 +28,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/sstp/1-to-2 b/src/migration-scripts/sstp/1-to-2 index 94cb04831..f7ecbb6d4 100755 --- a/src/migration-scripts/sstp/1-to-2 +++ b/src/migration-scripts/sstp/1-to-2 @@ -25,7 +25,7 @@ from shutil import copy2 from stat import S_IRUSR, S_IWUSR, S_IRGRP, S_IROTH from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/sstp/2-to-3 b/src/migration-scripts/sstp/2-to-3 index 963b2ba4b..245db7ad6 100755 --- a/src/migration-scripts/sstp/2-to-3 +++ b/src/migration-scripts/sstp/2-to-3 @@ -21,7 +21,7 @@ from vyos.configtree import ConfigTree from sys import argv from sys import exit -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/sstp/3-to-4 b/src/migration-scripts/sstp/3-to-4 index ea814fdc5..00ca7a52d 100755 --- a/src/migration-scripts/sstp/3-to-4 +++ b/src/migration-scripts/sstp/3-to-4 @@ -28,7 +28,7 @@ from vyos.pki import encode_certificate from vyos.pki import encode_private_key from vyos.utils.process import run -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/system/10-to-11 b/src/migration-scripts/system/10-to-11 index 3c49f0d95..5d662af40 100755 --- a/src/migration-scripts/system/10-to-11 +++ b/src/migration-scripts/system/10-to-11 @@ -6,7 +6,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/system/11-to-12 b/src/migration-scripts/system/11-to-12 index 9cddaa1a7..880ab56dc 100755 --- a/src/migration-scripts/system/11-to-12 +++ b/src/migration-scripts/system/11-to-12 @@ -8,7 +8,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/system/12-to-13 b/src/migration-scripts/system/12-to-13 index 36311a19d..e6c4e3802 100755 --- a/src/migration-scripts/system/12-to-13 +++ b/src/migration-scripts/system/12-to-13 @@ -8,7 +8,7 @@ import re from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/system/13-to-14 b/src/migration-scripts/system/13-to-14 index 1751f1865..1fa781869 100755 --- a/src/migration-scripts/system/13-to-14 +++ b/src/migration-scripts/system/13-to-14 @@ -15,7 +15,7 @@ from vyos.configtree import ConfigTree from vyos.utils.process import cmd -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/system/14-to-15 b/src/migration-scripts/system/14-to-15 index c055dad1f..feaac37de 100755 --- a/src/migration-scripts/system/14-to-15 +++ b/src/migration-scripts/system/14-to-15 @@ -11,7 +11,7 @@ ipv6_blacklist_file = '/etc/modprobe.d/vyatta_blacklist_ipv6.conf' from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/system/15-to-16 b/src/migration-scripts/system/15-to-16 index 2491e3d0d..aa1c34032 100755 --- a/src/migration-scripts/system/15-to-16 +++ b/src/migration-scripts/system/15-to-16 @@ -7,7 +7,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/system/16-to-17 b/src/migration-scripts/system/16-to-17 index e70893d55..37e02611d 100755 --- a/src/migration-scripts/system/16-to-17 +++ b/src/migration-scripts/system/16-to-17 @@ -25,7 +25,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/system/17-to-18 b/src/migration-scripts/system/17-to-18 index 8f762c0e2..f6adebb06 100755 --- a/src/migration-scripts/system/17-to-18 +++ b/src/migration-scripts/system/17-to-18 @@ -22,7 +22,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/system/18-to-19 b/src/migration-scripts/system/18-to-19 index 38479d222..fad1d17a4 100755 --- a/src/migration-scripts/system/18-to-19 +++ b/src/migration-scripts/system/18-to-19 @@ -24,7 +24,7 @@ from sys import argv, exit from vyos.ifconfig import Interface from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/system/19-to-20 b/src/migration-scripts/system/19-to-20 index eb20fd8db..c04e6a5a6 100755 --- a/src/migration-scripts/system/19-to-20 +++ b/src/migration-scripts/system/19-to-20 @@ -21,7 +21,7 @@ import os from sys import exit, argv from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/system/20-to-21 b/src/migration-scripts/system/20-to-21 index 1728995de..4bcf4edab 100755 --- a/src/migration-scripts/system/20-to-21 +++ b/src/migration-scripts/system/20-to-21 @@ -21,7 +21,7 @@ import os from sys import argv from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/system/21-to-22 b/src/migration-scripts/system/21-to-22 index ad41be646..810b634ab 100755 --- a/src/migration-scripts/system/21-to-22 +++ b/src/migration-scripts/system/21-to-22 @@ -19,7 +19,7 @@ import os from sys import exit, argv from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/system/22-to-23 b/src/migration-scripts/system/22-to-23 index 7f832e48a..8ed198383 100755 --- a/src/migration-scripts/system/22-to-23 +++ b/src/migration-scripts/system/22-to-23 @@ -19,7 +19,7 @@ import os from sys import exit, argv from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/system/23-to-24 b/src/migration-scripts/system/23-to-24 index 97fe82462..fd68dbf22 100755 --- a/src/migration-scripts/system/23-to-24 +++ b/src/migration-scripts/system/23-to-24 @@ -22,7 +22,7 @@ from sys import exit, argv from vyos.configtree import ConfigTree from vyos.template import is_ipv4 -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/system/24-to-25 b/src/migration-scripts/system/24-to-25 index c2f70689d..1c81a76e7 100755 --- a/src/migration-scripts/system/24-to-25 +++ b/src/migration-scripts/system/24-to-25 @@ -19,7 +19,7 @@ from sys import exit, argv from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/system/25-to-26 b/src/migration-scripts/system/25-to-26 index 615274430..7bdf3be98 100755 --- a/src/migration-scripts/system/25-to-26 +++ b/src/migration-scripts/system/25-to-26 @@ -21,7 +21,7 @@ from sys import exit, argv from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/system/6-to-7 b/src/migration-scripts/system/6-to-7 index bf07abf3a..d24521134 100755 --- a/src/migration-scripts/system/6-to-7 +++ b/src/migration-scripts/system/6-to-7 @@ -6,7 +6,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/system/7-to-8 b/src/migration-scripts/system/7-to-8 index 4cbb21f17..5d084d2bf 100755 --- a/src/migration-scripts/system/7-to-8 +++ b/src/migration-scripts/system/7-to-8 @@ -6,7 +6,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/system/8-to-9 b/src/migration-scripts/system/8-to-9 index db3fefdea..e3bb2bca8 100755 --- a/src/migration-scripts/system/8-to-9 +++ b/src/migration-scripts/system/8-to-9 @@ -6,7 +6,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/vrf/0-to-1 b/src/migration-scripts/vrf/0-to-1 index 5df751113..8187138d9 100755 --- a/src/migration-scripts/vrf/0-to-1 +++ b/src/migration-scripts/vrf/0-to-1 @@ -20,7 +20,7 @@ from sys import argv from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 2): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/vrf/1-to-2 b/src/migration-scripts/vrf/1-to-2 index 9bc704e02..52d4c2c7b 100755 --- a/src/migration-scripts/vrf/1-to-2 +++ b/src/migration-scripts/vrf/1-to-2 @@ -20,7 +20,7 @@ from sys import argv from sys import exit from vyos.configtree import ConfigTree -if (len(argv) < 2): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/vrf/2-to-3 b/src/migration-scripts/vrf/2-to-3 index 8e0f97141..d45b185ee 100755 --- a/src/migration-scripts/vrf/2-to-3 +++ b/src/migration-scripts/vrf/2-to-3 @@ -69,7 +69,7 @@ def _search_tables(config_commands, table_num): return table_items -if (len(argv) < 2): +if len(argv) < 2: print("Must specify file name!") exit(1) diff --git a/src/migration-scripts/vrrp/1-to-2 b/src/migration-scripts/vrrp/1-to-2 index b2e61dd38..dba5af81c 100755 --- a/src/migration-scripts/vrrp/1-to-2 +++ b/src/migration-scripts/vrrp/1-to-2 @@ -21,7 +21,7 @@ import sys from vyos.configtree import ConfigTree -if (len(sys.argv) < 1): +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/migration-scripts/vrrp/2-to-3 b/src/migration-scripts/vrrp/2-to-3 index 1151ae18c..ed583b489 100755 --- a/src/migration-scripts/vrrp/2-to-3 +++ b/src/migration-scripts/vrrp/2-to-3 @@ -19,7 +19,7 @@ from sys import argv from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print('Must specify file name!') exit(1) diff --git a/src/migration-scripts/vrrp/3-to-4 b/src/migration-scripts/vrrp/3-to-4 index b0a6975c2..e5d93578c 100755 --- a/src/migration-scripts/vrrp/3-to-4 +++ b/src/migration-scripts/vrrp/3-to-4 @@ -17,7 +17,7 @@ from sys import argv from vyos.configtree import ConfigTree -if (len(argv) < 1): +if len(argv) < 2: print('Must specify file name!') exit(1) diff --git a/src/migration-scripts/webproxy/1-to-2 b/src/migration-scripts/webproxy/1-to-2 index 070ff356d..03f357878 100755 --- a/src/migration-scripts/webproxy/1-to-2 +++ b/src/migration-scripts/webproxy/1-to-2 @@ -7,7 +7,7 @@ import sys from vyos.configtree import ConfigTree -if len(sys.argv) < 1: +if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) diff --git a/src/op_mode/bridge.py b/src/op_mode/bridge.py index 1834b9cc9..185db4f20 100755 --- a/src/op_mode/bridge.py +++ b/src/op_mode/bridge.py @@ -29,7 +29,6 @@ from vyos.utils.dict import dict_search import vyos.opmode - def _get_json_data(): """ Get bridge data format JSON @@ -46,11 +45,14 @@ def _get_raw_data_summary(): return data_dict -def _get_raw_data_vlan(): +def _get_raw_data_vlan(tunnel:bool=False): """ :returns dict """ - json_data = cmd('bridge --json --compressvlans vlan show') + show = 'show' + if tunnel: + show = 'tunnel' + json_data = cmd(f'bridge --json --compressvlans vlan {show}') data_dict = json.loads(json_data) return data_dict @@ -134,10 +136,34 @@ def _get_formatted_output_vlan(data): flags = ', '.join(flags_raw if isinstance(flags_raw,list) else "").lower() data_entries.append([interface, vlan, flags]) - headers = ["Interface", "Vlan", "Flags"] + headers = ["Interface", "VLAN", "Flags"] output = tabulate(data_entries, headers) return output +def _get_formatted_output_vlan_tunnel(data): + data_entries = [] + for entry in data: + interface = entry.get('ifname') + first = True + for tunnel_entry in entry.get('tunnels'): + vlan = tunnel_entry.get('vlan') + vni = tunnel_entry.get('tunid') + if first: + data_entries.append([interface, vlan, vni]) + first = False + else: + # Group by VXLAN interface only - no need to repeat + # VXLAN interface name for every VLAN <-> VNI mapping + # + # Interface VLAN VNI + # ----------- ------ ----- + # vxlan0 100 100 + # 200 200 + data_entries.append(['', vlan, vni]) + + headers = ["Interface", "VLAN", "VNI"] + output = tabulate(data_entries, headers) + return output def _get_formatted_output_fdb(data): data_entries = [] @@ -192,12 +218,15 @@ def show(raw: bool): return _get_formatted_output_summary(bridge_data) -def show_vlan(raw: bool): - bridge_vlan = _get_raw_data_vlan() +def show_vlan(raw: bool, tunnel: typing.Optional[bool]): + bridge_vlan = _get_raw_data_vlan(tunnel) if raw: return bridge_vlan else: - return _get_formatted_output_vlan(bridge_vlan) + if tunnel: + return _get_formatted_output_vlan_tunnel(bridge_vlan) + else: + return _get_formatted_output_vlan(bridge_vlan) def show_fdb(raw: bool, interface: str): diff --git a/src/op_mode/dhcp.py b/src/op_mode/dhcp.py index 20ef698bd..f558c18b7 100755 --- a/src/op_mode/dhcp.py +++ b/src/op_mode/dhcp.py @@ -295,8 +295,10 @@ def show_server_leases(raw: bool, family: ArgFamily, pool: typing.Optional[str], def _get_raw_client_leases(family='inet', interface=None): from time import mktime from datetime import datetime + from vyos.defaults import directories + from vyos.utils.network import get_interface_vrf - lease_dir = '/var/lib/dhcp' + lease_dir = directories['isc_dhclient_dir'] lease_files = [] lease_data = [] @@ -324,6 +326,10 @@ def _get_raw_client_leases(family='inet', interface=None): k, v = line.split('=') tmp.update({k : v.replace("'", "")}) + if 'interface' in tmp: + vrf = get_interface_vrf(tmp['interface']) + if vrf: tmp.update({'vrf' : vrf}) + lease_data.append(tmp) return lease_data @@ -352,6 +358,8 @@ def _get_formatted_client_leases(lease_data, family): data_entries.append(["DHCP Server", lease['new_dhcp_server_identifier']]) if 'new_dhcp_lease_time' in lease: data_entries.append(["DHCP Server", lease['new_dhcp_lease_time']]) + if 'vrf' in lease: + data_entries.append(["VRF", lease['vrf']]) if 'last_update' in lease: tmp = strftime(time_string, localtime(int(lease['last_update']))) data_entries.append(["Last Update", tmp]) diff --git a/src/op_mode/show_techsupport_report.py b/src/op_mode/show_techsupport_report.py index d27221e54..53144fd52 100644 --- a/src/op_mode/show_techsupport_report.py +++ b/src/op_mode/show_techsupport_report.py @@ -91,7 +91,8 @@ def show_package_repository_config() -> None: def show_user_startup_scripts() -> None: """Prints the user startup scripts.""" - execute_command('cat /config/scripts/vyos-postconfig-bootup.script', 'User Startup Scripts') + execute_command('cat /config/scripts/vyos-preconfig-bootup.script', 'User Startup Scripts (Preconfig)') + execute_command('cat /config/scripts/vyos-postconfig-bootup.script', 'User Startup Scripts (Postconfig)') def show_frr_config() -> None: diff --git a/src/systemd/dhclient@.service b/src/systemd/dhclient@.service index 23cd4cfc3..099f7ed52 100644 --- a/src/systemd/dhclient@.service +++ b/src/systemd/dhclient@.service @@ -1,18 +1,17 @@ [Unit] Description=DHCP client on %i Documentation=man:dhclient(8) -ConditionPathExists=/var/lib/dhcp/dhclient_%i.conf -ConditionPathExists=/var/lib/dhcp/dhclient_%i.options +StartLimitIntervalSec=0 After=vyos-router.service [Service] -WorkingDirectory=/var/lib/dhcp Type=exec -EnvironmentFile=-/var/lib/dhcp/dhclient_%i.options -PIDFile=/var/lib/dhcp/dhclient_%i.pid -ExecStart=/sbin/dhclient -4 $DHCLIENT_OPTS -ExecStop=/sbin/dhclient -4 $DHCLIENT_OPTS -r +ExecStart=/sbin/dhclient -4 -d $DHCLIENT_OPTS +ExecStop=/sbin/dhclient -4 -r $DHCLIENT_OPTS Restart=always +RestartPreventExitStatus= +RestartSec=10 +RuntimeDirectoryPreserve=yes TimeoutStopSec=20 SendSIGKILL=true FinalKillSignal=SIGABRT diff --git a/src/systemd/dhcp6c@.service b/src/systemd/dhcp6c@.service index 495cb7e26..f634bd944 100644 --- a/src/systemd/dhcp6c@.service +++ b/src/systemd/dhcp6c@.service @@ -1,19 +1,19 @@ [Unit] Description=WIDE DHCPv6 client on %i Documentation=man:dhcp6c(8) man:dhcp6c.conf(5) -ConditionPathExists=/run/dhcp6c/dhcp6c.%i.conf -ConditionPathExists=/run/dhcp6c/dhcp6c.%i.options -After=vyos-router.service StartLimitIntervalSec=0 +After=vyos-router.service [Service] +Type=forking WorkingDirectory=/run/dhcp6c EnvironmentFile=-/run/dhcp6c/dhcp6c.%i.options -Type=forking PIDFile=/run/dhcp6c/dhcp6c.%i.pid ExecStart=/usr/sbin/dhcp6c $DHCP6C_OPTS -Restart=on-failure -RestartSec=20 +Restart=always +RestartPreventExitStatus= +RestartSec=10 +RuntimeDirectoryPreserve=yes [Install] WantedBy=multi-user.target diff --git a/src/tests/test_util.py b/src/tests/test_utils.py index 27ee648d4..9ae329ced 100644 --- a/src/tests/test_util.py +++ b/src/tests/test_utils.py @@ -15,8 +15,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. from unittest import TestCase - -class TestVyOSUtil(TestCase): +class TestVyOSUtils(TestCase): def test_key_mangling(self): from vyos.utils.dict import mangle_dict_keys data = {"foo-bar": {"baz-quux": None}} diff --git a/src/tests/test_utils_network.py b/src/tests/test_utils_network.py new file mode 100644 index 000000000..5a6dc2586 --- /dev/null +++ b/src/tests/test_utils_network.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +# +# 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 +# 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 vyos.utils.network +from unittest import TestCase + +class TestVyOSUtilsNetwork(TestCase): + def setUp(self): + pass + + def test_is_addr_assigned(self): + self.assertTrue(vyos.utils.network.is_addr_assigned('127.0.0.1')) + self.assertTrue(vyos.utils.network.is_addr_assigned('::1')) + self.assertFalse(vyos.utils.network.is_addr_assigned('127.251.255.123')) + + def test_is_ipv6_link_local(self): + self.assertFalse(vyos.utils.network.is_ipv6_link_local('169.254.0.1')) + self.assertTrue(vyos.utils.network.is_ipv6_link_local('fe80::')) + self.assertTrue(vyos.utils.network.is_ipv6_link_local('fe80::affe:1')) + self.assertTrue(vyos.utils.network.is_ipv6_link_local('fe80::affe:1%eth0')) + self.assertFalse(vyos.utils.network.is_ipv6_link_local('2001:db8::')) + self.assertFalse(vyos.utils.network.is_ipv6_link_local('2001:db8::%eth0')) + self.assertFalse(vyos.utils.network.is_ipv6_link_local('VyOS')) + self.assertFalse(vyos.utils.network.is_ipv6_link_local('::1')) + self.assertFalse(vyos.utils.network.is_ipv6_link_local('::1%lo')) + + def test_is_ipv6_link_local(self): + self.assertTrue(vyos.utils.network.is_loopback_addr('127.0.0.1')) + self.assertTrue(vyos.utils.network.is_loopback_addr('127.0.1.1')) + self.assertTrue(vyos.utils.network.is_loopback_addr('127.1.1.1')) + self.assertTrue(vyos.utils.network.is_loopback_addr('::1')) + + self.assertFalse(vyos.utils.network.is_loopback_addr('::2')) + self.assertFalse(vyos.utils.network.is_loopback_addr('192.0.2.1')) + + + diff --git a/src/tests/test_validate.py b/src/tests/test_validate.py deleted file mode 100644 index 68a257d25..000000000 --- a/src/tests/test_validate.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2020 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 vyos.validate -from unittest import TestCase - -class TestVyOSValidate(TestCase): - def setUp(self): - pass - - def test_is_addr_assigned(self): - self.assertTrue(vyos.validate.is_addr_assigned('127.0.0.1')) - self.assertTrue(vyos.validate.is_addr_assigned('::1')) - self.assertFalse(vyos.validate.is_addr_assigned('127.251.255.123')) - - def test_is_ipv6_link_local(self): - self.assertFalse(vyos.validate.is_ipv6_link_local('169.254.0.1')) - self.assertTrue(vyos.validate.is_ipv6_link_local('fe80::')) - self.assertTrue(vyos.validate.is_ipv6_link_local('fe80::affe:1')) - self.assertTrue(vyos.validate.is_ipv6_link_local('fe80::affe:1%eth0')) - self.assertFalse(vyos.validate.is_ipv6_link_local('2001:db8::')) - self.assertFalse(vyos.validate.is_ipv6_link_local('2001:db8::%eth0')) - self.assertFalse(vyos.validate.is_ipv6_link_local('VyOS')) - self.assertFalse(vyos.validate.is_ipv6_link_local('::1')) - self.assertFalse(vyos.validate.is_ipv6_link_local('::1%lo')) - - def test_is_ipv6_link_local(self): - self.assertTrue(vyos.validate.is_loopback_addr('127.0.0.1')) - self.assertTrue(vyos.validate.is_loopback_addr('127.0.1.1')) - self.assertTrue(vyos.validate.is_loopback_addr('127.1.1.1')) - self.assertTrue(vyos.validate.is_loopback_addr('::1')) - - self.assertFalse(vyos.validate.is_loopback_addr('::2')) - self.assertFalse(vyos.validate.is_loopback_addr('192.0.2.1')) - - - diff --git a/src/validators/ipv6-link-local b/src/validators/ipv6-link-local index 05e693b77..6ac3ea710 100755 --- a/src/validators/ipv6-link-local +++ b/src/validators/ipv6-link-local @@ -1,7 +1,7 @@ #!/usr/bin/python3 import sys -from vyos.validate import is_ipv6_link_local +from vyos.utils.network import is_ipv6_link_local if __name__ == '__main__': if len(sys.argv)>1: |