mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-26 18:53:01 +02:00
Compare commits
@@ -178,6 +178,7 @@ CONFIG_NET_SCHED=y
|
||||
CONFIG_NET_CLS_BASIC=y
|
||||
CONFIG_NET_CLS_BPF=y
|
||||
CONFIG_NET_CLS_FLOWER=y
|
||||
CONFIG_DCB=y
|
||||
CONFIG_NETLINK_DIAG=y
|
||||
CONFIG_MPLS=y
|
||||
CONFIG_NET_MPLS_GSO=y
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# Generate a self signed certificate with unlimited expire time
|
||||
|
||||
import argparse
|
||||
|
||||
from cryptography import x509
|
||||
from cryptography.x509.oid import NameOID
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
# Generate private key
|
||||
private_key = rsa.generate_private_key(
|
||||
public_exponent=65537,
|
||||
key_size=2048,
|
||||
backend=default_backend()
|
||||
|
||||
)
|
||||
|
||||
parser = argparse.ArgumentParser(description="Generate a self signed certificate")
|
||||
parser.add_argument('--country', required=True, help="Set country")
|
||||
parser.add_argument('--state', required=True, help="Set state or province name")
|
||||
parser.add_argument('--city', required=True, help="Set city name")
|
||||
parser.add_argument('--organisation', required=True, help="Set organisation name")
|
||||
parser.add_argument('--organisation-unit', required=True, help="Set organisation unit name")
|
||||
parser.add_argument('--common-name', required=True, help="Set common name")
|
||||
parser.add_argument('--out-certificate', required=True, help="Output certificate")
|
||||
parser.add_argument('--out-key', required=True, help="Output key")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Builder for certificate
|
||||
subject = issuer = x509.Name([
|
||||
x509.NameAttribute(NameOID.COUNTRY_NAME, args.country),
|
||||
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, args.state),
|
||||
x509.NameAttribute(NameOID.LOCALITY_NAME, args.city),
|
||||
x509.NameAttribute(NameOID.ORGANIZATION_NAME, args.organisation),
|
||||
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, args.organisation_unit),
|
||||
x509.NameAttribute(NameOID.COMMON_NAME, args.common_name),
|
||||
])
|
||||
certificate = x509.CertificateBuilder().subject_name(
|
||||
subject
|
||||
).issuer_name(
|
||||
issuer
|
||||
).public_key(
|
||||
private_key.public_key()
|
||||
).serial_number(
|
||||
x509.random_serial_number()
|
||||
).not_valid_before(
|
||||
datetime(2000, 1, 1)
|
||||
).not_valid_after(
|
||||
datetime(9999, 1, 1)
|
||||
).add_extension(
|
||||
x509.SubjectAlternativeName([x509.DNSName(args.common_name)]),
|
||||
critical=False,
|
||||
).sign(private_key, hashes.SHA256(), default_backend())
|
||||
|
||||
# Serialize certificate and private key
|
||||
with open(args.out_certificate, "wb") as f:
|
||||
f.write(certificate.public_bytes(serialization.Encoding.PEM))
|
||||
with open(args.out_key, "wb") as f:
|
||||
f.write(private_key.private_bytes(
|
||||
encoding=serialization.Encoding.PEM,
|
||||
format=serialization.PrivateFormat.PKCS8,
|
||||
encryption_algorithm=serialization.NoEncryption()
|
||||
))
|
||||
@@ -54,7 +54,6 @@ BR2_PACKAGE_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
|
||||
BR2_PACKAGE_UBOOT_TOOLS_FIT_CHECK_SIGN=y
|
||||
BR2_PACKAGE_UBOOT_TOOLS_MKENVIMAGE=y
|
||||
BR2_PACKAGE_PYTHON3=y
|
||||
BR2_PACKAGE_PYTHON_CRYPTOGRAPHY=y
|
||||
BR2_PACKAGE_PYTHON_GUNICORN=y
|
||||
BR2_PACKAGE_LIBSSH_OPENSSL=y
|
||||
BR2_PACKAGE_LIBSSH2=y
|
||||
@@ -130,6 +129,7 @@ INFIX_SUPPORT="mailto:kernelkit@googlegroups.com"
|
||||
BR2_PACKAGE_CONFD=y
|
||||
BR2_PACKAGE_CURIOS_HTTPD=y
|
||||
BR2_PACKAGE_EXECD=y
|
||||
BR2_PACKAGE_GENCERT=y
|
||||
BR2_PACKAGE_STATD=y
|
||||
BR2_PACKAGE_FACTORY=y
|
||||
BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y
|
||||
@@ -142,6 +142,7 @@ BR2_PACKAGE_IITO=y
|
||||
BR2_PACKAGE_K8S_LOGGER=y
|
||||
BR2_PACKAGE_KEYACK=y
|
||||
BR2_PACKAGE_KLISH_PLUGIN_INFIX=y
|
||||
BR2_PACKAGE_LANDING=y
|
||||
BR2_PACKAGE_LOWDOWN=y
|
||||
BR2_PACKAGE_MCD=y
|
||||
BR2_PACKAGE_MDNS_ALIAS=y
|
||||
|
||||
@@ -13,7 +13,7 @@ BR2_TARGET_GENERIC_HOSTNAME="infix"
|
||||
BR2_TARGET_GENERIC_ISSUE="Infix by KernelKit"
|
||||
BR2_INIT_FINIT=y
|
||||
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
|
||||
BR2_ROOTFS_DEVICE_TABLE="system/device_table.txt ${BR2_EXTERNAL_INFIX_PATH}/board/common/xattrs ${BR2_EXTERNAL_INFIX_PATH}/board/netconf/xattrs"
|
||||
BR2_ROOTFS_DEVICE_TABLE="system/device_table.txt ${BR2_EXTERNAL_INFIX_PATH}/board/common/xattrs"
|
||||
# BR2_TARGET_ENABLE_ROOT_LOGIN is not set
|
||||
BR2_SYSTEM_BIN_SH_BASH=y
|
||||
BR2_TARGET_GENERIC_GETTY_PORT="@console"
|
||||
@@ -22,8 +22,8 @@ BR2_SYSTEM_DHCP="eth0"
|
||||
BR2_ENABLE_LOCALE_WHITELIST="C en_US en_CA"
|
||||
BR2_GENERATE_LOCALE="en_US en_CA"
|
||||
BR2_TARGET_TZ_INFO=y
|
||||
BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/rootfs ${BR2_EXTERNAL_INFIX_PATH}/board/netconf/rootfs"
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="$(BR2_EXTERNAL_INFIX_PATH)/board/aarch64/r2s/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/netconf/post-build.sh"
|
||||
BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/rootfs"
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="$(BR2_EXTERNAL_INFIX_PATH)/board/aarch64/r2s/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh"
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh support/scripts/genimage.sh"
|
||||
BR2_ROOTFS_POST_SCRIPT_ARGS="-c $(BR2_EXTERNAL_INFIX_PATH)/board/aarch64/r2s/genimage.cfg"
|
||||
BR2_LINUX_KERNEL=y
|
||||
@@ -64,7 +64,6 @@ BR2_PACKAGE_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
|
||||
BR2_PACKAGE_UBOOT_TOOLS_FIT_CHECK_SIGN=y
|
||||
BR2_PACKAGE_UBOOT_TOOLS_MKENVIMAGE=y
|
||||
BR2_PACKAGE_PYTHON3=y
|
||||
BR2_PACKAGE_PYTHON_CRYPTOGRAPHY=y
|
||||
BR2_PACKAGE_PYTHON_GUNICORN=y
|
||||
BR2_PACKAGE_CA_CERTIFICATES=y
|
||||
BR2_PACKAGE_LIBSSH_OPENSSL=y
|
||||
@@ -159,6 +158,7 @@ INFIX_DOC="https://github.com/kernelkit/infix/tree/main/doc"
|
||||
INFIX_SUPPORT="mailto:kernelkit@googlegroups.com"
|
||||
BR2_PACKAGE_CONFD=y
|
||||
BR2_PACKAGE_EXECD=y
|
||||
BR2_PACKAGE_GENCERT=y
|
||||
BR2_PACKAGE_STATD=y
|
||||
BR2_PACKAGE_FACTORY=y
|
||||
BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y
|
||||
@@ -171,6 +171,7 @@ BR2_PACKAGE_IITO=y
|
||||
BR2_PACKAGE_K8S_LOGGER=y
|
||||
BR2_PACKAGE_KEYACK=y
|
||||
BR2_PACKAGE_KLISH_PLUGIN_INFIX=y
|
||||
BR2_PACKAGE_LANDING=y
|
||||
BR2_PACKAGE_LOWDOWN=y
|
||||
BR2_PACKAGE_MCD=y
|
||||
BR2_PACKAGE_MDNS_ALIAS=y
|
||||
|
||||
@@ -49,7 +49,6 @@ BR2_PACKAGE_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
|
||||
BR2_PACKAGE_UBOOT_TOOLS_FIT_CHECK_SIGN=y
|
||||
BR2_PACKAGE_UBOOT_TOOLS_MKENVIMAGE=y
|
||||
BR2_PACKAGE_PYTHON3=y
|
||||
BR2_PACKAGE_PYTHON_CRYPTOGRAPHY=y
|
||||
BR2_PACKAGE_PYTHON_GUNICORN=y
|
||||
BR2_PACKAGE_LIBSSH_OPENSSL=y
|
||||
BR2_PACKAGE_LIBSSH2=y
|
||||
@@ -133,6 +132,7 @@ INFIX_SUPPORT="mailto:kernelkit@googlegroups.com"
|
||||
BR2_PACKAGE_CONFD=y
|
||||
BR2_PACKAGE_CURIOS_HTTPD=y
|
||||
BR2_PACKAGE_EXECD=y
|
||||
BR2_PACKAGE_GENCERT=y
|
||||
BR2_PACKAGE_STATD=y
|
||||
BR2_PACKAGE_FACTORY=y
|
||||
BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y
|
||||
@@ -145,6 +145,7 @@ BR2_PACKAGE_IITO=y
|
||||
BR2_PACKAGE_K8S_LOGGER=y
|
||||
BR2_PACKAGE_KEYACK=y
|
||||
BR2_PACKAGE_KLISH_PLUGIN_INFIX=y
|
||||
BR2_PACKAGE_LANDING=y
|
||||
BR2_PACKAGE_LOWDOWN=y
|
||||
BR2_PACKAGE_MCD=y
|
||||
BR2_PACKAGE_MDNS_ALIAS=y
|
||||
|
||||
@@ -4,6 +4,24 @@ Change Log
|
||||
All notable changes to the project are documented in this file.
|
||||
|
||||
|
||||
[v24.04.1][] - 2024-05-03
|
||||
-------------------------
|
||||
|
||||
### Changes
|
||||
- Default web landing page refactored into a Buildroot package to make
|
||||
it possible to overload from customer repos.
|
||||
- Enable DCB support in aarch64 kernel (for EtherType prio override)
|
||||
- Topology mapper improvements, including option for deterministic
|
||||
reproduction of logical to physical mappings
|
||||
- New version of `gencert` tool, for self signed HTTPS certificates.
|
||||
This allows dropping dependency on building a host rust toolchain
|
||||
- Issue #374: add timestamps to dagger .log files
|
||||
|
||||
### Fixes
|
||||
- Add missing LICENSE hash for factory reset tool
|
||||
- Fix #424: regression, root user can log in without password
|
||||
|
||||
|
||||
[v24.04.0][] - 2024-04-30
|
||||
-------------------------
|
||||
|
||||
@@ -844,6 +862,7 @@ Supported YANG models in addition to those used by sysrepo and netopeer:
|
||||
|
||||
[buildroot]: https://buildroot.org/
|
||||
[UNRELEASED]: https://github.com/kernelkit/infix/compare/v24.04.0...HEAD
|
||||
[v24.04.1]: https://github.com/kernelkit/infix/compare/v24.04.0...v24.04.1
|
||||
[v24.04.0]: https://github.com/kernelkit/infix/compare/v24.02.0...v24.04.0
|
||||
[v24.02.0]: https://github.com/kernelkit/infix/compare/v23.11.0...v24.02.0
|
||||
[v23.11.0]: https://github.com/kernelkit/infix/compare/v23.10.0...v23.11.0
|
||||
|
||||
@@ -67,7 +67,7 @@ $ sudo apt install bc binutils build-essential bzip2 cpio \
|
||||
diffutils file findutils git gzip \
|
||||
libncurses-dev libssl-dev perl patch \
|
||||
python3 rsync sed tar unzip wget \
|
||||
autopoint
|
||||
autopoint bison flex
|
||||
```
|
||||
|
||||
For testing, a few more tools and services are required on your system:
|
||||
|
||||
@@ -410,6 +410,45 @@ You can now freely debug the network activity of your test and the
|
||||
responses from the DUT.
|
||||
|
||||
|
||||
### Deterministic Topology Mappings
|
||||
|
||||
By default, mappings from logical to physical topologies are not
|
||||
stable across test case executions. This can be very frustrating when
|
||||
debugging a failing test, since logical nodes are suffled around
|
||||
between phyical nodes. In such cases, supplying a `PYTHONHASHSEED`
|
||||
variable (set to any 32-bit unsigned integer) when launching the test
|
||||
environment will make sure that topology mappings are deterministic:
|
||||
|
||||
$ make PYTHONHASHSEED=0 test-sh
|
||||
|
||||
If a seed is not supplied, a random value is chosen. This seed is
|
||||
logged by the `meta/reproducible.py` test case when running a test
|
||||
suite:
|
||||
|
||||
$ make test
|
||||
Info: Generating topology
|
||||
Info: Generating node YAML
|
||||
Info: Generating executables
|
||||
Info: Launching dut1
|
||||
Info: Launching dut2
|
||||
Info: Launching dut3
|
||||
Info: Launching dut4
|
||||
9PM - Simplicity is the ultimate sophistication
|
||||
|
||||
Starting test 0002-reproducible.py
|
||||
2024-05-03 10:40:30 # Starting (2024-05-03 10:40:30)
|
||||
2024-05-03 10:40:30 # Specify PYTHONHASHSEED=3773822171 to reproduce this test environment
|
||||
2024-05-03 10:40:30 ok 1 - $PYTHONHASHSEED is set
|
||||
2024-05-03 10:40:30 # Exiting (2024-05-03 10:40:30)
|
||||
2024-05-03 10:40:30 1..1
|
||||
...
|
||||
|
||||
This is useful because this value can then be used to rerun a test (or
|
||||
the whole suite) with identical topology mappings:
|
||||
|
||||
$ make PYTHONHASHSEED=3773822171 INFIX_TESTS=case/ietf_system/hostname.py test
|
||||
|
||||
|
||||
[9PM]: https://github.com/rical/9pm
|
||||
[Qeneth]: https://github.com/wkz/qeneth
|
||||
[TAP]: https://testanything.org/
|
||||
|
||||
+4
-2
@@ -1,10 +1,12 @@
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/confd/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/curios-httpd/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/execd/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/gencert/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/statd/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/factory/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/faux/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/finit/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/greenpak-programmer/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/ifupdown-ng/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/iito/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/k8s-logger/Config.in"
|
||||
@@ -12,13 +14,13 @@ 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/landing/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"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/mdns-alias/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/netbrowse/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/podman/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/python-statd/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/skeleton-init-finit/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/tetris/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/greenpak-programmer/Config.in"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
sha256 518cd23d81f17b912f1c4ccc6acb67ff614ddcc2caf14def5044126d1a60f364 LICENSE
|
||||
@@ -0,0 +1,8 @@
|
||||
config BR2_PACKAGE_GENCERT
|
||||
bool "gencert"
|
||||
select BR2_PACKAGE_OPENSSL
|
||||
help
|
||||
Generate a self-signed certificate for embedded systems confused
|
||||
about the current time. Start date: 2000-01-01, end: 9999-01-01
|
||||
|
||||
https://github.com/kernelkit/infix
|
||||
@@ -0,0 +1 @@
|
||||
sha256 fff5e150e496c6bb6035ae388ee13cf2d0df842335e5145a4b902ef6b7892088 LICENSE
|
||||
@@ -0,0 +1,22 @@
|
||||
################################################################################
|
||||
#
|
||||
# gencert
|
||||
#
|
||||
################################################################################
|
||||
|
||||
GENCERT_VERSION = 1.0
|
||||
GENCERT_SITE_METHOD = local
|
||||
GENCERT_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/gencert
|
||||
GENCERT_LICENSE = ISC
|
||||
GENCERT_LICENSE_FILES = LICENSE
|
||||
GENCERT_REDISTRIBUTE = NO
|
||||
GENCERT_DEPENDENCIES = openssl
|
||||
GENCERT_AUTORECONF = YES
|
||||
|
||||
define GENCERT_CONF_ENV
|
||||
CFLAGS="$(INFIX_CFLAGS)"
|
||||
endef
|
||||
|
||||
GENCERT_CONF_OPTS = --prefix= --disable-silent-rules
|
||||
|
||||
$(eval $(autotools-package))
|
||||
@@ -0,0 +1,6 @@
|
||||
config BR2_PACKAGE_LANDING
|
||||
bool "Landing page (temporary)"
|
||||
help
|
||||
Temporary landing page before upcoming webui.
|
||||
|
||||
https://github.com/kernelkit/infix
|
||||
@@ -0,0 +1 @@
|
||||
sha256 fff5e150e496c6bb6035ae388ee13cf2d0df842335e5145a4b902ef6b7892088 LICENSE
|
||||
@@ -0,0 +1,18 @@
|
||||
################################################################################
|
||||
#
|
||||
# landing
|
||||
#
|
||||
################################################################################
|
||||
|
||||
LANDING_VERSION = 1.0
|
||||
LANDING_SITE_METHOD = local
|
||||
LANDING_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/landing
|
||||
LANDING_LICENSE = ISC
|
||||
LANDING_LICENSE_FILES = LICENSE
|
||||
|
||||
define LANDING_INSTALL_TARGET_CMDS
|
||||
cp $(@D)/*.html $(TARGET_DIR)/usr/html/
|
||||
cp $(@D)/*.png $(TARGET_DIR)/usr/html/
|
||||
endef
|
||||
|
||||
$(eval $(generic-package))
|
||||
@@ -1,2 +1,3 @@
|
||||
pkglibexec_SCRIPTS = bootstrap error load gen-service \
|
||||
gen-hostkeys gen-admin-auth gen-hostname gen-interfaces gen-motd gen-hardware
|
||||
pkglibexec_SCRIPTS = bootstrap error load gen-service gen-hostkeys gen-admin-auth \
|
||||
gen-hostname gen-interfaces gen-motd gen-hardware
|
||||
sbin_SCRIPTS = dagger
|
||||
|
||||
@@ -50,8 +50,8 @@ action_exec()
|
||||
|
||||
for node in $order; do
|
||||
for work in $(find "$actdir/$node" -type f -executable 2>/dev/null | sort); do
|
||||
$work >>"$work.log" 2>&1 || code=$?
|
||||
echo "[exit:$code]" >>"$work.log"
|
||||
$work | ts >>"$work.log" 2>&1 || code=$?
|
||||
echo "[exit:$code]" | ts >>"$work.log"
|
||||
|
||||
[ $code -eq 0 ] || abort "$work failed with exitcode $code"
|
||||
done
|
||||
@@ -49,7 +49,6 @@ cat <<EOF
|
||||
Exec prefix...........: $eprefix
|
||||
Sysconfdir............: `eval echo $sysconfdir`
|
||||
Localstatedir.........: `eval echo $localstatedir`
|
||||
Default fstab.........: `eval echo $fstab`
|
||||
System environment....: ${sysconfig_path:-${sysconfig}}
|
||||
C Compiler............: $CC $CFLAGS $CPPFLAGS $LDFLAGS $LIBS
|
||||
Linker................: $LD $LLDP_LDFLAGS $LLDP_BIN_LDFLAGS $LDFLAGS $LIBS
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
*~
|
||||
*.o
|
||||
gencert
|
||||
|
||||
/aclocal.m4
|
||||
/autom4te.cache/
|
||||
/aux
|
||||
/clixon.xml
|
||||
/compile
|
||||
/config.h
|
||||
/config.h.in
|
||||
/config.guess
|
||||
/config.log
|
||||
/config.status
|
||||
/config.sub
|
||||
/configure
|
||||
/depcomp
|
||||
/install-sh
|
||||
/libtool
|
||||
/ltmain.sh
|
||||
/m4
|
||||
/missing
|
||||
|
||||
GPATH
|
||||
GRTAGS
|
||||
GTAGS
|
||||
Makefile
|
||||
Makefile.in
|
||||
@@ -0,0 +1,14 @@
|
||||
Copyright (c) 2024 The KernelKit Authors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||
with or without fee is hereby granted, provided that the above copyright notice
|
||||
and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
DISTCLEANFILES = *~ *.d
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
bin_PROGRAMS = gencert
|
||||
gencert_SOURCES = gencert.c
|
||||
gencert_CFLAGS = -W -Wall -Wextra -Wno-unused
|
||||
gencert_CFLAGS = $(ssl_CFLAGS)
|
||||
gencert_LDADD = $(ssl_LIBS)
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
autoreconf -W portability -vifm
|
||||
@@ -0,0 +1,64 @@
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT([gencert], [3.0], [https://github.com/kernelkit/infix/issues])
|
||||
AM_INIT_AUTOMAKE(1.11 foreign)
|
||||
AM_SILENT_RULES(yes)
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
])
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
|
||||
# Check for pkg-config first, warn if it's not installed
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
PKG_CHECK_MODULES([ssl], [openssl >= 3.0.0])
|
||||
|
||||
test "x$prefix" = xNONE && prefix=$ac_default_prefix
|
||||
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
|
||||
|
||||
DATAROOTDIR=`eval echo $datarootdir`
|
||||
DATAROOTDIR=`eval echo $DATAROOTDIR`
|
||||
AC_SUBST(DATAROOTDIR)
|
||||
|
||||
LIBDIR=`eval echo $libdir`
|
||||
LIBDIR=`eval echo $LIBDIR`
|
||||
AC_SUBST(LIBDIR)
|
||||
|
||||
LOCALSTATEDIR=`eval echo $localstatedir`
|
||||
LOCALSTATEDIR=`eval echo $LOCALSTATEDIR`
|
||||
AC_SUBST(LOCALSTATEDIR)
|
||||
|
||||
RUNSTATEDIR=`eval echo $runstatedir`
|
||||
RUNSTATEDIR=`eval echo $RUNSTATEDIR`
|
||||
AC_SUBST(RUNSTATEDIR)
|
||||
|
||||
SYSCONFDIR=`eval echo $sysconfdir`
|
||||
SYSCONFDIR=`eval echo $SYSCONFDIR`
|
||||
AC_SUBST(SYSCONFDIR)
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
cat <<EOF
|
||||
|
||||
------------------ Summary ------------------
|
||||
$PACKAGE_NAME version $PACKAGE_VERSION
|
||||
Prefix................: $prefix
|
||||
Exec prefix...........: $eprefix
|
||||
Sysconfdir............: `eval echo $sysconfdir`
|
||||
Localstatedir.........: `eval echo $localstatedir`
|
||||
System environment....: ${sysconfig_path:-${sysconfig}}
|
||||
C Compiler............: $CC $CFLAGS $CPPFLAGS $LDFLAGS $LIBS
|
||||
Linker................: $LD $LLDP_LDFLAGS $LLDP_BIN_LDFLAGS $LDFLAGS $LIBS
|
||||
|
||||
------------- Compiler version --------------
|
||||
$($CC --version || true)
|
||||
-------------- Linker version ---------------
|
||||
$($LD --version || true)
|
||||
---------------------------------------------
|
||||
|
||||
Check the above options and compile with:
|
||||
${MAKE-make}
|
||||
|
||||
EOF
|
||||
@@ -0,0 +1,172 @@
|
||||
/* SPDX-License-Identifier: ISC */
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
extern char *__progname;
|
||||
|
||||
static int usage(int rc)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" --country COUNTRY Set country, default: US\n"
|
||||
" --state STATE Set state or province, default: California\n"
|
||||
" --city CITY Set city name, default: Berkeley\n"
|
||||
" --organization ORG Set organization name, default: Acme, Inc.\n"
|
||||
" --organization-unit UNIT Set organization unit name, default: Second\n"
|
||||
" --common-name CN Set common name, default: none (required!)\n"
|
||||
" --out-certificate FILE Output certificate\n"
|
||||
" --out-key FILE Output private key\n"
|
||||
, __progname);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct option opts[] = {
|
||||
{"city", required_argument, 0, 'l'},
|
||||
{"common-name", required_argument, 0, 'n'},
|
||||
{"country", required_argument, 0, 'c'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"organization", required_argument, 0, 'o'},
|
||||
{"organisation", required_argument, 0, 'o'},
|
||||
{"organization-unit", required_argument, 0, 'u'},
|
||||
{"organisation-unit", required_argument, 0, 'u'},
|
||||
{"out-certificate", required_argument, 0, 'p'},
|
||||
{"out-key", required_argument, 0, 'k'},
|
||||
{"state", required_argument, 0, 's'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
char *common_name = NULL, *cert = "certificate.pem", *key = "private.key";
|
||||
char *country = "US", *state = "California", *locality = "Berkeley";
|
||||
char *organization = "Acme, Inc.", *unit = "Second";
|
||||
ASN1_INTEGER *asn1_serno;
|
||||
EVP_PKEY_CTX *pkey_ctx;
|
||||
BIGNUM *bn_serial;
|
||||
X509_NAME *name;
|
||||
EVP_PKEY *pkey;
|
||||
X509 *x509;
|
||||
FILE *fp;
|
||||
int c;
|
||||
|
||||
while ((c = getopt_long(argc, argv, "c:hs:l:o:u:n:", opts, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'c':
|
||||
country = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
return usage(0);
|
||||
case 'k':
|
||||
key = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
locality = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
common_name = optarg;
|
||||
break;
|
||||
case 'o':
|
||||
organization = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
cert = optarg;
|
||||
break;
|
||||
case 's':
|
||||
state = optarg;
|
||||
break;
|
||||
case 'u':
|
||||
unit = optarg;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "got here: '%c'\n", c);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
if (!common_name)
|
||||
return usage(1);
|
||||
|
||||
OpenSSL_add_all_algorithms();
|
||||
|
||||
/* Key generation using EVP */
|
||||
pkey = EVP_PKEY_new();
|
||||
pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
|
||||
if (!EVP_PKEY_keygen_init(pkey_ctx) || !EVP_PKEY_CTX_set_rsa_keygen_bits(pkey_ctx, 2048) ||
|
||||
!EVP_PKEY_keygen(pkey_ctx, &pkey)) {
|
||||
fprintf(stderr, "Error generating RSA key\n");
|
||||
EVP_PKEY_CTX_free(pkey_ctx);
|
||||
return 1;
|
||||
}
|
||||
EVP_PKEY_CTX_free(pkey_ctx);
|
||||
|
||||
/* Certificate creation */
|
||||
x509 = X509_new();
|
||||
assert(x509);
|
||||
X509_set_version(x509, 2);
|
||||
|
||||
/* Generating a random serial number */
|
||||
bn_serial = BN_new();
|
||||
assert(bn_serial);
|
||||
BN_rand(bn_serial, 160, 0, 0); /* Generate a 160-bit serial number */
|
||||
asn1_serno = BN_to_ASN1_INTEGER(bn_serial, NULL);
|
||||
assert(asn1_serno);
|
||||
X509_set_serialNumber(x509, asn1_serno);
|
||||
|
||||
ASN1_TIME_set_string(X509_getm_notBefore(x509), "20000101000000Z");
|
||||
ASN1_TIME_set_string(X509_getm_notAfter(x509), "99990101000000Z");
|
||||
|
||||
name = X509_get_subject_name(x509);
|
||||
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *)country, -1, -1, 0);
|
||||
X509_NAME_add_entry_by_txt(name, "ST", MBSTRING_ASC, (unsigned char *)state, -1, -1, 0);
|
||||
X509_NAME_add_entry_by_txt(name, "L", MBSTRING_ASC, (unsigned char *)locality, -1, -1, 0);
|
||||
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char *)organization, -1, -1, 0);
|
||||
X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_ASC, (unsigned char *)unit, -1, -1, 0);
|
||||
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)common_name, -1, -1, 0);
|
||||
|
||||
X509_set_issuer_name(x509, name);
|
||||
X509_set_pubkey(x509, pkey);
|
||||
|
||||
if (!X509_sign(x509, pkey, EVP_sha256())) {
|
||||
fprintf(stderr, "Error signing certificate\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Saving the certificate */
|
||||
fp = fopen(cert, "w");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Failed opening %s for writing: %s\n", cert, strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
PEM_write_X509(fp, x509);
|
||||
fclose(fp);
|
||||
|
||||
/* Saving the private key */
|
||||
fp = fopen(key, "w");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Failed opening %s for writing: %s\n", key, strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL);
|
||||
fclose(fp);
|
||||
|
||||
done: /* Cleanup */
|
||||
X509_free(x509);
|
||||
EVP_PKEY_free(pkey);
|
||||
BN_free(bn_serial);
|
||||
ASN1_INTEGER_free(asn1_serno);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
Copyright (c) 2024 The KernelKit Authors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||
with or without fee is hereby granted, provided that the above copyright notice
|
||||
and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
Default Landing Page for Infix
|
||||
==============================
|
||||
|
||||
This is a temporary landing page for the Infix web interface pending the
|
||||
upcoming RESTCONF based WebUI application.
|
||||
|
||||
Use `gen.sh` to update `index.html` from the top-level project README.md
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
@@ -1,4 +1,5 @@
|
||||
---
|
||||
- case: meta/reproducible.py
|
||||
- case: meta/wait.py
|
||||
|
||||
- name: Misc tests
|
||||
|
||||
@@ -12,7 +12,7 @@ env = infamy.Env()
|
||||
ctrl = env.ptop.get_ctrl()
|
||||
infixen = env.ptop.get_infixen()
|
||||
for ix in infixen:
|
||||
(_, cport), (_, ixport) = env.ptop.get_path(ctrl, ix)
|
||||
cport, ixport = env.ptop.get_mgmt_link(ctrl, ix)
|
||||
print(f"Attaching to {ix}:{ixport} via {ctrl}:{cport}")
|
||||
exec(f"{ix} = env.attach(\"{ix}\", \"{ixport}\")")
|
||||
|
||||
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
|
||||
import infamy
|
||||
|
||||
with infamy.Test() as test:
|
||||
with test.step("$PYTHONHASHSEED is set"):
|
||||
seed = os.environ.get("PYTHONHASHSEED")
|
||||
if seed == None:
|
||||
print("$PYTHONHASHSEED must be set in order to create a reproducible test environment")
|
||||
test.fail()
|
||||
else:
|
||||
print(f"Specify PYTHONHASHSEED={seed} to reproduce this test environment")
|
||||
|
||||
test.succeed()
|
||||
@@ -8,13 +8,13 @@ import infamy, infamy.neigh
|
||||
def ll6ping(node):
|
||||
neigh = None
|
||||
|
||||
for (_, cport), (_, nport) in env.ptop.get_paths(ctrl, node):
|
||||
neigh = infamy.neigh.ll6ping(cport, flags=["-w1", "-c1", "-L", "-n"])
|
||||
if neigh:
|
||||
print(f"Found {neigh} on {cport} (connected to {node}:{nport})")
|
||||
break
|
||||
cport, nport = env.ptop.get_mgmt_link(ctrl, node)
|
||||
neigh = infamy.neigh.ll6ping(cport, flags=["-w1", "-c1", "-L", "-n"])
|
||||
if neigh:
|
||||
print(f"Found {neigh} on {cport} (connected to {node}:{nport})")
|
||||
return neigh
|
||||
|
||||
return neigh
|
||||
return None
|
||||
|
||||
def netconf_syn(neigh):
|
||||
try:
|
||||
|
||||
@@ -157,6 +157,7 @@ if [ "$containerize" ]; then
|
||||
--cap-add=NET_RAW \
|
||||
--cap-add=NET_ADMIN \
|
||||
--device=/dev/net/tun \
|
||||
--env PYTHONHASHSEED=${PYTHONHASHSEED:-$(shuf -i 0-$(((1 << 32) - 1)) -n 1)} \
|
||||
--env VIRTUAL_ENV_DISABLE_PROMPT=yes \
|
||||
--env PROMPT_DIRTRIM="$ixdir" \
|
||||
--env PS1='\e[1m$(date "+%H:%M:%S") \h\e[0m:\W # ' \
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ class Env(object):
|
||||
if not password:
|
||||
password = "admin"
|
||||
ctrl = self.ptop.get_ctrl()
|
||||
_, cport = self.ptop.get_path(ctrl, (node, port))[0]
|
||||
cport, _ = self.ptop.get_mgmt_link(ctrl, node)
|
||||
|
||||
print(f"Probing {node} on port {cport} for IPv6LL mgmt address ...")
|
||||
mgmtip = neigh.ll6ping(cport)
|
||||
|
||||
+64
-78
@@ -1,88 +1,79 @@
|
||||
import networkx as nx
|
||||
from networkx.algorithms import isomorphism
|
||||
|
||||
def qstrip(text):
|
||||
if text.startswith("\"") and text.endswith("\""):
|
||||
return text[1:-1]
|
||||
return text
|
||||
def map_edges(les, pes):
|
||||
acc = []
|
||||
les = sorted(list(les.values()), key=lambda x: x.get("kind", ""), reverse=True)
|
||||
pes = sorted(list(pes.values()), key=lambda x: x.get("kind", ""), reverse=True)
|
||||
|
||||
def match_node(n1attrs, n2attrs):
|
||||
return n1attrs.get("kind") == n2attrs.get("kind")
|
||||
for i in range(len(les)):
|
||||
if pes[i].get("kind") != les[i].get("kind"):
|
||||
return None
|
||||
|
||||
def match_edge(e1attrs, e2attrs):
|
||||
if "kind" in e1attrs or "kind" in e2attrs:
|
||||
return e1attrs.get("kind") == e2attrs.get("kind")
|
||||
acc.append((les[i], pes[i]))
|
||||
|
||||
return True
|
||||
return acc
|
||||
|
||||
def match_node(pn, ln):
|
||||
return pn.get("kind") == ln.get("kind")
|
||||
|
||||
def match_edge(pes, les):
|
||||
return map_edges(les, pes) != None
|
||||
|
||||
class Topology:
|
||||
def __init__(self, dotg):
|
||||
def _qstrip(text):
|
||||
if text == None:
|
||||
return None
|
||||
|
||||
if text.startswith("\"") and text.endswith("\""):
|
||||
return text[1:-1]
|
||||
return text
|
||||
|
||||
self.dotg = dotg
|
||||
edges = {}
|
||||
self.g = nx.MultiGraph()
|
||||
|
||||
for n in self.dotg.get_nodes():
|
||||
name = n.get_name()
|
||||
if name in ("node", "edge"):
|
||||
continue
|
||||
|
||||
repr(n.get_attributes())
|
||||
attrs = { _qstrip(k): _qstrip(v) for k, v in n.get_attributes().items() if k != "label" }
|
||||
self.g.add_node(name, **attrs)
|
||||
|
||||
for e in self.dotg.get_edges():
|
||||
attrs = e.get_attributes()
|
||||
if "weight" not in attrs:
|
||||
attrs["weight"] = 1
|
||||
|
||||
edges[tuple(e.get_source().split(":"))] = { tuple(e.get_destination().split(":")): attrs }
|
||||
sn, sp = e.get_source().split(":")
|
||||
dn, dp = e.get_destination().split(":")
|
||||
|
||||
|
||||
self.g = nx.Graph(edges, weight=1)
|
||||
for e in list(self.g.edges):
|
||||
s, d = e
|
||||
self.g.nodes[s]["kind"] = "port"
|
||||
self.g.nodes[d]["kind"] = "port"
|
||||
|
||||
sn, sp = s
|
||||
dn, dp = d
|
||||
|
||||
try:
|
||||
sk = qstrip(self.dotg.get_node(sn)[0].get_attributes()["kind"])
|
||||
except:
|
||||
raise ValueError("\"{}\"'s kind is not known".format(sn))
|
||||
|
||||
try:
|
||||
dk = qstrip(self.dotg.get_node(dn)[0].get_attributes()["kind"])
|
||||
except:
|
||||
raise ValueError("\"{}\"'s kind is not known".format(dn))
|
||||
|
||||
self.g.add_node(sn, kind=sk)
|
||||
self.g.add_edge(sn, s, weight=0)
|
||||
self.g.add_node(dn, kind=dk)
|
||||
self.g.add_edge(dn, d, weight=0)
|
||||
attrs = { _qstrip(k): _qstrip(v) for k, v in e.get_attributes().items() }
|
||||
attrs[sn] = sp
|
||||
attrs[dn] = dp
|
||||
self.g.add_edge(sn, dn, **attrs)
|
||||
|
||||
def map_to(self, phy):
|
||||
def _map_node(lnode, pnode):
|
||||
if lnode in self.mapping:
|
||||
assert(self.mapping[lnode][None] == pnode)
|
||||
else:
|
||||
self.mapping[lnode] = { None: pnode }
|
||||
|
||||
def _map_port(log, phy):
|
||||
(lnode, lport) = log
|
||||
(pnode, pport) = phy
|
||||
|
||||
if lport in self.mapping[lnode]:
|
||||
assert(self.mapping[lnode][lport] == pport)
|
||||
else:
|
||||
self.mapping[lnode][lport] = pport
|
||||
|
||||
nxmap = isomorphism.GraphMatcher(phy.g, self.g, edge_match=match_edge, node_match=match_node)
|
||||
if not nxmap.subgraph_is_isomorphic():
|
||||
mapper = isomorphism.MultiGraphMatcher(phy.g, self.g,
|
||||
edge_match=match_edge,
|
||||
node_match=match_node)
|
||||
if not mapper.subgraph_is_monomorphic():
|
||||
return False
|
||||
|
||||
self.phy = phy
|
||||
self.mapping = {}
|
||||
for (phy, log) in nxmap.mapping.items():
|
||||
if isinstance(log, tuple):
|
||||
lnode, lport = log
|
||||
pnode, pport = phy
|
||||
|
||||
_map_node(lnode, pnode)
|
||||
_map_port((lnode, lport), (pnode, pport))
|
||||
else:
|
||||
_map_node(log, phy)
|
||||
for pn, ln in mapper.mapping.items():
|
||||
self.mapping.setdefault(ln, { None: pn })
|
||||
|
||||
for lsrc, ldst in set(self.g.edges()):
|
||||
psrc = self.mapping[lsrc][None]
|
||||
pdst = self.mapping[ldst][None]
|
||||
|
||||
les = self.g.get_edge_data(lsrc, ldst)
|
||||
pes = self.phy.g.get_edge_data(psrc, pdst)
|
||||
|
||||
for le, pe in map_edges(les, pes):
|
||||
self.mapping[lsrc][le[lsrc]] = pe[psrc]
|
||||
self.mapping[ldst][le[ldst]] = pe[pdst]
|
||||
|
||||
return True
|
||||
|
||||
@@ -116,20 +107,16 @@ class Topology:
|
||||
password=b.get("password")
|
||||
return qstrip(password) if password is not None else None
|
||||
|
||||
def get_ports(self, node):
|
||||
ports = self.get_nodes(lambda name, _: name.startswith(f"{node}:"))
|
||||
return { p.removeprefix(f"{node}:") for p in ports }
|
||||
def get_link(self, src, dst, flt=lambda _: True):
|
||||
es = self.g.get_edge_data(src, dst)
|
||||
for e in es.values():
|
||||
if flt(e):
|
||||
return e[src], e[dst]
|
||||
|
||||
def get_path(self, src, dst):
|
||||
path = nx.shortest_path(self.g, src, dst)
|
||||
return path[1:-1] if path else None
|
||||
return None
|
||||
|
||||
def get_paths(self, src, dst):
|
||||
paths = nx.all_shortest_paths(self.g, src, dst)
|
||||
if not paths:
|
||||
return None
|
||||
|
||||
return map(lambda path: path[1:-1], paths)
|
||||
def get_mgmt_link(self, src, dst):
|
||||
return self.get_link(src, dst, lambda e: e.get("kind") == "mgmt")
|
||||
|
||||
def get_ctrl(self):
|
||||
ns = self.get_nodes(lambda _, attrs: attrs.get("kind") == "controller")
|
||||
@@ -139,7 +126,6 @@ class Topology:
|
||||
def get_infixen(self):
|
||||
return self.get_nodes(lambda _, attrs: attrs.get("kind") == "infix")
|
||||
|
||||
|
||||
# Support calling this script like so...
|
||||
#
|
||||
# python3 topology.py <physical> <logical>
|
||||
|
||||
Reference in New Issue
Block a user