From 9032ab087f578998eb0e75e07aaa111117739108 Mon Sep 17 00:00:00 2001 From: bfinnema Date: Thu, 11 Jul 2024 22:06:45 +0200 Subject: [PATCH] Added the L2VPN service with QinQ. Moved the l3vpn_qinq services to Backup folder --- .../l3vpn_qinq_cfs}/README | 0 .../load-dir/l3vpn_qinq_cfs.fxs | Bin 0 -> 14497 bytes .../l3vpn_qinq_cfs}/package-meta-data.xml | 0 .../python/l3vpn_qinq_cfs/__init__.py | 0 .../python/l3vpn_qinq_cfs/main.py | 83 ++++++++++ .../l3vpn_qinq_cfs}/src/Makefile | 0 .../src/yang/l3vpn_qinq_cfs.yang | 4 +- .../templates/l3vpn_qinq_cfs-template.xml | 0 .../templates/l3vpn_qinq_pe-template.xml | 4 +- .../l3vpn_qinq_cfs}/test/Makefile | 0 .../l3vpn_qinq_cfs}/test/internal/Makefile | 0 .../test/internal/lux/Makefile | 0 .../test/internal/lux/service/Makefile | 0 .../internal/lux/service/dummy-device.xml | 0 .../internal/lux/service/dummy-service.xml | 0 .../test/internal/lux/service/pyvm.xml | 0 .../test/internal/lux/service/run.lux | 0 .../l3vpn_qinq_cpe_rfs}/README | 0 .../l3vpn_qinq_cpe_rfs}/package-meta-data.xml | 0 .../python/l3vpn_qinq_cpe_rfs/__init__.py | 0 .../python/l3vpn_qinq_cpe_rfs/main.py | 0 .../l3vpn_qinq_cpe_rfs}/src/Makefile | 0 .../src/yang/l3vpn_qinq_cpe_rfs.yang | 0 .../templates/l3vpn_qinq_cpe_rfs-template.xml | 0 .../l3vpn_qinq_cpe_rfs}/test/Makefile | 0 .../test/internal/Makefile | 0 .../test/internal/lux/Makefile | 0 .../test/internal/lux/service/Makefile | 0 .../internal/lux/service/dummy-device.xml | 0 .../internal/lux/service/dummy-service.xml | 0 .../test/internal/lux/service/pyvm.xml | 0 .../test/internal/lux/service/run.lux | 0 .../l3vpn_qinq_pe_rfs}/README | 0 .../load-dir/l3vpn_qinq_pe_rfs.fxs | Bin .../l3vpn_qinq_pe_rfs}/package-meta-data.xml | 0 .../python/l3vpn_qinq_pe_rfs/__init__.py | 0 .../python/l3vpn_qinq_pe_rfs/main.py | 0 .../l3vpn_qinq_pe_rfs}/src/Makefile | 0 .../src/yang/l3vpn_qinq_pe_rfs.yang | 0 .../templates/l3vpn_qinq_pe_rfs-template.xml | 0 .../l3vpn_qinq_pe_rfs}/test/Makefile | 0 .../l3vpn_qinq_pe_rfs}/test/internal/Makefile | 0 .../test/internal/lux/Makefile | 0 .../test/internal/lux/service/Makefile | 0 .../internal/lux/service/dummy-device.xml | 0 .../internal/lux/service/dummy-service.xml | 0 .../test/internal/lux/service/pyvm.xml | 0 .../test/internal/lux/service/run.lux | 0 .../l3vpn_qinq_sw_rfs}/README | 0 .../l3vpn_qinq_sw_rfs}/package-meta-data.xml | 0 .../python/l3vpn_qinq_sw_rfs/__init__.py | 0 .../python/l3vpn_qinq_sw_rfs/main.py | 0 .../l3vpn_qinq_sw_rfs}/src/Makefile | 0 .../src/yang/l3vpn_qinq_sw_rfs.yang | 0 .../templates/l3vpn_qinq_sw_rfs-template.xml | 0 .../l3vpn_qinq_sw_rfs}/test/Makefile | 0 .../l3vpn_qinq_sw_rfs}/test/internal/Makefile | 0 .../test/internal/lux/Makefile | 0 .../test/internal/lux/service/Makefile | 0 .../internal/lux/service/dummy-device.xml | 0 .../internal/lux/service/dummy-service.xml | 0 .../test/internal/lux/service/pyvm.xml | 0 .../test/internal/lux/service/run.lux | 0 l2vpn_cfs/README | 23 +++ l2vpn_cfs/load-dir/l2vpn_cfs.fxs | Bin 0 -> 13616 bytes l2vpn_cfs/package-meta-data.xml | 13 ++ l2vpn_cfs/python/l2vpn_cfs/__init__.py | 0 l2vpn_cfs/python/l2vpn_cfs/main.py | 109 +++++++++++++ l2vpn_cfs/src/Makefile | 32 ++++ l2vpn_cfs/src/yang/l2vpn_cfs.yang | 120 ++++++++++++++ l2vpn_cfs/templates/l2vpn_cpe-template.xml | 13 ++ l2vpn_cfs/templates/l2vpn_pe-template.xml | 14 ++ l2vpn_cfs/templates/l2vpn_sw-template.xml | 19 +++ l2vpn_cfs/test/Makefile | 37 +++++ l2vpn_cfs/test/internal/Makefile | 21 +++ l2vpn_cfs/test/internal/lux/Makefile | 21 +++ l2vpn_cfs/test/internal/lux/service/Makefile | 26 +++ .../internal/lux/service/dummy-device.xml | 11 ++ .../internal/lux/service/dummy-service.xml | 12 ++ l2vpn_cfs/test/internal/lux/service/pyvm.xml | 8 + l2vpn_cfs/test/internal/lux/service/run.lux | 53 +++++++ l2vpn_cpe_rfs/README | 23 +++ l2vpn_cpe_rfs/load-dir/l2vpn_cpe_rfs.fxs | Bin 0 -> 13164 bytes l2vpn_cpe_rfs/package-meta-data.xml | 13 ++ .../python/l2vpn_cpe_rfs/__init__.py | 0 l2vpn_cpe_rfs/python/l2vpn_cpe_rfs/main.py | 65 ++++++++ l2vpn_cpe_rfs/src/Makefile | 32 ++++ l2vpn_cpe_rfs/src/yang/l2vpn_cpe_rfs.yang | 89 +++++++++++ .../templates/l2vpn_cpe_rfs-template.xml | 81 ++++++++++ l2vpn_cpe_rfs/test/Makefile | 37 +++++ l2vpn_cpe_rfs/test/internal/Makefile | 21 +++ l2vpn_cpe_rfs/test/internal/lux/Makefile | 21 +++ .../test/internal/lux/service/Makefile | 26 +++ .../internal/lux/service/dummy-device.xml | 11 ++ .../internal/lux/service/dummy-service.xml | 12 ++ .../test/internal/lux/service/pyvm.xml | 8 + .../test/internal/lux/service/run.lux | 53 +++++++ l2vpn_pe_rfs/README | 23 +++ l2vpn_pe_rfs/load-dir/l2vpn_pe_rfs.fxs | Bin 0 -> 13252 bytes l2vpn_pe_rfs/package-meta-data.xml | 13 ++ l2vpn_pe_rfs/python/l2vpn_pe_rfs/__init__.py | 0 l2vpn_pe_rfs/python/l2vpn_pe_rfs/main.py | 65 ++++++++ l2vpn_pe_rfs/src/Makefile | 32 ++++ l2vpn_pe_rfs/src/yang/l2vpn_pe_rfs.yang | 94 +++++++++++ .../templates/l2vpn_pe_rfs-template.xml | 150 ++++++++++++++++++ l2vpn_pe_rfs/test/Makefile | 37 +++++ l2vpn_pe_rfs/test/internal/Makefile | 21 +++ l2vpn_pe_rfs/test/internal/lux/Makefile | 21 +++ .../test/internal/lux/service/Makefile | 26 +++ .../internal/lux/service/dummy-device.xml | 11 ++ .../internal/lux/service/dummy-service.xml | 12 ++ .../test/internal/lux/service/pyvm.xml | 8 + .../test/internal/lux/service/run.lux | 53 +++++++ l2vpn_sw_rfs/README | 23 +++ l2vpn_sw_rfs/load-dir/l2vpn_sw_rfs.fxs | Bin 0 -> 13318 bytes l2vpn_sw_rfs/package-meta-data.xml | 13 ++ l2vpn_sw_rfs/python/l2vpn_sw_rfs/__init__.py | 0 l2vpn_sw_rfs/python/l2vpn_sw_rfs/main.py | 65 ++++++++ l2vpn_sw_rfs/src/Makefile | 32 ++++ l2vpn_sw_rfs/src/yang/l2vpn_sw_rfs.yang | 98 ++++++++++++ .../templates/l2vpn_sw_rfs-template.xml | 85 ++++++++++ l2vpn_sw_rfs/test/Makefile | 37 +++++ l2vpn_sw_rfs/test/internal/Makefile | 21 +++ l2vpn_sw_rfs/test/internal/lux/Makefile | 21 +++ .../test/internal/lux/service/Makefile | 26 +++ .../internal/lux/service/dummy-device.xml | 11 ++ .../internal/lux/service/dummy-service.xml | 12 ++ .../test/internal/lux/service/pyvm.xml | 8 + .../test/internal/lux/service/run.lux | 53 +++++++ .../templates/l3vpn_cpe_rfs-template.xml | 2 +- l3vpn_qinq_cfs/load-dir/l3vpn_qinq_cfs.fxs | Bin 14588 -> 0 bytes l3vpn_qinq_cfs/python/l3vpn_qinq_cfs/main.py | 44 ----- netbox_test/README | 23 +++ netbox_test/load-dir/netbox_test.fxs | Bin 0 -> 12514 bytes netbox_test/package-meta-data.xml | 13 ++ netbox_test/python/netbox_test/__init__.py | 0 netbox_test/python/netbox_test/main.py | 50 ++++++ netbox_test/src/Makefile | 32 ++++ netbox_test/src/yang/netbox_test.yang | 55 +++++++ .../templates/netbox_test-template.xml | 20 +++ netbox_test/test/Makefile | 37 +++++ netbox_test/test/internal/Makefile | 21 +++ netbox_test/test/internal/lux/Makefile | 21 +++ .../test/internal/lux/service/Makefile | 26 +++ .../internal/lux/service/dummy-device.xml | 11 ++ .../internal/lux/service/dummy-service.xml | 12 ++ .../test/internal/lux/service/pyvm.xml | 8 + netbox_test/test/internal/lux/service/run.lux | 53 +++++++ 148 files changed, 2565 insertions(+), 49 deletions(-) rename {l3vpn_qinq_cfs => backup/l3vpn_qinq_cfs}/README (100%) create mode 100644 backup/l3vpn_qinq_cfs/load-dir/l3vpn_qinq_cfs.fxs rename {l3vpn_qinq_cfs => backup/l3vpn_qinq_cfs}/package-meta-data.xml (100%) rename {l3vpn_qinq_cfs => backup/l3vpn_qinq_cfs}/python/l3vpn_qinq_cfs/__init__.py (100%) create mode 100644 backup/l3vpn_qinq_cfs/python/l3vpn_qinq_cfs/main.py rename {l3vpn_qinq_cfs => backup/l3vpn_qinq_cfs}/src/Makefile (100%) rename {l3vpn_qinq_cfs => backup/l3vpn_qinq_cfs}/src/yang/l3vpn_qinq_cfs.yang (98%) rename {l3vpn_qinq_cfs => backup/l3vpn_qinq_cfs}/templates/l3vpn_qinq_cfs-template.xml (100%) rename {l3vpn_qinq_cfs => backup/l3vpn_qinq_cfs}/templates/l3vpn_qinq_pe-template.xml (92%) rename {l3vpn_qinq_cfs => backup/l3vpn_qinq_cfs}/test/Makefile (100%) rename {l3vpn_qinq_cfs => backup/l3vpn_qinq_cfs}/test/internal/Makefile (100%) rename {l3vpn_qinq_cfs => backup/l3vpn_qinq_cfs}/test/internal/lux/Makefile (100%) rename {l3vpn_qinq_cfs => backup/l3vpn_qinq_cfs}/test/internal/lux/service/Makefile (100%) rename {l3vpn_qinq_cfs => backup/l3vpn_qinq_cfs}/test/internal/lux/service/dummy-device.xml (100%) rename {l3vpn_qinq_cfs => backup/l3vpn_qinq_cfs}/test/internal/lux/service/dummy-service.xml (100%) rename {l3vpn_qinq_cfs => backup/l3vpn_qinq_cfs}/test/internal/lux/service/pyvm.xml (100%) rename {l3vpn_qinq_cfs => backup/l3vpn_qinq_cfs}/test/internal/lux/service/run.lux (100%) rename {l3vpn_qinq_cpe_rfs => backup/l3vpn_qinq_cpe_rfs}/README (100%) rename {l3vpn_qinq_cpe_rfs => backup/l3vpn_qinq_cpe_rfs}/package-meta-data.xml (100%) rename {l3vpn_qinq_cpe_rfs => backup/l3vpn_qinq_cpe_rfs}/python/l3vpn_qinq_cpe_rfs/__init__.py (100%) rename {l3vpn_qinq_cpe_rfs => backup/l3vpn_qinq_cpe_rfs}/python/l3vpn_qinq_cpe_rfs/main.py (100%) rename {l3vpn_qinq_cpe_rfs => backup/l3vpn_qinq_cpe_rfs}/src/Makefile (100%) rename {l3vpn_qinq_cpe_rfs => backup/l3vpn_qinq_cpe_rfs}/src/yang/l3vpn_qinq_cpe_rfs.yang (100%) rename {l3vpn_qinq_cpe_rfs => backup/l3vpn_qinq_cpe_rfs}/templates/l3vpn_qinq_cpe_rfs-template.xml (100%) rename {l3vpn_qinq_cpe_rfs => backup/l3vpn_qinq_cpe_rfs}/test/Makefile (100%) rename {l3vpn_qinq_cpe_rfs => backup/l3vpn_qinq_cpe_rfs}/test/internal/Makefile (100%) rename {l3vpn_qinq_cpe_rfs => backup/l3vpn_qinq_cpe_rfs}/test/internal/lux/Makefile (100%) rename {l3vpn_qinq_cpe_rfs => backup/l3vpn_qinq_cpe_rfs}/test/internal/lux/service/Makefile (100%) rename {l3vpn_qinq_cpe_rfs => backup/l3vpn_qinq_cpe_rfs}/test/internal/lux/service/dummy-device.xml (100%) rename {l3vpn_qinq_cpe_rfs => backup/l3vpn_qinq_cpe_rfs}/test/internal/lux/service/dummy-service.xml (100%) rename {l3vpn_qinq_cpe_rfs => backup/l3vpn_qinq_cpe_rfs}/test/internal/lux/service/pyvm.xml (100%) rename {l3vpn_qinq_cpe_rfs => backup/l3vpn_qinq_cpe_rfs}/test/internal/lux/service/run.lux (100%) rename {l3vpn_qinq_pe_rfs => backup/l3vpn_qinq_pe_rfs}/README (100%) rename {l3vpn_qinq_pe_rfs => backup/l3vpn_qinq_pe_rfs}/load-dir/l3vpn_qinq_pe_rfs.fxs (100%) rename {l3vpn_qinq_pe_rfs => backup/l3vpn_qinq_pe_rfs}/package-meta-data.xml (100%) rename {l3vpn_qinq_pe_rfs => backup/l3vpn_qinq_pe_rfs}/python/l3vpn_qinq_pe_rfs/__init__.py (100%) rename {l3vpn_qinq_pe_rfs => backup/l3vpn_qinq_pe_rfs}/python/l3vpn_qinq_pe_rfs/main.py (100%) rename {l3vpn_qinq_pe_rfs => backup/l3vpn_qinq_pe_rfs}/src/Makefile (100%) rename {l3vpn_qinq_pe_rfs => backup/l3vpn_qinq_pe_rfs}/src/yang/l3vpn_qinq_pe_rfs.yang (100%) rename {l3vpn_qinq_pe_rfs => backup/l3vpn_qinq_pe_rfs}/templates/l3vpn_qinq_pe_rfs-template.xml (100%) rename {l3vpn_qinq_pe_rfs => backup/l3vpn_qinq_pe_rfs}/test/Makefile (100%) rename {l3vpn_qinq_pe_rfs => backup/l3vpn_qinq_pe_rfs}/test/internal/Makefile (100%) rename {l3vpn_qinq_pe_rfs => backup/l3vpn_qinq_pe_rfs}/test/internal/lux/Makefile (100%) rename {l3vpn_qinq_pe_rfs => backup/l3vpn_qinq_pe_rfs}/test/internal/lux/service/Makefile (100%) rename {l3vpn_qinq_pe_rfs => backup/l3vpn_qinq_pe_rfs}/test/internal/lux/service/dummy-device.xml (100%) rename {l3vpn_qinq_pe_rfs => backup/l3vpn_qinq_pe_rfs}/test/internal/lux/service/dummy-service.xml (100%) rename {l3vpn_qinq_pe_rfs => backup/l3vpn_qinq_pe_rfs}/test/internal/lux/service/pyvm.xml (100%) rename {l3vpn_qinq_pe_rfs => backup/l3vpn_qinq_pe_rfs}/test/internal/lux/service/run.lux (100%) rename {l3vpn_qinq_sw_rfs => backup/l3vpn_qinq_sw_rfs}/README (100%) rename {l3vpn_qinq_sw_rfs => backup/l3vpn_qinq_sw_rfs}/package-meta-data.xml (100%) rename {l3vpn_qinq_sw_rfs => backup/l3vpn_qinq_sw_rfs}/python/l3vpn_qinq_sw_rfs/__init__.py (100%) rename {l3vpn_qinq_sw_rfs => backup/l3vpn_qinq_sw_rfs}/python/l3vpn_qinq_sw_rfs/main.py (100%) rename {l3vpn_qinq_sw_rfs => backup/l3vpn_qinq_sw_rfs}/src/Makefile (100%) rename {l3vpn_qinq_sw_rfs => backup/l3vpn_qinq_sw_rfs}/src/yang/l3vpn_qinq_sw_rfs.yang (100%) rename {l3vpn_qinq_sw_rfs => backup/l3vpn_qinq_sw_rfs}/templates/l3vpn_qinq_sw_rfs-template.xml (100%) rename {l3vpn_qinq_sw_rfs => backup/l3vpn_qinq_sw_rfs}/test/Makefile (100%) rename {l3vpn_qinq_sw_rfs => backup/l3vpn_qinq_sw_rfs}/test/internal/Makefile (100%) rename {l3vpn_qinq_sw_rfs => backup/l3vpn_qinq_sw_rfs}/test/internal/lux/Makefile (100%) rename {l3vpn_qinq_sw_rfs => backup/l3vpn_qinq_sw_rfs}/test/internal/lux/service/Makefile (100%) rename {l3vpn_qinq_sw_rfs => backup/l3vpn_qinq_sw_rfs}/test/internal/lux/service/dummy-device.xml (100%) rename {l3vpn_qinq_sw_rfs => backup/l3vpn_qinq_sw_rfs}/test/internal/lux/service/dummy-service.xml (100%) rename {l3vpn_qinq_sw_rfs => backup/l3vpn_qinq_sw_rfs}/test/internal/lux/service/pyvm.xml (100%) rename {l3vpn_qinq_sw_rfs => backup/l3vpn_qinq_sw_rfs}/test/internal/lux/service/run.lux (100%) create mode 100644 l2vpn_cfs/README create mode 100644 l2vpn_cfs/load-dir/l2vpn_cfs.fxs create mode 100644 l2vpn_cfs/package-meta-data.xml create mode 100644 l2vpn_cfs/python/l2vpn_cfs/__init__.py create mode 100644 l2vpn_cfs/python/l2vpn_cfs/main.py create mode 100644 l2vpn_cfs/src/Makefile create mode 100644 l2vpn_cfs/src/yang/l2vpn_cfs.yang create mode 100644 l2vpn_cfs/templates/l2vpn_cpe-template.xml create mode 100644 l2vpn_cfs/templates/l2vpn_pe-template.xml create mode 100644 l2vpn_cfs/templates/l2vpn_sw-template.xml create mode 100644 l2vpn_cfs/test/Makefile create mode 100644 l2vpn_cfs/test/internal/Makefile create mode 100644 l2vpn_cfs/test/internal/lux/Makefile create mode 100644 l2vpn_cfs/test/internal/lux/service/Makefile create mode 100644 l2vpn_cfs/test/internal/lux/service/dummy-device.xml create mode 100644 l2vpn_cfs/test/internal/lux/service/dummy-service.xml create mode 100644 l2vpn_cfs/test/internal/lux/service/pyvm.xml create mode 100644 l2vpn_cfs/test/internal/lux/service/run.lux create mode 100644 l2vpn_cpe_rfs/README create mode 100644 l2vpn_cpe_rfs/load-dir/l2vpn_cpe_rfs.fxs create mode 100644 l2vpn_cpe_rfs/package-meta-data.xml create mode 100644 l2vpn_cpe_rfs/python/l2vpn_cpe_rfs/__init__.py create mode 100644 l2vpn_cpe_rfs/python/l2vpn_cpe_rfs/main.py create mode 100644 l2vpn_cpe_rfs/src/Makefile create mode 100644 l2vpn_cpe_rfs/src/yang/l2vpn_cpe_rfs.yang create mode 100644 l2vpn_cpe_rfs/templates/l2vpn_cpe_rfs-template.xml create mode 100644 l2vpn_cpe_rfs/test/Makefile create mode 100644 l2vpn_cpe_rfs/test/internal/Makefile create mode 100644 l2vpn_cpe_rfs/test/internal/lux/Makefile create mode 100644 l2vpn_cpe_rfs/test/internal/lux/service/Makefile create mode 100644 l2vpn_cpe_rfs/test/internal/lux/service/dummy-device.xml create mode 100644 l2vpn_cpe_rfs/test/internal/lux/service/dummy-service.xml create mode 100644 l2vpn_cpe_rfs/test/internal/lux/service/pyvm.xml create mode 100644 l2vpn_cpe_rfs/test/internal/lux/service/run.lux create mode 100644 l2vpn_pe_rfs/README create mode 100644 l2vpn_pe_rfs/load-dir/l2vpn_pe_rfs.fxs create mode 100644 l2vpn_pe_rfs/package-meta-data.xml create mode 100644 l2vpn_pe_rfs/python/l2vpn_pe_rfs/__init__.py create mode 100644 l2vpn_pe_rfs/python/l2vpn_pe_rfs/main.py create mode 100644 l2vpn_pe_rfs/src/Makefile create mode 100644 l2vpn_pe_rfs/src/yang/l2vpn_pe_rfs.yang create mode 100644 l2vpn_pe_rfs/templates/l2vpn_pe_rfs-template.xml create mode 100644 l2vpn_pe_rfs/test/Makefile create mode 100644 l2vpn_pe_rfs/test/internal/Makefile create mode 100644 l2vpn_pe_rfs/test/internal/lux/Makefile create mode 100644 l2vpn_pe_rfs/test/internal/lux/service/Makefile create mode 100644 l2vpn_pe_rfs/test/internal/lux/service/dummy-device.xml create mode 100644 l2vpn_pe_rfs/test/internal/lux/service/dummy-service.xml create mode 100644 l2vpn_pe_rfs/test/internal/lux/service/pyvm.xml create mode 100644 l2vpn_pe_rfs/test/internal/lux/service/run.lux create mode 100644 l2vpn_sw_rfs/README create mode 100644 l2vpn_sw_rfs/load-dir/l2vpn_sw_rfs.fxs create mode 100644 l2vpn_sw_rfs/package-meta-data.xml create mode 100644 l2vpn_sw_rfs/python/l2vpn_sw_rfs/__init__.py create mode 100644 l2vpn_sw_rfs/python/l2vpn_sw_rfs/main.py create mode 100644 l2vpn_sw_rfs/src/Makefile create mode 100644 l2vpn_sw_rfs/src/yang/l2vpn_sw_rfs.yang create mode 100644 l2vpn_sw_rfs/templates/l2vpn_sw_rfs-template.xml create mode 100644 l2vpn_sw_rfs/test/Makefile create mode 100644 l2vpn_sw_rfs/test/internal/Makefile create mode 100644 l2vpn_sw_rfs/test/internal/lux/Makefile create mode 100644 l2vpn_sw_rfs/test/internal/lux/service/Makefile create mode 100644 l2vpn_sw_rfs/test/internal/lux/service/dummy-device.xml create mode 100644 l2vpn_sw_rfs/test/internal/lux/service/dummy-service.xml create mode 100644 l2vpn_sw_rfs/test/internal/lux/service/pyvm.xml create mode 100644 l2vpn_sw_rfs/test/internal/lux/service/run.lux delete mode 100644 l3vpn_qinq_cfs/load-dir/l3vpn_qinq_cfs.fxs delete mode 100644 l3vpn_qinq_cfs/python/l3vpn_qinq_cfs/main.py create mode 100644 netbox_test/README create mode 100644 netbox_test/load-dir/netbox_test.fxs create mode 100644 netbox_test/package-meta-data.xml create mode 100644 netbox_test/python/netbox_test/__init__.py create mode 100644 netbox_test/python/netbox_test/main.py create mode 100644 netbox_test/src/Makefile create mode 100644 netbox_test/src/yang/netbox_test.yang create mode 100644 netbox_test/templates/netbox_test-template.xml create mode 100644 netbox_test/test/Makefile create mode 100644 netbox_test/test/internal/Makefile create mode 100644 netbox_test/test/internal/lux/Makefile create mode 100644 netbox_test/test/internal/lux/service/Makefile create mode 100644 netbox_test/test/internal/lux/service/dummy-device.xml create mode 100644 netbox_test/test/internal/lux/service/dummy-service.xml create mode 100644 netbox_test/test/internal/lux/service/pyvm.xml create mode 100644 netbox_test/test/internal/lux/service/run.lux diff --git a/l3vpn_qinq_cfs/README b/backup/l3vpn_qinq_cfs/README similarity index 100% rename from l3vpn_qinq_cfs/README rename to backup/l3vpn_qinq_cfs/README diff --git a/backup/l3vpn_qinq_cfs/load-dir/l3vpn_qinq_cfs.fxs b/backup/l3vpn_qinq_cfs/load-dir/l3vpn_qinq_cfs.fxs new file mode 100644 index 0000000000000000000000000000000000000000..e7b49e3b4f5738bfb6df4e747b9f83f3f0a0f947 GIT binary patch literal 14497 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/as_number} {/customer_as_number} {$cpe_interface_address} - {/ovlan} - {/ivlan} + {$ovlan} + {$ivlan} {$pe_interface_name} {$pe_interface_number} diff --git a/l3vpn_qinq_cfs/test/Makefile b/backup/l3vpn_qinq_cfs/test/Makefile similarity index 100% rename from l3vpn_qinq_cfs/test/Makefile rename to backup/l3vpn_qinq_cfs/test/Makefile diff --git a/l3vpn_qinq_cfs/test/internal/Makefile b/backup/l3vpn_qinq_cfs/test/internal/Makefile similarity index 100% rename from l3vpn_qinq_cfs/test/internal/Makefile rename to backup/l3vpn_qinq_cfs/test/internal/Makefile diff --git a/l3vpn_qinq_cfs/test/internal/lux/Makefile b/backup/l3vpn_qinq_cfs/test/internal/lux/Makefile similarity index 100% rename from l3vpn_qinq_cfs/test/internal/lux/Makefile rename to backup/l3vpn_qinq_cfs/test/internal/lux/Makefile diff --git a/l3vpn_qinq_cfs/test/internal/lux/service/Makefile b/backup/l3vpn_qinq_cfs/test/internal/lux/service/Makefile similarity index 100% rename from l3vpn_qinq_cfs/test/internal/lux/service/Makefile rename to backup/l3vpn_qinq_cfs/test/internal/lux/service/Makefile diff --git a/l3vpn_qinq_cfs/test/internal/lux/service/dummy-device.xml b/backup/l3vpn_qinq_cfs/test/internal/lux/service/dummy-device.xml similarity index 100% rename from l3vpn_qinq_cfs/test/internal/lux/service/dummy-device.xml rename to backup/l3vpn_qinq_cfs/test/internal/lux/service/dummy-device.xml diff --git a/l3vpn_qinq_cfs/test/internal/lux/service/dummy-service.xml b/backup/l3vpn_qinq_cfs/test/internal/lux/service/dummy-service.xml similarity index 100% rename from l3vpn_qinq_cfs/test/internal/lux/service/dummy-service.xml rename to backup/l3vpn_qinq_cfs/test/internal/lux/service/dummy-service.xml diff --git a/l3vpn_qinq_cfs/test/internal/lux/service/pyvm.xml b/backup/l3vpn_qinq_cfs/test/internal/lux/service/pyvm.xml similarity index 100% rename from l3vpn_qinq_cfs/test/internal/lux/service/pyvm.xml rename to backup/l3vpn_qinq_cfs/test/internal/lux/service/pyvm.xml diff --git a/l3vpn_qinq_cfs/test/internal/lux/service/run.lux b/backup/l3vpn_qinq_cfs/test/internal/lux/service/run.lux similarity index 100% rename from l3vpn_qinq_cfs/test/internal/lux/service/run.lux rename to backup/l3vpn_qinq_cfs/test/internal/lux/service/run.lux diff --git a/l3vpn_qinq_cpe_rfs/README b/backup/l3vpn_qinq_cpe_rfs/README similarity index 100% rename from l3vpn_qinq_cpe_rfs/README rename to backup/l3vpn_qinq_cpe_rfs/README diff --git a/l3vpn_qinq_cpe_rfs/package-meta-data.xml b/backup/l3vpn_qinq_cpe_rfs/package-meta-data.xml similarity index 100% rename from l3vpn_qinq_cpe_rfs/package-meta-data.xml rename to backup/l3vpn_qinq_cpe_rfs/package-meta-data.xml diff --git a/l3vpn_qinq_cpe_rfs/python/l3vpn_qinq_cpe_rfs/__init__.py b/backup/l3vpn_qinq_cpe_rfs/python/l3vpn_qinq_cpe_rfs/__init__.py similarity index 100% rename from l3vpn_qinq_cpe_rfs/python/l3vpn_qinq_cpe_rfs/__init__.py rename to backup/l3vpn_qinq_cpe_rfs/python/l3vpn_qinq_cpe_rfs/__init__.py diff --git a/l3vpn_qinq_cpe_rfs/python/l3vpn_qinq_cpe_rfs/main.py b/backup/l3vpn_qinq_cpe_rfs/python/l3vpn_qinq_cpe_rfs/main.py similarity index 100% rename from l3vpn_qinq_cpe_rfs/python/l3vpn_qinq_cpe_rfs/main.py rename to backup/l3vpn_qinq_cpe_rfs/python/l3vpn_qinq_cpe_rfs/main.py diff --git a/l3vpn_qinq_cpe_rfs/src/Makefile b/backup/l3vpn_qinq_cpe_rfs/src/Makefile similarity index 100% rename from l3vpn_qinq_cpe_rfs/src/Makefile rename to backup/l3vpn_qinq_cpe_rfs/src/Makefile diff --git a/l3vpn_qinq_cpe_rfs/src/yang/l3vpn_qinq_cpe_rfs.yang b/backup/l3vpn_qinq_cpe_rfs/src/yang/l3vpn_qinq_cpe_rfs.yang similarity index 100% rename from l3vpn_qinq_cpe_rfs/src/yang/l3vpn_qinq_cpe_rfs.yang rename to backup/l3vpn_qinq_cpe_rfs/src/yang/l3vpn_qinq_cpe_rfs.yang diff --git a/l3vpn_qinq_cpe_rfs/templates/l3vpn_qinq_cpe_rfs-template.xml b/backup/l3vpn_qinq_cpe_rfs/templates/l3vpn_qinq_cpe_rfs-template.xml similarity index 100% rename from l3vpn_qinq_cpe_rfs/templates/l3vpn_qinq_cpe_rfs-template.xml rename to backup/l3vpn_qinq_cpe_rfs/templates/l3vpn_qinq_cpe_rfs-template.xml diff --git a/l3vpn_qinq_cpe_rfs/test/Makefile b/backup/l3vpn_qinq_cpe_rfs/test/Makefile similarity index 100% rename from l3vpn_qinq_cpe_rfs/test/Makefile rename to backup/l3vpn_qinq_cpe_rfs/test/Makefile diff --git a/l3vpn_qinq_cpe_rfs/test/internal/Makefile b/backup/l3vpn_qinq_cpe_rfs/test/internal/Makefile similarity index 100% rename from l3vpn_qinq_cpe_rfs/test/internal/Makefile rename to backup/l3vpn_qinq_cpe_rfs/test/internal/Makefile diff --git a/l3vpn_qinq_cpe_rfs/test/internal/lux/Makefile b/backup/l3vpn_qinq_cpe_rfs/test/internal/lux/Makefile similarity index 100% rename from l3vpn_qinq_cpe_rfs/test/internal/lux/Makefile rename to backup/l3vpn_qinq_cpe_rfs/test/internal/lux/Makefile diff --git a/l3vpn_qinq_cpe_rfs/test/internal/lux/service/Makefile b/backup/l3vpn_qinq_cpe_rfs/test/internal/lux/service/Makefile similarity index 100% rename from l3vpn_qinq_cpe_rfs/test/internal/lux/service/Makefile rename to backup/l3vpn_qinq_cpe_rfs/test/internal/lux/service/Makefile diff --git a/l3vpn_qinq_cpe_rfs/test/internal/lux/service/dummy-device.xml b/backup/l3vpn_qinq_cpe_rfs/test/internal/lux/service/dummy-device.xml similarity index 100% rename from l3vpn_qinq_cpe_rfs/test/internal/lux/service/dummy-device.xml rename to backup/l3vpn_qinq_cpe_rfs/test/internal/lux/service/dummy-device.xml diff --git a/l3vpn_qinq_cpe_rfs/test/internal/lux/service/dummy-service.xml b/backup/l3vpn_qinq_cpe_rfs/test/internal/lux/service/dummy-service.xml similarity index 100% rename from l3vpn_qinq_cpe_rfs/test/internal/lux/service/dummy-service.xml rename to backup/l3vpn_qinq_cpe_rfs/test/internal/lux/service/dummy-service.xml diff --git a/l3vpn_qinq_cpe_rfs/test/internal/lux/service/pyvm.xml b/backup/l3vpn_qinq_cpe_rfs/test/internal/lux/service/pyvm.xml similarity index 100% rename from l3vpn_qinq_cpe_rfs/test/internal/lux/service/pyvm.xml rename to backup/l3vpn_qinq_cpe_rfs/test/internal/lux/service/pyvm.xml diff --git a/l3vpn_qinq_cpe_rfs/test/internal/lux/service/run.lux b/backup/l3vpn_qinq_cpe_rfs/test/internal/lux/service/run.lux similarity index 100% rename from l3vpn_qinq_cpe_rfs/test/internal/lux/service/run.lux rename to backup/l3vpn_qinq_cpe_rfs/test/internal/lux/service/run.lux diff --git a/l3vpn_qinq_pe_rfs/README b/backup/l3vpn_qinq_pe_rfs/README similarity index 100% rename from l3vpn_qinq_pe_rfs/README rename to backup/l3vpn_qinq_pe_rfs/README diff --git a/l3vpn_qinq_pe_rfs/load-dir/l3vpn_qinq_pe_rfs.fxs b/backup/l3vpn_qinq_pe_rfs/load-dir/l3vpn_qinq_pe_rfs.fxs similarity index 100% rename from l3vpn_qinq_pe_rfs/load-dir/l3vpn_qinq_pe_rfs.fxs rename to backup/l3vpn_qinq_pe_rfs/load-dir/l3vpn_qinq_pe_rfs.fxs diff --git a/l3vpn_qinq_pe_rfs/package-meta-data.xml b/backup/l3vpn_qinq_pe_rfs/package-meta-data.xml similarity index 100% rename from l3vpn_qinq_pe_rfs/package-meta-data.xml rename to backup/l3vpn_qinq_pe_rfs/package-meta-data.xml diff --git a/l3vpn_qinq_pe_rfs/python/l3vpn_qinq_pe_rfs/__init__.py b/backup/l3vpn_qinq_pe_rfs/python/l3vpn_qinq_pe_rfs/__init__.py similarity index 100% rename from l3vpn_qinq_pe_rfs/python/l3vpn_qinq_pe_rfs/__init__.py rename to backup/l3vpn_qinq_pe_rfs/python/l3vpn_qinq_pe_rfs/__init__.py diff --git a/l3vpn_qinq_pe_rfs/python/l3vpn_qinq_pe_rfs/main.py b/backup/l3vpn_qinq_pe_rfs/python/l3vpn_qinq_pe_rfs/main.py similarity index 100% rename from l3vpn_qinq_pe_rfs/python/l3vpn_qinq_pe_rfs/main.py rename to backup/l3vpn_qinq_pe_rfs/python/l3vpn_qinq_pe_rfs/main.py diff --git a/l3vpn_qinq_pe_rfs/src/Makefile b/backup/l3vpn_qinq_pe_rfs/src/Makefile similarity index 100% rename from l3vpn_qinq_pe_rfs/src/Makefile rename to backup/l3vpn_qinq_pe_rfs/src/Makefile diff --git a/l3vpn_qinq_pe_rfs/src/yang/l3vpn_qinq_pe_rfs.yang b/backup/l3vpn_qinq_pe_rfs/src/yang/l3vpn_qinq_pe_rfs.yang similarity index 100% rename from l3vpn_qinq_pe_rfs/src/yang/l3vpn_qinq_pe_rfs.yang rename to backup/l3vpn_qinq_pe_rfs/src/yang/l3vpn_qinq_pe_rfs.yang diff --git a/l3vpn_qinq_pe_rfs/templates/l3vpn_qinq_pe_rfs-template.xml b/backup/l3vpn_qinq_pe_rfs/templates/l3vpn_qinq_pe_rfs-template.xml similarity index 100% rename from l3vpn_qinq_pe_rfs/templates/l3vpn_qinq_pe_rfs-template.xml rename to backup/l3vpn_qinq_pe_rfs/templates/l3vpn_qinq_pe_rfs-template.xml diff --git a/l3vpn_qinq_pe_rfs/test/Makefile b/backup/l3vpn_qinq_pe_rfs/test/Makefile similarity index 100% rename from l3vpn_qinq_pe_rfs/test/Makefile rename to backup/l3vpn_qinq_pe_rfs/test/Makefile diff --git a/l3vpn_qinq_pe_rfs/test/internal/Makefile b/backup/l3vpn_qinq_pe_rfs/test/internal/Makefile similarity index 100% rename from l3vpn_qinq_pe_rfs/test/internal/Makefile rename to backup/l3vpn_qinq_pe_rfs/test/internal/Makefile diff --git a/l3vpn_qinq_pe_rfs/test/internal/lux/Makefile b/backup/l3vpn_qinq_pe_rfs/test/internal/lux/Makefile similarity index 100% rename from l3vpn_qinq_pe_rfs/test/internal/lux/Makefile rename to backup/l3vpn_qinq_pe_rfs/test/internal/lux/Makefile diff --git a/l3vpn_qinq_pe_rfs/test/internal/lux/service/Makefile b/backup/l3vpn_qinq_pe_rfs/test/internal/lux/service/Makefile similarity index 100% rename from l3vpn_qinq_pe_rfs/test/internal/lux/service/Makefile rename to backup/l3vpn_qinq_pe_rfs/test/internal/lux/service/Makefile diff --git a/l3vpn_qinq_pe_rfs/test/internal/lux/service/dummy-device.xml b/backup/l3vpn_qinq_pe_rfs/test/internal/lux/service/dummy-device.xml similarity index 100% rename from l3vpn_qinq_pe_rfs/test/internal/lux/service/dummy-device.xml rename to backup/l3vpn_qinq_pe_rfs/test/internal/lux/service/dummy-device.xml diff --git a/l3vpn_qinq_pe_rfs/test/internal/lux/service/dummy-service.xml b/backup/l3vpn_qinq_pe_rfs/test/internal/lux/service/dummy-service.xml similarity index 100% rename from l3vpn_qinq_pe_rfs/test/internal/lux/service/dummy-service.xml rename to backup/l3vpn_qinq_pe_rfs/test/internal/lux/service/dummy-service.xml diff --git a/l3vpn_qinq_pe_rfs/test/internal/lux/service/pyvm.xml b/backup/l3vpn_qinq_pe_rfs/test/internal/lux/service/pyvm.xml similarity index 100% rename from l3vpn_qinq_pe_rfs/test/internal/lux/service/pyvm.xml rename to backup/l3vpn_qinq_pe_rfs/test/internal/lux/service/pyvm.xml diff --git a/l3vpn_qinq_pe_rfs/test/internal/lux/service/run.lux b/backup/l3vpn_qinq_pe_rfs/test/internal/lux/service/run.lux similarity index 100% rename from l3vpn_qinq_pe_rfs/test/internal/lux/service/run.lux rename to backup/l3vpn_qinq_pe_rfs/test/internal/lux/service/run.lux diff --git a/l3vpn_qinq_sw_rfs/README b/backup/l3vpn_qinq_sw_rfs/README similarity index 100% rename from l3vpn_qinq_sw_rfs/README rename to backup/l3vpn_qinq_sw_rfs/README diff --git a/l3vpn_qinq_sw_rfs/package-meta-data.xml b/backup/l3vpn_qinq_sw_rfs/package-meta-data.xml similarity index 100% rename from l3vpn_qinq_sw_rfs/package-meta-data.xml rename to backup/l3vpn_qinq_sw_rfs/package-meta-data.xml diff --git a/l3vpn_qinq_sw_rfs/python/l3vpn_qinq_sw_rfs/__init__.py b/backup/l3vpn_qinq_sw_rfs/python/l3vpn_qinq_sw_rfs/__init__.py similarity index 100% rename from l3vpn_qinq_sw_rfs/python/l3vpn_qinq_sw_rfs/__init__.py rename to backup/l3vpn_qinq_sw_rfs/python/l3vpn_qinq_sw_rfs/__init__.py diff --git a/l3vpn_qinq_sw_rfs/python/l3vpn_qinq_sw_rfs/main.py b/backup/l3vpn_qinq_sw_rfs/python/l3vpn_qinq_sw_rfs/main.py similarity index 100% rename from l3vpn_qinq_sw_rfs/python/l3vpn_qinq_sw_rfs/main.py rename to backup/l3vpn_qinq_sw_rfs/python/l3vpn_qinq_sw_rfs/main.py diff --git a/l3vpn_qinq_sw_rfs/src/Makefile b/backup/l3vpn_qinq_sw_rfs/src/Makefile similarity index 100% rename from l3vpn_qinq_sw_rfs/src/Makefile rename to backup/l3vpn_qinq_sw_rfs/src/Makefile diff --git a/l3vpn_qinq_sw_rfs/src/yang/l3vpn_qinq_sw_rfs.yang b/backup/l3vpn_qinq_sw_rfs/src/yang/l3vpn_qinq_sw_rfs.yang similarity index 100% rename from l3vpn_qinq_sw_rfs/src/yang/l3vpn_qinq_sw_rfs.yang rename to backup/l3vpn_qinq_sw_rfs/src/yang/l3vpn_qinq_sw_rfs.yang diff --git a/l3vpn_qinq_sw_rfs/templates/l3vpn_qinq_sw_rfs-template.xml b/backup/l3vpn_qinq_sw_rfs/templates/l3vpn_qinq_sw_rfs-template.xml similarity index 100% rename from l3vpn_qinq_sw_rfs/templates/l3vpn_qinq_sw_rfs-template.xml rename to backup/l3vpn_qinq_sw_rfs/templates/l3vpn_qinq_sw_rfs-template.xml diff --git a/l3vpn_qinq_sw_rfs/test/Makefile b/backup/l3vpn_qinq_sw_rfs/test/Makefile similarity index 100% rename from l3vpn_qinq_sw_rfs/test/Makefile rename to backup/l3vpn_qinq_sw_rfs/test/Makefile diff --git a/l3vpn_qinq_sw_rfs/test/internal/Makefile b/backup/l3vpn_qinq_sw_rfs/test/internal/Makefile similarity index 100% rename from l3vpn_qinq_sw_rfs/test/internal/Makefile rename to backup/l3vpn_qinq_sw_rfs/test/internal/Makefile diff --git a/l3vpn_qinq_sw_rfs/test/internal/lux/Makefile b/backup/l3vpn_qinq_sw_rfs/test/internal/lux/Makefile similarity index 100% rename from l3vpn_qinq_sw_rfs/test/internal/lux/Makefile rename to backup/l3vpn_qinq_sw_rfs/test/internal/lux/Makefile diff --git a/l3vpn_qinq_sw_rfs/test/internal/lux/service/Makefile b/backup/l3vpn_qinq_sw_rfs/test/internal/lux/service/Makefile similarity index 100% rename from l3vpn_qinq_sw_rfs/test/internal/lux/service/Makefile rename to backup/l3vpn_qinq_sw_rfs/test/internal/lux/service/Makefile diff --git a/l3vpn_qinq_sw_rfs/test/internal/lux/service/dummy-device.xml b/backup/l3vpn_qinq_sw_rfs/test/internal/lux/service/dummy-device.xml similarity index 100% rename from l3vpn_qinq_sw_rfs/test/internal/lux/service/dummy-device.xml rename to backup/l3vpn_qinq_sw_rfs/test/internal/lux/service/dummy-device.xml diff --git a/l3vpn_qinq_sw_rfs/test/internal/lux/service/dummy-service.xml b/backup/l3vpn_qinq_sw_rfs/test/internal/lux/service/dummy-service.xml similarity index 100% rename from l3vpn_qinq_sw_rfs/test/internal/lux/service/dummy-service.xml rename to backup/l3vpn_qinq_sw_rfs/test/internal/lux/service/dummy-service.xml diff --git a/l3vpn_qinq_sw_rfs/test/internal/lux/service/pyvm.xml b/backup/l3vpn_qinq_sw_rfs/test/internal/lux/service/pyvm.xml similarity index 100% rename from l3vpn_qinq_sw_rfs/test/internal/lux/service/pyvm.xml rename to backup/l3vpn_qinq_sw_rfs/test/internal/lux/service/pyvm.xml diff --git a/l3vpn_qinq_sw_rfs/test/internal/lux/service/run.lux b/backup/l3vpn_qinq_sw_rfs/test/internal/lux/service/run.lux similarity index 100% rename from l3vpn_qinq_sw_rfs/test/internal/lux/service/run.lux rename to backup/l3vpn_qinq_sw_rfs/test/internal/lux/service/run.lux diff --git a/l2vpn_cfs/README b/l2vpn_cfs/README new file mode 100644 index 0000000..e9b9de3 --- /dev/null +++ b/l2vpn_cfs/README @@ -0,0 +1,23 @@ +This is a generated Python package, made by: + + ncs-make-package --service-skeleton python-and-template \ + --component-class main.Main l2vpn_cfs + +It contains a dummy YANG model which implements a minimal Service +and an Action that doesn't really do anything useful. They are +there just to get you going. + +You will also find two test cases in: + + test/internal/lux/service/ + test/internal/lux/action/ + +that you can run if you have the 'lux' testing tool. +Your top Makefile also need to implement some Make targets +as described in the Makefiles of the test cases. +You can also just read the corresponding run.lux tests and +do them manually if you wish. + +The 'lux' test tool can be obtained from: + + https://github.com/hawk/lux.git diff --git a/l2vpn_cfs/load-dir/l2vpn_cfs.fxs b/l2vpn_cfs/load-dir/l2vpn_cfs.fxs new file mode 100644 index 0000000000000000000000000000000000000000..e10b2bff4c5098d9ecf33a59a585b8bcb472a5d3 GIT binary patch literal 13616 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 + l2vpn_cfs + 1.0 + Generated Python package + 6.2 + + + main + + l2vpn_cfs.main.Main + + + diff --git a/l2vpn_cfs/python/l2vpn_cfs/__init__.py b/l2vpn_cfs/python/l2vpn_cfs/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/l2vpn_cfs/python/l2vpn_cfs/main.py b/l2vpn_cfs/python/l2vpn_cfs/main.py new file mode 100644 index 0000000..91f8336 --- /dev/null +++ b/l2vpn_cfs/python/l2vpn_cfs/main.py @@ -0,0 +1,109 @@ +# -*- mode: python; python-indent: 4 -*- +import ncs +from ncs.application import Service +import requests + +class ServiceCallbacks(Service): + + @Service.create + def cb_create(self, tctx, root, service, proplist): + self.log.info('Service create(service=', service._path, ')') + + headers = {"Authorization":"Token e657404c0e1f57481ad0a06c293e8fe794e720ac", "Accept": "application/json", "Content-Type": "application/json"} + body = {} + + vars = ncs.template.Variables() + template = ncs.template.Template(service) + + for endpoint in service.endpoint: + + # Get an Outer VLAN from Netbox. The VLAN group for outer VLAN's is #2. + api_url="https://10.101.180.45/api/ipam/vlan-groups/2/available-vlans/" + ovlan_name = "L2VPN-Outer-VLAN-"+str(endpoint.pe_device)+"-"+str(endpoint.id) + body = {"name": ovlan_name} + try: + response=requests.post(api_url, headers=headers, json=body, verify=False) + self.log.info('Netbox response, Outer VLAN reservation: ', response.json()) + ovlan_id = response.json()["vid"] + self.log.info('VLAN from Netbox: ', ovlan_id) + except: + if endpoint.ovlan: + ovlan_id = endpoint.ovlan + else: + ovlan_id = 254 + self.log.info('Connection to Netbox failed. Statically allocated Outer VLAN: ', ovlan_id) + vars.add('ovlan', ovlan_id) + + # Get an Inner VLAN from Netbox. The VLAN group for inner VLAN's is #3. + api_url="https://10.101.180.45/api/ipam/vlan-groups/3/available-vlans/" + ivlan_name = "L2VPN-Inner-VLAN-"+str(endpoint.pe_device)+"-"+str(endpoint.id) + body = {"name": ivlan_name} + try: + response=requests.post(api_url, headers=headers, json=body, verify=False) + self.log.info('Netbox response, Inner VLAN reservation: ', response.json()) + ivlan_id = response.json()["vid"] + self.log.info('VLAN from Netbox: ', ivlan_id) + except: + if endpoint.ivlan: + ivlan_id = endpoint.ivlan + else: + ivlan_id = 253 + self.log.info('Connection to Netbox failed. Statically allocated Inner VLAN: ', ivlan_id) + vars.add('ivlan', ivlan_id) + + # PE part + name = "L2VPN-"+str(endpoint.pe_device)+"-"+str(endpoint.id) + vars.add('name', name) + self.log.info('Name for PE instance: ', name) + vars.add('pe_device', endpoint.pe_device) + vars.add('bridge_group_name', str(endpoint.id)) + # PE to Switch interface configuration: + vars.add('pe_interface_name', endpoint.pe_interface.interface_name) + vars.add('pe_interface_number', endpoint.pe_interface.interface_number) + pe_interface_description = "L2VPN interface to " + str(endpoint.sw_device) + ", interface " + str(endpoint.sw_pe_interface.interface_name) + str(endpoint.sw_pe_interface.interface_number) + vars.add('pe_interface_description', pe_interface_description) + self.log.info('pe_interface_description: ', pe_interface_description) + template.apply('l2vpn_pe-template', vars) + + # Switch part + name = "L2VPN-"+str(endpoint.sw_device)+"-"+str(endpoint.id) + vars.add('name', name) + self.log.info('Name for Switch instance: ', name) + vars.add('sw_device', endpoint.sw_device) + vars.add('vlan_name', str(endpoint.id)) + # Switch to PE interface configuration: + vars.add('sw_pe_interface_name', endpoint.sw_pe_interface.interface_name) + vars.add('sw_pe_interface_number', endpoint.sw_pe_interface.interface_number) + sw_pe_interface_description = "L2VPN interface to " + str(endpoint.pe_device) + ", interface " + str(endpoint.pe_interface.interface_name) + str(endpoint.pe_interface.interface_number) + vars.add('sw_pe_interface_description', sw_pe_interface_description) + self.log.info('sw_pe_interface_description: ', sw_pe_interface_description) + # Switch to CPE interface configuration: + vars.add('sw_cpe_interface_name', endpoint.sw_cpe_interface.interface_name) + vars.add('sw_cpe_interface_number', endpoint.sw_cpe_interface.interface_number) + sw_cpe_interface_description = "L2VPN interface to " + str(endpoint.cpe_device) + ", interface " + str(endpoint.cpe_interface.interface_name) + str(endpoint.cpe_interface.interface_number) + vars.add('sw_cpe_interface_description', sw_cpe_interface_description) + self.log.info('sw_cpe_interface_description: ', sw_cpe_interface_description) + template.apply('l2vpn_sw-template', vars) + + # CPE part + name = "L2VPN-"+str(endpoint.cpe_device)+"-"+str(endpoint.id) + vars.add('name', name) + self.log.info('Name for CPE instance: ', name) + vars.add('cpe_device', endpoint.cpe_device) + vars.add('vlan_name', str(endpoint.id)) + # CPE to Switch interface configuration: + vars.add('cpe_interface_name', endpoint.cpe_interface.interface_name) + vars.add('cpe_interface_number', endpoint.cpe_interface.interface_number) + cpe_interface_description = "L2VPN interface to " + str(endpoint.sw_device) + ", interface " + str(endpoint.sw_cpe_interface.interface_name) + str(endpoint.sw_cpe_interface.interface_number) + vars.add('cpe_interface_description', cpe_interface_description) + self.log.info('cpe_interface_description: ', cpe_interface_description) + template.apply('l2vpn_cpe-template', vars) + + +class Main(ncs.application.Application): + def setup(self): + self.log.info('Main RUNNING') + self.register_service('l2vpn_cfs-servicepoint', ServiceCallbacks) + + def teardown(self): + self.log.info('Main FINISHED') diff --git a/l2vpn_cfs/src/Makefile b/l2vpn_cfs/src/Makefile new file mode 100644 index 0000000..3a0f88c --- /dev/null +++ b/l2vpn_cfs/src/Makefile @@ -0,0 +1,32 @@ +all: fxs +.PHONY: all + +# Include standard NCS examples build definitions and rules +include $(NCS_DIR)/src/ncs/build/include.ncs.mk + +SRC = $(wildcard yang/*.yang) +DIRS = ../load-dir +FXS = $(SRC:yang/%.yang=../load-dir/%.fxs) + +## Uncomment and patch the line below if you have a dependency to a NED +## or to other YANG files +# YANGPATH += ../..//src/ncsc-out/modules/yang \ +# ../..//src/yang + +NCSCPATH = $(YANGPATH:%=--yangpath %) +YANGERPATH = $(YANGPATH:%=--path %) + +fxs: $(DIRS) $(FXS) + +$(DIRS): + mkdir -p $@ + +../load-dir/%.fxs: yang/%.yang + $(NCSC) `ls $*-ann.yang > /dev/null 2>&1 && echo "-a $*-ann.yang"` \ + --fail-on-warnings \ + $(NCSCPATH) \ + -c -o $@ $< + +clean: + rm -rf $(DIRS) +.PHONY: clean diff --git a/l2vpn_cfs/src/yang/l2vpn_cfs.yang b/l2vpn_cfs/src/yang/l2vpn_cfs.yang new file mode 100644 index 0000000..eacc461 --- /dev/null +++ b/l2vpn_cfs/src/yang/l2vpn_cfs.yang @@ -0,0 +1,120 @@ +module l2vpn_cfs { + + namespace "http://example.com/l2vpn_cfs"; + prefix l2vpn_cfs; + + import ietf-inet-types { + prefix inet; + } + import tailf-common { + prefix tailf; + } + import tailf-ncs { + prefix ncs; + } + + description + "CFS, L2VPN service with QinQ in the switched network between PE and CPE"; + + revision 2024-07-11 { + description + "Initial revision."; + } + + grouping interface_grouping { + leaf interface_name { + tailf:info "Interface name. For example TenGigE."; + type enumeration { + enum FastEthernet; + enum GigabitEthernet; + enum TenGigE; + enum TwentyFiveGigE; + enum FortyGigE; + enum FiftyGigE; + enum HundredGigE; + enum TwoHundredGigE; + enum FourHundredGigE; + enum EightHundredGigE; + enum xe; + } + } + leaf interface_number { + tailf:info "Interface number. For example 0 or 1/0"; + type string { + pattern "[0-9]{1,2}(/[0-9]{1,2}){1,4}"; + } + } + leaf interface_description { + tailf:info "Interface description."; + type string; + } + } + + list l2vpn_cfs { + description "This is an RFS skeleton service"; + + key name; + leaf name { + tailf:info "Unique service id"; + tailf:cli-allow-range; + type string; + } + + uses ncs:service-data; + ncs:servicepoint l2vpn_cfs-servicepoint; + + list endpoint { + key id; + leaf id { + tailf:info "Endpoint identifier. It should contain the id of the CPE."; + type string; + } + + leaf pe_device { + type leafref { + path "/ncs:devices/ncs:device/ncs:name"; + } + } + + leaf sw_device { + type leafref { + path "/ncs:devices/ncs:device/ncs:name"; + } + } + + leaf cpe_device { + type leafref { + path "/ncs:devices/ncs:device/ncs:name"; + } + } + + container pe_interface { + uses interface_grouping; + } + + container sw_pe_interface { + uses interface_grouping; + } + + container sw_cpe_interface { + uses interface_grouping; + } + + container cpe_interface { + uses interface_grouping; + } + + leaf ovlan { + tailf:info "Outer VLAN eg 10"; + type uint16; + default 50; + } + + leaf ivlan { + tailf:info "Inner VLAN eg 20"; + type uint16; + default 30; + } + } + } +} diff --git a/l2vpn_cfs/templates/l2vpn_cpe-template.xml b/l2vpn_cfs/templates/l2vpn_cpe-template.xml new file mode 100644 index 0000000..d8e34bc --- /dev/null +++ b/l2vpn_cfs/templates/l2vpn_cpe-template.xml @@ -0,0 +1,13 @@ + + + {$name} + {$cpe_device} + {$ovlan} + {$ivlan} + + {$cpe_interface_name} + {$cpe_interface_number} + {$cpe_interface_description} + + + diff --git a/l2vpn_cfs/templates/l2vpn_pe-template.xml b/l2vpn_cfs/templates/l2vpn_pe-template.xml new file mode 100644 index 0000000..a7cc56c --- /dev/null +++ b/l2vpn_cfs/templates/l2vpn_pe-template.xml @@ -0,0 +1,14 @@ + + + {$name} + {$pe_device} + {$ovlan} + {$ivlan} + {$bridge_group_name} + + {$pe_interface_name} + {$pe_interface_number} + {$pe_interface_description} + + + diff --git a/l2vpn_cfs/templates/l2vpn_sw-template.xml b/l2vpn_cfs/templates/l2vpn_sw-template.xml new file mode 100644 index 0000000..4cda32b --- /dev/null +++ b/l2vpn_cfs/templates/l2vpn_sw-template.xml @@ -0,0 +1,19 @@ + + + {$name} + {$sw_device} + {$ovlan} + {$ivlan} + {$vlan_name} + + {$sw_pe_interface_name} + {$sw_pe_interface_number} + {$sw_pe_interface_description} + + + {$sw_cpe_interface_name} + {$sw_cpe_interface_number} + {$sw_cpe_interface_description} + + + diff --git a/l2vpn_cfs/test/Makefile b/l2vpn_cfs/test/Makefile new file mode 100644 index 0000000..32f02d6 --- /dev/null +++ b/l2vpn_cfs/test/Makefile @@ -0,0 +1,37 @@ +DIRS = external internal + +ifeq ($(BUILD_JOB),external) +DIR = external +endif + +ifeq ($(BUILD_JOB),internal_realhw) +DIR = internal +JOB_DIR = realhw +endif + +ifeq ($(BUILD_JOB),internal_simulated) +DIR = internal +JOB_DIR = simulated +endif + +ifeq ($(BUILD_JOB),) +DIR = internal +JOB_DIR = simulated +endif + +all: test + +build: + $(MAKE) -C $(DIR) build JOB_DIR=$(JOB_DIR) || exit 1 + +clean: + $(MAKE) -C $(DIR) clean JOB_DIR=$(JOB_DIR) || exit 1 + +test: + $(MAKE) -C $(DIR) test JOB_DIR=$(JOB_DIR) || exit 1 + +desc: + @echo "==Test Cases for NED==" + @for d in $(DIRS) ; do \ + $(MAKE) -sC $$d desc || exit 1; \ + done diff --git a/l2vpn_cfs/test/internal/Makefile b/l2vpn_cfs/test/internal/Makefile new file mode 100644 index 0000000..982aa57 --- /dev/null +++ b/l2vpn_cfs/test/internal/Makefile @@ -0,0 +1,21 @@ +DIRS = lux + +build: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d build || exit 1; \ + done + +clean: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d clean || exit 1; \ + done + +test: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d test || exit 1; \ + done + +desc: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d desc || exit 1; \ + done diff --git a/l2vpn_cfs/test/internal/lux/Makefile b/l2vpn_cfs/test/internal/lux/Makefile new file mode 100644 index 0000000..2558f02 --- /dev/null +++ b/l2vpn_cfs/test/internal/lux/Makefile @@ -0,0 +1,21 @@ +DIRS = service + +build: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d build || exit 1; \ + done + +clean: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d clean || exit 1; \ + done + +test: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d test || exit 1; \ + done + +desc: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d desc || exit 1; \ + done diff --git a/l2vpn_cfs/test/internal/lux/service/Makefile b/l2vpn_cfs/test/internal/lux/service/Makefile new file mode 100644 index 0000000..d2dc5be --- /dev/null +++ b/l2vpn_cfs/test/internal/lux/service/Makefile @@ -0,0 +1,26 @@ +# +# The 'lux' test tool can be obtained from: +# +# https://github.com/hawk/lux.git +# + +# Make sure the TARGET_DIR has got the following make targets: +.PHONY: clean build start stop + +export TARGET_DIR=../../../../../.. + +.PHONY: test +test: + lux run.lux + +clean: + $(MAKE) -C $(TARGET_DIR) clean + +build: + $(MAKE) -C $(TARGET_DIR) build + +start: + $(MAKE) -C $(TARGET_DIR) start + +stop: + $(MAKE) -C $(TARGET_DIR) stop diff --git a/l2vpn_cfs/test/internal/lux/service/dummy-device.xml b/l2vpn_cfs/test/internal/lux/service/dummy-device.xml new file mode 100644 index 0000000..df09281 --- /dev/null +++ b/l2vpn_cfs/test/internal/lux/service/dummy-device.xml @@ -0,0 +1,11 @@ + + + + eth +

