Add a new packet python-statd

Actually a part of statd, but had to make
a separarate package to get it to work.

Statd helper-scripts are now pre-compiled instead of doing it
in runtime.

Fixes #379
This commit is contained in:
Mattias Walström
2024-04-16 12:47:16 +02:00
parent 635acd504f
commit 8c9c432847
20 changed files with 157 additions and 69 deletions
+1
View File
@@ -12,6 +12,7 @@ source "$BR2_EXTERNAL_INFIX_PATH/package/keyack/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/klish-plugin-infix/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/klish/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/klish-plugin-sysrepo/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/python-statd/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/libsrx/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/lowdown/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/mcd/Config.in"
+6
View File
@@ -0,0 +1,6 @@
config BR2_PACKAGE_PYTHON_STATD
bool "python-statd"
select BR2_PACKAGE_HOST_PYTHON3
select BR2_PACKAGE_STATD
help
Python helpers for statd.
+1
View File
@@ -0,0 +1 @@
sha256 755d3a387cd124ff34e2b73cc58e7cec4d8d85ae6c295e30ffeb8d36eacecb1d LICENSE
+16
View File
@@ -0,0 +1,16 @@
PYTHON_STATD_VERSION = 1.0
PYTHON_STATD_SITE_METHOD = local
PYTHON_STATD_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/statd/python
STATD_LICENSE = BSD-3-Clause
STATD_LICENSE_FILES = LICENSE
PYTHON_STATD_DEPENDENCIES = host-python3 python3 host-python-poetry-core
PYTHON_STATD_SETUP_TYPE = pep517 # poetry
define PYTHON_STATD_MOVE_BINARIES
mkdir -p $(TARGET_DIR)/usr/libexec/statd
mv $(TARGET_DIR)/usr/bin/yanger $(TARGET_DIR)/usr/libexec/statd/
mv $(TARGET_DIR)/usr/bin/cli-pretty $(TARGET_DIR)/usr/libexec/statd/
mv $(TARGET_DIR)/usr/bin/ospf-status $(TARGET_DIR)/usr/libexec/statd/
endef
PYTHON_STATD_POST_INSTALL_TARGET_HOOKS += PYTHON_STATD_MOVE_BINARIES
$(eval $(python-package))
+1
View File
@@ -5,6 +5,7 @@ config BR2_PACKAGE_STATD
select BR2_PACKAGE_SYSREPO
select BR2_PACKAGE_LIBSRX
select BR2_PACKAGE_LIBITE
select BR2_PACKAGE_PYTHON_STATD
help
Operational Status Daemon. Responsible for handling sysrepo
operational run-time info. Such as interface state and address.
+1 -1
View File
@@ -10,7 +10,7 @@ STATD_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/statd
STATD_LICENSE = BSD-3-Clause
STATD_LICENSE_FILES = LICENSE
STATD_REDISTRIBUTE = NO
STATD_DEPENDENCIES = sysrepo libev libsrx jansson
STATD_DEPENDENCIES = sysrepo libev libsrx jansson python-statd
STATD_AUTORECONF = YES
define STATD_CONF_ENV
-1
View File
@@ -1,4 +1,3 @@
Copyright (c) 2020 Denis Kalashnikov
Copyright (c) 2023 The KernelKit Authors
All rights reserved.
-2
View File
@@ -1,8 +1,6 @@
DISTCLEANFILES = *~ *.d
ACLOCAL_AMFLAGS = -I m4
pkglibexec_SCRIPTS = cli-pretty yanger ospf-status
sbin_PROGRAMS = statd
statd_SOURCES = statd.c shared.c shared.h
statd_CPPFLAGS = -D_DEFAULT_SOURCE -D_GNU_SOURCE
-60
View File
@@ -1,60 +0,0 @@
#!/usr/bin/python3
# This script is used to transform the output from the show ip ospf commands and order
# them to match the ietf-ospf YANG model. For example, interfaces is ordered under
# area but FRR has areas in interfaces.
#
# This makes the parsing for the operational parts of YANG model more easy
#
import json
import subprocess
iface_out=subprocess.check_output("vtysh -c 'show ip ospf interface json'", shell=True)
ospf_out=subprocess.check_output("vtysh -c 'show ip ospf json'", shell=True)
neighbor_out=subprocess.check_output("vtysh -c 'show ip ospf neighbor detail json'", shell=True)
interfaces=json.loads(iface_out)
ospf=json.loads(ospf_out)
neighbors=json.loads(neighbor_out)
for ifname,iface in interfaces["interfaces"].items():
iface["name"] = ifname
iface["neighbors"] = []
for area_id in ospf["areas"]:
area_type=""
stub=False
if("NSSA" in iface["area"]):
iface_area_id = iface["area"][:-7]
area_type = "nssa-area"
elif("Stub" in iface["area"]):
iface_area_id = iface["area"][:-7]
iface["areaId"] = iface["area"][:-7]
area_type = "stub-area"
else:
iface_area_id = iface["area"]
area_type = "normal-area"
if(iface_area_id != area_id):
continue
ospf["areas"][area_id]["area-type"] = area_type
iface["area"] = iface_area_id
for nbrAddress,nbrDatas in neighbors["neighbors"].items():
for nbrData in nbrDatas:
nbrIfname=nbrData["ifaceName"].split(":")[0]
if(("NSSA" in nbrData.get("areaId", {})) or ("Stub" in nbrData.get("areaId", {}))):
nbrData["areaId"] = nbrData["areaId"][:-7]
if ((nbrIfname != ifname) and (area_id != nbrData.get("areaId"))):
#print(f'Continute {ifname} {nbrData.get("areaId")}')
continue
nbrData["neighborIp"] = nbrAddress
iface["neighbors"].append(nbrData)
if(not ospf["areas"][area_id].get("interfaces", None)):
ospf["areas"][area_id]["interfaces"] = []
ospf["areas"][area_id]["interfaces"].append(iface)
print(json.dumps(ospf))
+27
View File
@@ -0,0 +1,27 @@
Copyright (c) 2023 The KernelKit Authors
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of copyright holders nor the names of
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+4
View File
@@ -0,0 +1,4 @@
from .cli_pretty import main
if __name__ == "__main__":
main()
@@ -1,8 +1,8 @@
#!/usr/bin/env python3
import argparse
import json
import re
import argparse
import sys
import re
class Pad:
iface = 16
@@ -619,5 +619,6 @@ def main():
print(f"Error, unknown command {args.command}")
sys.exit(1)
if __name__ == "__main__":
main()
+4
View File
@@ -0,0 +1,4 @@
from .ospf_status import main
if __name__ == "__main__":
main()
+63
View File
@@ -0,0 +1,63 @@
#!/usr/bin/python3
# This script is used to transform the output from the show ip ospf commands and order
# them to match the ietf-ospf YANG model. For example, interfaces is ordered under
# area but FRR has areas in interfaces.
#
# This makes the parsing for the operational parts of YANG model more easy
#
import json
import subprocess
def main():
iface_out=subprocess.check_output("vtysh -c 'show ip ospf interface json'", shell=True)
ospf_out=subprocess.check_output("vtysh -c 'show ip ospf json'", shell=True)
neighbor_out=subprocess.check_output("vtysh -c 'show ip ospf neighbor detail json'", shell=True)
interfaces=json.loads(iface_out)
ospf=json.loads(ospf_out)
neighbors=json.loads(neighbor_out)
for ifname,iface in interfaces["interfaces"].items():
iface["name"] = ifname
iface["neighbors"] = []
for area_id in ospf["areas"]:
area_type=""
stub=False
if("NSSA" in iface["area"]):
iface_area_id = iface["area"][:-7]
area_type = "nssa-area"
elif("Stub" in iface["area"]):
iface_area_id = iface["area"][:-7]
iface["areaId"] = iface["area"][:-7]
area_type = "stub-area"
else:
iface_area_id = iface["area"]
area_type = "normal-area"
if(iface_area_id != area_id):
continue
ospf["areas"][area_id]["area-type"] = area_type
iface["area"] = iface_area_id
for nbrAddress,nbrDatas in neighbors["neighbors"].items():
for nbrData in nbrDatas:
nbrIfname=nbrData["ifaceName"].split(":")[0]
if(("NSSA" in nbrData.get("areaId", {})) or ("Stub" in nbrData.get("areaId", {}))):
nbrData["areaId"] = nbrData["areaId"][:-7]
if ((nbrIfname != ifname) and (area_id != nbrData.get("areaId"))):
#print(f'Continute {ifname} {nbrData.get("areaId")}')
continue
nbrData["neighborIp"] = nbrAddress
iface["neighbors"].append(nbrData)
if(not ospf["areas"][area_id].get("interfaces", None)):
ospf["areas"][area_id]["interfaces"] = []
ospf["areas"][area_id]["interfaces"].append(iface)
print(json.dumps(ospf))
if __name__ == "__main__":
main()
+23
View File
@@ -0,0 +1,23 @@
[tool.poetry]
name = "infix-yang-tools"
version = "1.0"
description = "Linux to infix-YANG"
license = "MIT"
packages = [
{ include = "yanger/*.py" },
{ include = "cli_pretty/*.py" },
{ include = "ospf_status/*.py" }
]
authors = [
"KernelKit developers"
]
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
[tool.poetry.scripts]
yanger = "yanger:main"
cli-pretty = "cli_pretty:main"
ospf-status = "ospf_status:main"
+4
View File
@@ -0,0 +1,4 @@
from .yanger import main
if __name__ == "__main__":
main()
+1 -1
View File
@@ -4,7 +4,7 @@ SCRIPT_PATH="$(dirname "$(readlink -f "$0")")"
ROOT_PATH="$SCRIPT_PATH/../../../"
CLI_OUTPUT_PATH="$SCRIPT_PATH/cli-output/"
CLI_PRETTY_TOOL="$ROOT_PATH/src/statd/cli-pretty"
CLI_PRETTY_TOOL="$ROOT_PATH/src/statd/python/cli_pretty/cli_pretty.py"
SR_EMULATOR_TOOL="$SCRIPT_PATH/sysrepo-emulator.sh"
CLI_OUTPUT_FILE="$(mktemp)"
+1 -1
View File
@@ -3,7 +3,7 @@
SCRIPT_PATH="$(dirname "$(readlink -f "$0")")"
ROOT_PATH="$SCRIPT_PATH/../../../"
YANGER_TOOL="$ROOT_PATH/src/statd/yanger"
YANGER_TOOL="$ROOT_PATH/src/statd/python/yanger/yanger.py"
INTERFACES="br0 br1 e0 e1 e2 e3 e4"
+1 -1
View File
@@ -18,7 +18,7 @@ if [ ! -e "$SCRIPT_PATH/$json" ]; then
fi
cat "$SCRIPT_PATH/$json" | \
"$SCRIPT_PATH"/../../../src/statd/cli-pretty \
"$SCRIPT_PATH"/../../../src/statd/python/cli_pretty/cli_pretty.py \
"$command" $*
if [ $? -eq 0 ]; then
echo "ok 1 - $json printed without crashing"