summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/package-smoketest.yml43
-rw-r--r--.github/workflows/trigger-rebuild-repo-package.yml15
-rw-r--r--data/templates/frr/daemons.frr.tmpl2
-rw-r--r--data/templates/frr/fabricd.frr.j272
-rw-r--r--interface-definitions/include/isis/protocol-common-config.xml.i20
-rw-r--r--interface-definitions/include/log-adjacency-changes.xml.i8
-rw-r--r--interface-definitions/include/net.xml.i14
-rw-r--r--interface-definitions/include/openfabric/password.xml.i20
-rw-r--r--interface-definitions/protocols_openfabric.xml.in218
-rw-r--r--interface-definitions/system_option.xml.in20
-rw-r--r--op-mode-definitions/execute-ssh.xml.in34
-rw-r--r--op-mode-definitions/include/show-route-openfabric.xml.i8
-rw-r--r--op-mode-definitions/monitor-log.xml.in6
-rw-r--r--op-mode-definitions/restart-frr.xml.in6
-rw-r--r--op-mode-definitions/show-ip-route.xml.in1
-rw-r--r--op-mode-definitions/show-ipv6-route.xml.in1
-rw-r--r--op-mode-definitions/show-log.xml.in6
-rw-r--r--op-mode-definitions/show-openfabric.xml.in51
-rw-r--r--python/vyos/frr.py2
-rw-r--r--smoketest/scripts/cli/test_protocols_openfabric.py186
-rwxr-xr-xsrc/conf_mode/policy.py8
-rw-r--r--src/conf_mode/protocols_openfabric.py145
-rwxr-xr-xsrc/conf_mode/system_option.py45
-rwxr-xr-xsrc/op_mode/restart.py42
-rwxr-xr-xsrc/op_mode/restart_frr.py2
25 files changed, 916 insertions, 59 deletions
diff --git a/.github/workflows/package-smoketest.yml b/.github/workflows/package-smoketest.yml
index 467ff062e..a74c35adf 100644
--- a/.github/workflows/package-smoketest.yml
+++ b/.github/workflows/package-smoketest.yml
@@ -15,6 +15,9 @@ permissions:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed for PR comments
+ BUILD_BY: autobuild@vyos.net
+ DEBIAN_MIRROR: http://deb.debian.org/debian/
+ VYOS_MIRROR: https://rolling-packages.vyos.net/current/
jobs:
build_iso:
@@ -23,9 +26,6 @@ jobs:
container:
image: vyos/vyos-build:current
options: --sysctl net.ipv6.conf.lo.disable_ipv6=0 --privileged
- env:
- BUILD_BY: autobuild@vyos.net
- DEBIAN_MIRROR: http://deb.debian.org/debian/
outputs:
build_version: ${{ steps.version.outputs.build_version }}
steps:
@@ -52,9 +52,11 @@ jobs:
sudo --preserve-env ./build-vyos-image \
--architecture amd64 \
--build-by $BUILD_BY \
+ --build-type release \
+ --custom-package vyos-1x-smoketest \
--debian-mirror $DEBIAN_MIRROR \
--version ${{ steps.version.outputs.build_version }} \
- --build-type release \
+ --vyos-mirror $VYOS_MIRROR \
generic
- uses: actions/upload-artifact@v4
with:
@@ -154,11 +156,43 @@ jobs:
echo "exit_code=fail" >> $GITHUB_OUTPUT
fi
+ test_encrypted_config_tpm:
+ needs: build_iso
+ runs-on: ubuntu-24.04
+ timeout-minutes: 30
+ container:
+ image: vyos/vyos-build:current
+ options: --sysctl net.ipv6.conf.lo.disable_ipv6=0 --privileged
+ outputs:
+ exit_code: ${{ steps.test.outputs.exit_code }}
+ steps:
+ # We need the test script from vyos-build repo
+ - name: Clone vyos-build source code
+ uses: actions/checkout@v4
+ with:
+ repository: vyos/vyos-build
+ - uses: actions/download-artifact@v4
+ with:
+ name: vyos-${{ needs.build_iso.outputs.build_version }}
+ path: build
+ - name: VyOS TPM encryption tests
+ id: test
+ shell: bash
+ run: |
+ set -e
+ sudo make testtpm
+ if [[ $? == 0 ]]; then
+ echo "exit_code=success" >> $GITHUB_OUTPUT
+ else
+ echo "exit_code=fail" >> $GITHUB_OUTPUT
+ fi
+
result:
needs:
- test_smoketest_cli
- test_config_load
- test_raid1_install
+ - test_encrypted_config_tpm
runs-on: ubuntu-24.04
timeout-minutes: 5
if: always()
@@ -177,6 +211,7 @@ jobs:
* CLI Smoketests ${{ needs.test_smoketest_cli.outputs.exit_code == 'success' && '👍 passed' || '❌ failed' }}
* Config tests ${{ needs.test_config_load.outputs.exit_code == 'success' && '👍 passed' || '❌ failed' }}
* RAID1 tests ${{ needs.test_raid1_install.outputs.exit_code == 'success' && '👍 passed' || '❌ failed' }}
+ * TPM tests ${{ needs.test_encrypted_config_tpm.outputs.exit_code == 'success' && '👍 passed' || '❌ failed' }}
message-id: "SMOKETEST_RESULTS"
allow-repeats: false
diff --git a/.github/workflows/trigger-rebuild-repo-package.yml b/.github/workflows/trigger-rebuild-repo-package.yml
index d0936b572..37ec83274 100644
--- a/.github/workflows/trigger-rebuild-repo-package.yml
+++ b/.github/workflows/trigger-rebuild-repo-package.yml
@@ -1,7 +1,7 @@
name: Trigger to build a deb package from repo
on:
- pull_request:
+ pull_request_target:
types:
- closed
branches:
@@ -23,11 +23,10 @@ jobs:
needs: get_repo_name
uses: vyos/.github/.github/workflows/trigger-rebuild-repo-package.yml@current
with:
- branch: ${{ github.ref_name }}
- package_name: ${{ needs.get_repo_name.outputs.PACKAGE_NAME }}
- REF: main # optinal because the default value is main
+ branch: ${{ github.ref_name }}
+ package_name: ${{ needs.get_repo_name.outputs.PACKAGE_NAME }}
secrets:
- REMOTE_OWNER: ${{ secrets.REMOTE_OWNER }}
- REMOTE_REUSE_REPO: ${{ secrets.REMOTE_REUSE_REPO }}
- GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }}
- PAT: ${{ secrets.PAT }}
+ REMOTE_OWNER: ${{ secrets.REMOTE_OWNER }}
+ REMOTE_REUSE_REPO: ${{ secrets.REMOTE_REUSE_REPO }}
+ GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }}
+ PAT: ${{ secrets.PAT }}
diff --git a/data/templates/frr/daemons.frr.tmpl b/data/templates/frr/daemons.frr.tmpl
index 339b4e52f..3506528d2 100644
--- a/data/templates/frr/daemons.frr.tmpl
+++ b/data/templates/frr/daemons.frr.tmpl
@@ -36,7 +36,7 @@ babeld=yes
sharpd=no
pbrd=no
bfdd=yes
-fabricd=no
+fabricd=yes
vrrpd=no
pathd=no
diff --git a/data/templates/frr/fabricd.frr.j2 b/data/templates/frr/fabricd.frr.j2
new file mode 100644
index 000000000..8f2ae6466
--- /dev/null
+++ b/data/templates/frr/fabricd.frr.j2
@@ -0,0 +1,72 @@
+!
+{% for name, router_config in domain.items() %}
+{% if router_config.interface is vyos_defined %}
+{% for iface, iface_config in router_config.interface.items() %}
+interface {{ iface }}
+{% if iface_config.address_family.ipv4 is vyos_defined %}
+ ip router openfabric {{ name }}
+{% endif %}
+{% if iface_config.address_family.ipv6 is vyos_defined %}
+ ipv6 router openfabric {{ name }}
+{% endif %}
+{% if iface_config.csnp_interval is vyos_defined %}
+ openfabric csnp-interval {{ iface_config.csnp_interval }}
+{% endif %}
+{% if iface_config.hello_interval is vyos_defined %}
+ openfabric hello-interval {{ iface_config.hello_interval }}
+{% endif %}
+{% if iface_config.hello_multiplier is vyos_defined %}
+ openfabric hello-multiplier {{ iface_config.hello_multiplier }}
+{% endif %}
+{% if iface_config.metric is vyos_defined %}
+ openfabric metric {{ iface_config.metric }}
+{% endif %}
+{% if iface_config.passive is vyos_defined or iface == 'lo' %}
+ openfabric passive
+{% endif %}
+{% if iface_config.password.md5 is vyos_defined %}
+ openfabric password md5 {{ iface_config.password.md5 }}
+{% elif iface_config.password.plaintext_password is vyos_defined %}
+ openfabric password clear {{ iface_config.password.plaintext_password }}
+{% endif %}
+{% if iface_config.psnp_interval is vyos_defined %}
+ openfabric psnp-interval {{ iface_config.psnp_interval }}
+{% endif %}
+exit
+!
+{% endfor %}
+{% endif %}
+router openfabric {{ name }}
+ net {{ net }}
+{% if router_config.domain_password.md5 is vyos_defined %}
+ domain-password md5 {{ router_config.domain_password.plaintext_password }}
+{% elif router_config.domain_password.plaintext_password is vyos_defined %}
+ domain-password clear {{ router_config.domain_password.plaintext_password }}
+{% endif %}
+{% if router_config.log_adjacency_changes is vyos_defined %}
+ log-adjacency-changes
+{% endif %}
+{% if router_config.set_overload_bit is vyos_defined %}
+ set-overload-bit
+{% endif %}
+{% if router_config.purge_originator is vyos_defined %}
+ purge-originator
+{% endif %}
+{% if router_config.fabric_tier is vyos_defined %}
+ fabric-tier {{ router_config.fabric_tier }}
+{% endif %}
+{% if router_config.lsp_gen_interval is vyos_defined %}
+ lsp-gen-interval {{ router_config.lsp_gen_interval }}
+{% endif %}
+{% if router_config.lsp_refresh_interval is vyos_defined %}
+ lsp-refresh-interval {{ router_config.lsp_refresh_interval }}
+{% endif %}
+{% if router_config.max_lsp_lifetime is vyos_defined %}
+ max-lsp-lifetime {{ router_config.max_lsp_lifetime }}
+{% endif %}
+{% if router_config.spf_interval is vyos_defined %}
+ spf-interval {{ router_config.spf_interval }}
+{% endif %}
+exit
+!
+{% endfor %}
diff --git a/interface-definitions/include/isis/protocol-common-config.xml.i b/interface-definitions/include/isis/protocol-common-config.xml.i
index 0e79ca5f2..35ce80be9 100644
--- a/interface-definitions/include/isis/protocol-common-config.xml.i
+++ b/interface-definitions/include/isis/protocol-common-config.xml.i
@@ -86,12 +86,7 @@
</constraint>
</properties>
</leafNode>
-<leafNode name="log-adjacency-changes">
- <properties>
- <help>Log adjacency state changes</help>
- <valueless/>
- </properties>
-</leafNode>
+#include <include/log-adjacency-changes.xml.i>
<leafNode name="lsp-gen-interval">
<properties>
<help>Minimum interval between regenerating same LSP</help>
@@ -208,18 +203,7 @@
#include <include/isis/lfa-protocol.xml.i>
</children>
</node>
-<leafNode name="net">
- <properties>
- <help>A Network Entity Title for this process (ISO only)</help>
- <valueHelp>
- <format>XX.XXXX. ... .XXX.XX</format>
- <description>Network entity title (NET)</description>
- </valueHelp>
- <constraint>
- <regex>[a-fA-F0-9]{2}(\.[a-fA-F0-9]{4}){3,9}\.[a-fA-F0-9]{2}</regex>
- </constraint>
- </properties>
-</leafNode>
+#include <include/net.xml.i>
<leafNode name="purge-originator">
<properties>
<help>Use the RFC 6232 purge-originator</help>
diff --git a/interface-definitions/include/log-adjacency-changes.xml.i b/interface-definitions/include/log-adjacency-changes.xml.i
new file mode 100644
index 000000000..a0628b8e2
--- /dev/null
+++ b/interface-definitions/include/log-adjacency-changes.xml.i
@@ -0,0 +1,8 @@
+<!-- include start from log-adjacency-changes.xml.i -->
+<leafNode name="log-adjacency-changes">
+ <properties>
+ <help>Log changes in adjacency state</help>
+ <valueless/>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/net.xml.i b/interface-definitions/include/net.xml.i
new file mode 100644
index 000000000..10b54ee49
--- /dev/null
+++ b/interface-definitions/include/net.xml.i
@@ -0,0 +1,14 @@
+<!-- include start from net.xml.i -->
+<leafNode name="net">
+ <properties>
+ <help>A Network Entity Title for the process (ISO only)</help>
+ <valueHelp>
+ <format>XX.XXXX. ... .XXX.XX</format>
+ <description>Network entity title (NET)</description>
+ </valueHelp>
+ <constraint>
+ <regex>[a-fA-F0-9]{2}(\.[a-fA-F0-9]{4}){3,9}\.[a-fA-F0-9]{2}</regex>
+ </constraint>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/openfabric/password.xml.i b/interface-definitions/include/openfabric/password.xml.i
new file mode 100644
index 000000000..fa34a4dab
--- /dev/null
+++ b/interface-definitions/include/openfabric/password.xml.i
@@ -0,0 +1,20 @@
+<!-- include start from openfabric/password.xml.i -->
+<leafNode name="plaintext-password">
+ <properties>
+ <help>Use plain text password</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Authentication password</description>
+ </valueHelp>
+ </properties>
+</leafNode>
+<leafNode name="md5">
+ <properties>
+ <help>Use MD5 hash authentication</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Authentication password</description>
+ </valueHelp>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/protocols_openfabric.xml.in b/interface-definitions/protocols_openfabric.xml.in
new file mode 100644
index 000000000..81200360e
--- /dev/null
+++ b/interface-definitions/protocols_openfabric.xml.in
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interfaceDefinition>
+ <node name="protocols">
+ <children>
+ <node name="openfabric" owner="${vyos_conf_scripts_dir}/protocols_openfabric.py">
+ <properties>
+ <help>OpenFabric protocol</help>
+ <priority>680</priority>
+ </properties>
+ <children>
+ #include <include/net.xml.i>
+ <tagNode name="domain">
+ <properties>
+ <help>OpenFabric process name</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Domain name</description>
+ </valueHelp>
+ </properties>
+ <children>
+ <tagNode name="interface">
+ <properties>
+ <help>Interface params</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces</script>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>Interface name</description>
+ </valueHelp>
+ <constraint>
+ #include <include/constraint/interface-name.xml.i>
+ </constraint>
+ </properties>
+ <children>
+ <node name="address-family">
+ <properties>
+ <help>Openfabric address family</help>
+ </properties>
+ <children>
+ <leafNode name="ipv4">
+ <properties>
+ <help>IPv4 OpenFabric</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="ipv6">
+ <properties>
+ <help>IPv6 OpenFabric</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ <leafNode name="csnp-interval">
+ <properties>
+ <help>Complete Sequence Number Packets (CSNP) interval</help>
+ <valueHelp>
+ <format>u32:1-600</format>
+ <description>CSNP interval in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-600"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="hello-interval">
+ <properties>
+ <help>Hello interval</help>
+ <valueHelp>
+ <format>u32:1-600</format>
+ <description>Hello interval in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-600"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="hello-multiplier">
+ <properties>
+ <help>Multiplier for Hello holding time</help>
+ <valueHelp>
+ <format>u32:2-100</format>
+ <description>Multiplier for Hello holding time</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 2-100"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="metric">
+ <properties>
+ <help>Interface metric value</help>
+ <valueHelp>
+ <format>u32:0-16777215</format>
+ <description>Interface metric value</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-16777215"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="passive">
+ <properties>
+ <help>Do not initiate adjacencies to the interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <node name="password">
+ <properties>
+ <help>Authentication password for the interface</help>
+ </properties>
+ <children>
+ #include <include/openfabric/password.xml.i>
+ </children>
+ </node>
+ <leafNode name="psnp-interval">
+ <properties>
+ <help>Partial Sequence Number Packets (PSNP) interval</help>
+ <valueHelp>
+ <format>u32:0-120</format>
+ <description>PSNP interval in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-120"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </tagNode>
+ <node name="domain-password">
+ <properties>
+ <help>Authentication password for a routing domain</help>
+ </properties>
+ <children>
+ #include <include/openfabric/password.xml.i>
+ </children>
+ </node>
+ #include <include/log-adjacency-changes.xml.i>
+ <leafNode name="set-overload-bit">
+ <properties>
+ <help>Overload bit to avoid any transit traffic</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="purge-originator">
+ <properties>
+ <help>RFC 6232 purge originator identification</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="fabric-tier">
+ <properties>
+ <help>Static tier number to advertise as location in the fabric</help>
+ <valueHelp>
+ <format>u32:0-14</format>
+ <description>Static tier number</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-14"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="lsp-gen-interval">
+ <properties>
+ <help>Minimum interval between regenerating same link-state packet (LSP)</help>
+ <valueHelp>
+ <format>u32:1-120</format>
+ <description>Minimum interval in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-120"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="lsp-refresh-interval">
+ <properties>
+ <help>Link-state packet (LSP) refresh interval</help>
+ <valueHelp>
+ <format>u32:1-65235</format>
+ <description>LSP refresh interval in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-65235"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="max-lsp-lifetime">
+ <properties>
+ <help>Maximum link-state packet lifetime</help>
+ <valueHelp>
+ <format>u32:360-65535</format>
+ <description>Maximum LSP lifetime in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 360-65535"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="spf-interval">
+ <properties>
+ <help>Minimum interval between SPF calculations</help>
+ <valueHelp>
+ <format>u32:1-120</format>
+ <description>Interval in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-120"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </tagNode>
+ </children>
+ </node>
+ </children>
+ </node>
+</interfaceDefinition>
diff --git a/interface-definitions/system_option.xml.in b/interface-definitions/system_option.xml.in
index e78a53552..dc9958ff5 100644
--- a/interface-definitions/system_option.xml.in
+++ b/interface-definitions/system_option.xml.in
@@ -49,6 +49,26 @@
<valueless/>
</properties>
</leafNode>
+ <leafNode name="amd-pstate-driver">
+ <properties>
+ <help>Enables and configures pstate driver for AMD Ryzen and Epyc CPUs</help>
+ <completionHelp>
+ <list>active passive guided</list>
+ </completionHelp>
+ <valueHelp>
+ <format>active</format>
+ <description>The firmware controls performance states and the system governor has no effect</description>
+ </valueHelp>
+ <valueHelp>
+ <format>passive</format>
+ <description>Allow the system governor to manage performance states</description>
+ </valueHelp>
+ <valueHelp>
+ <format>guided</format>
+ <description>The firmware controls performance states guided by the system governor</description>
+ </valueHelp>
+ </properties>
+ </leafNode>
<node name="debug">
<properties>
<help>Dynamic debugging for kernel module</help>
diff --git a/op-mode-definitions/execute-ssh.xml.in b/op-mode-definitions/execute-ssh.xml.in
new file mode 100644
index 000000000..7fa656f5e
--- /dev/null
+++ b/op-mode-definitions/execute-ssh.xml.in
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<interfaceDefinition>
+ <node name="execute">
+ <children>
+ <node name="ssh">
+ <properties>
+ <help>SSH to a node</help>
+ </properties>
+ <children>
+ <tagNode name="host">
+ <properties>
+ <help>Hostname or IP address</help>
+ <completionHelp>
+ <list>&lt;hostname&gt; &lt;x.x.x.x&gt; &lt;h:h:h:h:h:h:h:h&gt;</list>
+ </completionHelp>
+ </properties>
+ <command>/usr/bin/ssh $4</command>
+ <children>
+ <tagNode name="user">
+ <properties>
+ <help>Remote server username</help>
+ <completionHelp>
+ <list>&lt;username&gt;</list>
+ </completionHelp>
+ </properties>
+ <command>/usr/bin/ssh $6@$4</command>
+ </tagNode>
+ </children>
+ </tagNode>
+ </children>
+ </node>
+ </children>
+ </node>
+</interfaceDefinition>
diff --git a/op-mode-definitions/include/show-route-openfabric.xml.i b/op-mode-definitions/include/show-route-openfabric.xml.i
new file mode 100644
index 000000000..ae1ef380e
--- /dev/null
+++ b/op-mode-definitions/include/show-route-openfabric.xml.i
@@ -0,0 +1,8 @@
+<!-- included start from show-route-openfabric.xml.i -->
+<leafNode name="openfabric">
+ <properties>
+ <help>OpenFabric routes</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</leafNode>
+<!-- included end -->
diff --git a/op-mode-definitions/monitor-log.xml.in b/op-mode-definitions/monitor-log.xml.in
index a2d5d924a..6a2b7e53b 100644
--- a/op-mode-definitions/monitor-log.xml.in
+++ b/op-mode-definitions/monitor-log.xml.in
@@ -237,6 +237,12 @@
</properties>
<command>journalctl --follow --no-hostname --boot /usr/lib/frr/isisd</command>
</leafNode>
+ <leafNode name="openfabric">
+ <properties>
+ <help>Monitor log for OpenFabric</help>
+ </properties>
+ <command>journalctl --follow --no-hostname --boot /usr/lib/frr/fabricd</command>
+ </leafNode>
<leafNode name="nhrp">
<properties>
<help>Monitor log for NHRP</help>
diff --git a/op-mode-definitions/restart-frr.xml.in b/op-mode-definitions/restart-frr.xml.in
index 2c9d4b1cc..4772e8dd2 100644
--- a/op-mode-definitions/restart-frr.xml.in
+++ b/op-mode-definitions/restart-frr.xml.in
@@ -56,6 +56,12 @@
</properties>
<command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon isisd</command>
</leafNode>
+ <leafNode name="openfabric">
+ <properties>
+ <help>Restart OpenFabric routing daemon</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon fabricd</command>
+ </leafNode>
<leafNode name="pim6">
<properties>
<help>Restart IPv6 Protocol Independent Multicast (PIM) daemon</help>
diff --git a/op-mode-definitions/show-ip-route.xml.in b/op-mode-definitions/show-ip-route.xml.in
index c878bf712..37279d3d2 100644
--- a/op-mode-definitions/show-ip-route.xml.in
+++ b/op-mode-definitions/show-ip-route.xml.in
@@ -46,6 +46,7 @@
<command>ip -s route list $5</command>
</tagNode>
#include <include/show-route-isis.xml.i>
+ #include <include/show-route-openfabric.xml.i>
#include <include/show-route-kernel.xml.i>
#include <include/show-route-ospf.xml.i>
#include <include/show-route-rip.xml.i>
diff --git a/op-mode-definitions/show-ipv6-route.xml.in b/op-mode-definitions/show-ipv6-route.xml.in
index d73fb46b4..f68a94971 100644
--- a/op-mode-definitions/show-ipv6-route.xml.in
+++ b/op-mode-definitions/show-ipv6-route.xml.in
@@ -46,6 +46,7 @@
<command>ip -s -f inet6 route list $5</command>
</tagNode>
#include <include/show-route-isis.xml.i>
+ #include <include/show-route-openfabric.xml.i>
#include <include/show-route-kernel.xml.i>
#include <include/show-route-ospfv3.xml.i>
#include <include/show-route-ripng.xml.i>
diff --git a/op-mode-definitions/show-log.xml.in b/op-mode-definitions/show-log.xml.in
index 7ae3b890b..f0fad63d2 100644
--- a/op-mode-definitions/show-log.xml.in
+++ b/op-mode-definitions/show-log.xml.in
@@ -642,6 +642,12 @@
</properties>
<command>journalctl --boot /usr/lib/frr/isisd</command>
</leafNode>
+ <leafNode name="openfabric">
+ <properties>
+ <help>Show log for OpenFabric</help>
+ </properties>
+ <command>journalctl --boot /usr/lib/frr/fabricd</command>
+ </leafNode>
<leafNode name="nhrp">
<properties>
<help>Show log for NHRP</help>
diff --git a/op-mode-definitions/show-openfabric.xml.in b/op-mode-definitions/show-openfabric.xml.in
new file mode 100644
index 000000000..2f489866e
--- /dev/null
+++ b/op-mode-definitions/show-openfabric.xml.in
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<interfaceDefinition>
+ <node name="show">
+ <children>
+ <node name="openfabric">
+ <properties>
+ <help>Show OpenFabric routing protocol</help>
+ </properties>
+ <children>
+ <node name="database">
+ <properties>
+ <help>Show OpenFabric link state database</help>
+ </properties>
+ <children>
+ #include <include/vtysh-generic-detail.xml.i>
+ </children>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </node>
+ <node name="interface">
+ <properties>
+ <help>Show OpenFabric interfaces</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces</script>
+ </completionHelp>
+ </properties>
+ <children>
+ #include <include/vtysh-generic-detail.xml.i>
+ </children>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </node>
+ #include <include/vtysh-generic-interface-tagNode.xml.i>
+ <node name="neighbor">
+ <properties>
+ <help>Show OpenFabric neighbor adjacencies</help>
+ </properties>
+ <children>
+ #include <include/vtysh-generic-detail.xml.i>
+ </children>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </node>
+ <leafNode name="summary">
+ <properties>
+ <help>Show OpenFabric information summary</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+ </node>
+</interfaceDefinition>
diff --git a/python/vyos/frr.py b/python/vyos/frr.py
index e7743e9d5..6fb81803f 100644
--- a/python/vyos/frr.py
+++ b/python/vyos/frr.py
@@ -87,7 +87,7 @@ LOG.addHandler(ch)
LOG.addHandler(ch2)
_frr_daemons = ['zebra', 'staticd', 'bgpd', 'ospfd', 'ospf6d', 'ripd', 'ripngd',
- 'isisd', 'pimd', 'pim6d', 'ldpd', 'eigrpd', 'babeld', 'bfdd']
+ 'isisd', 'pimd', 'pim6d', 'ldpd', 'eigrpd', 'babeld', 'bfdd', 'fabricd']
path_vtysh = '/usr/bin/vtysh'
path_frr_reload = '/usr/lib/frr/frr-reload.py'
diff --git a/smoketest/scripts/cli/test_protocols_openfabric.py b/smoketest/scripts/cli/test_protocols_openfabric.py
new file mode 100644
index 000000000..e37aed456
--- /dev/null
+++ b/smoketest/scripts/cli/test_protocols_openfabric.py
@@ -0,0 +1,186 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 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 unittest
+
+from base_vyostest_shim import VyOSUnitTestSHIM
+from vyos.configsession import ConfigSessionError
+from vyos.utils.process import process_named_running
+
+PROCESS_NAME = 'fabricd'
+base_path = ['protocols', 'openfabric']
+
+domain = 'VyOS'
+net = '49.0001.1111.1111.1111.00'
+dummy_if = 'dum1234'
+address_families = ['ipv4', 'ipv6']
+
+path = base_path + ['domain', domain]
+
+class TestProtocolsOpenFabric(VyOSUnitTestSHIM.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ # call base-classes classmethod
+ super(TestProtocolsOpenFabric, cls).setUpClass()
+ # Retrieve FRR daemon PID - it is not allowed to crash, thus PID must remain the same
+ cls.daemon_pid = process_named_running(PROCESS_NAME)
+ # ensure we can also run this test on a live system - so lets clean
+ # out the current configuration :)
+ cls.cli_delete(cls, base_path)
+
+ def tearDown(self):
+ self.cli_delete(base_path)
+ self.cli_commit()
+
+ # check process health and continuity
+ self.assertEqual(self.daemon_pid, process_named_running(PROCESS_NAME))
+
+ def openfabric_base_config(self):
+ self.cli_set(['interfaces', 'dummy', dummy_if])
+ self.cli_set(base_path + ['net', net])
+ for family in address_families:
+ self.cli_set(path + ['interface', dummy_if, 'address-family', family])
+
+ def test_openfabric_01_router_params(self):
+ fabric_tier = '5'
+ lsp_gen_interval = '20'
+
+ self.cli_set(base_path)
+
+ # verify() - net id and domain name are mandatory
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.openfabric_base_config()
+
+ self.cli_set(path + ['log-adjacency-changes'])
+ self.cli_set(path + ['set-overload-bit'])
+ self.cli_set(path + ['fabric-tier', fabric_tier])
+ self.cli_set(path + ['lsp-gen-interval', lsp_gen_interval])
+
+ # Commit all changes
+ self.cli_commit()
+
+ # Verify all changes
+ tmp = self.getFRRconfig(f'router openfabric {domain}', daemon='fabricd')
+ self.assertIn(f' net {net}', tmp)
+ self.assertIn(f' log-adjacency-changes', tmp)
+ self.assertIn(f' set-overload-bit', tmp)
+ self.assertIn(f' fabric-tier {fabric_tier}', tmp)
+ self.assertIn(f' lsp-gen-interval {lsp_gen_interval}', tmp)
+
+ tmp = self.getFRRconfig(f'interface {dummy_if}', daemon='fabricd')
+ self.assertIn(f' ip router openfabric {domain}', tmp)
+ self.assertIn(f' ipv6 router openfabric {domain}', tmp)
+
+ def test_openfabric_02_loopback_interface(self):
+ interface = 'lo'
+ hello_interval = '100'
+ metric = '24478'
+
+ self.openfabric_base_config()
+ self.cli_set(path + ['interface', interface, 'address-family', 'ipv4'])
+
+ self.cli_set(path + ['interface', interface, 'hello-interval', hello_interval])
+ self.cli_set(path + ['interface', interface, 'metric', metric])
+
+ # Commit all changes
+ self.cli_commit()
+
+ # Verify FRR openfabric configuration
+ tmp = self.getFRRconfig(f'router openfabric {domain}', daemon='fabricd')
+ self.assertIn(f'router openfabric {domain}', tmp)
+ self.assertIn(f' net {net}', tmp)
+
+ # Verify interface configuration
+ tmp = self.getFRRconfig(f'interface {interface}', daemon='fabricd')
+ self.assertIn(f' ip router openfabric {domain}', tmp)
+ # for lo interface 'openfabric passive' is implied
+ self.assertIn(f' openfabric passive', tmp)
+ self.assertIn(f' openfabric metric {metric}', tmp)
+
+ def test_openfabric_03_password(self):
+ password = 'foo'
+
+ self.openfabric_base_config()
+
+ self.cli_set(path + ['interface', dummy_if, 'password', 'plaintext-password', f'{password}-{dummy_if}'])
+ self.cli_set(path + ['interface', dummy_if, 'password', 'md5', f'{password}-{dummy_if}'])
+
+ # verify() - can not use both md5 and plaintext-password for password for the interface
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_delete(path + ['interface', dummy_if, 'password', 'md5'])
+
+ self.cli_set(path + ['domain-password', 'plaintext-password', password])
+ self.cli_set(path + ['domain-password', 'md5', password])
+
+ # verify() - can not use both md5 and plaintext-password for domain-password
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_delete(path + ['domain-password', 'md5'])
+
+ # Commit all changes
+ self.cli_commit()
+
+ # Verify all changes
+ tmp = self.getFRRconfig(f'router openfabric {domain}', daemon='fabricd')
+ self.assertIn(f' net {net}', tmp)
+ self.assertIn(f' domain-password clear {password}', tmp)
+
+ tmp = self.getFRRconfig(f'interface {dummy_if}', daemon='fabricd')
+ self.assertIn(f' openfabric password clear {password}-{dummy_if}', tmp)
+
+ def test_openfabric_multiple_domains(self):
+ domain_2 = 'VyOS_2'
+ interface = 'dum5678'
+ new_path = base_path + ['domain', domain_2]
+
+ self.openfabric_base_config()
+
+ # set same interface for 2 OpenFabric domains
+ self.cli_set(['interfaces', 'dummy', interface])
+ self.cli_set(new_path + ['interface', interface, 'address-family', 'ipv4'])
+ self.cli_set(path + ['interface', interface, 'address-family', 'ipv4'])
+
+ # verify() - same interface can be used only for one OpenFabric instance
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_delete(path + ['interface', interface])
+
+ # Commit all changes
+ self.cli_commit()
+
+ # Verify FRR openfabric configuration
+ tmp = self.getFRRconfig(f'router openfabric {domain}', daemon='fabricd')
+ self.assertIn(f'router openfabric {domain}', tmp)
+ self.assertIn(f' net {net}', tmp)
+
+ tmp = self.getFRRconfig(f'router openfabric {domain_2}', daemon='fabricd')
+ self.assertIn(f'router openfabric {domain_2}', tmp)
+ self.assertIn(f' net {net}', tmp)
+
+ # Verify interface configuration
+ tmp = self.getFRRconfig(f'interface {dummy_if}', daemon='fabricd')
+ self.assertIn(f' ip router openfabric {domain}', tmp)
+ self.assertIn(f' ipv6 router openfabric {domain}', tmp)
+
+ tmp = self.getFRRconfig(f'interface {interface}', daemon='fabricd')
+ self.assertIn(f' ip router openfabric {domain_2}', tmp)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/src/conf_mode/policy.py b/src/conf_mode/policy.py
index 4df893ebf..a5963e72c 100755
--- a/src/conf_mode/policy.py
+++ b/src/conf_mode/policy.py
@@ -167,10 +167,10 @@ def verify(policy):
continue
for rule, rule_config in route_map_config['rule'].items():
- # Action 'deny' cannot be used with "continue"
- # FRR does not validate it T4827
- if rule_config['action'] == 'deny' and 'continue' in rule_config:
- raise ConfigError(f'rule {rule} "continue" cannot be used with action deny!')
+ # Action 'deny' cannot be used with "continue" or "on-match"
+ # FRR does not validate it T4827, T6676
+ if rule_config['action'] == 'deny' and ('continue' in rule_config or 'on_match' in rule_config):
+ raise ConfigError(f'rule {rule} "continue" or "on-match" cannot be used with action deny!')
# Specified community-list must exist
tmp = dict_search('match.community.community_list',
diff --git a/src/conf_mode/protocols_openfabric.py b/src/conf_mode/protocols_openfabric.py
new file mode 100644
index 000000000..8e8c50c06
--- /dev/null
+++ b/src/conf_mode/protocols_openfabric.py
@@ -0,0 +1,145 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from sys import exit
+
+from vyos.base import Warning
+from vyos.config import Config
+from vyos.configdict import node_changed
+from vyos.configverify import verify_interface_exists
+from vyos.template import render_to_string
+from vyos import ConfigError
+from vyos import frr
+from vyos import airbag
+
+airbag.enable()
+
+def get_config(config=None):
+ if config:
+ conf = config
+ else:
+ conf = Config()
+
+ base_path = ['protocols', 'openfabric']
+
+ openfabric = conf.get_config_dict(base_path, key_mangling=('-', '_'),
+ get_first_key=True,
+ no_tag_node_value_mangle=True)
+
+ # Remove per domain MPLS configuration - get a list of all changed Openfabric domains
+ # (removed and added) so that they will be properly rendered for the FRR config.
+ openfabric['domains_all'] = list(conf.list_nodes(' '.join(base_path) + f' domain') +
+ node_changed(conf, base_path + ['domain']))
+
+ # Get a list of all interfaces
+ openfabric['interfaces_all'] = []
+ for domain in openfabric['domains_all']:
+ interfaces_modified = list(node_changed(conf, base_path + ['domain', domain, 'interface']) +
+ conf.list_nodes(' '.join(base_path) + f' domain {domain} interface'))
+ openfabric['interfaces_all'].extend(interfaces_modified)
+
+ if not conf.exists(base_path):
+ openfabric.update({'deleted': ''})
+
+ return openfabric
+
+def verify(openfabric):
+ # bail out early - looks like removal from running config
+ if not openfabric or 'deleted' in openfabric:
+ return None
+
+ if 'net' not in openfabric:
+ raise ConfigError('Network entity is mandatory!')
+
+ # last byte in OpenFabric area address must be 0
+ tmp = openfabric['net'].split('.')
+ if int(tmp[-1]) != 0:
+ raise ConfigError('Last byte of OpenFabric network entity title must always be 0!')
+
+ if 'domain' not in openfabric:
+ raise ConfigError('OpenFabric domain name is mandatory!')
+
+ interfaces_used = []
+
+ for domain, domain_config in openfabric['domain'].items():
+ # If interface not set
+ if 'interface' not in domain_config:
+ raise ConfigError(f'Interface used for routing updates in OpenFabric "{domain}" is mandatory!')
+
+ for iface, iface_config in domain_config['interface'].items():
+ verify_interface_exists(openfabric, iface)
+
+ # interface can be activated only on one OpenFabric instance
+ if iface in interfaces_used:
+ raise ConfigError(f'Interface {iface} is already used in different OpenFabric instance!')
+
+ if 'address_family' not in iface_config or len(iface_config['address_family']) < 1:
+ raise ConfigError(f'Need to specify address family for the interface "{iface}"!')
+
+ # If md5 and plaintext-password set at the same time
+ if 'password' in iface_config:
+ if {'md5', 'plaintext_password'} <= set(iface_config['password']):
+ raise ConfigError(f'Can use either md5 or plaintext-password for password for the interface!')
+
+ if iface == 'lo' and 'passive' not in iface_config:
+ Warning('For loopback interface passive mode is implied!')
+
+ interfaces_used.append(iface)
+
+ # If md5 and plaintext-password set at the same time
+ password = 'domain_password'
+ if password in domain_config:
+ if {'md5', 'plaintext_password'} <= set(domain_config[password]):
+ raise ConfigError(f'Can use either md5 or plaintext-password for domain-password!')
+
+ return None
+
+def generate(openfabric):
+ if not openfabric or 'deleted' in openfabric:
+ return None
+
+ openfabric['frr_fabricd_config'] = render_to_string('frr/fabricd.frr.j2', openfabric)
+ return None
+
+def apply(openfabric):
+ openfabric_daemon = 'fabricd'
+
+ # Save original configuration prior to starting any commit actions
+ frr_cfg = frr.FRRConfig()
+
+ frr_cfg.load_configuration(openfabric_daemon)
+ for domain in openfabric['domains_all']:
+ frr_cfg.modify_section(f'^router openfabric {domain}', stop_pattern='^exit', remove_stop_mark=True)
+
+ for interface in openfabric['interfaces_all']:
+ frr_cfg.modify_section(f'^interface {interface}', stop_pattern='^exit', remove_stop_mark=True)
+
+ if 'frr_fabricd_config' in openfabric:
+ frr_cfg.add_before(frr.default_add_before, openfabric['frr_fabricd_config'])
+
+ frr_cfg.commit_configuration(openfabric_daemon)
+
+ return None
+
+if __name__ == '__main__':
+ try:
+ c = get_config()
+ verify(c)
+ generate(c)
+ apply(c)
+ except ConfigError as e:
+ print(e)
+ exit(1)
diff --git a/src/conf_mode/system_option.py b/src/conf_mode/system_option.py
index 52d0b7cda..a84572f83 100755
--- a/src/conf_mode/system_option.py
+++ b/src/conf_mode/system_option.py
@@ -19,11 +19,13 @@ import os
from sys import exit
from time import sleep
+
from vyos.config import Config
from vyos.configverify import verify_source_interface
from vyos.configverify import verify_interface_exists
from vyos.system import grub_util
from vyos.template import render
+from vyos.utils.cpu import get_cpus
from vyos.utils.dict import dict_search
from vyos.utils.file import write_file
from vyos.utils.kernel import check_kmod
@@ -35,6 +37,7 @@ from vyos.configdep import set_dependents
from vyos.configdep import call_dependents
from vyos import ConfigError
from vyos import airbag
+
airbag.enable()
curlrc_config = r'/etc/curlrc'
@@ -42,10 +45,8 @@ ssh_config = r'/etc/ssh/ssh_config.d/91-vyos-ssh-client-options.conf'
systemd_action_file = '/lib/systemd/system/ctrl-alt-del.target'
usb_autosuspend = r'/etc/udev/rules.d/40-usb-autosuspend.rules'
kernel_dynamic_debug = r'/sys/kernel/debug/dynamic_debug/control'
-time_format_to_locale = {
- '12-hour': 'en_US.UTF-8',
- '24-hour': 'en_GB.UTF-8'
-}
+time_format_to_locale = {'12-hour': 'en_US.UTF-8', '24-hour': 'en_GB.UTF-8'}
+
def get_config(config=None):
if config:
@@ -53,9 +54,9 @@ def get_config(config=None):
else:
conf = Config()
base = ['system', 'option']
- options = conf.get_config_dict(base, key_mangling=('-', '_'),
- get_first_key=True,
- with_recursive_defaults=True)
+ options = conf.get_config_dict(
+ base, key_mangling=('-', '_'), get_first_key=True, with_recursive_defaults=True
+ )
if 'performance' in options:
# Update IPv4/IPv6 and sysctl options after tuned applied it's settings
@@ -64,6 +65,7 @@ def get_config(config=None):
return options
+
def verify(options):
if 'http_client' in options:
config = options['http_client']
@@ -71,7 +73,9 @@ def verify(options):
verify_interface_exists(options, config['source_interface'])
if {'source_address', 'source_interface'} <= set(config):
- raise ConfigError('Can not define both HTTP source-interface and source-address')
+ raise ConfigError(
+ 'Can not define both HTTP source-interface and source-address'
+ )
if 'source_address' in config:
if not is_addr_assigned(config['source_address']):
@@ -92,10 +96,20 @@ def verify(options):
address = config['source_address']
interface = config['source_interface']
if not is_intf_addr_assigned(interface, address):
- raise ConfigError(f'Address "{address}" not assigned on interface "{interface}"!')
+ raise ConfigError(
+ f'Address "{address}" not assigned on interface "{interface}"!'
+ )
+
+ if 'kernel' in options:
+ cpu_vendor = get_cpus()[0]['vendor_id']
+ if 'amd_pstate_driver' in options['kernel'] and cpu_vendor != 'AuthenticAMD':
+ raise ConfigError(
+ f'AMD pstate driver cannot be used with "{cpu_vendor}" CPU!'
+ )
return None
+
def generate(options):
render(curlrc_config, 'system/curlrc.j2', options)
render(ssh_config, 'system/ssh_config.j2', options)
@@ -107,10 +121,16 @@ def generate(options):
cmdline_options.append('mitigations=off')
if 'disable_power_saving' in options['kernel']:
cmdline_options.append('intel_idle.max_cstate=0 processor.max_cstate=1')
+ if 'amd_pstate_driver' in options['kernel']:
+ mode = options['kernel']['amd_pstate_driver']
+ cmdline_options.append(
+ f'initcall_blacklist=acpi_cpufreq_init amd_pstate={mode}'
+ )
grub_util.update_kernel_cmdline_options(' '.join(cmdline_options))
return None
+
def apply(options):
# System bootup beep
beep_service = 'vyos-beep.service'
@@ -149,7 +169,7 @@ def apply(options):
if 'performance' in options:
cmd('systemctl restart tuned.service')
# wait until daemon has started before sending configuration
- while (not is_systemd_service_running('tuned.service')):
+ while not is_systemd_service_running('tuned.service'):
sleep(0.250)
cmd('tuned-adm profile network-{performance}'.format(**options))
else:
@@ -164,9 +184,9 @@ def apply(options):
# Enable/diable root-partition-auto-resize SystemD service
if 'root_partition_auto_resize' in options:
- cmd('systemctl enable root-partition-auto-resize.service')
+ cmd('systemctl enable root-partition-auto-resize.service')
else:
- cmd('systemctl disable root-partition-auto-resize.service')
+ cmd('systemctl disable root-partition-auto-resize.service')
# Time format 12|24-hour
if 'time_format' in options:
@@ -186,6 +206,7 @@ def apply(options):
else:
write_file(kernel_dynamic_debug, f'module {module} -p')
+
if __name__ == '__main__':
try:
c = get_config()
diff --git a/src/op_mode/restart.py b/src/op_mode/restart.py
index 813d3a2b7..a83c8b9d8 100755
--- a/src/op_mode/restart.py
+++ b/src/op_mode/restart.py
@@ -25,11 +25,11 @@ from vyos.utils.commit import commit_in_progress
config = ConfigTreeQuery()
service_map = {
- 'dhcp' : {
+ 'dhcp': {
'systemd_service': 'kea-dhcp4-server',
'path': ['service', 'dhcp-server'],
},
- 'dhcpv6' : {
+ 'dhcpv6': {
'systemd_service': 'kea-dhcp6-server',
'path': ['service', 'dhcpv6-server'],
},
@@ -61,24 +61,40 @@ service_map = {
'systemd_service': 'radvd',
'path': ['service', 'router-advert'],
},
- 'snmp' : {
+ 'snmp': {
'systemd_service': 'snmpd',
},
- 'ssh' : {
+ 'ssh': {
'systemd_service': 'ssh',
},
- 'suricata' : {
+ 'suricata': {
'systemd_service': 'suricata',
},
- 'vrrp' : {
+ 'vrrp': {
'systemd_service': 'keepalived',
'path': ['high-availability', 'vrrp'],
},
- 'webproxy' : {
+ 'webproxy': {
'systemd_service': 'squid',
},
}
-services = typing.Literal['dhcp', 'dhcpv6', 'dns_dynamic', 'dns_forwarding', 'igmp_proxy', 'ipsec', 'mdns_repeater', 'reverse_proxy', 'router_advert', 'snmp', 'ssh', 'suricata' 'vrrp', 'webproxy']
+services = typing.Literal[
+ 'dhcp',
+ 'dhcpv6',
+ 'dns_dynamic',
+ 'dns_forwarding',
+ 'igmp_proxy',
+ 'ipsec',
+ 'mdns_repeater',
+ 'reverse_proxy',
+ 'router_advert',
+ 'snmp',
+ 'ssh',
+ 'suricata',
+ 'vrrp',
+ 'webproxy',
+]
+
def _verify(func):
"""Decorator checks if DHCP(v6) config exists"""
@@ -102,13 +118,18 @@ def _verify(func):
# Check if config does not exist
if not config.exists(path):
- raise vyos.opmode.UnconfiguredSubsystem(f'Service {human_name} is not configured!')
+ raise vyos.opmode.UnconfiguredSubsystem(
+ f'Service {human_name} is not configured!'
+ )
if config.exists(path + ['disable']):
- raise vyos.opmode.UnconfiguredSubsystem(f'Service {human_name} is disabled!')
+ raise vyos.opmode.UnconfiguredSubsystem(
+ f'Service {human_name} is disabled!'
+ )
return func(*args, **kwargs)
return _wrapper
+
@_verify
def restart_service(raw: bool, name: services, vrf: typing.Optional[str]):
systemd_service = service_map[name]['systemd_service']
@@ -117,6 +138,7 @@ def restart_service(raw: bool, name: services, vrf: typing.Optional[str]):
else:
call(f'systemctl restart "{systemd_service}.service"')
+
if __name__ == '__main__':
try:
res = vyos.opmode.run(sys.modules[__name__])
diff --git a/src/op_mode/restart_frr.py b/src/op_mode/restart_frr.py
index 8841b0eca..83146f5ec 100755
--- a/src/op_mode/restart_frr.py
+++ b/src/op_mode/restart_frr.py
@@ -139,7 +139,7 @@ def _reload_config(daemon):
# define program arguments
cmd_args_parser = argparse.ArgumentParser(description='restart frr daemons')
cmd_args_parser.add_argument('--action', choices=['restart'], required=True, help='action to frr daemons')
-cmd_args_parser.add_argument('--daemon', choices=['zebra', 'staticd', 'bgpd', 'eigrpd', 'ospfd', 'ospf6d', 'ripd', 'ripngd', 'isisd', 'pimd', 'pim6d', 'ldpd', 'babeld', 'bfdd'], required=False, nargs='*', help='select single or multiple daemons')
+cmd_args_parser.add_argument('--daemon', choices=['zebra', 'staticd', 'bgpd', 'eigrpd', 'ospfd', 'ospf6d', 'ripd', 'ripngd', 'isisd', 'pimd', 'pim6d', 'ldpd', 'babeld', 'bfdd', 'fabricd'], required=False, nargs='*', help='select single or multiple daemons')
# parse arguments
cmd_args = cmd_args_parser.parse_args()