192.168.110.1
+ + southbound-locked + + + + diff --git a/l2vpn_cfs/test/internal/lux/service/dummy-service.xml b/l2vpn_cfs/test/internal/lux/service/dummy-service.xml new file mode 100644 index 0000000..5df16cb --- /dev/null +++ b/l2vpn_cfs/test/internal/lux/service/dummy-service.xml @@ -0,0 +1,12 @@ + + + + true + + + + 33 + eth + 127.0.0.1 + + diff --git a/l2vpn_cfs/test/internal/lux/service/pyvm.xml b/l2vpn_cfs/test/internal/lux/service/pyvm.xml new file mode 100644 index 0000000..531521c --- /dev/null +++ b/l2vpn_cfs/test/internal/lux/service/pyvm.xml @@ -0,0 +1,8 @@ + + + + ./logs/ncs-python-vm + level-info + + + diff --git a/l2vpn_cfs/test/internal/lux/service/run.lux b/l2vpn_cfs/test/internal/lux/service/run.lux new file mode 100644 index 0000000..2df3bd0 --- /dev/null +++ b/l2vpn_cfs/test/internal/lux/service/run.lux @@ -0,0 +1,53 @@ +# +# The 'lux' test tool can be obtained from: +# +# https://github.com/hawk/lux.git +# +[global target_dir=../../../../../..] +[config skip_unless=PYTHON] + +[shell top] + !make stop build + !echo ==$$?== + ?==0== + ?SH-PROMPT: + + !rm ${target_dir}/ncs-cdb/* + ?SH-PROMPT: + !cp pyvm.xml ${target_dir}/ncs-cdb/. + ?SH-PROMPT: + + !make start + !echo ==$$?== + ?==0== + ?SH-PROMPT: + + [progress \nCreate a dummy device...\n] + !ncs_load -lm dummy-device.xml + ?SH-PROMPT: + [progress \nCreate a dummy device...ok\n] + + [sleep 3] + + [progress \nCreate the dummy service...\n] + !ncs_load -lm dummy-service.xml + ?SH-PROMPT: + [progress \nCreate the dummy service...ok\n] + + +[shell log] + !cd ${target_dir} + ?SH-PROMPT: + + [progress \nVerify that the service code has been invoked...\n] + !tail -f ./logs/ncs-python-vm-l2vpn_cfs.log + ?.*Worker RUNNING.* + ?.*Service create.* + [progress \nVerify that the service code has been invoked...ok\n] + + +[cleanup] + !make stop + !echo ==$$?== + ?==0== + ?SH-PROMPT: diff --git a/l2vpn_cpe_rfs/README b/l2vpn_cpe_rfs/README new file mode 100644 index 0000000..eb40d6b --- /dev/null +++ b/l2vpn_cpe_rfs/README @@ -0,0 +1,23 @@ +This is a generated Python package, made by: + + ncs-make-package --service-skeleton python-and-template \ + --component-class main.Main l2vpn_cpe_rfs + +It contains a dummy YANG model which implements a minimal Service +and an Action that doesn't really do anything useful. They are +there just to get you going. + +You will also find two test cases in: + + test/internal/lux/service/ + test/internal/lux/action/ + +that you can run if you have the 'lux' testing tool. +Your top Makefile also need to implement some Make targets +as described in the Makefiles of the test cases. +You can also just read the corresponding run.lux tests and +do them manually if you wish. + +The 'lux' test tool can be obtained from: + + https://github.com/hawk/lux.git diff --git a/l2vpn_cpe_rfs/load-dir/l2vpn_cpe_rfs.fxs b/l2vpn_cpe_rfs/load-dir/l2vpn_cpe_rfs.fxs new file mode 100644 index 0000000000000000000000000000000000000000..e767c1f079bc3b7ed878a9cbe788fa08ea48cd0d GIT binary patch literal 13164 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 literal 0 HcmV?d00001 diff --git a/l2vpn_cpe_rfs/package-meta-data.xml b/l2vpn_cpe_rfs/package-meta-data.xml new file mode 100644 index 0000000..79f1364 --- /dev/null +++ b/l2vpn_cpe_rfs/package-meta-data.xml @@ -0,0 +1,13 @@ + + l2vpn_cpe_rfs + 1.0 + Generated Python package + 6.2 + + + main + + l2vpn_cpe_rfs.main.Main + + + diff --git a/l2vpn_cpe_rfs/python/l2vpn_cpe_rfs/__init__.py b/l2vpn_cpe_rfs/python/l2vpn_cpe_rfs/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/l2vpn_cpe_rfs/python/l2vpn_cpe_rfs/main.py b/l2vpn_cpe_rfs/python/l2vpn_cpe_rfs/main.py new file mode 100644 index 0000000..bd85477 --- /dev/null +++ b/l2vpn_cpe_rfs/python/l2vpn_cpe_rfs/main.py @@ -0,0 +1,65 @@ +# -*- mode: python; python-indent: 4 -*- +import ncs +from ncs.application import Service + + +# ------------------------ +# SERVICE CALLBACK EXAMPLE +# ------------------------ +class ServiceCallbacks(Service): + + # The create() callback is invoked inside NCS FASTMAP and + # must always exist. + @Service.create + def cb_create(self, tctx, root, service, proplist): + self.log.info('Service create(service=', service._path, ')') + + vars = ncs.template.Variables() + vars.add('DUMMY', '127.0.0.1') + template = ncs.template.Template(service) + template.apply('l2vpn_cpe_rfs-template', vars) + + # The pre_modification() and post_modification() callbacks are optional, + # and are invoked outside FASTMAP. pre_modification() is invoked before + # create, update, or delete of the service, as indicated by the enum + # ncs_service_operation op parameter. Conversely + # post_modification() is invoked after create, update, or delete + # of the service. These functions can be useful e.g. for + # allocations that should be stored and existing also when the + # service instance is removed. + + # @Service.pre_modification + # def cb_pre_modification(self, tctx, op, kp, root, proplist): + # self.log.info('Service premod(service=', kp, ')') + + # @Service.post_modification + # def cb_post_modification(self, tctx, op, kp, root, proplist): + # self.log.info('Service postmod(service=', kp, ')') + + +# --------------------------------------------- +# COMPONENT THREAD THAT WILL BE STARTED BY NCS. +# --------------------------------------------- +class Main(ncs.application.Application): + def setup(self): + # The application class sets up logging for us. It is accessible + # through 'self.log' and is a ncs.log.Log instance. + self.log.info('Main RUNNING') + + # Service callbacks require a registration for a 'service point', + # as specified in the corresponding data model. + # + self.register_service('l2vpn_cpe_rfs-servicepoint', ServiceCallbacks) + + # If we registered any callback(s) above, the Application class + # took care of creating a daemon (related to the service/action point). + + # When this setup method is finished, all registrations are + # considered done and the application is 'started'. + + def teardown(self): + # When the application is finished (which would happen if NCS went + # down, packages were reloaded or some error occurred) this teardown + # method will be called. + + self.log.info('Main FINISHED') diff --git a/l2vpn_cpe_rfs/src/Makefile b/l2vpn_cpe_rfs/src/Makefile new file mode 100644 index 0000000..3a0f88c --- /dev/null +++ b/l2vpn_cpe_rfs/src/Makefile @@ -0,0 +1,32 @@ +all: fxs +.PHONY: all + +# Include standard NCS examples build definitions and rules +include $(NCS_DIR)/src/ncs/build/include.ncs.mk + +SRC = $(wildcard yang/*.yang) +DIRS = ../load-dir +FXS = $(SRC:yang/%.yang=../load-dir/%.fxs) + +## Uncomment and patch the line below if you have a dependency to a NED +## or to other YANG files +# YANGPATH += ../..//src/ncsc-out/modules/yang \ +# ../..//src/yang + +NCSCPATH = $(YANGPATH:%=--yangpath %) +YANGERPATH = $(YANGPATH:%=--path %) + +fxs: $(DIRS) $(FXS) + +$(DIRS): + mkdir -p $@ + +../load-dir/%.fxs: yang/%.yang + $(NCSC) `ls $*-ann.yang > /dev/null 2>&1 && echo "-a $*-ann.yang"` \ + --fail-on-warnings \ + $(NCSCPATH) \ + -c -o $@ $< + +clean: + rm -rf $(DIRS) +.PHONY: clean diff --git a/l2vpn_cpe_rfs/src/yang/l2vpn_cpe_rfs.yang b/l2vpn_cpe_rfs/src/yang/l2vpn_cpe_rfs.yang new file mode 100644 index 0000000..61bc614 --- /dev/null +++ b/l2vpn_cpe_rfs/src/yang/l2vpn_cpe_rfs.yang @@ -0,0 +1,89 @@ +module l2vpn_cpe_rfs { + + namespace "http://example.com/l2vpn_cpe_rfs"; + prefix l2vpn_cpe_rfs; + + import ietf-inet-types { + prefix inet; + } + import tailf-common { + prefix tailf; + } + import tailf-ncs { + prefix ncs; + } + + description + "The CPE part of the L2VPN service with QinQ in the switched network between PE and CPE"; + + revision 2024-07-10 { + description + "Initial revision."; + } + + grouping interface_grouping { + leaf interface_name { + tailf:info "Interface name. For example TenGigE."; + type enumeration { + enum FastEthernet; + enum GigabitEthernet; + enum TenGigE; + enum TwentyFiveGigE; + enum FortyGigE; + enum FiftyGigE; + enum HundredGigE; + enum TwoHundredGigE; + enum FourHundredGigE; + enum EightHundredGigE; + enum xe; + } + } + leaf interface_number { + tailf:info "Interface number. For example 0 or 1/0"; + type string { + pattern "[0-9]{1,2}(/[0-9]{1,2}){1,4}"; + } + } + leaf interface_description { + tailf:info "Interface description."; + type string; + } + } + + list l2vpn_cpe_rfs { + description "This is an RFS skeleton service"; + + key name; + leaf name { + tailf:info "Unique service id"; + tailf:cli-allow-range; + type string; + } + + uses ncs:service-data; + ncs:servicepoint l2vpn_cpe_rfs-servicepoint; + + leaf device { + tailf:info "The CPE device"; + type leafref { + path "/ncs:devices/ncs:device/ncs:name"; + } + } + + leaf ovlan { + tailf:info "Outer VLAN eg 10"; + type uint16; + mandatory true; + } + + leaf ivlan { + tailf:info "Inner VLAN eg 20"; + type uint16; + mandatory true; + } + + container interface { + uses interface_grouping; + } + } +} diff --git a/l2vpn_cpe_rfs/templates/l2vpn_cpe_rfs-template.xml b/l2vpn_cpe_rfs/templates/l2vpn_cpe_rfs-template.xml new file mode 100644 index 0000000..07e5f65 --- /dev/null +++ b/l2vpn_cpe_rfs/templates/l2vpn_cpe_rfs-template.xml @@ -0,0 +1,81 @@ + + + + {/device} + + + + + {/interface/interface_number} + {/interface/interface_description} + + + {/ovlan} + + + + {/ovlan} + {/ivlan} + + + + + + 2 + symmetric + + + + + {/ivlan} + + + + + + + + {/interface/interface_number} + {/interface/interface_description} + + + {/ovlan} + + + + {/ovlan} + {/ivlan} + + + + + + 2 + symmetric + + + + + {/ivlan} + + + + + + + + {/ivlan} + +
+ +
{/ovlan}.{/ovlan}.{/ovlan}.2
+ 255.255.255.0 +
+
+
+
+
+
+
+
+
diff --git a/l2vpn_cpe_rfs/test/Makefile b/l2vpn_cpe_rfs/test/Makefile new file mode 100644 index 0000000..32f02d6 --- /dev/null +++ b/l2vpn_cpe_rfs/test/Makefile @@ -0,0 +1,37 @@ +DIRS = external internal + +ifeq ($(BUILD_JOB),external) +DIR = external +endif + +ifeq ($(BUILD_JOB),internal_realhw) +DIR = internal +JOB_DIR = realhw +endif + +ifeq ($(BUILD_JOB),internal_simulated) +DIR = internal +JOB_DIR = simulated +endif + +ifeq ($(BUILD_JOB),) +DIR = internal +JOB_DIR = simulated +endif + +all: test + +build: + $(MAKE) -C $(DIR) build JOB_DIR=$(JOB_DIR) || exit 1 + +clean: + $(MAKE) -C $(DIR) clean JOB_DIR=$(JOB_DIR) || exit 1 + +test: + $(MAKE) -C $(DIR) test JOB_DIR=$(JOB_DIR) || exit 1 + +desc: + @echo "==Test Cases for NED==" + @for d in $(DIRS) ; do \ + $(MAKE) -sC $$d desc || exit 1; \ + done diff --git a/l2vpn_cpe_rfs/test/internal/Makefile b/l2vpn_cpe_rfs/test/internal/Makefile new file mode 100644 index 0000000..982aa57 --- /dev/null +++ b/l2vpn_cpe_rfs/test/internal/Makefile @@ -0,0 +1,21 @@ +DIRS = lux + +build: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d build || exit 1; \ + done + +clean: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d clean || exit 1; \ + done + +test: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d test || exit 1; \ + done + +desc: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d desc || exit 1; \ + done diff --git a/l2vpn_cpe_rfs/test/internal/lux/Makefile b/l2vpn_cpe_rfs/test/internal/lux/Makefile new file mode 100644 index 0000000..2558f02 --- /dev/null +++ b/l2vpn_cpe_rfs/test/internal/lux/Makefile @@ -0,0 +1,21 @@ +DIRS = service + +build: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d build || exit 1; \ + done + +clean: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d clean || exit 1; \ + done + +test: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d test || exit 1; \ + done + +desc: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d desc || exit 1; \ + done diff --git a/l2vpn_cpe_rfs/test/internal/lux/service/Makefile b/l2vpn_cpe_rfs/test/internal/lux/service/Makefile new file mode 100644 index 0000000..d2dc5be --- /dev/null +++ b/l2vpn_cpe_rfs/test/internal/lux/service/Makefile @@ -0,0 +1,26 @@ +# +# The 'lux' test tool can be obtained from: +# +# https://github.com/hawk/lux.git +# + +# Make sure the TARGET_DIR has got the following make targets: +.PHONY: clean build start stop + +export TARGET_DIR=../../../../../.. + +.PHONY: test +test: + lux run.lux + +clean: + $(MAKE) -C $(TARGET_DIR) clean + +build: + $(MAKE) -C $(TARGET_DIR) build + +start: + $(MAKE) -C $(TARGET_DIR) start + +stop: + $(MAKE) -C $(TARGET_DIR) stop diff --git a/l2vpn_cpe_rfs/test/internal/lux/service/dummy-device.xml b/l2vpn_cpe_rfs/test/internal/lux/service/dummy-device.xml new file mode 100644 index 0000000..df09281 --- /dev/null +++ b/l2vpn_cpe_rfs/test/internal/lux/service/dummy-device.xml @@ -0,0 +1,11 @@ + + + + eth +
192.168.110.1
+ + southbound-locked + +
+
+
diff --git a/l2vpn_cpe_rfs/test/internal/lux/service/dummy-service.xml b/l2vpn_cpe_rfs/test/internal/lux/service/dummy-service.xml new file mode 100644 index 0000000..92a928b --- /dev/null +++ b/l2vpn_cpe_rfs/test/internal/lux/service/dummy-service.xml @@ -0,0 +1,12 @@ + + + + true + + + + 33 + eth + 127.0.0.1 + + diff --git a/l2vpn_cpe_rfs/test/internal/lux/service/pyvm.xml b/l2vpn_cpe_rfs/test/internal/lux/service/pyvm.xml new file mode 100644 index 0000000..531521c --- /dev/null +++ b/l2vpn_cpe_rfs/test/internal/lux/service/pyvm.xml @@ -0,0 +1,8 @@ + + + + ./logs/ncs-python-vm + level-info + + + diff --git a/l2vpn_cpe_rfs/test/internal/lux/service/run.lux b/l2vpn_cpe_rfs/test/internal/lux/service/run.lux new file mode 100644 index 0000000..4fabfc7 --- /dev/null +++ b/l2vpn_cpe_rfs/test/internal/lux/service/run.lux @@ -0,0 +1,53 @@ +# +# The 'lux' test tool can be obtained from: +# +# https://github.com/hawk/lux.git +# +[global target_dir=../../../../../..] +[config skip_unless=PYTHON] + +[shell top] + !make stop build + !echo ==$$?== + ?==0== + ?SH-PROMPT: + + !rm ${target_dir}/ncs-cdb/* + ?SH-PROMPT: + !cp pyvm.xml ${target_dir}/ncs-cdb/. + ?SH-PROMPT: + + !make start + !echo ==$$?== + ?==0== + ?SH-PROMPT: + + [progress \nCreate a dummy device...\n] + !ncs_load -lm dummy-device.xml + ?SH-PROMPT: + [progress \nCreate a dummy device...ok\n] + + [sleep 3] + + [progress \nCreate the dummy service...\n] + !ncs_load -lm dummy-service.xml + ?SH-PROMPT: + [progress \nCreate the dummy service...ok\n] + + +[shell log] + !cd ${target_dir} + ?SH-PROMPT: + + [progress \nVerify that the service code has been invoked...\n] + !tail -f ./logs/ncs-python-vm-l2vpn_cpe_rfs.log + ?.*Worker RUNNING.* + ?.*Service create.* + [progress \nVerify that the service code has been invoked...ok\n] + + +[cleanup] + !make stop + !echo ==$$?== + ?==0== + ?SH-PROMPT: diff --git a/l2vpn_pe_rfs/README b/l2vpn_pe_rfs/README new file mode 100644 index 0000000..7fe80fb --- /dev/null +++ b/l2vpn_pe_rfs/README @@ -0,0 +1,23 @@ +This is a generated Python package, made by: + + ncs-make-package --service-skeleton python-and-template \ + --component-class main.Main l2vpn_pe_rfs + +It contains a dummy YANG model which implements a minimal Service +and an Action that doesn't really do anything useful. They are +there just to get you going. + +You will also find two test cases in: + + test/internal/lux/service/ + test/internal/lux/action/ + +that you can run if you have the 'lux' testing tool. +Your top Makefile also need to implement some Make targets +as described in the Makefiles of the test cases. +You can also just read the corresponding run.lux tests and +do them manually if you wish. + +The 'lux' test tool can be obtained from: + + https://github.com/hawk/lux.git diff --git a/l2vpn_pe_rfs/load-dir/l2vpn_pe_rfs.fxs b/l2vpn_pe_rfs/load-dir/l2vpn_pe_rfs.fxs new file mode 100644 index 0000000000000000000000000000000000000000..5c5ea1a96270000668040f4507d8f30fe38ff637 GIT binary patch literal 13252 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 + l2vpn_pe_rfs + 1.0 + Generated Python package + 6.2 + + + main + + l2vpn_pe_rfs.main.Main + + + diff --git a/l2vpn_pe_rfs/python/l2vpn_pe_rfs/__init__.py b/l2vpn_pe_rfs/python/l2vpn_pe_rfs/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/l2vpn_pe_rfs/python/l2vpn_pe_rfs/main.py b/l2vpn_pe_rfs/python/l2vpn_pe_rfs/main.py new file mode 100644 index 0000000..50e634f --- /dev/null +++ b/l2vpn_pe_rfs/python/l2vpn_pe_rfs/main.py @@ -0,0 +1,65 @@ +# -*- mode: python; python-indent: 4 -*- +import ncs +from ncs.application import Service + + +# ------------------------ +# SERVICE CALLBACK EXAMPLE +# ------------------------ +class ServiceCallbacks(Service): + + # The create() callback is invoked inside NCS FASTMAP and + # must always exist. + @Service.create + def cb_create(self, tctx, root, service, proplist): + self.log.info('Service create(service=', service._path, ')') + + vars = ncs.template.Variables() + vars.add('DUMMY', '127.0.0.1') + template = ncs.template.Template(service) + template.apply('l2vpn_pe_rfs-template', vars) + + # The pre_modification() and post_modification() callbacks are optional, + # and are invoked outside FASTMAP. pre_modification() is invoked before + # create, update, or delete of the service, as indicated by the enum + # ncs_service_operation op parameter. Conversely + # post_modification() is invoked after create, update, or delete + # of the service. These functions can be useful e.g. for + # allocations that should be stored and existing also when the + # service instance is removed. + + # @Service.pre_modification + # def cb_pre_modification(self, tctx, op, kp, root, proplist): + # self.log.info('Service premod(service=', kp, ')') + + # @Service.post_modification + # def cb_post_modification(self, tctx, op, kp, root, proplist): + # self.log.info('Service postmod(service=', kp, ')') + + +# --------------------------------------------- +# COMPONENT THREAD THAT WILL BE STARTED BY NCS. +# --------------------------------------------- +class Main(ncs.application.Application): + def setup(self): + # The application class sets up logging for us. It is accessible + # through 'self.log' and is a ncs.log.Log instance. + self.log.info('Main RUNNING') + + # Service callbacks require a registration for a 'service point', + # as specified in the corresponding data model. + # + self.register_service('l2vpn_pe_rfs-servicepoint', ServiceCallbacks) + + # If we registered any callback(s) above, the Application class + # took care of creating a daemon (related to the service/action point). + + # When this setup method is finished, all registrations are + # considered done and the application is 'started'. + + def teardown(self): + # When the application is finished (which would happen if NCS went + # down, packages were reloaded or some error occurred) this teardown + # method will be called. + + self.log.info('Main FINISHED') diff --git a/l2vpn_pe_rfs/src/Makefile b/l2vpn_pe_rfs/src/Makefile new file mode 100644 index 0000000..3a0f88c --- /dev/null +++ b/l2vpn_pe_rfs/src/Makefile @@ -0,0 +1,32 @@ +all: fxs +.PHONY: all + +# Include standard NCS examples build definitions and rules +include $(NCS_DIR)/src/ncs/build/include.ncs.mk + +SRC = $(wildcard yang/*.yang) +DIRS = ../load-dir +FXS = $(SRC:yang/%.yang=../load-dir/%.fxs) + +## Uncomment and patch the line below if you have a dependency to a NED +## or to other YANG files +# YANGPATH += ../..//src/ncsc-out/modules/yang \ +# ../..//src/yang + +NCSCPATH = $(YANGPATH:%=--yangpath %) +YANGERPATH = $(YANGPATH:%=--path %) + +fxs: $(DIRS) $(FXS) + +$(DIRS): + mkdir -p $@ + +../load-dir/%.fxs: yang/%.yang + $(NCSC) `ls $*-ann.yang > /dev/null 2>&1 && echo "-a $*-ann.yang"` \ + --fail-on-warnings \ + $(NCSCPATH) \ + -c -o $@ $< + +clean: + rm -rf $(DIRS) +.PHONY: clean diff --git a/l2vpn_pe_rfs/src/yang/l2vpn_pe_rfs.yang b/l2vpn_pe_rfs/src/yang/l2vpn_pe_rfs.yang new file mode 100644 index 0000000..f01fa3e --- /dev/null +++ b/l2vpn_pe_rfs/src/yang/l2vpn_pe_rfs.yang @@ -0,0 +1,94 @@ +module l2vpn_pe_rfs { + + namespace "http://example.com/l2vpn_pe_rfs"; + prefix l2vpn_pe_rfs; + + import ietf-inet-types { + prefix inet; + } + import tailf-common { + prefix tailf; + } + import tailf-ncs { + prefix ncs; + } + + description + "The PE part of the L2VPN service with QinQ to the switched network between PE and CPE"; + + revision 2024-07-10 { + description + "Initial revision."; + } + + grouping interface_grouping { + leaf interface_name { + tailf:info "Interface name. For example TenGigE."; + type enumeration { + enum FastEthernet; + enum GigabitEthernet; + enum TenGigE; + enum TwentyFiveGigE; + enum FortyGigE; + enum FiftyGigE; + enum HundredGigE; + enum TwoHundredGigE; + enum FourHundredGigE; + enum EightHundredGigE; + enum xe; + } + } + leaf interface_number { + tailf:info "Interface number. For example 0 or 1/0"; + type string { + pattern "[0-9]{1,2}(/[0-9]{1,2}){1,4}"; + } + } + leaf interface_description { + tailf:info "Interface description."; + type string; + } + } + + list l2vpn_pe_rfs { + description "This is an RFS skeleton service"; + + key name; + leaf name { + tailf:info "Unique service id"; + tailf:cli-allow-range; + type string; + } + + uses ncs:service-data; + ncs:servicepoint l2vpn_pe_rfs-servicepoint; + + leaf device { + tailf:info "The PE device"; + type leafref { + path "/ncs:devices/ncs:device/ncs:name"; + } + } + + leaf ovlan { + tailf:info "Outer VLAN eg 10"; + type uint16; + mandatory true; + } + + leaf ivlan { + tailf:info "Inner VLAN eg 20"; + type uint16; + mandatory true; + } + + leaf bridge_group_name { + tailf:info "Name of the L2VPN bridge group"; + type string; + } + + container interface { + uses interface_grouping; + } + } +} diff --git a/l2vpn_pe_rfs/templates/l2vpn_pe_rfs-template.xml b/l2vpn_pe_rfs/templates/l2vpn_pe_rfs-template.xml new file mode 100644 index 0000000..59b4fc2 --- /dev/null +++ b/l2vpn_pe_rfs/templates/l2vpn_pe_rfs-template.xml @@ -0,0 +1,150 @@ + + + + {/device} + + + + + + + {/interface/interface_number}.{/ovlan} + {/interface/interface_description} + l2transport + + + {/ovlan} + {/ivlan} + + + + + + 2 + symmetric + + + + + + + + + + {/interface/interface_number}.{/ovlan} + l2transport + + + {/ovlan} + {/ivlan} + + + + + + 2 + symmetric + + + + + + + + {/ovlan} + +
+ {/ovlan}.{/ovlan}.{/ovlan}.1 + 255.255.255.0 +
+
+
+
+ + + + {/bridge_group_name} + + {/bridge_group_name} + + {/interface/interface_name}{/interface/interface_number}.{/ovlan} + + + + BVI{/ovlan} + + + + + + + + + + + + {/interface/interface_name}{/interface/interface_number}.{/ovlan} + + + + {/interface/interface_description} + + + {/ovlan} + {/ivlan} + + + + + + + + + + + + + + BVI{/ovlan} + + +
+
{/ovlan}.{/ovlan}.{/ovlan}.1
+ 255.255.255.0 +
+
+
+
+
+ + + + + + {/bridge_group_name} + + + {/bridge_group_name} + + + {/interface/interface_name}{/interface/interface_number}.{/ovlan} + + + + + BVI{/ovlan} + + + + + + + + + + + +
+
+
+
diff --git a/l2vpn_pe_rfs/test/Makefile b/l2vpn_pe_rfs/test/Makefile new file mode 100644 index 0000000..32f02d6 --- /dev/null +++ b/l2vpn_pe_rfs/test/Makefile @@ -0,0 +1,37 @@ +DIRS = external internal + +ifeq ($(BUILD_JOB),external) +DIR = external +endif + +ifeq ($(BUILD_JOB),internal_realhw) +DIR = internal +JOB_DIR = realhw +endif + +ifeq ($(BUILD_JOB),internal_simulated) +DIR = internal +JOB_DIR = simulated +endif + +ifeq ($(BUILD_JOB),) +DIR = internal +JOB_DIR = simulated +endif + +all: test + +build: + $(MAKE) -C $(DIR) build JOB_DIR=$(JOB_DIR) || exit 1 + +clean: + $(MAKE) -C $(DIR) clean JOB_DIR=$(JOB_DIR) || exit 1 + +test: + $(MAKE) -C $(DIR) test JOB_DIR=$(JOB_DIR) || exit 1 + +desc: + @echo "==Test Cases for NED==" + @for d in $(DIRS) ; do \ + $(MAKE) -sC $$d desc || exit 1; \ + done diff --git a/l2vpn_pe_rfs/test/internal/Makefile b/l2vpn_pe_rfs/test/internal/Makefile new file mode 100644 index 0000000..982aa57 --- /dev/null +++ b/l2vpn_pe_rfs/test/internal/Makefile @@ -0,0 +1,21 @@ +DIRS = lux + +build: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d build || exit 1; \ + done + +clean: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d clean || exit 1; \ + done + +test: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d test || exit 1; \ + done + +desc: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d desc || exit 1; \ + done diff --git a/l2vpn_pe_rfs/test/internal/lux/Makefile b/l2vpn_pe_rfs/test/internal/lux/Makefile new file mode 100644 index 0000000..2558f02 --- /dev/null +++ b/l2vpn_pe_rfs/test/internal/lux/Makefile @@ -0,0 +1,21 @@ +DIRS = service + +build: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d build || exit 1; \ + done + +clean: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d clean || exit 1; \ + done + +test: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d test || exit 1; \ + done + +desc: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d desc || exit 1; \ + done diff --git a/l2vpn_pe_rfs/test/internal/lux/service/Makefile b/l2vpn_pe_rfs/test/internal/lux/service/Makefile new file mode 100644 index 0000000..d2dc5be --- /dev/null +++ b/l2vpn_pe_rfs/test/internal/lux/service/Makefile @@ -0,0 +1,26 @@ +# +# The 'lux' test tool can be obtained from: +# +# https://github.com/hawk/lux.git +# + +# Make sure the TARGET_DIR has got the following make targets: +.PHONY: clean build start stop + +export TARGET_DIR=../../../../../.. + +.PHONY: test +test: + lux run.lux + +clean: + $(MAKE) -C $(TARGET_DIR) clean + +build: + $(MAKE) -C $(TARGET_DIR) build + +start: + $(MAKE) -C $(TARGET_DIR) start + +stop: + $(MAKE) -C $(TARGET_DIR) stop diff --git a/l2vpn_pe_rfs/test/internal/lux/service/dummy-device.xml b/l2vpn_pe_rfs/test/internal/lux/service/dummy-device.xml new file mode 100644 index 0000000..df09281 --- /dev/null +++ b/l2vpn_pe_rfs/test/internal/lux/service/dummy-device.xml @@ -0,0 +1,11 @@ + + + + eth +
192.168.110.1
+ + southbound-locked + +
+
+
diff --git a/l2vpn_pe_rfs/test/internal/lux/service/dummy-service.xml b/l2vpn_pe_rfs/test/internal/lux/service/dummy-service.xml new file mode 100644 index 0000000..9b48e30 --- /dev/null +++ b/l2vpn_pe_rfs/test/internal/lux/service/dummy-service.xml @@ -0,0 +1,12 @@ + + + + true + + + + 33 + eth + 127.0.0.1 + + diff --git a/l2vpn_pe_rfs/test/internal/lux/service/pyvm.xml b/l2vpn_pe_rfs/test/internal/lux/service/pyvm.xml new file mode 100644 index 0000000..531521c --- /dev/null +++ b/l2vpn_pe_rfs/test/internal/lux/service/pyvm.xml @@ -0,0 +1,8 @@ + + + + ./logs/ncs-python-vm + level-info + + + diff --git a/l2vpn_pe_rfs/test/internal/lux/service/run.lux b/l2vpn_pe_rfs/test/internal/lux/service/run.lux new file mode 100644 index 0000000..63887d3 --- /dev/null +++ b/l2vpn_pe_rfs/test/internal/lux/service/run.lux @@ -0,0 +1,53 @@ +# +# The 'lux' test tool can be obtained from: +# +# https://github.com/hawk/lux.git +# +[global target_dir=../../../../../..] +[config skip_unless=PYTHON] + +[shell top] + !make stop build + !echo ==$$?== + ?==0== + ?SH-PROMPT: + + !rm ${target_dir}/ncs-cdb/* + ?SH-PROMPT: + !cp pyvm.xml ${target_dir}/ncs-cdb/. + ?SH-PROMPT: + + !make start + !echo ==$$?== + ?==0== + ?SH-PROMPT: + + [progress \nCreate a dummy device...\n] + !ncs_load -lm dummy-device.xml + ?SH-PROMPT: + [progress \nCreate a dummy device...ok\n] + + [sleep 3] + + [progress \nCreate the dummy service...\n] + !ncs_load -lm dummy-service.xml + ?SH-PROMPT: + [progress \nCreate the dummy service...ok\n] + + +[shell log] + !cd ${target_dir} + ?SH-PROMPT: + + [progress \nVerify that the service code has been invoked...\n] + !tail -f ./logs/ncs-python-vm-l2vpn_pe_rfs.log + ?.*Worker RUNNING.* + ?.*Service create.* + [progress \nVerify that the service code has been invoked...ok\n] + + +[cleanup] + !make stop + !echo ==$$?== + ?==0== + ?SH-PROMPT: diff --git a/l2vpn_sw_rfs/README b/l2vpn_sw_rfs/README new file mode 100644 index 0000000..d027c67 --- /dev/null +++ b/l2vpn_sw_rfs/README @@ -0,0 +1,23 @@ +This is a generated Python package, made by: + + ncs-make-package --service-skeleton python-and-template \ + --component-class main.Main l2vpn_sw_rfs + +It contains a dummy YANG model which implements a minimal Service +and an Action that doesn't really do anything useful. They are +there just to get you going. + +You will also find two test cases in: + + test/internal/lux/service/ + test/internal/lux/action/ + +that you can run if you have the 'lux' testing tool. +Your top Makefile also need to implement some Make targets +as described in the Makefiles of the test cases. +You can also just read the corresponding run.lux tests and +do them manually if you wish. + +The 'lux' test tool can be obtained from: + + https://github.com/hawk/lux.git diff --git a/l2vpn_sw_rfs/load-dir/l2vpn_sw_rfs.fxs b/l2vpn_sw_rfs/load-dir/l2vpn_sw_rfs.fxs new file mode 100644 index 0000000000000000000000000000000000000000..62f41ad9f966561f934a61a104b8285298ffc533 GIT binary patch literal 13318 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 literal 0 HcmV?d00001 diff --git a/l2vpn_sw_rfs/package-meta-data.xml b/l2vpn_sw_rfs/package-meta-data.xml new file mode 100644 index 0000000..5713bbd --- /dev/null +++ b/l2vpn_sw_rfs/package-meta-data.xml @@ -0,0 +1,13 @@ + + l2vpn_sw_rfs + 1.0 + Generated Python package + 6.2 + + + main + + l2vpn_sw_rfs.main.Main + + + diff --git a/l2vpn_sw_rfs/python/l2vpn_sw_rfs/__init__.py b/l2vpn_sw_rfs/python/l2vpn_sw_rfs/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/l2vpn_sw_rfs/python/l2vpn_sw_rfs/main.py b/l2vpn_sw_rfs/python/l2vpn_sw_rfs/main.py new file mode 100644 index 0000000..baa51d7 --- /dev/null +++ b/l2vpn_sw_rfs/python/l2vpn_sw_rfs/main.py @@ -0,0 +1,65 @@ +# -*- mode: python; python-indent: 4 -*- +import ncs +from ncs.application import Service + + +# ------------------------ +# SERVICE CALLBACK EXAMPLE +# ------------------------ +class ServiceCallbacks(Service): + + # The create() callback is invoked inside NCS FASTMAP and + # must always exist. + @Service.create + def cb_create(self, tctx, root, service, proplist): + self.log.info('Service create(service=', service._path, ')') + + vars = ncs.template.Variables() + vars.add('DUMMY', '127.0.0.1') + template = ncs.template.Template(service) + template.apply('l2vpn_sw_rfs-template', vars) + + # The pre_modification() and post_modification() callbacks are optional, + # and are invoked outside FASTMAP. pre_modification() is invoked before + # create, update, or delete of the service, as indicated by the enum + # ncs_service_operation op parameter. Conversely + # post_modification() is invoked after create, update, or delete + # of the service. These functions can be useful e.g. for + # allocations that should be stored and existing also when the + # service instance is removed. + + # @Service.pre_modification + # def cb_pre_modification(self, tctx, op, kp, root, proplist): + # self.log.info('Service premod(service=', kp, ')') + + # @Service.post_modification + # def cb_post_modification(self, tctx, op, kp, root, proplist): + # self.log.info('Service postmod(service=', kp, ')') + + +# --------------------------------------------- +# COMPONENT THREAD THAT WILL BE STARTED BY NCS. +# --------------------------------------------- +class Main(ncs.application.Application): + def setup(self): + # The application class sets up logging for us. It is accessible + # through 'self.log' and is a ncs.log.Log instance. + self.log.info('Main RUNNING') + + # Service callbacks require a registration for a 'service point', + # as specified in the corresponding data model. + # + self.register_service('l2vpn_sw_rfs-servicepoint', ServiceCallbacks) + + # If we registered any callback(s) above, the Application class + # took care of creating a daemon (related to the service/action point). + + # When this setup method is finished, all registrations are + # considered done and the application is 'started'. + + def teardown(self): + # When the application is finished (which would happen if NCS went + # down, packages were reloaded or some error occurred) this teardown + # method will be called. + + self.log.info('Main FINISHED') diff --git a/l2vpn_sw_rfs/src/Makefile b/l2vpn_sw_rfs/src/Makefile new file mode 100644 index 0000000..3a0f88c --- /dev/null +++ b/l2vpn_sw_rfs/src/Makefile @@ -0,0 +1,32 @@ +all: fxs +.PHONY: all + +# Include standard NCS examples build definitions and rules +include $(NCS_DIR)/src/ncs/build/include.ncs.mk + +SRC = $(wildcard yang/*.yang) +DIRS = ../load-dir +FXS = $(SRC:yang/%.yang=../load-dir/%.fxs) + +## Uncomment and patch the line below if you have a dependency to a NED +## or to other YANG files +# YANGPATH += ../..//src/ncsc-out/modules/yang \ +# ../..//src/yang + +NCSCPATH = $(YANGPATH:%=--yangpath %) +YANGERPATH = $(YANGPATH:%=--path %) + +fxs: $(DIRS) $(FXS) + +$(DIRS): + mkdir -p $@ + +../load-dir/%.fxs: yang/%.yang + $(NCSC) `ls $*-ann.yang > /dev/null 2>&1 && echo "-a $*-ann.yang"` \ + --fail-on-warnings \ + $(NCSCPATH) \ + -c -o $@ $< + +clean: + rm -rf $(DIRS) +.PHONY: clean diff --git a/l2vpn_sw_rfs/src/yang/l2vpn_sw_rfs.yang b/l2vpn_sw_rfs/src/yang/l2vpn_sw_rfs.yang new file mode 100644 index 0000000..6bfae48 --- /dev/null +++ b/l2vpn_sw_rfs/src/yang/l2vpn_sw_rfs.yang @@ -0,0 +1,98 @@ +module l2vpn_sw_rfs { + + namespace "http://example.com/l2vpn_sw_rfs"; + prefix l2vpn_sw_rfs; + + import ietf-inet-types { + prefix inet; + } + import tailf-common { + prefix tailf; + } + import tailf-ncs { + prefix ncs; + } + + description + "The switch part of the L2VPN service with QinQ in the switched network between PE and CPE"; + + revision 2024-07-10 { + description + "Initial revision."; + } + + grouping interface_grouping { + leaf interface_name { + tailf:info "Interface name. For example TenGigE."; + type enumeration { + enum FastEthernet; + enum GigabitEthernet; + enum TenGigE; + enum TwentyFiveGigE; + enum FortyGigE; + enum FiftyGigE; + enum HundredGigE; + enum TwoHundredGigE; + enum FourHundredGigE; + enum EightHundredGigE; + enum xe; + } + } + leaf interface_number { + tailf:info "Interface number. For example 0 or 1/0"; + type string { + pattern "[0-9]{1,2}(/[0-9]{1,2}){1,4}"; + } + } + leaf interface_description { + tailf:info "Interface description."; + type string; + } + } + + list l2vpn_sw_rfs { + description "This is an RFS skeleton service"; + + key name; + leaf name { + tailf:info "Unique service id"; + tailf:cli-allow-range; + type string; + } + + uses ncs:service-data; + ncs:servicepoint l2vpn_sw_rfs-servicepoint; + + leaf device { + tailf:info "The Switch device"; + type leafref { + path "/ncs:devices/ncs:device/ncs:name"; + } + } + + leaf ovlan { + tailf:info "Outer VLAN eg 10"; + type uint16; + mandatory true; + } + + leaf ivlan { + tailf:info "Inner VLAN eg 20"; + type uint16; + mandatory true; + } + + leaf vlan_name { + tailf:info "Name of the L2VPN bridge group"; + type string; + } + + container pe_interface { + uses interface_grouping; + } + + container cpe_interface { + uses interface_grouping; + } + } +} diff --git a/l2vpn_sw_rfs/templates/l2vpn_sw_rfs-template.xml b/l2vpn_sw_rfs/templates/l2vpn_sw_rfs-template.xml new file mode 100644 index 0000000..cdea7ac --- /dev/null +++ b/l2vpn_sw_rfs/templates/l2vpn_sw_rfs-template.xml @@ -0,0 +1,85 @@ + + + + {/device} + + + + {/ovlan} + {/vlan_name} + + + + + + {/cpe_interface/interface_number} + {/cpe_interface/interface_description} + + + + + + {/ovlan} + + + + + + + + {/cpe_interface/interface_number} + {/cpe_interface/interface_description} + + + + + + {/ovlan} + + + + + + + + {/pe_interface/interface_number} + {/pe_interface/interface_description} + + + + + + {/ovlan} + + + + + + + {/pe_interface/interface_number} + {/pe_interface/interface_description} + + + + + + {/ovlan} + + + + + + + + + diff --git a/l2vpn_sw_rfs/test/Makefile b/l2vpn_sw_rfs/test/Makefile new file mode 100644 index 0000000..32f02d6 --- /dev/null +++ b/l2vpn_sw_rfs/test/Makefile @@ -0,0 +1,37 @@ +DIRS = external internal + +ifeq ($(BUILD_JOB),external) +DIR = external +endif + +ifeq ($(BUILD_JOB),internal_realhw) +DIR = internal +JOB_DIR = realhw +endif + +ifeq ($(BUILD_JOB),internal_simulated) +DIR = internal +JOB_DIR = simulated +endif + +ifeq ($(BUILD_JOB),) +DIR = internal +JOB_DIR = simulated +endif + +all: test + +build: + $(MAKE) -C $(DIR) build JOB_DIR=$(JOB_DIR) || exit 1 + +clean: + $(MAKE) -C $(DIR) clean JOB_DIR=$(JOB_DIR) || exit 1 + +test: + $(MAKE) -C $(DIR) test JOB_DIR=$(JOB_DIR) || exit 1 + +desc: + @echo "==Test Cases for NED==" + @for d in $(DIRS) ; do \ + $(MAKE) -sC $$d desc || exit 1; \ + done diff --git a/l2vpn_sw_rfs/test/internal/Makefile b/l2vpn_sw_rfs/test/internal/Makefile new file mode 100644 index 0000000..982aa57 --- /dev/null +++ b/l2vpn_sw_rfs/test/internal/Makefile @@ -0,0 +1,21 @@ +DIRS = lux + +build: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d build || exit 1; \ + done + +clean: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d clean || exit 1; \ + done + +test: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d test || exit 1; \ + done + +desc: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d desc || exit 1; \ + done diff --git a/l2vpn_sw_rfs/test/internal/lux/Makefile b/l2vpn_sw_rfs/test/internal/lux/Makefile new file mode 100644 index 0000000..2558f02 --- /dev/null +++ b/l2vpn_sw_rfs/test/internal/lux/Makefile @@ -0,0 +1,21 @@ +DIRS = service + +build: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d build || exit 1; \ + done + +clean: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d clean || exit 1; \ + done + +test: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d test || exit 1; \ + done + +desc: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d desc || exit 1; \ + done diff --git a/l2vpn_sw_rfs/test/internal/lux/service/Makefile b/l2vpn_sw_rfs/test/internal/lux/service/Makefile new file mode 100644 index 0000000..d2dc5be --- /dev/null +++ b/l2vpn_sw_rfs/test/internal/lux/service/Makefile @@ -0,0 +1,26 @@ +# +# The 'lux' test tool can be obtained from: +# +# https://github.com/hawk/lux.git +# + +# Make sure the TARGET_DIR has got the following make targets: +.PHONY: clean build start stop + +export TARGET_DIR=../../../../../.. + +.PHONY: test +test: + lux run.lux + +clean: + $(MAKE) -C $(TARGET_DIR) clean + +build: + $(MAKE) -C $(TARGET_DIR) build + +start: + $(MAKE) -C $(TARGET_DIR) start + +stop: + $(MAKE) -C $(TARGET_DIR) stop diff --git a/l2vpn_sw_rfs/test/internal/lux/service/dummy-device.xml b/l2vpn_sw_rfs/test/internal/lux/service/dummy-device.xml new file mode 100644 index 0000000..df09281 --- /dev/null +++ b/l2vpn_sw_rfs/test/internal/lux/service/dummy-device.xml @@ -0,0 +1,11 @@ + + + + eth +
192.168.110.1
+ + southbound-locked + +
+
+
diff --git a/l2vpn_sw_rfs/test/internal/lux/service/dummy-service.xml b/l2vpn_sw_rfs/test/internal/lux/service/dummy-service.xml new file mode 100644 index 0000000..c6df86d --- /dev/null +++ b/l2vpn_sw_rfs/test/internal/lux/service/dummy-service.xml @@ -0,0 +1,12 @@ + + + + true + + + + 33 + eth + 127.0.0.1 + + diff --git a/l2vpn_sw_rfs/test/internal/lux/service/pyvm.xml b/l2vpn_sw_rfs/test/internal/lux/service/pyvm.xml new file mode 100644 index 0000000..531521c --- /dev/null +++ b/l2vpn_sw_rfs/test/internal/lux/service/pyvm.xml @@ -0,0 +1,8 @@ + + + + ./logs/ncs-python-vm + level-info + + + diff --git a/l2vpn_sw_rfs/test/internal/lux/service/run.lux b/l2vpn_sw_rfs/test/internal/lux/service/run.lux new file mode 100644 index 0000000..b248ee8 --- /dev/null +++ b/l2vpn_sw_rfs/test/internal/lux/service/run.lux @@ -0,0 +1,53 @@ +# +# The 'lux' test tool can be obtained from: +# +# https://github.com/hawk/lux.git +# +[global target_dir=../../../../../..] +[config skip_unless=PYTHON] + +[shell top] + !make stop build + !echo ==$$?== + ?==0== + ?SH-PROMPT: + + !rm ${target_dir}/ncs-cdb/* + ?SH-PROMPT: + !cp pyvm.xml ${target_dir}/ncs-cdb/. + ?SH-PROMPT: + + !make start + !echo ==$$?== + ?==0== + ?SH-PROMPT: + + [progress \nCreate a dummy device...\n] + !ncs_load -lm dummy-device.xml + ?SH-PROMPT: + [progress \nCreate a dummy device...ok\n] + + [sleep 3] + + [progress \nCreate the dummy service...\n] + !ncs_load -lm dummy-service.xml + ?SH-PROMPT: + [progress \nCreate the dummy service...ok\n] + + +[shell log] + !cd ${target_dir} + ?SH-PROMPT: + + [progress \nVerify that the service code has been invoked...\n] + !tail -f ./logs/ncs-python-vm-l2vpn_sw_rfs.log + ?.*Worker RUNNING.* + ?.*Service create.* + [progress \nVerify that the service code has been invoked...ok\n] + + +[cleanup] + !make stop + !echo ==$$?== + ?==0== + ?SH-PROMPT: diff --git a/l3vpn_cpe_rfs/templates/l3vpn_cpe_rfs-template.xml b/l3vpn_cpe_rfs/templates/l3vpn_cpe_rfs-template.xml index 04a9c83..8179c05 100644 --- a/l3vpn_cpe_rfs/templates/l3vpn_cpe_rfs-template.xml +++ b/l3vpn_cpe_rfs/templates/l3vpn_cpe_rfs-template.xml @@ -16,7 +16,7 @@ - + {/interface/interface_number} diff --git a/l3vpn_qinq_cfs/load-dir/l3vpn_qinq_cfs.fxs b/l3vpn_qinq_cfs/load-dir/l3vpn_qinq_cfs.fxs deleted file mode 100644 index 5696a99b347e46cc749bbb65a6b5bd4026c580a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14588 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 literal 0 HcmV?d00001 diff --git a/netbox_test/package-meta-data.xml b/netbox_test/package-meta-data.xml new file mode 100644 index 0000000..67db70b --- /dev/null +++ b/netbox_test/package-meta-data.xml @@ -0,0 +1,13 @@ + + netbox_test + 1.0 + Generated Python package + 6.2 + + + main + + netbox_test.main.Main + + + diff --git a/netbox_test/python/netbox_test/__init__.py b/netbox_test/python/netbox_test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/netbox_test/python/netbox_test/main.py b/netbox_test/python/netbox_test/main.py new file mode 100644 index 0000000..27a9454 --- /dev/null +++ b/netbox_test/python/netbox_test/main.py @@ -0,0 +1,50 @@ +# -*- mode: python; python-indent: 4 -*- +import ncs +from ncs.application import Service +import requests +import socket +import struct + +class ServiceCallbacks(Service): + @Service.create + def cb_create(self, tctx, root, service, proplist): + self.log.info('Service create(service=', service._path, ')') + + def cidr_to_netmask(cidr): + network, net_bits = cidr.split('/') + host_bits = 32 - int(net_bits) + netmask = socket.inet_ntoa(struct.pack('!I', (1 << 32) - (1 << host_bits))) + return network, netmask, net_bits + + api_url="https://10.101.180.45/api/ipam/prefixes/1/available-ips/" + headers = {"Authorization":"Token e657404c0e1f57481ad0a06c293e8fe794e720ac", "Accept": "application/json", "Content-Type": "application/json"} + body = {} + + response=requests.post(api_url, headers=headers, json=body, verify=False) + self.log.info('Netbox response, IP address reservation: ', response.json()) + ipv4_cidr = response.json()["address"] + self.log.info('CIDR from Netbox: ', ipv4_cidr) + ipv4_address, ipv4_mask, ipv4_cidr_mask = cidr_to_netmask(ipv4_cidr) + self.log.info('Address: ', ipv4_address) + self.log.info('Net Mask: ', ipv4_mask) + self.log.info('CIDR Mask: ', ipv4_cidr_mask) + + api_url="https://10.101.180.45/api/ipam/vlan-groups/1/available-vlans/" + body = {"name": service.ovlan_name} + + response=requests.post(api_url, headers=headers, json=body, verify=False) + self.log.info('Netbox response, VLAN reservation: ', response.json()) + vlan_id = response.json()["vid"] + self.log.info('VLAN from Netbox: ', vlan_id) + + vars = ncs.template.Variables() + template = ncs.template.Template(service) + template.apply('netbox_test-template', vars) + +class Main(ncs.application.Application): + def setup(self): + self.log.info('Main RUNNING') + self.register_service('netbox_test-servicepoint', ServiceCallbacks) + + def teardown(self): + self.log.info('Main FINISHED') diff --git a/netbox_test/src/Makefile b/netbox_test/src/Makefile new file mode 100644 index 0000000..3a0f88c --- /dev/null +++ b/netbox_test/src/Makefile @@ -0,0 +1,32 @@ +all: fxs +.PHONY: all + +# Include standard NCS examples build definitions and rules +include $(NCS_DIR)/src/ncs/build/include.ncs.mk + +SRC = $(wildcard yang/*.yang) +DIRS = ../load-dir +FXS = $(SRC:yang/%.yang=../load-dir/%.fxs) + +## Uncomment and patch the line below if you have a dependency to a NED +## or to other YANG files +# YANGPATH += ../..//src/ncsc-out/modules/yang \ +# ../..//src/yang + +NCSCPATH = $(YANGPATH:%=--yangpath %) +YANGERPATH = $(YANGPATH:%=--path %) + +fxs: $(DIRS) $(FXS) + +$(DIRS): + mkdir -p $@ + +../load-dir/%.fxs: yang/%.yang + $(NCSC) `ls $*-ann.yang > /dev/null 2>&1 && echo "-a $*-ann.yang"` \ + --fail-on-warnings \ + $(NCSCPATH) \ + -c -o $@ $< + +clean: + rm -rf $(DIRS) +.PHONY: clean diff --git a/netbox_test/src/yang/netbox_test.yang b/netbox_test/src/yang/netbox_test.yang new file mode 100644 index 0000000..13dfa20 --- /dev/null +++ b/netbox_test/src/yang/netbox_test.yang @@ -0,0 +1,55 @@ +module netbox_test { + + namespace "http://example.com/netbox_test"; + prefix netbox_test; + + import ietf-inet-types { + prefix inet; + } + import tailf-common { + prefix tailf; + } + import tailf-ncs { + prefix ncs; + } + + description + "Bla bla..."; + + revision 2016-01-01 { + description + "Initial revision."; + } + + list netbox_test { + description "This is an RFS skeleton service"; + + key name; + leaf name { + tailf:info "Unique service id"; + tailf:cli-allow-range; + type string; + } + + uses ncs:service-data; + ncs:servicepoint netbox_test-servicepoint; + + // may replace this with other ways of refering to the devices. + leaf-list device { + type leafref { + path "/ncs:devices/ncs:device/ncs:name"; + } + } + + leaf ovlan_name { + tailf:info "VLAN name must be unigue for each reservation from same Netbox VLAN Group"; + type string; + mandatory true; + } + + // replace with your own stuff here + leaf dummy { + type inet:ipv4-address; + } + } +} diff --git a/netbox_test/templates/netbox_test-template.xml b/netbox_test/templates/netbox_test-template.xml new file mode 100644 index 0000000..1c16c7d --- /dev/null +++ b/netbox_test/templates/netbox_test-template.xml @@ -0,0 +1,20 @@ + + + + + {/device} + + + + + + diff --git a/netbox_test/test/Makefile b/netbox_test/test/Makefile new file mode 100644 index 0000000..32f02d6 --- /dev/null +++ b/netbox_test/test/Makefile @@ -0,0 +1,37 @@ +DIRS = external internal + +ifeq ($(BUILD_JOB),external) +DIR = external +endif + +ifeq ($(BUILD_JOB),internal_realhw) +DIR = internal +JOB_DIR = realhw +endif + +ifeq ($(BUILD_JOB),internal_simulated) +DIR = internal +JOB_DIR = simulated +endif + +ifeq ($(BUILD_JOB),) +DIR = internal +JOB_DIR = simulated +endif + +all: test + +build: + $(MAKE) -C $(DIR) build JOB_DIR=$(JOB_DIR) || exit 1 + +clean: + $(MAKE) -C $(DIR) clean JOB_DIR=$(JOB_DIR) || exit 1 + +test: + $(MAKE) -C $(DIR) test JOB_DIR=$(JOB_DIR) || exit 1 + +desc: + @echo "==Test Cases for NED==" + @for d in $(DIRS) ; do \ + $(MAKE) -sC $$d desc || exit 1; \ + done diff --git a/netbox_test/test/internal/Makefile b/netbox_test/test/internal/Makefile new file mode 100644 index 0000000..982aa57 --- /dev/null +++ b/netbox_test/test/internal/Makefile @@ -0,0 +1,21 @@ +DIRS = lux + +build: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d build || exit 1; \ + done + +clean: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d clean || exit 1; \ + done + +test: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d test || exit 1; \ + done + +desc: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d desc || exit 1; \ + done diff --git a/netbox_test/test/internal/lux/Makefile b/netbox_test/test/internal/lux/Makefile new file mode 100644 index 0000000..2558f02 --- /dev/null +++ b/netbox_test/test/internal/lux/Makefile @@ -0,0 +1,21 @@ +DIRS = service + +build: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d build || exit 1; \ + done + +clean: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d clean || exit 1; \ + done + +test: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d test || exit 1; \ + done + +desc: + @for d in $(DIRS) ; do \ + $(MAKE) -C $$d desc || exit 1; \ + done diff --git a/netbox_test/test/internal/lux/service/Makefile b/netbox_test/test/internal/lux/service/Makefile new file mode 100644 index 0000000..d2dc5be --- /dev/null +++ b/netbox_test/test/internal/lux/service/Makefile @@ -0,0 +1,26 @@ +# +# The 'lux' test tool can be obtained from: +# +# https://github.com/hawk/lux.git +# + +# Make sure the TARGET_DIR has got the following make targets: +.PHONY: clean build start stop + +export TARGET_DIR=../../../../../.. + +.PHONY: test +test: + lux run.lux + +clean: + $(MAKE) -C $(TARGET_DIR) clean + +build: + $(MAKE) -C $(TARGET_DIR) build + +start: + $(MAKE) -C $(TARGET_DIR) start + +stop: + $(MAKE) -C $(TARGET_DIR) stop diff --git a/netbox_test/test/internal/lux/service/dummy-device.xml b/netbox_test/test/internal/lux/service/dummy-device.xml new file mode 100644 index 0000000..df09281 --- /dev/null +++ b/netbox_test/test/internal/lux/service/dummy-device.xml @@ -0,0 +1,11 @@ + + + + eth +
192.168.110.1
+ + southbound-locked + +
+
+
diff --git a/netbox_test/test/internal/lux/service/dummy-service.xml b/netbox_test/test/internal/lux/service/dummy-service.xml new file mode 100644 index 0000000..4e08e71 --- /dev/null +++ b/netbox_test/test/internal/lux/service/dummy-service.xml @@ -0,0 +1,12 @@ + + + + true + + + + 33 + eth + 127.0.0.1 + + diff --git a/netbox_test/test/internal/lux/service/pyvm.xml b/netbox_test/test/internal/lux/service/pyvm.xml new file mode 100644 index 0000000..531521c --- /dev/null +++ b/netbox_test/test/internal/lux/service/pyvm.xml @@ -0,0 +1,8 @@ + + + + ./logs/ncs-python-vm + level-info + + + diff --git a/netbox_test/test/internal/lux/service/run.lux b/netbox_test/test/internal/lux/service/run.lux new file mode 100644 index 0000000..63b49a8 --- /dev/null +++ b/netbox_test/test/internal/lux/service/run.lux @@ -0,0 +1,53 @@ +# +# The 'lux' test tool can be obtained from: +# +# https://github.com/hawk/lux.git +# +[global target_dir=../../../../../..] +[config skip_unless=PYTHON] + +[shell top] + !make stop build + !echo ==$$?== + ?==0== + ?SH-PROMPT: + + !rm ${target_dir}/ncs-cdb/* + ?SH-PROMPT: + !cp pyvm.xml ${target_dir}/ncs-cdb/. + ?SH-PROMPT: + + !make start + !echo ==$$?== + ?==0== + ?SH-PROMPT: + + [progress \nCreate a dummy device...\n] + !ncs_load -lm dummy-device.xml + ?SH-PROMPT: + [progress \nCreate a dummy device...ok\n] + + [sleep 3] + + [progress \nCreate the dummy service...\n] + !ncs_load -lm dummy-service.xml + ?SH-PROMPT: + [progress \nCreate the dummy service...ok\n] + + +[shell log] + !cd ${target_dir} + ?SH-PROMPT: + + [progress \nVerify that the service code has been invoked...\n] + !tail -f ./logs/ncs-python-vm-netbox_test.log + ?.*Worker RUNNING.* + ?.*Service create.* + [progress \nVerify that the service code has been invoked...ok\n] + + +[cleanup] + !make stop + !echo ==$$?== + ?==0== + ?SH-PROMPT: