Rewrite NTS Framework. 66/4966/1
authorAlex Stancu <alexandru.stancu@highstreet-technologies.com>
Mon, 2 Nov 2020 15:34:59 +0000 (17:34 +0200)
committerAlex Stancu <alexandru.stancu@highstreet-technologies.com>
Mon, 2 Nov 2020 15:35:26 +0000 (17:35 +0200)
Align NTS framework with the new sysrepo/Netopeer2 versions. Complete refactoring of the code.

Issue-ID: SIM-38
Change-Id: I86cad6aeef7e7f4c58b8ce3735ff2cf2d773992c
Signed-off-by: Alex Stancu <alexandru.stancu@highstreet-technologies.com>
277 files changed:
ntsimulator/.gitignore [deleted file]
ntsimulator/CMakeLists.txt [deleted file]
ntsimulator/CMakeModules/FindSYSREPO.cmake [deleted file]
ntsimulator/README.md [deleted file]
ntsimulator/deploy/Dockerfile [deleted file]
ntsimulator/deploy/base/build_ntsim-ng.sh [new file with mode: 0755]
ntsimulator/deploy/base/build_regxstring.sh [new file with mode: 0755]
ntsimulator/deploy/base/ca.key [moved from ntsimulator/deploy/tls/ca.key with 100% similarity]
ntsimulator/deploy/base/ca.pem [moved from ntsimulator/deploy/tls/ca.pem with 100% similarity]
ntsimulator/deploy/base/client.crt [moved from ntsimulator/deploy/tls/client.crt with 100% similarity]
ntsimulator/deploy/base/container-tag.yaml [new file with mode: 0644]
ntsimulator/deploy/base/generate-ssh-keys.sh [new file with mode: 0755]
ntsimulator/deploy/base/pm_files/pm-bulk-a2.xml [new file with mode: 0644]
ntsimulator/deploy/base/pm_files/pm-bulk-a3-1.xml [new file with mode: 0644]
ntsimulator/deploy/base/pm_files/pm-bulk-a3.xml [new file with mode: 0644]
ntsimulator/deploy/base/ubuntu.Dockerfile [new file with mode: 0644]
ntsimulator/deploy/base/vsftpd.conf [new file with mode: 0644]
ntsimulator/deploy/base/vsftpd.userlist [new file with mode: 0644]
ntsimulator/deploy/base/yang/ietf-inet-types.yang [moved from ntsimulator/yang/o-ran-sc/o-ran-ru/ietf-inet-types.yang with 100% similarity]
ntsimulator/deploy/base/yang/ietf-system.yang [new file with mode: 0644]
ntsimulator/deploy/base/yang/nts-common.yang [new file with mode: 0644]
ntsimulator/deploy/base/yang/nts-network-function.yang [new file with mode: 0644]
ntsimulator/deploy/base/yang/onap-system.yang [new file with mode: 0644]
ntsimulator/deploy/container-tag.yaml [deleted file]
ntsimulator/deploy/nts-manager/CMakeLists.txt [deleted file]
ntsimulator/deploy/nts-manager/Dockerfile [deleted file]
ntsimulator/deploy/nts-manager/config.json [new file with mode: 0644]
ntsimulator/deploy/nts-manager/container-tag.yaml
ntsimulator/deploy/nts-manager/docker_stats.sh [deleted file]
ntsimulator/deploy/nts-manager/model-install.sh.in [deleted file]
ntsimulator/deploy/nts-manager/supervisord.conf
ntsimulator/deploy/nts-manager/ubuntu.Dockerfile [new file with mode: 0644]
ntsimulator/deploy/nts-manager/yang/nts-manager.yang [new file with mode: 0644]
ntsimulator/deploy/nts-manager/yang/nts-o-ran-pac.yang [new file with mode: 0644]
ntsimulator/deploy/nts-manager/yang/nts-x-ran-pac.yang [new file with mode: 0644]
ntsimulator/deploy/o-ran-sc/o-ran-ru/CMakeLists.txt [deleted file]
ntsimulator/deploy/o-ran-sc/o-ran-ru/Dockerfile [deleted file]
ntsimulator/deploy/o-ran-sc/o-ran-ru/container-tag.yaml [deleted file]
ntsimulator/deploy/o-ran-sc/o-ran-ru/supervisord.conf [deleted file]
ntsimulator/deploy/o-ran-sc/o-ran-ru/sysrepo-configuration-load.sh [deleted file]
ntsimulator/deploy/o-ran/config.json [new file with mode: 0644]
ntsimulator/deploy/o-ran/container-tag.yaml [new file with mode: 0644]
ntsimulator/deploy/o-ran/ru-fh/CMakeLists.txt [deleted file]
ntsimulator/deploy/o-ran/ru-fh/Dockerfile [deleted file]
ntsimulator/deploy/o-ran/ru-fh/container-tag.yaml [deleted file]
ntsimulator/deploy/o-ran/ru-fh/edit-config-after-activate.sh [deleted file]
ntsimulator/deploy/o-ran/ru-fh/edit-config-after-activate.xml [deleted file]
ntsimulator/deploy/o-ran/ru-fh/edit-config-after-download.sh [deleted file]
ntsimulator/deploy/o-ran/ru-fh/edit-config-after-download.xml [deleted file]
ntsimulator/deploy/o-ran/ru-fh/edit-config-demo-start.sh [deleted file]
ntsimulator/deploy/o-ran/ru-fh/edit-config-demo-start.xml [deleted file]
ntsimulator/deploy/o-ran/ru-fh/supervisord.conf [deleted file]
ntsimulator/deploy/o-ran/supervisord.conf [new file with mode: 0644]
ntsimulator/deploy/o-ran/ubuntu.Dockerfile [new file with mode: 0644]
ntsimulator/deploy/o-ran/yang/iana-hardware.yang [moved from ntsimulator/yang/o-ran-sc/o-ran-ru/iana-hardware.yang with 100% similarity, mode: 0755]
ntsimulator/deploy/o-ran/yang/iana-if-type.yang [moved from ntsimulator/yang/o-ran/ru-fh/iana-if-type.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/ietf-crypto-types.yang [moved from ntsimulator/yang/o-ran/ru-fh/ietf-crypto-types.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/ietf-dhcpv6-types.yang [moved from ntsimulator/yang/o-ran/ru-fh/ietf-dhcpv6-types.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/ietf-hardware.yang [moved from ntsimulator/yang/o-ran-sc/o-ran-ru/ietf-hardware.yang with 100% similarity, mode: 0755]
ntsimulator/deploy/o-ran/yang/ietf-inet-types.yang [moved from ntsimulator/yang/o-ran/ru-fh/ietf-inet-types.yang with 100% similarity, mode: 0755]
ntsimulator/deploy/o-ran/yang/ietf-interfaces.yang [moved from ntsimulator/yang/o-ran-sc/o-ran-ru/ietf-interfaces.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/ietf-ip.yang [moved from ntsimulator/yang/o-ran/ru-fh/ietf-ip.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/ietf-netconf-acm.yang [moved from ntsimulator/yang/o-ran/ru-fh/ietf-netconf-acm.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/ietf-netconf-monitoring.yang [moved from ntsimulator/yang/o-ran/ru-fh/ietf-netconf-monitoring.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/ietf-yang-types.yang [moved from ntsimulator/yang/o-ran-sc/o-ran-ru/ietf-yang-types.yang with 100% similarity, mode: 0755]
ntsimulator/deploy/o-ran/yang/o-ran-alarm-id.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-alarm-id.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-ald-port.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-ald-port.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-ald.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-ald.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-antenna-calibration.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-antenna-calibration.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-beamforming.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-beamforming.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-compression-factors.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-compression-factors.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-delay-management.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-delay-management.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-dhcp.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-dhcp.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-ecpri-delay.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-ecpri-delay.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-externalio.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-externalio.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-fan.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-fan.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-file-management.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-file-management.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-fm.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-fm.yang with 96% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-hardware.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-hardware.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-interfaces.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-interfaces.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-laa-operations.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-laa-operations.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-laa.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-laa.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-lbm.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-lbm.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-module-cap.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-module-cap.yang with 99% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-mplane-int.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-mplane-int.yang with 97% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-operations.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-operations.yang with 94% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-performance-management.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-performance-management.yang with 99% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-processing-element.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-processing-element.yang with 89% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-software-management.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-software-management.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-supervision.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-supervision.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-sync.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-sync.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-trace.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-trace.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-transceiver.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-transceiver.yang with 99% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-troubleshooting.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-troubleshooting.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-udp-echo.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-udp-echo.yang with 100% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-uplane-conf.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-uplane-conf.yang with 99% similarity]
ntsimulator/deploy/o-ran/yang/o-ran-usermgmt.yang [moved from ntsimulator/yang/o-ran/ru-fh/o-ran-usermgmt.yang with 96% similarity]
ntsimulator/deploy/supervisord.conf [deleted file]
ntsimulator/deploy/tls/ca.srl [deleted file]
ntsimulator/deploy/tls/client.key [deleted file]
ntsimulator/deploy/tls/enable_connections.sh [deleted file]
ntsimulator/deploy/tls/enable_netconf_call_home.sh [deleted file]
ntsimulator/deploy/tls/enable_ssh_key.sh [deleted file]
ntsimulator/deploy/tls/enable_tls.sh [deleted file]
ntsimulator/deploy/tls/netconf_browser.crt [deleted file]
ntsimulator/deploy/tls/netconf_browser.csr [deleted file]
ntsimulator/deploy/tls/set_NTS_IP.sh [deleted file]
ntsimulator/deploy/x-ran/CMakeLists.txt [deleted file]
ntsimulator/deploy/x-ran/Dockerfile [deleted file]
ntsimulator/deploy/x-ran/config.json [new file with mode: 0644]
ntsimulator/deploy/x-ran/container-tag.yaml
ntsimulator/deploy/x-ran/edit-config-after-activate.sh [deleted file]
ntsimulator/deploy/x-ran/edit-config-after-activate.xml [deleted file]
ntsimulator/deploy/x-ran/edit-config-after-download.sh [deleted file]
ntsimulator/deploy/x-ran/edit-config-after-download.xml [deleted file]
ntsimulator/deploy/x-ran/edit-config-demo-start.sh [deleted file]
ntsimulator/deploy/x-ran/edit-config-demo-start.xml [deleted file]
ntsimulator/deploy/x-ran/supervisord.conf
ntsimulator/deploy/x-ran/ubuntu.Dockerfile [new file with mode: 0644]
ntsimulator/deploy/x-ran/yang/iana-hardware.yang [moved from ntsimulator/yang/o-ran/ru-fh/iana-hardware.yang with 100% similarity, mode: 0755]
ntsimulator/deploy/x-ran/yang/iana-if-type.yang [moved from ntsimulator/yang/x-ran/iana-if-type.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/ietf-crypto-types.yang [moved from ntsimulator/yang/x-ran/ietf-crypto-types.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/ietf-dhcpv6-types.yang [moved from ntsimulator/yang/x-ran/ietf-dhcpv6-types.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/ietf-hardware.yang [moved from ntsimulator/yang/o-ran/ru-fh/ietf-hardware.yang with 100% similarity, mode: 0755]
ntsimulator/deploy/x-ran/yang/ietf-inet-types.yang [moved from ntsimulator/yang/x-ran/ietf-inet-types.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/ietf-interfaces.yang [moved from ntsimulator/yang/o-ran/ru-fh/ietf-interfaces.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/ietf-ip.yang [moved from ntsimulator/yang/x-ran/ietf-ip.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/ietf-netconf-acm.yang [moved from ntsimulator/yang/x-ran/ietf-netconf-acm.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/ietf-netconf-monitoring.yang [moved from ntsimulator/yang/x-ran/ietf-netconf-monitoring.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/ietf-yang-types.yang [moved from ntsimulator/yang/o-ran/ru-fh/ietf-yang-types.yang with 100% similarity, mode: 0755]
ntsimulator/deploy/x-ran/yang/org-openroadm-user-mgmt.yang [moved from ntsimulator/yang/x-ran/org-openroadm-user-mgmt.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-alarm-id.yang [moved from ntsimulator/yang/x-ran/xran-alarm-id.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-ald-port.yang [moved from ntsimulator/yang/x-ran/xran-ald-port.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-ald.yang [moved from ntsimulator/yang/x-ran/xran-ald.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-beamforming.yang [moved from ntsimulator/yang/x-ran/xran-beamforming.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-delay-management.yang [moved from ntsimulator/yang/x-ran/xran-delay-management.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-dhcp.yang [moved from ntsimulator/yang/x-ran/xran-dhcp.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-ecpri-delay.yang [moved from ntsimulator/yang/x-ran/xran-ecpri-delay.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-externalio.yang [moved from ntsimulator/yang/x-ran/xran-externalio.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-fan.yang [moved from ntsimulator/yang/x-ran/xran-fan.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-file-management.yang [moved from ntsimulator/yang/x-ran/xran-file-management.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-fm.yang [moved from ntsimulator/yang/x-ran/xran-fm.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-hardware.yang [moved from ntsimulator/yang/x-ran/xran-hardware.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-interfaces.yang [moved from ntsimulator/yang/x-ran/xran-interfaces.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-lbm.yang [moved from ntsimulator/yang/x-ran/xran-lbm.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-module-cap.yang [moved from ntsimulator/yang/x-ran/xran-module-cap.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-mplane-int.yang [moved from ntsimulator/yang/x-ran/xran-mplane-int.yang with 98% similarity]
ntsimulator/deploy/x-ran/yang/xran-operations.yang [moved from ntsimulator/yang/x-ran/xran-operations.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-performance-management.yang [moved from ntsimulator/yang/x-ran/xran-performance-management.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-processing-element.yang [moved from ntsimulator/yang/x-ran/xran-processing-element.yang with 89% similarity]
ntsimulator/deploy/x-ran/yang/xran-software-management.yang [moved from ntsimulator/yang/x-ran/xran-software-management.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-supervision.yang [moved from ntsimulator/yang/x-ran/xran-supervision.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-sync.yang [moved from ntsimulator/yang/x-ran/xran-sync.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-transceiver.yang [moved from ntsimulator/yang/x-ran/xran-transceiver.yang with 98% similarity]
ntsimulator/deploy/x-ran/yang/xran-troubleshooting.yang [moved from ntsimulator/yang/x-ran/xran-troubleshooting.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-udp-echo.yang [moved from ntsimulator/yang/x-ran/xran-udp-echo.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-uplane-conf.yang [moved from ntsimulator/yang/x-ran/xran-uplane-conf.yang with 100% similarity]
ntsimulator/deploy/x-ran/yang/xran-usermgmt.yang [moved from ntsimulator/yang/x-ran/xran-usermgmt.yang with 96% similarity]
ntsimulator/docker-build-nts-manager.sh [deleted file]
ntsimulator/docker-build-nts-o-ran-ru-fh.sh [deleted file]
ntsimulator/docker-build-nts-o-ran-sc-o-ran-ru.sh [deleted file]
ntsimulator/docker-build-nts-xran.sh [deleted file]
ntsimulator/inc/utils/utils.h [deleted file]
ntsimulator/nts-ng-docker-image-build-ubuntu.yaml [new file with mode: 0644]
ntsimulator/ntsim-ng/core/app/manager.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/app/manager.h [new file with mode: 0644]
ntsimulator/ntsim-ng/core/app/manager_operations.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/app/network_function.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/app/network_function.h [new file with mode: 0644]
ntsimulator/ntsim-ng/core/context.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/context.h [new file with mode: 0644]
ntsimulator/ntsim-ng/core/datastore/populate.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/datastore/populate.h [new file with mode: 0644]
ntsimulator/ntsim-ng/core/datastore/populate_rec.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/datastore/schema.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/datastore/schema.h [moved from ntsimulator/src/ves-messages/heartbeat.h with 61% similarity]
ntsimulator/ntsim-ng/core/docker.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/docker.h [new file with mode: 0644]
ntsimulator/ntsim-ng/core/faults/faults.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/faults/faults.h [new file with mode: 0644]
ntsimulator/ntsim-ng/core/faults/faults_counters.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/faults/faults_logic.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/faults/faults_processing.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/faults/faults_ves.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/framework.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/framework.h [new file with mode: 0644]
ntsimulator/ntsim-ng/core/nc_config.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/nc_config.h [new file with mode: 0644]
ntsimulator/ntsim-ng/core/session.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/session.h [new file with mode: 0644]
ntsimulator/ntsim-ng/core/test.c [new file with mode: 0644]
ntsimulator/ntsim-ng/core/test.h [new file with mode: 0644]
ntsimulator/ntsim-ng/features/manual_notification/manual_notification.c [new file with mode: 0644]
ntsimulator/ntsim-ng/features/manual_notification/manual_notification.h [new file with mode: 0644]
ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.c [new file with mode: 0644]
ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.h [new file with mode: 0644]
ntsimulator/ntsim-ng/features/ves_file_ready/ves_file_ready.c [new file with mode: 0644]
ntsimulator/ntsim-ng/features/ves_file_ready/ves_file_ready.h [new file with mode: 0644]
ntsimulator/ntsim-ng/features/ves_heartbeat/ves_heartbeat.c [new file with mode: 0644]
ntsimulator/ntsim-ng/features/ves_heartbeat/ves_heartbeat.h [new file with mode: 0644]
ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.c [new file with mode: 0644]
ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.h [new file with mode: 0644]
ntsimulator/ntsim-ng/main.c [new file with mode: 0644]
ntsimulator/ntsim-ng/utils/http_client.c [new file with mode: 0644]
ntsimulator/ntsim-ng/utils/http_client.h [new file with mode: 0644]
ntsimulator/ntsim-ng/utils/log_utils.c [new file with mode: 0644]
ntsimulator/ntsim-ng/utils/log_utils.h [new file with mode: 0644]
ntsimulator/ntsim-ng/utils/nc_client.c [new file with mode: 0644]
ntsimulator/ntsim-ng/utils/nc_client.h [new file with mode: 0644]
ntsimulator/ntsim-ng/utils/nts_utils.c [new file with mode: 0644]
ntsimulator/ntsim-ng/utils/nts_utils.h [new file with mode: 0644]
ntsimulator/ntsim-ng/utils/rand_utils.c [new file with mode: 0644]
ntsimulator/ntsim-ng/utils/rand_utils.h [new file with mode: 0644]
ntsimulator/ntsim-ng/utils/sys_utils.c [new file with mode: 0644]
ntsimulator/ntsim-ng/utils/sys_utils.h [new file with mode: 0644]
ntsimulator/ntsim-ng/utils/type_utils.c [new file with mode: 0644]
ntsimulator/ntsim-ng/utils/type_utils.h [new file with mode: 0644]
ntsimulator/regxstring/CHANGES [new file with mode: 0644]
ntsimulator/regxstring/LICENSE [new file with mode: 0644]
ntsimulator/regxstring/README.md [new file with mode: 0644]
ntsimulator/regxstring/gen_regex.cpp [new file with mode: 0644]
ntsimulator/regxstring/main.cpp [new file with mode: 0644]
ntsimulator/regxstring/regxstring.cpp [new file with mode: 0644]
ntsimulator/regxstring/regxstring.h [new file with mode: 0644]
ntsimulator/regxstring/regxstring_impl.cpp [new file with mode: 0644]
ntsimulator/regxstring/regxstring_impl.h [new file with mode: 0644]
ntsimulator/scripts/clean.sh [deleted file]
ntsimulator/scripts/configuration.json [deleted file]
ntsimulator/scripts/docker-compose.yml [deleted file]
ntsimulator/scripts/docker_stats.sh [deleted file]
ntsimulator/scripts/model-install.sh.in [deleted file]
ntsimulator/scripts/model-uninstall.sh [deleted file]
ntsimulator/scripts/model-uninstall.sh.in [deleted file]
ntsimulator/scripts/stock_config.xml [deleted file]
ntsimulator/scripts/tls/ca.key [deleted file]
ntsimulator/scripts/tls/ca.pem [deleted file]
ntsimulator/scripts/tls/ca.srl [deleted file]
ntsimulator/scripts/tls/client.crt [deleted file]
ntsimulator/scripts/tls/client.key [deleted file]
ntsimulator/scripts/tls/enable_ssh_key.sh [deleted file]
ntsimulator/scripts/tls/enable_tls.sh [deleted file]
ntsimulator/scripts/tls/netconf_browser.crt [deleted file]
ntsimulator/scripts/tls/netconf_browser.csr [deleted file]
ntsimulator/src/CMakeLists.txt [deleted file]
ntsimulator/src/generic-notifications/CMakeLists.txt [deleted file]
ntsimulator/src/generic-notifications/generic-notifications.c [deleted file]
ntsimulator/src/ntsimulator-manager/CMakeLists.txt [deleted file]
ntsimulator/src/ntsimulator-manager/ntsimulator-manager.c [deleted file]
ntsimulator/src/ntsimulator-manager/simulator-operations.c [deleted file]
ntsimulator/src/ntsimulator-manager/simulator-operations.h [deleted file]
ntsimulator/src/o-ran-notifications/CMakeLists.txt [deleted file]
ntsimulator/src/o-ran-notifications/o-ran-notifications.c [deleted file]
ntsimulator/src/software-management-oran/CMakeLists.txt [deleted file]
ntsimulator/src/software-management-oran/sw-management-rpc.c [deleted file]
ntsimulator/src/software-management-xran/CMakeLists.txt [deleted file]
ntsimulator/src/software-management-xran/sw-management-rpc.c [deleted file]
ntsimulator/src/utils/utils.c [deleted file]
ntsimulator/src/ves-messages/CMakeLists.txt [deleted file]
ntsimulator/src/ves-messages/heartbeat.c [deleted file]
ntsimulator/ubuntu_build.sh [new file with mode: 0755]
ntsimulator/yang/auto-load-yangs.sh [deleted file]
ntsimulator/yang/nts-manager/network-topology-simulator.xml [deleted file]
ntsimulator/yang/nts-manager/network-topology-simulator.yang [deleted file]
ntsimulator/yang/o-ran-sc/o-ran-ru/ietf-alarms.yang [deleted file]
ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-alarms-v1.yang [deleted file]
ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-common-alarms-v1.yang [deleted file]
ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-hardware-v1.yang [deleted file]
ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-interfaces-v1.yang [deleted file]
ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-root-v1.yang [deleted file]
ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-ru-alarms-v1.yang [deleted file]
ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-ru-v1.yang [deleted file]
ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-types-v1.yang [deleted file]
ntsimulator/yang/sysrepo-configuration-load.sh [deleted file]
ntsimulator/yang/x-ran/iana-hardware.yang [deleted file]
ntsimulator/yang/x-ran/ietf-hardware.yang [deleted file]
ntsimulator/yang/x-ran/ietf-interfaces.yang [deleted file]
ntsimulator/yang/x-ran/ietf-yang-types.yang [deleted file]

diff --git a/ntsimulator/.gitignore b/ntsimulator/.gitignore
deleted file mode 100644 (file)
index 4be233c..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-# Prerequisites
-*.d
-
-# Object files
-*.o
-*.ko
-*.obj
-*.elf
-
-# Linker output
-*.ilk
-*.map
-*.exp
-
-# Precompiled Headers
-*.gch
-*.pch
-
-# Libraries
-*.lib
-*.a
-*.la
-*.lo
-
-# Shared objects (inc. Windows DLLs)
-*.dll
-*.so
-*.so.*
-*.dylib
-
-# Executables
-*.exe
-*.out
-*.app
-*.i*86
-*.x86_64
-*.hex
-
-# Debug files
-*.dSYM/
-*.su
-*.idb
-*.pdb
-
-# Kernel Module Compile Results
-*.mod*
-*.cmd
-.tmp_versions/
-modules.order
-Module.symvers
-Mkfile.old
-dkms.conf
-.cproject
-.project
-build
\ No newline at end of file
diff --git a/ntsimulator/CMakeLists.txt b/ntsimulator/CMakeLists.txt
deleted file mode 100644 (file)
index 804f80b..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-cmake_minimum_required(VERSION 2.8.12)
-project(ntsimulator)
-set(PROJECT_DESC "Network Topology Simulator using sysrepo and netopeer2")
-include(GNUInstallDirs)
-
-# setup version
-set(NTSIMULATOR_MAJOR_VERSION 1)
-set(NTSIMULATOR_MINOR_VERSION 1)
-set(NTSIMULATOR_PATCH_VERSION 1)
-set(NTSIMULATOR_VERSION ${NTSIMULATOR_MAJOR_VERSION}.${NTSIMULATOR_MINOR_VERSION}.${NTSIMULATOR_PATCH_VERSION})
-set(NTSIMULATOR_SOVERSION ${NTSIMULATOR_MAJOR_VERSION}.${NTSIMULATOR_MINOR_VERSION})
-
-# osx specific
-set(CMAKE_MACOSX_RPATH TRUE)
-
-# set default build type if not specified by user
-if(NOT CMAKE_BUILD_TYPE)
-    set(CMAKE_BUILD_TYPE debug)
-endif()
-string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
-
-set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
-
-set(CMAKE_C_FLAGS         "${CMAKE_C_FLAGS} -Wall -Wpedantic -std=gnu11 -Wno-language-extension-token")
-if(CMAKE_COMPILER_IS_GNUCC)
-    # disable strict aliasing in GCC, since it produces false alarams in libev
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-strict-aliasing")
-endif()
-set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O2")
-set(CMAKE_C_FLAGS_DEBUG   "-g -O0")
-
-if(NOT UNIX)
-    message(FATAL_ERROR "Only Unix-like systems are supported.")
-endif()
-
-if(NOT DEFINED IS_DEVELOPER_CONFIGURATION)
-    if(CMAKE_BUILD_TYPE_LOWER MATCHES "debug" AND NOT CMAKE_BUILD_TYPE_LOWER MATCHES "^rel")
-        set(IS_DEVELOPER_CONFIGURATION true)
-    else()
-        set(IS_DEVELOPER_CONFIGURATION false)
-    endif()
-endif()
-
-# location of system repository
-if(${IS_DEVELOPER_CONFIGURATION})
-    set(REPOSITORY_LOC "${CMAKE_BINARY_DIR}/repository" CACHE PATH "System repository location, contains configuration schema and data files.")
-else()
-    set(REPOSITORY_LOC "/etc/sysrepo" CACHE PATH "System repository location, contains configuration schema and data files.")
-endif()
-
-# include custom Modules
-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMakeModules/")
-include_directories(${CMAKE_CURRENT_BINARY_DIR})
-include_directories("${CMAKE_CURRENT_SOURCE_DIR}/inc")
-
-# find required libraries
-find_package(SYSREPO REQUIRED)
-include_directories(${SYSREPO_INCLUDE_DIR})
-
-# add subdirectories
-add_subdirectory(src)
-
-# find sysrepoctl
-if (NOT SYSREPOCTL_EXECUTABLE)
-    find_program(SYSREPOCTL_EXECUTABLE sysrepoctl)
-endif()
-if (NOT SYSREPOCTL_EXECUTABLE)
-    message(FATAL_ERROR "Unable to find sysrepoctl, set SYSREPOCTL_EXECUTABLE manually.")
-endif()
-
-# find sysrepocfg
-if (NOT SYSREPOCFG_EXECUTABLE)
-    find_program(SYSREPOCFG_EXECUTABLE sysrepocfg)
-endif()
-if (NOT SYSREPOCFG_EXECUTABLE)
-    message(FATAL_ERROR "Unable to find sysrepocfg, set SYSREPOCFG_EXECUTABLE manually.")
-endif()
-
-# Command line options to be passed to `sysrepoctl` when working with modules
-# which should only be accessible by an administrator
-if (NOT SYSREPOCTL_ROOT_PERMS)
-    set(SYSREPOCTL_ROOT_PERMS "-o root:root -p 600")
-endif()
-
-install(CODE "
-    set(ENV{SYSREPOCTL} ${SYSREPOCTL_EXECUTABLE})
-    set(ENV{SYSREPOCFG} ${SYSREPOCFG_EXECUTABLE})
-    set(ENV{SYSREPOCTL_ROOT_PERMS} SYSREPOCTL_ROOT_PERMS)
-    execute_process(COMMAND ${PROJECT_BINARY_DIR}/model-install.sh)")
-
-
-
diff --git a/ntsimulator/CMakeModules/FindSYSREPO.cmake b/ntsimulator/CMakeModules/FindSYSREPO.cmake
deleted file mode 100644 (file)
index 7bce85c..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#  SYSREPO_FOUND - System has libsysrepo
-#  SYSREPO_INCLUDE_DIRS - The libsysrepo include directories
-#  SYSREPO_LIBRARIES - The libraries needed to use libsysrepo
-#  SYSREPO_DEFINITIONS - Compiler switches required for using libsysrepo
-
-find_package(PkgConfig QUIET)
-if(PKG_CONFIG_FOUND)
-    pkg_check_modules(PC_SYSREPO QUIET sysrepo)
-    set(SYSREPO_DEFINITIONS ${PC_SYSREPO_CFLAGS_OTHER})
-endif()
-
-find_path(SYSREPO_INCLUDE_DIR sysrepo.h
-          HINTS ${PC_SYSREPO_INCLUDEDIR} ${PC_SYSREPO_INCLUDE_DIRS}
-          PATH_SUFFIXES sysrepo)
-
-find_library(SYSREPO_LIBRARY NAMES sysrepo 
-             HINTS ${PC_SYSREPO_LIBDIR} ${PC_SYSREPO_LIBRARY_DIRS})
-
-set(SYSREPO_LIBRARIES ${SYSREPO_LIBRARY} )
-set(SYSREPO_INCLUDE_DIRS ${SYSREPO_INCLUDE_DIR})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(sysrepo  DEFAULT_MSG
-                                  SYSREPO_LIBRARY SYSREPO_INCLUDE_DIR)
-
-mark_as_advanced(SYSREPO_INCLUDE_DIR SYSREPO_LIBRARY)
diff --git a/ntsimulator/README.md b/ntsimulator/README.md
deleted file mode 100644 (file)
index 1b545d4..0000000
+++ /dev/null
@@ -1,394 +0,0 @@
-# Network Topology Simulator (NTS)
-
-The Network Topology Simulator is a framework that allows simulating devices that expose a management interface through a NETCONF/YANG interface.
-
-## Description
-
-### Overview
-
-The NETCONF/YANG management interface is simulated, and any YANG models can be loaded by the framework to be exposed. Random data is generated based on the specific models, such that each simulated device presents different data on its management interface.
-
-The NTS Manager can be used to specify the simulation details and to manage the simulation environment at runtime.
-
-The NTS framework is based on several open-source projects:
-* [Netopeer2](https://github.com/CESNET/Netopeer2) 
-* [libnetconf2](https://github.com/CESNET/libnetconf2) 
-* [libyang](https://github.com/CESNET/libyang)
-* [sysrepo](https://github.com/sysrepo/sysrepo) - all of these are used for the implementation of the NETCONF Server, both in the NTS Manager and in each simulated device
-* [cJSON](https://github.com/DaveGamble/cJSON) - used to create the JSON payloads for talking with the simulation framework
-* [pyang](https://github.com/mbj4668/pyang) - used to create random data from the YANG models that are exposed
-
-Each simulated device is represented as a docker container, where the NETCONF Server is running. The creation and deletion of docker containers associated with simulated devices is handled by the NTS Manager. The NTS Manager is also running as a docker container and exposes a NETCONF/YANG interface to control the simulation.
-
-### NTS Manager
-
-The purpose of the NTS Manager is to ease the utilization of the NTS framework. It enables the user to interact with the simulation framework through a NETCONF/YANG interface. The user has the ability to modify the simulation parameters at runtime and to see the status of the current state of the NTS. The NETCONF/YANG interface will be detailed below.
-
-```
-module: network-topology-simulator
-  +--rw simulator-config!
-  |  +--rw simulated-devices?      uint32
-  |  +--rw mounted-devices?        uint32
-  |  +--rw netconf-call-home?      boolean
-  |  +--rw notification-config
-  |  |  +--rw fault-notification-delay-period*   uint32
-  |  |  +--rw ves-heartbeat-period?              uint32
-  |  |  +--rw is-netconf-available?              boolean
-  |  |  +--rw is-ves-available?                  boolean
-  |  +--rw controller-details
-  |  |  +--rw controller-ip?            inet:ip-address
-  |  |  +--rw controller-port?          inet:port-number
-  |  |  +--rw netconf-call-home-port?   inet:port-number
-  |  |  +--rw controller-username?      string
-  |  |  +--rw controller-password?      string
-  |  +--rw ves-endpoint-details
-  |     +--rw ves-endpoint-ip?            inet:ip-address
-  |     +--rw ves-endpoint-port?          inet:port-number
-  |     +--rw ves-endpoint-auth-method?   authentication-method-type
-  |     +--rw ves-endpoint-username?      string
-  |     +--rw ves-endpoint-password?      string
-  |     +--rw ves-endpoint-certificate?   string
-  |     +--rw ves-registration?           boolean
-  +--ro simulator-status
-     +--ro simulation-usage-details
-     |  +--ro running-simulated-devices?   uint32
-     |  +--ro running-mounted-devices?     uint32
-     |  +--ro ssh-connections?             uint32
-     |  +--ro tls-connections?             uint32
-     |  +--ro base-netconf-port?           uint32
-     |  +--ro cpu-usage?                   percent
-     |  +--ro mem-usage?                   uint32
-     +--ro notification-count
-     |  +--ro total-ves-notifications
-     |  |  +--ro normal?     uint32
-     |  |  +--ro warning?    uint32
-     |  |  +--ro minor?      uint32
-     |  |  +--ro major?      uint32
-     |  |  +--ro critical?   uint32
-     |  +--ro total-netconf-notifications
-     |     +--ro normal?     uint32
-     |     +--ro warning?    uint32
-     |     +--ro minor?      uint32
-     |     +--ro major?      uint32
-     |     +--ro critical?   uint32
-     +--ro simulated-devices-list* [uuid]
-        +--ro uuid                  string
-        +--ro device-ip?            string
-        +--ro device-port*          uint32
-        +--ro is-mounted?           boolean
-        +--ro operational-state?    operational-state-type
-        +--ro notification-count
-           +--ro ves-notifications
-           |  +--ro normal?     uint32
-           |  +--ro warning?    uint32
-           |  +--ro minor?      uint32
-           |  +--ro major?      uint32
-           |  +--ro critical?   uint32
-           +--ro netconf-notifications
-              +--ro normal?     uint32
-              +--ro warning?    uint32
-              +--ro minor?      uint32
-              +--ro major?      uint32
-              +--ro critical?   uint32
-
-  rpcs:
-    +---x restart-simulation
-    +---x add-key-pair-to-odl
-    +---x invoke-notification
-       +---w input
-       |  +---w device-id              string
-       |  +---w yang-module-name       string
-       |  +---w notification-object    string
-       +--ro output
-          +--ro status    enumeration
-```
-
-#### Detailed information about the YANG attributes
-
-##### Configuration
-
-* **simulated-devices** - represents the number of simulated devices. The default value is 0, meaning that when the NTS is started, there are no simulated devices. When this value is increased to **n**, the NTS Manager starts docker containers in order to reach **n** simulated devices. If the value is decreased to **k**, the NTS Manager will remove docker containers, until the number of simulated devices reaches **k**;
-* **mounted-devices** - represents the number of devices to be mounted to an ODL based SDN Controller. The same phylosophy as in the case of the previous leaf applies. If this number is increased, the number of ODL mountpoints increases. Else, the simulated devices are being unmounted from ODL. The number of mounted devices cannot exceed the number of simulated devices. The details about the ODL controller where to mount/unmount are given by the **controller-details** container; **Please note that this cannot be set to a value > 0 if the *ves-registration* leaf is set to 'True'**; For each simulated device, a number of NETCONF endpoints will be mounted, according to the **ssh-connections** and **tls-connections** leafs. See **NETCONF Endpoints** section for more details;
-* **netconf-call-home** - if set to `true`, each simulated device will try to use NETCONF Call Home feature and try to reach the ODL Controller. The default value is `false`.
-*  **notification-config** - this container groups the configuration about fault notification generation of each simulated device;
-* **fault-notification-delay-period** - the amount of seconds between two generated fault notifications. For example, if this has a value of *10*, each simulated device will generate a **random** fault notification every *10* seconds; **when this is set to 0, it will reset the notification counters for the VES and NETCONF notifications, which are exposed in the simulator-status**; The type is a leaf-list, such that the user could define a pattern for sending the notifications. E.g.: [10, 3, 5] means that a notification will be sent after 10 seconds, then after another 3 seconds, then after 5 seconds, and then again after 10, 3, 5 etc.
-* **ves-heartbeat-period** - the amount of seconds between VES heartbeat messages that can be generated by each simulated device. The details about the VES connection endpoint are given in the **ves-endpoint-details** container;
-* **is-netconf-available** - if set to 'True', NETCONF notifications will be sent when a random fault notification is generated, The NETCONF notification that is being sent is currently *o-ran-fm:alarm-notif*; if set to 'False', NETCONF notifications are not being sent out;
-* **is-ves-available** - if set to 'True', VES *faultNotification* messages will be sent when a random fault notification is generated; if set to 'False', VES *faultNotification* messages are not generated;
-* **controller-details** - this container groups the configuration related to the ODL based SDN controller that the simulated devices can connect to;
-* **controller-ip** - the IP address of the ODL based SDN controller where the simulated devices can be mounted. Both IPv4 and IPv6 are supported;
-* **controller-port** - the port of the ODL based SDN controller;
-* **netconf-call-home-port** - the NETCONF Call Home port of the ODL based SDN controller;
-* **controller-username** - the username to be used when connecting to the ODL based SDN controller;
-* **controller-password** - the password to be used when connecting to the ODL based SDN controller;
-* **ves-endpoint-details** - this container groups the configuration related to the VES endpoint where the VES messages are targeted;
-* **ves-endpoint-ip** - the IP address of the VES endpoint where VES messages are targeted;
-* **ves-endpoint-port** - the port address of the VES endpoint where VES messages are targeted;
-* **ves-endpoint-auth-method** - the authentication method to be used when sending the VES message to the VES endpoint. Possible values are:
-  + *no-auth* - no authentication;
-  + *cert-only* - certificate only authentication; in this case the certificate to be used for the communication must be configured;
-  + *basic-auth* - classic username/password authentication; in this case both the username and password need to be configured;
-  + *cert-basic-auth* - authentication that uses both username/password and a certificate; all three values need to be configured in this case;
-* **ves-endpoint-username** - the username to be used when authenticating to the VES endpoint;
-* **ves-endpoint-password** - the password to be used when authenticating to the VES endpoint;
-* **ves-endpoint-certificate** - the certificate to be used when authenticating to the VES endpoint;
-* **ves-registration** - if this is set to 'True' **when simulated devices are starting**, each simulated device will send out *pnfRegistration* VES messages to the configured VES endpoint; if this is set to 'False', *pnfRegistration* VES messages will not be sent out. **Please note that this cannot be set to 'True' is simulated devices are already mounted to ODL based SDN controller (mounted-devices leaf > 0)**; For each simulated device, **ssh-connections + tls-connections** pnfRegistration VES messages will be sent out. See **NETCONF Endpoints** section for more details.
-
-##### Status
-
-* **simulation-usage-details** - this container groups the information about the current simulator status;
-* **running-simulated-devices** - the current number of running simulated devices;
-* **running-mounted-devices** - the current number of running simulated devices that have been mounted to the ODL based SDN controller; For each simulated device, 10 NETCONF endpoints will be mounted (7 SSH + 3 TLS). See **NETCONF Endpoints** section for more details.
-* **ssh-connections** - represents the number of SSH endpoints that are exposed by each of the simulated devices. **Please note that the total number of SSH and TLS connections cannot exceed 100.** The default value is 1. **The value can only be changed when the NTS Manager is started, through the SshConnections environment variable**.
-* **tls-connections** - represents the number of TLS endpoints that are exposed by each of the simulated devices. **Please note that the total number of SSH and TLS connections cannot exceed 100.** The default value is 0. **The value can only be changed when the NTS Manager is started, through the SshConnections environment variable**.
-* **base-netconf-port** - the port that was used as a base when craeting simulated devices;
-* **cpu-usage** - the percentage of the CPU used currently by the simulation framework;
-* **mem-usage** - the amount of RAM used (in MB) currently by the simulation framework;
-* **notification-count** - this container groups the details about the total number of notifications that were generated by the simulated devices;
-* **total-ves-notifications** - this container groups the details about the total number of VES notifications that were generated by the simulated devices, grouped by severity;
-* **total-netcnof-notifications** - this container groups the details about the total number of NETCONF notifications that were generated by the simulated devices - grouped by severity;
-* **simulated-devices-list** - this list contains the details about each simulated devices that is currently running;
-* **uuid** - the Universally Unique ID of the simulated device;
-* **device-ip** - the IP address of the simulated device;
-* **device-port** - the port of the simulated device, where the NETCONF connection is exposed;
-* **is-mounted** - boolean to show whether the device is currently mounted to an ODL based SDN controller;
-* **operational-state** - the operational state of the current simulated device; it can be either *not-specified*, *created*, *running* or *exited*;
-* **notification-count** - this container groups the details about the number of notifications that were generated by this particular simulated device;
-* **ves-notifications** - this container groups the details about the number of VES notifications that were generated by this simulated device, grouped by severity;
-* **netconf-notifications** - this container groups the details about the number of NETCONF notifications that were generated by this simulated device - grouped by severity.
-
-##### RPCs
-
-* **add-key-pair-to-odl** - this RPC can be used to trigger the loading of a *keystore* entry in an ODL based SDN controller such that the controller can connect to the simulated devices via **TLS**. A private key, an associated certificate and a trusted certificate are loaded in the *keystore* entry in ODL. The certificate associated with the private key to be used by ODL in the TLS communication is signed by the same CA as the certificates used by the simulated devices, easing the TLS configuration in both the NETCONF Server and the ODL.
-* **restart-simulation** - this RPC is not yet implemented.
-* **invoke-notification** - this RPC is used for forcing a simulated device to send a NETCONF notification, as defined by the user. 
-    - The **input** needed by the RPC:
-        - **device-id** - this is a string containing the name of the simulated device that we want to send the notification. The user is responsible to give a correct name which really exists, otherwise the RPC will fail.
-        - **yang-module-name** - this is a string containing the name of the YANG module which implements the notification that we want to send. E.g.: ***org-openroadm-device*** module defines several notifications.
-        - **notification-object** - this is a string containing the notification object that we are trying to send from the simulated device, in JSON format. **Please note that the user has the responsibility to ensure that the JSON object is valid, according to the definition of the notification in the YANG module.** There is no possibility to see what was wrong when trying to send an incorrect notification. The RPC will only respond with an "ERROR" status in that case, without further information. E.g. of a JSON containing a notification object of type ***otdr-scan-result*** defined in the ***org-openroadm-device*** YANG module: ***{"org-openroadm-device:otdr-scan-result":{"status":"Successful","status-message":"Scan result was successful","result-file":"/home/result-file.txt"}}***. **Please note that the notification object contains also the name of the YANG model defning it, as a namespace, as seen in the example.**
-    - The **output** returned by the RPC:
-        - **status** - if the notification was send successfully by the simulated device, the RPC will return a **SUCCESS** value. Else, the RPC will return a **ERROR** value.
-
-### Simulated Device
-
-Each simulated device is represented as a docker container, inside which the NETCONF Server runs. The simulated device exposes the YANG models which are found inside the **yang** folder. A custom version of the *pyang* utility is used to generate random data for each of the YANG modules found inside the **yang** folder.
-
-#### NETCONF Endpoints
-
-Each simulated device exposes a number of NETCONF endpoints which represented by the sum of the **SshConnections** and **TlsConnections** environment variables, on consecutive ports. The first simulated device uses the ports starting from the **NETCONF_BASE** environment variable used when starting the NTS Manager, while the next one uses the next ports and so on and so forth. E.g. if the **NETCONF_BASE=50000** and **SshConnections=5** and **TlsConnections=3**, the first simulated device will expose ports from *50000* to *50007*, the second simulated device will expose ports from *5008* to *50015* etc.
-
-The first **SshConnections** ports exposed by a simulated device are **SSH** based. A NETCONF client can connect to the exposed endpoint using one of the SSH ports (e.g. 50000 to 50007, considering the previous example) and the **username/password**: *netconf/netconf*.
-
-The last **TlsConnections** ports exposed by a simulated device are **TLS** based. A NETCONF client can connect to the exposed endpoint using one of the TLS ports (e.g. 50006 to 50008, considering the previous example), using a valid certificate and the **username**: *netconf*. 
-
-## Usage
-
-### Building the images
-
-The `docker-build-nts-manager.sh` script can be used to built the docker image associated with the NTS Manager. This will create a docker image named *ntsim_manager_light*, which will be used to start the simulation framework. Inside the docker image, port 830 will wait for connections for the NETCONF/YANG management interface.
-
-The `docker-build-onf-core-model-1-2.sh` script can be used to build the docker image associated with a simulated device, exposing the ONF CoreModel version 1.2.
-
-The `docker-build-onf-core-model-1-4.sh` script can be used to build the docker image associated with a simulated device, exposing the ONF CoreModel version 1.4.
-
-The `docker-build-openroadm.sh` script can be used to build the docker image associated with a simulated device, exposing the OpenROADM models.
-
-The `docker-build-o-ran-device.sh` script can be used to build the docker image associated with a simulated device, exposing the O-RAN models.
-
-The `docker-build-o-ran-sc-o-ran-ru.sh` script can be used to build the docker image associated with a simulated device, exposing the O-RAN-SC models.
-
-The `docker-build-x-ran-device.sh*` script can be used to build the docker image associated with a simulated device, exposing the X-RAN models.
-
-### Starting the NTS Manager
-
-The NTS Manager can be started using the `docker-compose.yml` file that is provided inside tthe **scripts** folder. Further, the parameters present in this file are explained.
-
-```yaml
-version: '3'
-services:
-  ntsimulator:
-    image: "ntsim_manager:latest"
-    container_name: NTS_Manager
-    ports:
-     - "8300:830"
-    volumes:
-     - "/var/run/docker.sock:/var/run/docker.sock"
-     - "/var/tmp/NTS_Manager:/opt/dev/scripts"
-     - "/usr/bin/docker:/usr/bin/docker"
-    labels:
-      "NTS-manager": ""
-    environment:
-      NTS_IP: "172.17.0.1"
-      NETCONF_BASE: 50000
-      DOCKER_ENGINE_VERSION: "1.40"
-      MODELS_IMAGE: "ntsim_oran"
-      VesHeartbeatPeriod: 0
-      IsVesAvailable: "true"
-      IsNetconfAvailable: "true"
-      VesRegistration: "false"
-      VesEndpointPort: 8080
-      VesEndpointIp: "172.17.0.1"
-      SshConnections: 1
-      TlsConnections: 0
-      K8S_DEPLOYMENT: "false"
-      CONTAINER_NAME: "ntsimulator"
-      NetconfCallHome: "true"
-      NetconfCallHomePort: 6666
-      ControllerIp: "10.20.11.121"
-      ControllerPort: 8181
-      ControllerUsername: "admin"
-      ControllerPassword: "admin"
-      IPv6Enabled: "true"
-```
-
-
-* Port mapping:
-    * `"8300:830"` - this maps the *830* port from inside the docker container of the NTS Manager to the port *8300* from the host, and binds it to any IP address on the host:
-    
-* Volumes - these map 3 important things:
-    * the docker socket from the host is mapped inside the docker container:
-        `/var/run/docker.sock:/var/run/docker.sock` - **please do not modify the path inside the container!**;
-    * any folder from the host can be mapped to inside the docker container into othe **/opt/dev/scripts** folder:
-        `/var/tmp/NTS_Manager:/opt/dev/scripts` - **please do not modify the path inside the container!**;
-    * the path to the docker executable needs to be mapped inside the container:
-        `/usr/bin/docker:/usr/bin/docker` - **please do not modify the path inside the container!**;
-        
-* Labels - this associates the *NTS-manager* label to the docker container where the NTS runs;
-* Environment variables:
-    * **NTS_IP** - this should point to an IP address **from the host**, through which the simulated devices will be accessed;
-    * **NETCONF_BASE** - this is the starting port used to expose NETCONF endpoints. Starting from this, each device will use 10 consecutive ports for its endpoints; **Please note that if multiple managers are deployed on the same machine, this environment variable needs to be different for each of the managers!**
-    * **DOCKER_ENGINE_VERSION** - this is the version of the *docker engine* installed currently on the host. This can be verified using `docker version` command in the host, and looking to the `API version:      #.##` variable from the Server details.
-    * **MODELS_IMAGE** - this represents the name of the docker image that represents the simulated device. The NTS Manager will start containers using this image, when starting simulated devices.
-    * **VesHeartbeatPeriod** - this can change the default value of the **ves-heartbeat-period** leaf used by the NTS Manager.
-    * **IsVesAvailable** - this can change the default value of the **is-ves-available** leaf used by the NTS Manager.
-    * **IsNetconfAvailable** - this can change the default value of the **is-netconf-available** leaf used by the NTS Manager.
-    * **VesRegistration** - this can change the default value of the **ves-registration** leaf used by the NTS Manager.
-    * **VesEndpointPort** - this can change the default value of the **ves-endpoint-port** leaf used by the NTS Manager.
-    * **VesEndpointIp** - this can change the default value of the **ves-endpoint-ip** leaf used by the NTS Manager.
-    * **SshConnections** - **this can change the number of SSH connection endpoints which are exposed by each simulated device.**
-    * **TlsConnections** - **this can change the number of TLS connection endpoints which are exposed by each simulated device.**
-    * **K8S_DEPLOYMENT** - this value can be set to `true` when the user wants to the NTS Framework in a Kubernetes deployment. The default is `false`.
-    * **CONTAINER_NAME** - this represents the name to be used by the NTS Manager for asigning to each simulated device, suffixed by a number. The default is `ntsim`. E.g.: the first simulated device will be *ntsim-0*, the second onoe *ntsim-1* and so on. **Please note that if multiple managers are deployed on the same machine, this environment variable needs to be different for each of the managers!**
-    * **ControllerIp** - this can change the default value of the **controller-ip** leaf used by the NTS Manager. The default is `172.17.0.1`.
-    * **ControllerPort** - this can change the default value of the **controller-port** leaf used by the NTS Manager. The default is `8181`.
-    * **NetconfCallHomePort** - this can change the default value of the **netconf-call-home-port** leaf used by the NTS Manager. The default is `6666`.
-    * **ControllerUsername** - this can change the default value of the **controller-username** leaf used by the NTS Manager. The default is `admin`.
-    * **ControllerPassword** - this can change the default value of the **controller-password** leaf used by the NTS Manager. The default is `admin`.
-    * **NetconfCallHome** - this can change the default value of the **netconf-call-home** leaf used by the NTS Manager. The default is `false`.
-    * **IPv6Enabled**: if this is set to `true`, IPv6 is enabled. **Please note that for a working configuration, it is the user responsibility to correctly configure the Docker daemon to work with IPv6, prior to starting the NTS Manager!**
-    
-After modifying the `docker-compose.yml` file with values specific to your host, the NTS Manager can be started by running the command `docker-compose up` from the **scripts** folder.
-
-After the NTS Manager is started, it will wait for connections on its NETCONF/YANG management interface. One can connect to this using a NETCONF Client. The **username/password** for connecting are: *netconf/netconf*.
-
-Example of `docker ps` command result, after the NTS Manager was started:
-
-```
-7ff723b7f794        ntsim_manager:latest   "sh -c '/usr/bin/sup…"   5 days ago          Up 5 days           0.0.0.0:8300->830/tcp       NTS_Manager
-```
-
-### Using the NTS Manager
-
-When the NTS Manager is started, its default configuration looks like this:
-
-```xml
-<simulator-config xmlns="urn:onf:params:xml:ns:yang:network-topology-simulator">
-    <simulated-devices>0</simulated-devices>
-    <mounted-devices>0</mounted-devices>
-    <netconf-call-home>false</netconf-call-home>
-    <notification-config>
-        <fault-notification-delay-period>0</fault-notification-delay-period>
-        <ves-heartbeat-period>0</ves-heartbeat-period>
-        <is-netconf-available>true</is-netconf-available>
-        <is-ves-available>true</is-ves-available>
-    </notification-config>
-    <controller-details>
-        <controller-ip>172.17.0.1</controller-ip>
-        <controller-port>8181</controller-port>
-        <netconf-call-home-port>6666</netconf-call-home-port>
-        <controller-username>admin</controller-username>
-        <controller-password>admin</controller-password>
-    </controller-details>
-    <ves-endpoint-details>
-        <ves-endpoint-ip>172.17.0.1</ves-endpoint-ip>
-        <ves-endpoint-port>30007</ves-endpoint-port>
-        <ves-endpoint-auth-method>no-auth</ves-endpoint-auth-method>
-        <ves-registration>false</ves-registration>
-    </ves-endpoint-details>
-</simulator-config>
-```
-
-This configuration can be altered by connecting to the NTS Manager with a NETCONF Client.
-
-### Starting a simulated device
-
-Example RPC for starting **one** simulated device:
-
-```xml
-<?xml version="1.0" encoding="utf-8"?>
-<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="">
-  <edit-config>
-    <target>
-      <running/>
-    </target>
-    <config>
-      <simulator-config xmlns="urn:onf:params:xml:ns:yang:network-topology-simulator">
-        <simulated-devices>1</simulated-devices>
-      </simulator-config>
-    </config>
-  </edit-config>
-</rpc>
-```
-
-
-If the leaf `<simulated-devices>1</simulated-devices>` will be set to a value of **1**, the NTS Manager will start a new docker container. We can verify that this was successfull by running the `docker ps` command. The results will look like this:
-
-```
-c18eb7a362f5        ntsim_oran             "sh -c '/usr/bin/sup…"   4 days ago          Up 4 days           172.17.0.1:50000->830/tcp, 172.17.0.1:50001->831/tcp, 172.17.0.1:50002->832/tcp, 172.17.0.1:50003->833/tcp, 172.17.0.1:50004->834/tcp, 172.17.0.1:50005->835/tcp, 172.17.0.1:50006->836/tcp, 172.17.0.1:50007->837/tcp, 172.17.0.1:50008->838/tcp, 172.17.0.1:50009->839/tcp   reverent_bhabha
-```
-
-
-## Troubleshooting
-
-### No simulated devices are starting
-
-If, after setting the leaf `<simulated-devices>1</simulated-devices>` to a value greater that 0, no new containers are created, please make sure that the image name specified in the **MODELS_IMAGE** environment variable when starting the NTS Manager is present in the host. You can verify that using the `docker images` command.
-
-Example of a result of such a command:
-
-```
-ntsim_oran_light       latest           57b065de4458     4 days ago     186MB
-```
-
-This means that `MODELS_IMAGE: "ntsim_oran_light:latest"` can be used as an environment variable when starting the NTS Manager.
-
-
-## Release notes
-
-### **version 0.6.5**
-
-Added features:
-* **basic-auth** is now available for pnfRegistration messages - if the VES Endpoint supports basic-auth (with username and password), the user can configure these endpoint details and the pnfRegistration message will use them.
-
-### **version 0.6.4**
-
-Bug fixes and improvements:
-* Fixed bug where pnfRegistration messages for TLS connections were not sent.
-* Fixed bug for manual notification generation failed when notification object was too long.
-
-### **version 0.6.1**
-
-Added features:
-* **Manual notification generation** - this enables the user to send a NETCONF notification from a simulated device, using the *invoke-notification* RPC defined in the NTS Manager.
-* **automatic pulling of the simulated device image** - the NTS Manager will automatically try to pull the image of the simulated device (as defined in the **MODELS_IMAGE** environment variable) before starting a simulated device.
-* **custom naming of simulated devices** - the user can now define its own name prefix for simulated devices, through the **CONTAINER_NAME** environment variable defined in the docker-compose.yml. E.g.: if CONTAINER_NAME: "ntsim", the simulated devices will be: *ntsim-0*, *ntsim-1* etc.
-
-Bug fixes and improvements:
-* **ssh-connections** and **tls-connections** are now removed from the simulator-config, and can be set only when the NTS Manager is started, through the **SshConnections** and **TlsConnections** environment variables defined in the docker-compose.yml. The leafs are not moved in the simulator-status, such that the user can check at runting what are the values defined.
-* **fault-notification-delay-period** has now the attribute *ordered-by user*, meaning that the order defined by the user when adding multiple values to the leaf-list is preserved.
-
-### **version 0.5.1**
-
-Added features:
-* **NETCONF Call Home** - this enables each simulated device to use the Call Home feature to connect to the ODL instance, once it boots up. **Please note that when a device is using Call Home, it will no longed expose all the number of *ssh-connections* and *tls-connections*, but a single Call Home endpoint. **
-* **controller-details** configuration leafs are now exposed can now be set at startup time in the docker-compose YAML file, as environment variables.
\ No newline at end of file
diff --git a/ntsimulator/deploy/Dockerfile b/ntsimulator/deploy/Dockerfile
deleted file mode 100644 (file)
index 5fa04e8..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-################################################################################
-#
-# Copyright 2019 highstreet technologies GmbH and others
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-# 
-#     http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-################################################################################
-FROM ubuntu:18.04
-
-MAINTAINER alexandru.stancu@highstreet-technologies.com
-
-LABEL maintainer="alexandru.stancu@highstreet-technologies.com"
-
-#ARG BUILD_DATE
-
-#LABEL build-date=$BUILD_DATE
-
-RUN \
-      apt-get update && apt-get install -y \
-      # general tools
-      git \
-      cmake \
-      build-essential \
-      vim \
-      supervisor \
-      # libyang
-      libpcre3-dev \
-      pkg-config \
-      # sysrepo
-      libavl-dev \
-      libev-dev \
-      libprotobuf-c-dev \
-      protobuf-c-compiler \
-      # netopeer2 \
-      libssh-dev \
-      libssl-dev \
-      # bindings
-      swig \
-      python-dev \
-      libcurl4 \
-      libcurl4-openssl-dev \
-      curl \
-      bc \
-      python-setuptools \
-      python-pip
-
-# add netconf user
-RUN \
-      adduser --system netconf && \
-      echo "netconf:netconf" | chpasswd
-
-# generate ssh keys for netconf user
-RUN \
-      mkdir -p /home/netconf/.ssh && \
-      ssh-keygen -A && \
-      ssh-keygen -t dsa -P '' -f /home/netconf/.ssh/id_dsa && \
-      cat /home/netconf/.ssh/id_dsa.pub > /home/netconf/.ssh/authorized_keys && \
-#echo "Host *\n    StrictHostKeyChecking accept-new" >> /home/netconf/.ssh/config
-      echo "    StrictHostKeyChecking no" >> /etc/ssh/ssh_config && \
-      mkdir -p /root/.ssh && \
-      cat /home/netconf/.ssh/id_dsa.pub > /root/.ssh/authorized_keys
-       
-# use /opt/dev as working directory
-RUN mkdir /opt/dev
-WORKDIR /opt/dev
-
-# libcjson
-RUN \
-         git clone https://github.com/Melacon/cJSON.git && \
-      cd cJSON && mkdir build && cd build && \
-      cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_CJSON_TEST=Off -DCMAKE_INSTALL_PREFIX=/usr .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# libyang
-RUN \
-         git clone https://github.com/Melacon/libyang.git && \
-      cd libyang && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_BUILD_TESTS=OFF .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# sysrepo
-RUN \
-         git clone https://github.com/Melacon/sysrepo.git && \
-      sed -i 's/#define MAX_BLOCKS_AVAIL_FOR_ALLOC    3/#define MAX_BLOCKS_AVAIL_FOR_ALLOC    6/g' ./sysrepo/src/common/sr_mem_mgmt.h && \
-      cd sysrepo && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_TESTS=OFF -DREPOSITORY_LOC:PATH=/etc/sysrepo -DREQUEST_TIMEOUT=60 -DOPER_DATA_PROVIDE_TIMEOUT=60 .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# libnetconf2
-RUN \
-         git clone https://github.com/Melacon/libnetconf2.git && \
-      cd libnetconf2 && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_BUILD_TESTS=OFF .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# keystore
-RUN \
-         cd /opt/dev && \
-         git clone https://github.com/Melacon/Netopeer2.git && \
-      cd Netopeer2 && \
-      cd keystored && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# overwrite number of endpoints exposed by the NETCONF server
-COPY ./scripts/stock_config.xml /opt/dev/Netopeer2/server/stock_config.xml
-# netopeer2
-RUN \
-      cd /opt/dev && \
-      cd Netopeer2/server && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" .. && \
-      make -j2 && \
-      make install && \
-      cd ../../cli && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" .. && \
-      make -j2 && \
-      make install
-
-RUN pip install rstr && pip install exrex && pip install ipaddress
-        
-# pyang 
-RUN \
-         cd /opt/dev && \
-         git clone https://github.com/Melacon/pyang.git && \
-         cd pyang && python setup.py build && python setup.py install
-         
-#NTSimulator Manager - notifications
-COPY . /opt/dev/ntsimulator
-RUN \
-      cd /opt/dev && \
-      cd ntsimulator && mkdir build  && cd build && \
-      cmake .. && \
-      make -j2&& \
-      make install
-
-COPY deploy/supervisord.conf /etc/supervisord.conf
-
-COPY ./scripts/tls /home/netconf/.ssh
-
-COPY ./yang /opt/dev/yang
-WORKDIR /opt/dev
-RUN \
-         cd yang && \
-         ./auto-load-yangs.sh
-         
-ENV EDITOR vim
-EXPOSE 830
-EXPOSE 831
-EXPOSE 832
-EXPOSE 833
-EXPOSE 834
-EXPOSE 835
-EXPOSE 836
-EXPOSE 837
-EXPOSE 838
-EXPOSE 839
-
-CMD ["sh", "-c", "/usr/bin/supervisord -c /etc/supervisord.conf"]
diff --git a/ntsimulator/deploy/base/build_ntsim-ng.sh b/ntsimulator/deploy/base/build_ntsim-ng.sh
new file mode 100755 (executable)
index 0000000..dbabaab
--- /dev/null
@@ -0,0 +1,85 @@
+#!/bin/bash
+
+# /*************************************************************************
+# *
+# * Copyright 2020 highstreet technologies GmbH and others
+# *
+# * Licensed under the Apache License, Version 2.0 (the "License");
+# * you may not use this file except in compliance with the License.
+# * You may obtain a copy of the License at
+# *
+# *     http://www.apache.org/licenses/LICENSE-2.0
+# *
+# * Unless required by applicable law or agreed to in writing, software
+# * distributed under the License is distributed on an "AS IS" BASIS,
+# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# * See the License for the specific language governing permissions and
+# * limitations under the License.
+# ***************************************************************************/
+
+files=(
+    "core/context.c"
+    "core/docker.c"
+    "core/framework.c"
+    "core/test.c"
+    "core/session.c"
+    "core/nc_config.c"
+    "core/app/manager.c"
+    "core/app/manager_operations.c"
+    "core/app/network_function.c"
+    "core/datastore/schema.c"
+    "core/datastore/populate.c"
+    "core/datastore/populate_rec.c"
+    "core/faults/faults.c"
+    "core/faults/faults_counters.c"
+    "core/faults/faults_processing.c"
+    "core/faults/faults_logic.c"
+    "core/faults/faults_ves.c"
+    "utils/log_utils.c"
+    "utils/rand_utils.c"
+    "utils/type_utils.c"
+    "utils/sys_utils.c"
+    "utils/http_client.c"
+    "utils/nts_utils.c"
+    "utils/nc_client.c"
+    "features/ves_pnf_registration/ves_pnf_registration.c"
+    "features/ves_heartbeat/ves_heartbeat.c"
+    "features/ves_file_ready/ves_file_ready.c"
+    "features/netconf_call_home/netconf_call_home.c"
+    "features/manual_notification/manual_notification.c"
+    "main.c"
+)
+
+libs=(
+    "argp"
+    "m"
+    "yang"
+    "sysrepo"
+    "netconf2"
+    "cjson"
+    "curl"
+    "pthread"
+)
+
+sources=""
+for i in ${files[@]}
+do
+    sources="$sources source/$i"
+done
+
+libraries=""
+for i in ${libs[@]}
+do
+    libraries="$libraries -l$i"
+done
+
+output="ntsim-ng"
+
+build="gcc -Wall -pedantic -Isource $sources $libraries -o$output"
+
+echo "Building with command: $build"
+$build
+if [ "$?" -ne "0" ]; then
+  echo "Build failed"
+  exit 1
+fi
diff --git a/ntsimulator/deploy/base/build_regxstring.sh b/ntsimulator/deploy/base/build_regxstring.sh
new file mode 100755 (executable)
index 0000000..6e5aa63
--- /dev/null
@@ -0,0 +1,22 @@
+# /*************************************************************************
+# *
+# * Copyright 2020 highstreet technologies GmbH and others
+# *
+# * Licensed under the Apache License, Version 2.0 (the "License");
+# * you may not use this file except in compliance with the License.
+# * You may obtain a copy of the License at
+# *
+# *     http://www.apache.org/licenses/LICENSE-2.0
+# *
+# * Unless required by applicable law or agreed to in writing, software
+# * distributed under the License is distributed on an "AS IS" BASIS,
+# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# * See the License for the specific language governing permissions and
+# * limitations under the License.
+# ***************************************************************************/
+
+g++ -Wno-return-local-addr -fPIC -O2 -DNDEBUG regxstring.cpp regxstring_impl.cpp gen_regex.cpp -oregxstring
+if [ "$?" -ne "0" ]; then
+  echo "Build failed"
+  exit 1
+fi
diff --git a/ntsimulator/deploy/base/container-tag.yaml b/ntsimulator/deploy/base/container-tag.yaml
new file mode 100644 (file)
index 0000000..d2806a1
--- /dev/null
@@ -0,0 +1,2 @@
+---
+1.0.0
\ No newline at end of file
diff --git a/ntsimulator/deploy/base/generate-ssh-keys.sh b/ntsimulator/deploy/base/generate-ssh-keys.sh
new file mode 100755 (executable)
index 0000000..a4a2bbf
--- /dev/null
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# Copyright 2020 highstreet technologies GmbH and others
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+cd /home/netconf/.ssh
+
+# generate a new private key
+openssl genrsa -out melacon.server.key 2048 2>/dev/null
+
+# create a new Certificate Signing Request
+openssl req -new -sha256 -key melacon.server.key -subj "/C=US/ST=CA/O=MeLaCon, Inc./CN=melacon.com" -out melacon.server.csr 2>/dev/null
+
+# sign the certificate with our own CA
+openssl x509 -req -in melacon.server.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out melacon.server.crt -days 500 -sha256 2>/dev/null
+rm melacon.server.csr
+
+# public key in SSH format
+ssh-keygen -y -f melacon.server.key > melacon.server.key.pub 2>/dev/null
+
+# public key in PEM format
+openssl rsa -in melacon.server.key -pubout > melacon.server.key.pub.pem 2>/dev/null
+
+exit 0
\ No newline at end of file
diff --git a/ntsimulator/deploy/base/pm_files/pm-bulk-a2.xml b/ntsimulator/deploy/base/pm_files/pm-bulk-a2.xml
new file mode 100644 (file)
index 0000000..0b18040
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="MeasDataCollection.xsl"?>
+<measCollecFile xmlns="http://www.3gpp.org/ftp/specs/archive/32_series/32.435#measCollec"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://www.3gpp.org/ftp/specs/archive/32_series/32.435#measCollec http://www.3gpp.org/ftp/specs/archive/32_series/32.435#measCollec">
+       <fileHeader fileFormatVersion="32.435 V7.0" vendorName="Company NN" dnPrefix="DC=a1.companyNN.com,SubNetwork=1,IRPAgent=1">
+               <fileSender localDn="SubNetwork=CountryNN,MeContext=MEC-Gbg-1,ManagedElement=RNC-Gbg-1" elementType="RNC"/>
+               <measCollec beginTime="2000-03-01T14:00:00+02:00"/>
+       </fileHeader>
+       <measData>
+               <managedElement localDn="SubNetwork=CountryNN,MeContext=MEC-Gbg-1,ManagedElement=RNC-Gbg-1" userLabel="RNC Telecomville"/>
+               <measInfo>
+                       <job jobId="1231"/>
+                       <granPeriod duration="PT900S" endTime="2000-03-01T14:14:30+02:00"/>
+                       <repPeriod duration="PT1800S"/>
+                       <measType p="1">attTCHSeizures</measType>
+                       <measType p="2">succTCHSeizures</measType>
+                       <measType p="3">attImmediateAssignProcs</measType>
+                       <measType p="4">succImmediateAssignProcs</measType>
+                       <measValue measObjLdn="RncFunction=RF-1,UtranCell=Gbg-997">
+                               <r p="1">234</r>
+                               <r p="2">345</r>
+                               <r p="3">567</r>
+                               <r p="4">789</r>
+                       </measValue>
+                       <measValue measObjLdn="RncFunction=RF-1,UtranCell=Gbg-998">
+                               <r p="1">890</r>
+                               <r p="2">901</r>
+                               <r p="3">123</r>
+                               <r p="4">234</r>
+                       </measValue>
+                       <measValue measObjLdn="RncFunction=RF-1,UtranCell=Gbg-999">
+                               <r p="1">456</r>
+                               <r p="2">567</r>
+                               <r p="3">678</r>
+                               <r p="4">789</r>
+                               <suspect>true</suspect>
+                       </measValue>
+               </measInfo>
+       </measData>
+       <fileFooter>
+               <measCollec endTime="2000-03-01T14:15:00+02:00"/>
+       </fileFooter>
+</measCollecFile>
diff --git a/ntsimulator/deploy/base/pm_files/pm-bulk-a3-1.xml b/ntsimulator/deploy/base/pm_files/pm-bulk-a3-1.xml
new file mode 100644 (file)
index 0000000..44a0044
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Sample PM File. All values are hypothetical but syntactically correct -->
+<measCollecFile xmlns="http://www.3gpp.org/ftp/specs/archive/32_series/32.435#measCollec" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.3gpp.org/ftp/specs/archive/32_series/32.435#measCollec">
+       <fileHeader fileFormatVersion="32.435 v6.1" vendorName="Company NN" dnPrefix="SubNetwork=1">
+               <fileSender elementType="Element Manager" localDn="OMC_PS=10"/>
+               <measCollec beginTime="2005-06-09T13:00:00-05:00"/>
+       </fileHeader>
+       <measData>
+               <managedElement localDn="ManagedElement=PS_Core" userLabel="SGSN" swVersion="R30.1.5"/>
+               <measInfo measInfoId="Category A">
+                       <job jobId="01"/>
+                       <granPeriod endTime="2005-06-09T13:15:00-06:00" duration="PT900S"/>
+                       <repPeriod duration="PT1800S"/>
+                       <measTypes>MM.AttGprsAttach MM.SuccGprsAttach MM. AbortedGprsAttach MM.AttIntraSgsnRaUpdate</measTypes>
+                       <measValue measObjLdn="SgsnFunction=1">
+                               <measResults>10 20 30 40</measResults>
+                       </measValue>
+               </measInfo>
+               <measInfo measInfoId="Category B">
+                       <job jobId="02"/>
+                       <granPeriod endTime="2005-06-09T13:15:00-06:00" duration="PT900S"/>
+                       <repPeriod duration="PT1800S"/>
+                       <measTypes>MM.AttCombiAttach MM.SuccCombiAttach MM. MM.AbortedCombiAttachMM.AttCombiDetachMs</measTypes>
+                       <measValue measObjLdn="SgsnFunction=2">
+                               <measResults>10 20 30 40</measResults>
+                       </measValue>
+               </measInfo>
+               <measInfo measInfoId="Category C">
+                       <job jobId="03"/>
+                       <granPeriod endTime="2005-06-09T13:15:00-06:00" duration="PT1800S"/>
+                       <repPeriod duration="PT900S"/>
+                       <measTypes>MM.AttPsPagingProcIu MM.SuccPsPagingProcIu</measTypes>
+                       <measValue measObjLdn="SgsnFunction=3">
+                               <measResults>25 25</measResults>
+                       </measValue>
+               </measInfo>
+       </measData>
+       <fileFooter>
+               <measCollec endTime="2005-06-09T13:15:00-06:00"/>
+       </fileFooter>
+</measCollecFile>
diff --git a/ntsimulator/deploy/base/pm_files/pm-bulk-a3.xml b/ntsimulator/deploy/base/pm_files/pm-bulk-a3.xml
new file mode 100644 (file)
index 0000000..44a0044
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Sample PM File. All values are hypothetical but syntactically correct -->
+<measCollecFile xmlns="http://www.3gpp.org/ftp/specs/archive/32_series/32.435#measCollec" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.3gpp.org/ftp/specs/archive/32_series/32.435#measCollec">
+       <fileHeader fileFormatVersion="32.435 v6.1" vendorName="Company NN" dnPrefix="SubNetwork=1">
+               <fileSender elementType="Element Manager" localDn="OMC_PS=10"/>
+               <measCollec beginTime="2005-06-09T13:00:00-05:00"/>
+       </fileHeader>
+       <measData>
+               <managedElement localDn="ManagedElement=PS_Core" userLabel="SGSN" swVersion="R30.1.5"/>
+               <measInfo measInfoId="Category A">
+                       <job jobId="01"/>
+                       <granPeriod endTime="2005-06-09T13:15:00-06:00" duration="PT900S"/>
+                       <repPeriod duration="PT1800S"/>
+                       <measTypes>MM.AttGprsAttach MM.SuccGprsAttach MM. AbortedGprsAttach MM.AttIntraSgsnRaUpdate</measTypes>
+                       <measValue measObjLdn="SgsnFunction=1">
+                               <measResults>10 20 30 40</measResults>
+                       </measValue>
+               </measInfo>
+               <measInfo measInfoId="Category B">
+                       <job jobId="02"/>
+                       <granPeriod endTime="2005-06-09T13:15:00-06:00" duration="PT900S"/>
+                       <repPeriod duration="PT1800S"/>
+                       <measTypes>MM.AttCombiAttach MM.SuccCombiAttach MM. MM.AbortedCombiAttachMM.AttCombiDetachMs</measTypes>
+                       <measValue measObjLdn="SgsnFunction=2">
+                               <measResults>10 20 30 40</measResults>
+                       </measValue>
+               </measInfo>
+               <measInfo measInfoId="Category C">
+                       <job jobId="03"/>
+                       <granPeriod endTime="2005-06-09T13:15:00-06:00" duration="PT1800S"/>
+                       <repPeriod duration="PT900S"/>
+                       <measTypes>MM.AttPsPagingProcIu MM.SuccPsPagingProcIu</measTypes>
+                       <measValue measObjLdn="SgsnFunction=3">
+                               <measResults>25 25</measResults>
+                       </measValue>
+               </measInfo>
+       </measData>
+       <fileFooter>
+               <measCollec endTime="2005-06-09T13:15:00-06:00"/>
+       </fileFooter>
+</measCollecFile>
diff --git a/ntsimulator/deploy/base/ubuntu.Dockerfile b/ntsimulator/deploy/base/ubuntu.Dockerfile
new file mode 100644 (file)
index 0000000..21439db
--- /dev/null
@@ -0,0 +1,200 @@
+#
+# Copyright 2020 highstreet technologies GmbH and others
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#################
+#### BUILDER ####
+#################
+
+FROM ubuntu:20.04 as builder
+LABEL maintainer="alexandru.stancu@highstreet-technologies.com / adrian.lita@highstreet-technologies.com"
+RUN apt-get update
+RUN DEBIAN_FRONTEND="noninteractive" apt-get install -y \
+    # basic tools
+    tzdata build-essential git cmake pkg-config supervisor \
+    # libyang dependencies
+    libpcre3-dev \
+    # libssh dependencies
+    zlib1g-dev libssl-dev
+
+# add netconf user and configure access
+RUN \
+    adduser --system netconf && \
+    echo "netconf:netconf" | chpasswd
+
+# use /opt/dev as working directory
+RUN mkdir /opt/dev
+WORKDIR /opt/dev
+
+# get required build libs from git
+RUN \
+    git config --global advice.detachedHead false && \
+    git clone --single-branch --branch v1.7.13 https://github.com/DaveGamble/cJSON.git && \
+    git clone --single-branch --branch v1.0.184 https://github.com/CESNET/libyang.git && \
+    git clone --single-branch --branch v1.4.70 https://github.com/sysrepo/sysrepo.git && \
+    git clone --single-branch --branch libssh-0.9.2 https://git.libssh.org/projects/libssh.git && \
+    git clone --single-branch --branch v1.1.26 https://github.com/CESNET/libnetconf2.git && \
+    git clone --single-branch --branch v1.1.39 https://github.com/CESNET/netopeer2.git && \
+    git clone --single-branch --branch curl-7_72_0 https://github.com/curl/curl.git
+
+# build and install cJSON
+RUN \
+    cd cJSON && \
+    mkdir build && cd build && \
+    cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_CJSON_TEST=Off && \
+    make -j2 && \
+    make install && \
+    ldconfig
+
+# build and install libyang
+RUN \
+    cd libyang && \
+    mkdir build && cd build  && \
+    cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_BUILD_TESTS=OFF .. && \
+    make -j2  && \
+    make install && \
+    ldconfig
+
+# build and install sysrepo
+RUN \
+    cd sysrepo && \
+    mkdir build && cd build  && \
+    cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_TESTS=OFF -DREPOSITORY_LOC:PATH=/etc/sysrepo -DREQUEST_TIMEOUT=60 -DOPER_DATA_PROVIDE_TIMEOUT=60 .. && \
+    make -j2 && \
+    make install && \
+    ldconfig
+
+# build and install libssh-dev
+RUN \
+    cd libssh && \
+    mkdir build && cd build  && \
+    cmake -DWITH_EXAMPLES=OFF ..  && \
+    make -j2 && \
+    make install && \
+    ldconfig
+
+
+# build and install libnetconf2
+RUN \
+    cd libnetconf2 && \
+    mkdir build && cd build && \
+    cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_BUILD_TESTS=OFF .. && \
+    make -j2 && \
+    make install && \
+    ldconfig
+
+# build and install netopeer2
+RUN \
+    cd netopeer2 && \
+    mkdir build && cd build && \
+    cmake -DCMAKE_BUILD_TYPE:String="Release" -DGENERATE_HOSTKEY=OFF -DMERGE_LISTEN_CONFIG=OFF .. && \
+    make -j2 && \
+    make install
+
+# build and install cURL
+RUN \
+    cd curl && \
+    mkdir build && cd build && \
+    cmake -DBUILD_TESTING=OFF .. && \
+    make -j2 && \
+    make install && \
+    ldconfig
+
+# regxstring copy, build and install
+RUN mkdir /opt/dev/regxstring
+COPY ./regxstring /opt/dev/regxstring
+COPY ./deploy/base/build_regxstring.sh /opt/dev/regxstring/build_regxstring.sh
+RUN \
+    cd /opt/dev/regxstring && \
+    ./build_regxstring.sh && \
+    cp regxstring /usr/bin && \
+    cd ..
+
+# ntsim-ng copy and build
+RUN \
+    mkdir /opt/dev/ntsim-ng && \
+    mkdir /opt/dev/ntsim-ng/config && \
+    mkdir /opt/dev/ntsim-ng/source
+COPY ./ntsim-ng /opt/dev/ntsim-ng/source
+COPY ./deploy/base/build_ntsim-ng.sh /opt/dev/ntsim-ng/build_ntsim-ng.sh
+RUN \
+    cd /opt/dev/ntsim-ng && \
+    sed -i '/argp/d' build_ntsim-ng.sh && \
+    ./build_ntsim-ng.sh
+
+# copy SSH related scripts and keys
+COPY ./deploy/base/ca.key /home/netconf/.ssh/ca.key
+COPY ./deploy/base/ca.pem /home/netconf/.ssh/ca.pem
+COPY ./deploy/base/client.crt /home/netconf/.ssh/client.crt
+COPY ./deploy/base/generate-ssh-keys.sh /home/netconf/.ssh/generate-ssh-keys.sh
+
+#############################
+#### Lightweight Base ####
+#############################
+
+FROM ubuntu:20.04
+LABEL maintainer="alexandru.stancu@highstreet-technologies.com / adrian.lita@highstreet-technologies.com"
+RUN apt-get update
+RUN apt-get install -y \
+    supervisor \
+    openssl \
+    openssh-client \
+    vsftpd \
+    openssh-server
+
+# add netconf user and configure access
+RUN \
+    adduser netconf && \
+    echo "netconf:netconf" | chpasswd && \
+    mkdir -p /home/netconf/.ssh
+
+COPY --from=builder /usr/local/bin /usr/local/bin
+COPY --from=builder /usr/local/lib /usr/local/lib
+COPY --from=builder /usr/local/share /usr/local/share
+
+COPY --from=builder /etc/sysrepo /etc/sysrepo
+RUN ldconfig
+
+# use /opt/dev as working directory
+RUN mkdir /opt/dev
+WORKDIR /opt/dev
+
+# copy common NTS yang models
+RUN mkdir /opt/dev/deploy
+COPY ./deploy/base/yang /opt/dev/deploy/yang
+
+# copy ntsim-ng and dependencies
+COPY --from=builder /usr/bin/regxstring /usr/bin/regxstring
+COPY --from=builder /opt/dev/ntsim-ng /opt/dev/ntsim-ng
+
+# copy SSH related scripts and keys
+COPY --from=builder /home/netconf/.ssh /home/netconf/.ssh
+
+### FTP configuration
+RUN \
+    mkdir /ftp && \
+    mkdir /var/run/vsftpd && \
+    mkdir /var/run/vsftpd/empty  && \
+    mkdir /run/sshd && \
+    echo "Match User netconf\n    ChrootDirectory /ftp\n    X11Forwarding no\n    AllowTcpForwarding no\n    ForceCommand internal-sftp" >> /etc/ssh/sshd_config
+
+COPY ./deploy/base/vsftpd.conf /etc/vsftpd.conf
+COPY ./deploy/base/vsftpd.userlist /etc/vsftpd.userlist
+COPY ./deploy/base/pm_files /ftp
+
+WORKDIR /opt/dev/workspace
+
+ENV SSH_CONNECTIONS=1
+ENV TLS_CONNECTIONS=0
+ENV IPv6_ENABLED=false
diff --git a/ntsimulator/deploy/base/vsftpd.conf b/ntsimulator/deploy/base/vsftpd.conf
new file mode 100644 (file)
index 0000000..9eeacc9
--- /dev/null
@@ -0,0 +1,36 @@
+listen=NO
+listen_ipv6=YES
+anonymous_enable=NO
+local_enable=YES
+write_enable=YES
+local_umask=022
+dirmessage_enable=YES
+use_localtime=YES
+xferlog_enable=YES
+connect_from_port_20=YES
+chroot_local_user=YES
+secure_chroot_dir=/var/run/vsftpd/empty
+pam_service_name=vsftpd
+pasv_enable=Yes
+pasv_min_port=10000
+pasv_max_port=11000
+user_sub_token=$USER
+local_root=/ftp
+userlist_enable=YES
+userlist_file=/etc/vsftpd.userlist
+userlist_deny=NO
+pasv_promiscuous=YES
+
+allow_writeable_chroot=YES
+
+rsa_cert_file=/home/netconf/.ssh/melacon.server.crt
+rsa_private_key_file=/home/netconf/.ssh/melacon.server.key
+ssl_enable=YES
+allow_anon_ssl=NO
+force_local_data_ssl=YES
+force_local_logins_ssl=YES
+ssl_tlsv1=YES
+ssl_sslv2=NO
+ssl_sslv3=NO
+require_ssl_reuse=NO
+ssl_ciphers=HIGH
\ No newline at end of file
diff --git a/ntsimulator/deploy/base/vsftpd.userlist b/ntsimulator/deploy/base/vsftpd.userlist
new file mode 100644 (file)
index 0000000..a9c7df8
--- /dev/null
@@ -0,0 +1 @@
+netconf
diff --git a/ntsimulator/deploy/base/yang/ietf-system.yang b/ntsimulator/deploy/base/yang/ietf-system.yang
new file mode 100644 (file)
index 0000000..141ddba
--- /dev/null
@@ -0,0 +1,802 @@
+module ietf-system {
+  namespace "urn:ietf:params:xml:ns:yang:ietf-system";
+  prefix "sys";
+
+  import ietf-yang-types {
+    prefix yang;
+  }
+
+  import ietf-inet-types {
+    prefix inet;
+  }
+
+  import ietf-netconf-acm {
+    prefix nacm;
+  }
+
+  import iana-crypt-hash {
+    prefix ianach;
+  }
+
+  organization
+    "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+  contact
+    "WG Web:   <http://tools.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     WG Chair: Thomas Nadeau
+               <mailto:tnadeau@lucidvision.com>
+
+     WG Chair: Juergen Schoenwaelder
+               <mailto:j.schoenwaelder@jacobs-university.de>
+
+     Editor:   Andy Bierman
+               <mailto:andy@yumaworks.com>
+
+     Editor:   Martin Bjorklund
+               <mailto:mbj@tail-f.com>";
+
+  description
+    "This module contains a collection of YANG definitions for the
+     configuration and identification of some common system
+     properties within a device containing a NETCONF server.  This
+     includes data node definitions for system identification,
+     time-of-day management, user management, DNS resolver
+     configuration, and some protocol operations for system
+     management.
+
+     Copyright (c) 2014 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 7317; see
+     the RFC itself for full legal notices.";
+
+  revision 2014-08-06 {
+    description
+      "Initial revision.";
+    reference
+      "RFC 7317: A YANG Data Model for System Management";
+  }
+
+ /*
+  * Typedefs
+  */
+
+  typedef timezone-name {
+    type string;
+    description
+      "A time zone name as used by the Time Zone Database,
+       sometimes referred to as the 'Olson Database'.
+
+       The exact set of valid values is an implementation-specific
+       matter.  Client discovery of the exact set of time zone names
+       for a particular server is out of scope.";
+    reference
+      "RFC 6557: Procedures for Maintaining the Time Zone Database";
+   }
+
+  /*
+   * Features
+   */
+
+  feature radius {
+    description
+      "Indicates that the device can be configured as a RADIUS
+       client.";
+    reference
+      "RFC 2865: Remote Authentication Dial In User Service (RADIUS)";
+  }
+
+  feature authentication {
+    description
+      "Indicates that the device supports configuration of
+       user authentication.";
+  }
+
+  feature local-users {
+    if-feature authentication;
+    description
+      "Indicates that the device supports configuration of
+       local user authentication.";
+  }
+
+  feature radius-authentication {
+    if-feature radius;
+    if-feature authentication;
+    description
+      "Indicates that the device supports configuration of user
+       authentication over RADIUS.";
+    reference
+      "RFC 2865: Remote Authentication Dial In User Service (RADIUS)
+       RFC 5607: Remote Authentication Dial-In User Service (RADIUS)
+                 Authorization for Network Access Server (NAS)
+                 Management";
+  }
+
+  feature ntp {
+    description
+      "Indicates that the device can be configured to use one or
+       more NTP servers to set the system date and time.";
+  }
+
+  feature ntp-udp-port {
+    if-feature ntp;
+    description
+      "Indicates that the device supports the configuration of
+       the UDP port for NTP servers.
+
+       This is a 'feature', since many implementations do not support
+       any port other than the default port.";
+  }
+
+  feature timezone-name {
+    description
+      "Indicates that the local time zone on the device
+       can be configured to use the TZ database
+       to set the time zone and manage daylight saving time.";
+    reference
+      "RFC 6557: Procedures for Maintaining the Time Zone Database";
+  }
+
+  feature dns-udp-tcp-port {
+    description
+      "Indicates that the device supports the configuration of
+       the UDP and TCP port for DNS servers.
+
+       This is a 'feature', since many implementations do not support
+       any port other than the default port.";
+  }
+
+
+  /*
+   * Identities
+   */
+
+  identity authentication-method {
+    description
+      "Base identity for user authentication methods.";
+  }
+
+  identity radius {
+    base authentication-method;
+    description
+      "Indicates user authentication using RADIUS.";
+    reference
+      "RFC 2865: Remote Authentication Dial In User Service (RADIUS)
+       RFC 5607: Remote Authentication Dial-In User Service (RADIUS)
+                 Authorization for Network Access Server (NAS)
+                 Management";
+  }
+
+  identity local-users {
+    base authentication-method;
+    description
+      "Indicates password-based authentication of locally
+       configured users.";
+  }
+
+  identity radius-authentication-type {
+    description
+      "Base identity for RADIUS authentication types.";
+  }
+
+  identity radius-pap {
+    base radius-authentication-type;
+    description
+      "The device requests Password Authentication Protocol (PAP)
+       authentication from the RADIUS server.";
+    reference
+      "RFC 2865: Remote Authentication Dial In User Service (RADIUS)";
+  }
+
+  identity radius-chap {
+    base radius-authentication-type;
+    description
+      "The device requests Challenge Handshake Authentication
+       Protocol (CHAP) authentication from the RADIUS server.";
+    reference
+      "RFC 2865: Remote Authentication Dial In User Service (RADIUS)";
+  }
+
+  /*
+   * Configuration data nodes
+   */
+
+  container system {
+    description
+      "System group configuration.";
+
+    leaf contact {
+      type string;
+      description
+        "The administrator contact information for the system.
+
+         A server implementation MAY map this leaf to the sysContact
+         MIB object.  Such an implementation needs to use some
+         mechanism to handle the differences in size and characters
+         allowed between this leaf and sysContact.  The definition of
+         such a mechanism is outside the scope of this document.";
+      reference
+        "RFC 3418: Management Information Base (MIB) for the
+                   Simple Network Management Protocol (SNMP)
+                   SNMPv2-MIB.sysContact";
+    }
+    leaf hostname {
+      type inet:domain-name;
+     description
+       "The name of the host.  This name can be a single domain
+        label or the fully qualified domain name of the host.";
+    }
+    leaf location {
+      type string;
+      description
+        "The system location.
+
+         A server implementation MAY map this leaf to the sysLocation
+         MIB object.  Such an implementation needs to use some
+         mechanism to handle the differences in size and characters
+         allowed between this leaf and sysLocation.  The definition
+         of such a mechanism is outside the scope of this document.";
+      reference
+        "RFC 3418: Management Information Base (MIB) for the
+                   Simple Network Management Protocol (SNMP)
+                   SNMPv2-MIB.sysLocation";
+    }
+
+    container clock {
+      description
+        "Configuration of the system date and time properties.";
+
+      choice timezone {
+        description
+          "The system time zone information.";
+
+        case timezone-name {
+          if-feature timezone-name;
+          leaf timezone-name {
+            type timezone-name;
+            description
+              "The TZ database name to use for the system, such
+               as 'Europe/Stockholm'.";
+          }
+        }
+        case timezone-utc-offset {
+          leaf timezone-utc-offset {
+            type int16 {
+              range "-1500 .. 1500";
+            }
+            units "minutes";
+            description
+              "The number of minutes to add to UTC time to
+               identify the time zone for this system.  For example,
+               'UTC - 8:00 hours' would be represented as '-480'.
+               Note that automatic daylight saving time adjustment
+               is not provided if this object is used.";
+          }
+        }
+      }
+    }
+
+    container ntp {
+      if-feature ntp;
+      presence
+        "Enables the NTP client unless the 'enabled' leaf
+         (which defaults to 'true') is set to 'false'";
+      description
+        "Configuration of the NTP client.";
+
+      leaf enabled {
+        type boolean;
+        default true;
+        description
+          "Indicates that the system should attempt to
+           synchronize the system clock with an NTP server
+           from the 'ntp/server' list.";
+      }
+      list server {
+        key name;
+        description
+          "List of NTP servers to use for system clock
+           synchronization.  If '/system/ntp/enabled'
+           is 'true', then the system will attempt to
+           contact and utilize the specified NTP servers.";
+
+        leaf name {
+          type string;
+          description
+            "An arbitrary name for the NTP server.";
+        }
+        choice transport {
+          mandatory true;
+          description
+            "The transport-protocol-specific parameters for this
+             server.";
+
+          case udp {
+            container udp {
+              description
+                "Contains UDP-specific configuration parameters
+                 for NTP.";
+              leaf address {
+                type inet:host;
+                mandatory true;
+                description
+                  "The address of the NTP server.";
+              }
+              leaf port {
+                if-feature ntp-udp-port;
+                type inet:port-number;
+                default 123;
+                description
+                  "The port number of the NTP server.";
+              }
+            }
+          }
+        }
+        leaf association-type {
+          type enumeration {
+            enum server {
+              description
+                "Use client association mode.  This device
+                 will not provide synchronization to the
+                 configured NTP server.";
+            }
+            enum peer {
+              description
+                "Use symmetric active association mode.
+                 This device may provide synchronization
+                 to the configured NTP server.";
+            }
+            enum pool {
+              description
+                "Use client association mode with one or
+                 more of the NTP servers found by DNS
+                 resolution of the domain name given by
+                 the 'address' leaf.  This device will not
+                 provide synchronization to the servers.";
+            }
+          }
+          default server;
+          description
+            "The desired association type for this NTP server.";
+        }
+        leaf iburst {
+          type boolean;
+          default false;
+          description
+            "Indicates whether this server should enable burst
+             synchronization or not.";
+        }
+        leaf prefer {
+          type boolean;
+          default false;
+          description
+            "Indicates whether this server should be preferred
+             or not.";
+        }
+      }
+    }
+
+    container dns-resolver {
+      description
+        "Configuration of the DNS resolver.";
+
+      leaf-list search {
+        type inet:domain-name;
+        ordered-by user;
+        description
+          "An ordered list of domains to search when resolving
+           a host name.";
+      }
+      list server {
+        key name;
+        ordered-by user;
+        description
+          "List of the DNS servers that the resolver should query.
+
+           When the resolver is invoked by a calling application, it
+           sends the query to the first name server in this list.  If
+           no response has been received within 'timeout' seconds,
+           the resolver continues with the next server in the list.
+           If no response is received from any server, the resolver
+           continues with the first server again.  When the resolver
+           has traversed the list 'attempts' times without receiving
+           any response, it gives up and returns an error to the
+           calling application.
+
+           Implementations MAY limit the number of entries in this
+           list.";
+
+        leaf name {
+          type string;
+          description
+            "An arbitrary name for the DNS server.";
+        }
+        choice transport {
+          mandatory true;
+          description
+            "The transport-protocol-specific parameters for this
+             server.";
+
+          case udp-and-tcp {
+            container udp-and-tcp {
+              description
+                "Contains UDP- and TCP-specific configuration
+                 parameters for DNS.";
+              reference
+                "RFC 1035: Domain Names - Implementation and
+                           Specification
+                 RFC 5966: DNS Transport over TCP - Implementation
+                           Requirements";
+
+              leaf address {
+                type inet:ip-address;
+                mandatory true;
+                description
+                  "The address of the DNS server.";
+              }
+              leaf port {
+                if-feature dns-udp-tcp-port;
+                type inet:port-number;
+                default 53;
+                description
+                  "The UDP and TCP port number of the DNS server.";
+              }
+            }
+          }
+        }
+      }
+      container options {
+        description
+          "Resolver options.  The set of available options has been
+           limited to those that are generally available across
+           different resolver implementations and generally useful.";
+        leaf timeout {
+          type uint8 {
+            range "1..max";
+          }
+          units "seconds";
+          default "5";
+          description
+            "The amount of time the resolver will wait for a
+             response from each remote name server before
+             retrying the query via a different name server.";
+        }
+        leaf attempts {
+          type uint8 {
+            range "1..max";
+          }
+          default "2";
+          description
+            "The number of times the resolver will send a query to
+             all of its name servers before giving up and returning
+             an error to the calling application.";
+        }
+      }
+    }
+
+    container radius {
+      if-feature radius;
+
+      description
+        "Configuration of the RADIUS client.";
+
+      list server {
+        key name;
+        ordered-by user;
+        description
+          "List of RADIUS servers used by the device.
+
+           When the RADIUS client is invoked by a calling
+           application, it sends the query to the first server in
+           this list.  If no response has been received within
+           'timeout' seconds, the client continues with the next
+           server in the list.  If no response is received from any
+           server, the client continues with the first server again.
+           When the client has traversed the list 'attempts' times
+           without receiving any response, it gives up and returns an
+           error to the calling application.";
+
+        leaf name {
+          type string;
+          description
+            "An arbitrary name for the RADIUS server.";
+        }
+        choice transport {
+          mandatory true;
+          description
+            "The transport-protocol-specific parameters for this
+             server.";
+
+          case udp {
+            container udp {
+              description
+                "Contains UDP-specific configuration parameters
+                 for RADIUS.";
+              leaf address {
+                type inet:host;
+                mandatory true;
+                description
+                  "The address of the RADIUS server.";
+              }
+
+              leaf authentication-port {
+                type inet:port-number;
+                default "1812";
+                description
+                  "The port number of the RADIUS server.";
+              }
+              leaf shared-secret {
+                type string;
+                mandatory true;
+                nacm:default-deny-all;
+                description
+                  "The shared secret, which is known to both the
+                   RADIUS client and server.";
+                reference
+                  "RFC 2865: Remote Authentication Dial In User
+                             Service (RADIUS)";
+              }
+            }
+          }
+        }
+        leaf authentication-type {
+          type identityref {
+            base radius-authentication-type;
+          }
+          default radius-pap;
+          description
+            "The authentication type requested from the RADIUS
+             server.";
+        }
+      }
+      container options {
+        description
+          "RADIUS client options.";
+
+        leaf timeout {
+          type uint8 {
+            range "1..max";
+          }
+          units "seconds";
+          default "5";
+          description
+            "The number of seconds the device will wait for a
+             response from each RADIUS server before trying with a
+             different server.";
+        }
+
+        leaf attempts {
+          type uint8 {
+            range "1..max";
+          }
+          default "2";
+          description
+            "The number of times the device will send a query to
+             all of its RADIUS servers before giving up.";
+        }
+      }
+    }
+
+    container authentication {
+      nacm:default-deny-write;
+      if-feature authentication;
+
+       description
+         "The authentication configuration subtree.";
+
+       leaf-list user-authentication-order {
+         type identityref {
+           base authentication-method;
+         }
+         must '(. != "sys:radius" or ../../radius/server)' {
+           error-message
+             "When 'radius' is used, a RADIUS server"
+           + " must be configured.";
+           description
+             "When 'radius' is used as an authentication method,
+              a RADIUS server must be configured.";
+         }
+         ordered-by user;
+
+         description
+           "When the device authenticates a user with a password,
+            it tries the authentication methods in this leaf-list in
+            order.  If authentication with one method fails, the next
+            method is used.  If no method succeeds, the user is
+            denied access.
+
+            An empty user-authentication-order leaf-list still allows
+            authentication of users using mechanisms that do not
+            involve a password.
+
+            If the 'radius-authentication' feature is advertised by
+            the NETCONF server, the 'radius' identity can be added to
+            this list.
+
+            If the 'local-users' feature is advertised by the
+            NETCONF server, the 'local-users' identity can be
+            added to this list.";
+       }
+
+       list user {
+         if-feature local-users;
+         key name;
+         description
+           "The list of local users configured on this device.";
+
+         leaf name {
+           type string;
+           description
+            "The user name string identifying this entry.";
+         }
+         leaf password {
+           type ianach:crypt-hash;
+           description
+             "The password for this entry.";
+         }
+         list authorized-key {
+           key name;
+           description
+             "A list of public SSH keys for this user.  These keys
+              are allowed for SSH authentication, as described in
+              RFC 4253.";
+           reference
+             "RFC 4253: The Secure Shell (SSH) Transport Layer
+                        Protocol";
+
+           leaf name {
+             type string;
+             description
+               "An arbitrary name for the SSH key.";
+           }
+
+           leaf algorithm {
+             type string;
+             mandatory true;
+             description
+               "The public key algorithm name for this SSH key.
+
+                Valid values are the values in the IANA 'Secure Shell
+                (SSH) Protocol Parameters' registry, Public Key
+                Algorithm Names.";
+             reference
+               "IANA 'Secure Shell (SSH) Protocol Parameters'
+                registry, Public Key Algorithm Names";
+           }
+           leaf key-data {
+             type binary;
+             mandatory true;
+             description
+               "The binary public key data for this SSH key, as
+                specified by RFC 4253, Section 6.6, i.e.:
+
+                  string    certificate or public key format
+                            identifier
+                  byte[n]   key/certificate data.";
+             reference
+               "RFC 4253: The Secure Shell (SSH) Transport Layer
+                          Protocol";
+           }
+         }
+       }
+     }
+  }
+
+  /*
+   * Operational state data nodes
+   */
+
+  container system-state {
+    config false;
+    description
+      "System group operational state.";
+
+    container platform {
+      description
+        "Contains vendor-specific information for
+         identifying the system platform and operating system.";
+      reference
+        "IEEE Std 1003.1-2008 - sys/utsname.h";
+
+      leaf os-name {
+        type string;
+        description
+          "The name of the operating system in use -
+           for example, 'Linux'.";
+        reference
+          "IEEE Std 1003.1-2008 - utsname.sysname";
+      }
+      leaf os-release {
+        type string;
+        description
+          "The current release level of the operating
+           system in use.  This string MAY indicate
+           the OS source code revision.";
+        reference
+          "IEEE Std 1003.1-2008 - utsname.release";
+      }
+      leaf os-version {
+        type string;
+        description
+          "The current version level of the operating
+           system in use.  This string MAY indicate
+           the specific OS build date and target variant
+           information.";
+        reference
+          "IEEE Std 1003.1-2008 - utsname.version";
+      }
+      leaf machine {
+        type string;
+        description
+          "A vendor-specific identifier string representing
+           the hardware in use.";
+        reference
+          "IEEE Std 1003.1-2008 - utsname.machine";
+      }
+    }
+
+    container clock {
+      description
+        "Monitoring of the system date and time properties.";
+
+      leaf current-datetime {
+        type yang:date-and-time;
+        description
+          "The current system date and time.";
+      }
+
+
+      leaf boot-datetime {
+        type yang:date-and-time;
+        description
+          "The system date and time when the system last restarted.";
+      }
+    }
+  }
+
+  rpc set-current-datetime {
+    nacm:default-deny-all;
+    description
+      "Set the /system-state/clock/current-datetime leaf
+       to the specified value.
+
+       If the system is using NTP (i.e., /system/ntp/enabled
+       is set to 'true'), then this operation will fail with
+       error-tag 'operation-failed' and error-app-tag value of
+       'ntp-active'.";
+    input {
+      leaf current-datetime {
+        type yang:date-and-time;
+        mandatory true;
+        description
+          "The current system date and time.";
+      }
+    }
+  }
+
+  rpc system-restart {
+    nacm:default-deny-all;
+    description
+      "Request that the entire system be restarted immediately.
+       A server SHOULD send an rpc reply to the client before
+       restarting the system.";
+  }
+
+  rpc system-shutdown {
+    nacm:default-deny-all;
+    description
+      "Request that the entire system be shut down immediately.
+       A server SHOULD send an rpc reply to the client before
+       shutting down the system.";
+  }
+
+}
diff --git a/ntsimulator/deploy/base/yang/nts-common.yang b/ntsimulator/deploy/base/yang/nts-common.yang
new file mode 100644 (file)
index 0000000..0dd1472
--- /dev/null
@@ -0,0 +1,342 @@
+module nts-common {
+  yang-version 1.1;
+  namespace "urn:o-ran-sc:params:xml:ns:yang:nts:common";
+  prefix ntsc;
+
+  import ietf-inet-types {
+    prefix inet;
+  }
+
+  organization
+    "O-RAN-SC";
+  contact
+    " Web: <https://wiki.o-ran-sc.org/display/SIM/SIM>
+        Editors:  
+        Alex Stancu <mailto:alexandru.stancu@highstreet-technologies.com>
+        Adrian Lita <mailto:adrian.lita@highstreet-technologies.com>
+        Martin Skorupski <mailto:martin.skorupski@highstreet-technologies.com>";
+  description
+    "This module contains common yang definitions YANG definitions for the Network Topology Simulator.";
+
+  revision 2020-10-22 {
+    description
+      "Add feature-type for the NETCONF Call Home feature.";
+    reference
+      "O-RAN-SC SIM project";
+  }
+
+  revision 2020-10-13 {
+    description
+      "Add feature-type typedef containing the features that can be activated in the Network Function.";
+    reference
+      "O-RAN-SC SIM project";
+  }
+
+  revision 2020-09-07 {
+    description
+      "Initial revision for the Network Topology Simulator - Next Generation common types.";
+    reference
+      "O-RAN-SC SIM project";
+  }
+
+  feature faults-status {
+      description
+        "This means that the server supports reporting back the number of faults that were generated";
+  }
+
+  typedef authentication-method-type {
+    type enumeration {
+      enum no-auth {
+        description
+          "no security (http)";
+      }
+      enum cert-only {
+        description
+          "auth by certificate (https)";
+      }
+      enum basic-auth {
+        description
+          "auth by basic auth username and password (https)";
+      }
+      enum cert-basic-auth {
+        description
+          "auth by certificate and basic auth username / password (https)";
+      }
+    }
+    description
+      "The authentication method for VES messaging.";
+  }
+
+  typedef feature-type {
+    type bits {
+        bit ves-file-ready {
+            position 0;
+            description
+            "Controls the ves-file-ready feature.";
+        }
+        bit ves-heartbeat {
+            position 1;
+            description
+            "Controls the ves-heartbeat feature.";
+        }
+        bit ves-pnf-registration {
+            position 2;
+            description
+            "Controls the ves-pnf-registration feature.";
+        }
+        bit manual-notification-generation {
+            position 3;
+            description
+            "Controls the manual notification generation feature.";
+        }
+        bit netconf-call-home {
+            position 4;
+            description
+            "Controls the NETCONF Call Home feature.";
+        }
+    }
+    description
+    "Describes the features that can be enabled/disabled in the Network Function.";
+  }
+
+  identity NTS_FUNCTION_TYPE_BASE {
+    description
+      "The reference of each identity represents the name of the associated docker image.";
+  }
+
+  grouping mount-point-details-g {
+      leaf mount-point-addressing-method {
+        type enumeration {
+            enum host-mapping {
+                description
+                "Uses IP and port mapped to the host machine to address the nework function.";
+            }
+            enum docker-mapping {
+                description
+                "Uses Docker IP and port to address the nework function.";
+            }
+        }
+        default docker-mapping;
+        description
+          "Specifies how to address the simulated network function: via the host machine or via docker.";
+    }
+      description
+        "Groups details about mount point";
+  }
+
+  grouping fault-delay-period-g {
+      list fault-delay-list {
+          key index;
+          ordered-by user;
+          leaf index {
+              type uint16;
+              description
+                "The index of the list.";
+          }
+          leaf delay-period {
+              type uint16;
+              units s;
+              description
+                "The amount of seconds before the next event.";
+          }
+          description
+            "The list defining the pattern for generating events.";
+      }
+      description
+        "For reusing the same fault-delay-period.";
+  }
+
+  grouping fault-count-g {
+      container fault-count {
+          if-feature faults-status;
+          config false;
+          leaf normal {
+              type uint32;
+              description
+                "Number of normal (non-alarmed) events.";
+          }
+          leaf warning {
+              type uint32;
+              description
+                "Number of warning events.";
+          }
+          leaf minor {
+              type uint32;
+              description
+                "Number of minor events.";
+          }
+          leaf major {
+              type uint32;
+              description
+                "Number of major events.";
+          }
+          leaf critical {
+              type uint32;
+              description
+                "Number of critical events.";
+          }
+          description
+            "Container which groups the number of fault events, by severity.";
+      }
+      description
+        "Grouping for counting the fault events, grouped by severity.";
+  }
+
+  grouping faults-g {
+    container fault-generation {
+      uses fault-delay-period-g;
+      uses fault-count-g;
+      description
+        "Groups the fault generation configuration and status.";
+    }
+    description
+      "Grouping for fault generation";
+  }
+
+  grouping faults-enabled-g {
+    leaf faults-enabled {
+        type boolean;
+        description
+          "For enabling the fault generation.";
+    }  
+    description
+      "Groups the enabling of faults.";
+  }
+
+  grouping netconf-config-g {
+    container netconf {
+        uses faults-enabled-g;
+        leaf call-home {
+            type boolean;
+            description
+            "For enabling the NETCONF Call Home feature. If set to 'true', each simulated device, when booting up, will try to Call Home to the SDN Controller.";
+        }
+        description
+        "Container for describing the NETCONF details.";
+    }
+    description
+      "Groups the configuration and status of NETCONF Fault notifications.";
+  }
+
+  grouping ves-config-g {
+      container ves {
+          uses faults-enabled-g;
+          leaf pnf-registration {
+              type boolean;
+              description
+                "For enabling the PNF Registration messages. If set to 'true', each simulated device, when booting up, will send a PNF Registration message to the VES Collector.";
+          }
+          leaf heartbeat-period {
+              type uint16;
+              description
+                "The number of seconds between VES heartbeat messages.";
+          }                    
+          description
+            "Container for describing the VES details.";
+      }
+    description
+      "Groups the configuration and status of VES Fault notifications.";
+  }
+
+  grouping controller-g {
+      leaf controller-ip {
+          type inet:ip-address;
+          description
+            "The IP address of the SDN Controller.";
+      }
+      leaf controller-port {
+          type inet:port-number;
+          description
+            "The port exposed by the SDN Controller.";
+      }
+      leaf controller-netconf-call-home-port {
+          type inet:port-number;
+          description
+            "The port exposed by the SDN Controller for NETCONF Call Home.";
+      }
+      leaf controller-username {
+          type string;
+          description
+            "The username for accessing the SDN Controller.";
+      }
+      leaf controller-password {
+          type string;
+          description
+            "The password for accessing the SDN Controller.";
+      }
+      description
+        "Groups information about the SDN Controller.";
+  }
+
+  grouping ves-endpoint-g {
+      leaf ves-endpoint-protocol {
+          type enumeration {
+              enum http {
+                  description
+                    "HTTP protocol will be used to connect to the VES Collector.";
+              }
+              enum https {
+                  description
+                    "HTTPS protocol will be used to connect to the VES Collector.";
+              }
+          }
+          default https;
+          description
+            "The protocol (HTTP / HTTPS) to be used to address the VES Collector.";
+      }
+      leaf ves-endpoint-ip {
+          type inet:ip-address;
+          description
+            "The IP address of the VES Collector.";
+      }
+      leaf ves-endpoint-port {
+          type inet:port-number;
+          description
+            "The port exposed by the VES Collector.";
+      }
+      leaf ves-endpoint-auth-method {
+        type authentication-method-type;
+        default "no-auth";
+        description
+          "The type of the authentication to be used with the VES Collector.";
+      }
+      leaf ves-endpoint-username {
+          type string;
+          description
+            "The username for accessing the VES Collector.";
+      }
+      leaf ves-endpoint-password {
+          type string;
+          description
+            "The password for accessing the VES Collector.";
+      }
+      leaf ves-endpoint-certificate {
+        type string;
+        description
+          "The Certificate to be used to authenticate to the VES Collector.";
+      }
+      description
+        "Groups information about the VES Collector.";
+  }
+
+  grouping rpc-status-g {
+      leaf status {
+          type enumeration {
+            enum SUCCESS {
+            description
+                "The RPC was successfully invoked.";
+            }
+            enum ERROR {
+            description
+                "An error was encountered when invoking the RPC.";
+            }
+          }
+        mandatory true;
+        description
+          "The status of the RPC.";
+      }
+      description
+        "RPC output grouping.";
+  }
+
+} //end module
\ No newline at end of file
diff --git a/ntsimulator/deploy/base/yang/nts-network-function.yang b/ntsimulator/deploy/base/yang/nts-network-function.yang
new file mode 100644 (file)
index 0000000..5575d33
--- /dev/null
@@ -0,0 +1,147 @@
+module nts-network-function {
+  yang-version 1.1;
+  namespace "urn:o-ran-sc:params:xml:ns:yang:nts:network:function";
+  prefix ntsnf;
+
+  import nts-common {
+    prefix ntsc;
+    revision-date 2020-10-22;
+  }
+
+  organization
+    "O-RAN-SC";
+  contact
+    " Web: <https://wiki.o-ran-sc.org/display/SIM/SIM>
+        Editors:  
+        Alex Stancu <mailto:alexandru.stancu@highstreet-technologies.com>
+        Adrian Lita <mailto:adrian.lita@highstreet-technologies.com>
+        Martin Skorupski <mailto:martin.skorupski@highstreet-technologies.com>";
+  description
+    "This module contains YANG definitions for the Network Topology Simulator - Network Functions";
+
+  revision 2020-10-28 {
+    description
+      "Add RPC for clearing the fault counters.";
+    reference
+      "O-RAN-SC SIM project";
+  }
+
+  revision 2020-10-13 {
+    description
+      "Add RPC for datastore populating and feature control.";
+    reference
+      "O-RAN-SC SIM project";
+  }
+
+  revision 2020-09-07 {
+    description
+      "Initial revision for the Network Topology Simulator - Next Generation";
+    reference
+      "O-RAN-SC SIM project";
+  }
+
+  container simulation {
+      container network-function {
+            uses ntsc:mount-point-details-g;
+            uses ntsc:faults-g;
+            uses ntsc:netconf-config-g;
+            uses ntsc:ves-config-g;
+          description
+            "Container which encompasses the details of the network function.";
+      }
+      container sdn-controller {
+          uses ntsc:controller-g;
+          description
+            "Groups details about the SDN Controller.";
+      }
+      container ves-endpoint {
+          uses ntsc:ves-endpoint-g;
+          description
+            "Groups details about the VES Collector endpoint.";
+      }
+      description
+        "Root level container which controls the Network Function.";
+  }
+
+  rpc datastore-random-populate {
+    description
+      "Operation to populate the datastore with random data for all the containing YANG models.";
+    
+    output {
+      uses ntsc:rpc-status-g;
+    }
+  }
+
+  rpc feature-control {
+    description
+      "Operation to control the features in a Network Function.";
+    input {
+      leaf features {
+          type ntsc:feature-type;
+          mandatory true;
+          description
+            "A bit-wise list with features to be activated.";
+      }
+    }
+    output {
+      uses ntsc:rpc-status-g;
+    }
+  }
+
+  rpc invoke-notification {
+    description
+      "Operation to control the features in a Network Function.";
+    input {
+      leaf notification-format {
+          type enumeration {
+            enum xml {
+            description
+              "The notification string is formatted as XML.";
+            }
+            enum json {
+            description
+              "The notification string is formatted as JSON.";
+            }
+          }
+          mandatory true;
+          description
+            "The format of the notification string.";
+      }
+      leaf notification-object {
+          type string;
+          mandatory true;
+          description
+            "A JSON string containing the notification object to be sent by the device.";
+      }
+    }
+    output {
+      uses ntsc:rpc-status-g;
+    }
+  }
+
+  rpc invoke-ves-pm-file-ready {
+    description
+      "Operation to generate a VES  notification from a Network Function.";
+    input {
+      leaf file-location {
+          type string;
+          mandatory true;
+          description
+            "A string containing the location of the file on the server.";
+      }
+    }
+    output {
+      uses ntsc:rpc-status-g;
+    }
+  }
+
+  rpc clear-fault-counters {
+    description
+      "Operation to clear the fault counters.";
+
+    output {
+      uses ntsc:rpc-status-g;
+    }
+  }
+
+} //end module
\ No newline at end of file
diff --git a/ntsimulator/deploy/base/yang/onap-system.yang b/ntsimulator/deploy/base/yang/onap-system.yang
new file mode 100644 (file)
index 0000000..3e19429
--- /dev/null
@@ -0,0 +1,59 @@
+module onap-system {
+  yang-version 1.1;
+  namespace "urn:onap:system";
+  prefix os;
+
+  import ietf-inet-types {
+    prefix inet;
+  }
+  import ietf-system {
+    prefix sys;
+  }
+
+  organization
+    "ONAP - Open Network Automation Platform";
+  contact
+    "Web: <https://www.onap.org>
+     Editors:
+        Alex Stancu <mailto:alexandru.stancu@highstreet-technologies.com>
+        Adrian Lita <mailto:adrian.lita@highstreet-technologies.com>
+        Martin Skorupski <mailto:martin.skorupski@highstreet-technologies.com>";
+  description
+    "This module augments ietf-system with ONAP details.
+
+     Copyright 2020 the O-RAN Alliance.
+
+     Licensed under the Apache License, Version 2.0 (the 'License');
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an 'AS IS' BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.";
+
+  revision 2020-10-26 {
+    description
+      "Initial revision for the ietf-system augmentation for ONAP.";
+    reference
+      "https://jira.onap.org/browse/SDNC-1396";
+  }
+
+  augment "/sys:system" {
+    leaf name {
+      type string;
+      description
+        "The name of the system.";
+    }
+    leaf web-ui {
+      type inet:uri;
+      description
+        "The URI of the system Web UI.";
+    }
+    description
+      "Enhancing the system information.";
+  }
+}
diff --git a/ntsimulator/deploy/container-tag.yaml b/ntsimulator/deploy/container-tag.yaml
deleted file mode 100644 (file)
index 12585e7..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
----
-tag: 0.0.2
diff --git a/ntsimulator/deploy/nts-manager/CMakeLists.txt b/ntsimulator/deploy/nts-manager/CMakeLists.txt
deleted file mode 100644 (file)
index 7e9a720..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-cmake_minimum_required(VERSION 2.8.12)
-project(ntsimulator)
-set(PROJECT_DESC "Network Topology Simulator using sysrepo and netopeer2")
-include(GNUInstallDirs)
-
-# setup version
-set(NTSIMULATOR_MAJOR_VERSION 1)
-set(NTSIMULATOR_MINOR_VERSION 1)
-set(NTSIMULATOR_PATCH_VERSION 1)
-set(NTSIMULATOR_VERSION ${NTSIMULATOR_MAJOR_VERSION}.${NTSIMULATOR_MINOR_VERSION}.${NTSIMULATOR_PATCH_VERSION})
-set(NTSIMULATOR_SOVERSION ${NTSIMULATOR_MAJOR_VERSION}.${NTSIMULATOR_MINOR_VERSION})
-
-# osx specific
-set(CMAKE_MACOSX_RPATH TRUE)
-
-# set default build type if not specified by user
-if(NOT CMAKE_BUILD_TYPE)
-    set(CMAKE_BUILD_TYPE debug)
-endif()
-string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
-
-set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
-
-set(CMAKE_C_FLAGS         "${CMAKE_C_FLAGS} -Wall -Wpedantic -std=gnu11 -Wno-language-extension-token")
-if(CMAKE_COMPILER_IS_GNUCC)
-    # disable strict aliasing in GCC, since it produces false alarams in libev
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-strict-aliasing")
-endif()
-set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O2")
-set(CMAKE_C_FLAGS_DEBUG   "-g -O0")
-
-if(NOT UNIX)
-    message(FATAL_ERROR "Only Unix-like systems are supported.")
-endif()
-
-if(NOT DEFINED IS_DEVELOPER_CONFIGURATION)
-    if(CMAKE_BUILD_TYPE_LOWER MATCHES "debug" AND NOT CMAKE_BUILD_TYPE_LOWER MATCHES "^rel")
-        set(IS_DEVELOPER_CONFIGURATION true)
-    else()
-        set(IS_DEVELOPER_CONFIGURATION false)
-    endif()
-endif()
-
-# location of system repository
-if(${IS_DEVELOPER_CONFIGURATION})
-    set(REPOSITORY_LOC "${CMAKE_BINARY_DIR}/repository" CACHE PATH "System repository location, contains configuration schema and data files.")
-else()
-    set(REPOSITORY_LOC "/etc/sysrepo" CACHE PATH "System repository location, contains configuration schema and data files.")
-endif()
-
-# include custom Modules
-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMakeModules/")
-include_directories(${CMAKE_CURRENT_BINARY_DIR})
-include_directories("${CMAKE_CURRENT_SOURCE_DIR}/inc")
-
-# find required libraries
-find_package(SYSREPO REQUIRED)
-include_directories(${SYSREPO_INCLUDE_DIR})
-
-# add subdirectories
-add_subdirectory(src)
-
-### NTS SPECIFIC ###
-# Configure install file for NTS Manager
-configure_file("${CMAKE_CURRENT_SOURCE_DIR}/deploy/nts-manager/model-install.sh.in" "${PROJECT_BINARY_DIR}/model-install.sh" ESCAPE_QUOTES @ONLY)
-### END NTS SPECIFIC ###
-
-# find sysrepoctl
-if (NOT SYSREPOCTL_EXECUTABLE)
-    find_program(SYSREPOCTL_EXECUTABLE sysrepoctl)
-endif()
-if (NOT SYSREPOCTL_EXECUTABLE)
-    message(FATAL_ERROR "Unable to find sysrepoctl, set SYSREPOCTL_EXECUTABLE manually.")
-endif()
-
-# find sysrepocfg
-if (NOT SYSREPOCFG_EXECUTABLE)
-    find_program(SYSREPOCFG_EXECUTABLE sysrepocfg)
-endif()
-if (NOT SYSREPOCFG_EXECUTABLE)
-    message(FATAL_ERROR "Unable to find sysrepocfg, set SYSREPOCFG_EXECUTABLE manually.")
-endif()
-
-# Command line options to be passed to `sysrepoctl` when working with modules
-# which should only be accessible by an administrator
-if (NOT SYSREPOCTL_ROOT_PERMS)
-    set(SYSREPOCTL_ROOT_PERMS "-o root:root -p 600")
-endif()
-
-install(CODE "
-    set(ENV{SYSREPOCTL} ${SYSREPOCTL_EXECUTABLE})
-    set(ENV{SYSREPOCFG} ${SYSREPOCFG_EXECUTABLE})
-    set(ENV{SYSREPOCTL_ROOT_PERMS} SYSREPOCTL_ROOT_PERMS)
-    execute_process(COMMAND ${PROJECT_BINARY_DIR}/model-install.sh)")
-
-
-
diff --git a/ntsimulator/deploy/nts-manager/Dockerfile b/ntsimulator/deploy/nts-manager/Dockerfile
deleted file mode 100644 (file)
index e5362ea..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-FROM ubuntu:18.04 AS builder
-
-LABEL maintainer="alexandru.stancu@highstreet-technologies.com"
-
-RUN \
-      apt-get update && apt-get install -y \
-      # general tools
-      git \
-      cmake \
-      build-essential \
-      vim \
-      supervisor \
-      # libyang
-      libpcre3-dev \
-      pkg-config \
-      # sysrepo
-      libavl-dev \
-      libev-dev \
-      libprotobuf-c-dev \
-      protobuf-c-compiler \
-      # netopeer2 \
-      libssh-dev \
-      libssl-dev \
-      # bindings
-      swig \
-      python-dev \
-      libcurl4 \
-      libcurl4-openssl-dev \
-      curl \
-      bc \
-      python-setuptools \
-      python-pip
-
-# add netconf user
-RUN \
-      adduser --system netconf && \
-      echo "netconf:netconf" | chpasswd
-
-# generate ssh keys for netconf user
-USER netconf
-RUN \
-      mkdir -p /home/netconf/.ssh && \
-      ssh-keygen -A && \
-      ssh-keygen -t rsa -P '' -f /home/netconf/.ssh/id_dsa && \
-      cat /home/netconf/.ssh/id_dsa.pub > /home/netconf/.ssh/authorized_keys
-#echo "Host *\n    StrictHostKeyChecking accept-new" >> /home/netconf/.ssh/config
-USER root
-RUN \
-      echo "    StrictHostKeyChecking no" >> /etc/ssh/ssh_config && \
-      mkdir -p /root/.ssh && \
-      cat /home/netconf/.ssh/id_dsa.pub > /root/.ssh/authorized_keys
-       
-# use /opt/dev as working directory
-RUN mkdir /opt/dev
-WORKDIR /opt/dev
-
-# libcjson
-RUN \
-      git clone https://github.com/Melacon/cJSON.git && \
-      cd cJSON && mkdir build && cd build && \
-      cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_CJSON_TEST=Off -DCMAKE_INSTALL_PREFIX=/usr .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# libyang
-RUN \
-      git clone https://github.com/Melacon/libyang.git && \
-      cd libyang && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_BUILD_TESTS=OFF .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# sysrepo
-RUN \
-      git clone https://github.com/Melacon/sysrepo.git && \
-      sed -i 's/#define MAX_BLOCKS_AVAIL_FOR_ALLOC    3/#define MAX_BLOCKS_AVAIL_FOR_ALLOC    6/g' ./sysrepo/src/common/sr_mem_mgmt.h && \
-      cd sysrepo && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_TESTS=OFF -DREPOSITORY_LOC:PATH=/etc/sysrepo -DREQUEST_TIMEOUT=60 -DOPER_DATA_PROVIDE_TIMEOUT=60 .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# libnetconf2
-RUN \
-      git clone https://github.com/Melacon/libnetconf2.git && \
-      cd libnetconf2 && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_BUILD_TESTS=OFF .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# keystore
-RUN \
-      git clone https://github.com/Melacon/Netopeer2.git && \
-      cd Netopeer2 && \
-      cd keystored && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" -DKEYSTORED_KEYS_DIR=/home/netconf/.ssh .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# netopeer2
-RUN \
-      cd /opt/dev/Netopeer2/server && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" .. && \
-      make -j2 && \
-      make install && \
-      cd ../../cli && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" .. && \
-      make -j2 && \
-      make install
-
-# NTSimulator Manager
-COPY . /opt/dev/ntsimulator
-COPY ./deploy/nts-manager/CMakeLists.txt /opt/dev/ntsimulator/CMakeLists.txt
-RUN \
-      cd /opt/dev && \
-      cd ntsimulator && mkdir build  && cd build && \
-      cmake .. && \
-      make -j2 && \
-      make install
-
-
-# Second stage
-FROM ubuntu:18.04  
-
-LABEL maintainer="alexandru.stancu@highstreet-technologies.com"
-
-ENV NETCONF_BASE=40000
-ENV NTS_IP="127.0.0.1"
-# ENV EXTERNAL_NTS_IP="172.17.0.1" - this can be given in the docker-compose.yml file to
-# overwrite the IP that is exposed via pnfRegistration or via mount HTTP REST; if not specified, NTS_IP will be used
-ENV SCRIPTS_DIR=/opt/dev/scripts
-ENV DOCKER_ENGINE_VERSION="1.40"
-ENV MODELS_IMAGE="ntsim_oran"
-ENV VesHeartbeatPeriod=0
-ENV IsVesAvailable=true
-ENV IsNetconfAvailable=true
-ENV VesRegistration=false
-ENV VesEndpointPort=8080
-ENV VesEndpointIp="172.17.0.1"
-ENV VesEndpointAuthMethod="no-auth"
-ENV VesEndpointUsername="admin"
-ENV VesEndpointPassword="admin"
-ENV SshConnections=1
-ENV TlsConnections=0
-ENV K8S_DEPLOYMENT=false
-ENV CONTAINER_NAME="ntsim"
-ENV ControllerIp="172.17.0.1"
-ENV ControllerPort=8181
-ENV NetconfCallHomePort=6666
-ENV ControllerUsername="admin"
-ENV ControllerPassword="admin"
-ENV NetconfCallHome=false
-ENV Ipv6Enabled=false
-
-RUN \
-      apt-get update && apt-get install -y supervisor bc
-
-# add netconf user
-RUN \
-      adduser --system netconf && \
-      echo "netconf:netconf" | chpasswd
-
-USER netconf
-# generate ssh keys for netconf user
-RUN \
-      mkdir -p /home/netconf/.ssh
-
-COPY --from=builder /home/netconf/.ssh /home/netconf/.ssh
-
-USER root
-COPY --from=builder /etc/ssh /etc/ssh
-COPY --from=builder /root/.ssh /root/.ssh
-COPY --from=builder /usr/local/lib /usr/local/lib
-COPY --from=builder /usr/local/bin /usr/local/bin
-COPY --from=builder /usr/local/include /usr/local/include
-COPY --from=builder /usr/lib/libavl.so /usr/lib/libavl.so
-COPY --from=builder /usr/lib/libavl.so.1 /usr/lib/libavl.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libev.so /usr/lib/x86_64-linux-gnu/libev.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libev.so.4 /usr/lib/x86_64-linux-gnu/libev.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcurl.so.4 /usr/lib/x86_64-linux-gnu/libcurl.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcurl.so /usr/lib/x86_64-linux-gnu/libcurl.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcjson_utils.so.1 /usr/lib/x86_64-linux-gnu/libcjson_utils.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcjson_utils.so /usr/lib/x86_64-linux-gnu/libcjson_utils.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcjson.so.1 /usr/lib/x86_64-linux-gnu/libcjson.so.1 
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcjson.so /usr/lib/x86_64-linux-gnu/libcjson.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libprotobuf.so.10 /usr/lib/x86_64-linux-gnu/libprotobuf.so.10
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.1 /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libprotobuf-c.so /usr/lib/x86_64-linux-gnu/libprotobuf-c.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libssh_threads.so.4 /usr/lib/x86_64-linux-gnu/libssh_threads.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libssh_threads.so /usr/lib/x86_64-linux-gnu/libssh_threads.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libssh.so.4 /usr/lib/x86_64-linux-gnu/libssh.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libssh.so /usr/lib/x86_64-linux-gnu/libssh.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libnghttp2.so.14 /usr/lib/x86_64-linux-gnu/libnghttp2.so.14
-COPY --from=builder /usr/lib/x86_64-linux-gnu/librtmp.so.1 /usr/lib/x86_64-linux-gnu/librtmp.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libpsl.so.5 /usr/lib/x86_64-linux-gnu/libpsl.so.5
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2 /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2 /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2
-COPY --from=builder /usr/lib/x86_64-linux-gnu/liblber-2.4.so.2 /usr/lib/x86_64-linux-gnu/liblber-2.4.so.2
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libkrb5.so.3 /usr/lib/x86_64-linux-gnu/libkrb5.so.3
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libk5crypto.so.3 /usr/lib/x86_64-linux-gnu/libk5crypto.so.3
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libkrb5support.so.0 /usr/lib/x86_64-linux-gnu/libkrb5support.so.0
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libsasl2.so.2 /usr/lib/x86_64-linux-gnu/libsasl2.so.2
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libgssapi.so.3 /usr/lib/x86_64-linux-gnu/libgssapi.so.3
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libheimntlm.so.0 /usr/lib/x86_64-linux-gnu/libheimntlm.so.0
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libkrb5.so.26 /usr/lib/x86_64-linux-gnu/libkrb5.so.26
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libasn1.so.8 /usr/lib/x86_64-linux-gnu/libasn1.so.8
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libhcrypto.so.4 /usr/lib/x86_64-linux-gnu/libhcrypto.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libroken.so.18 /usr/lib/x86_64-linux-gnu/libroken.so.18
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libwind.so.0 /usr/lib/x86_64-linux-gnu/libwind.so.0
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libheimbase.so.1 /usr/lib/x86_64-linux-gnu/libheimbase.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libhx509.so.5 /usr/lib/x86_64-linux-gnu/libhx509.so.5
-
-COPY --from=builder /lib/x86_64-linux-gnu/libkeyutils.so.1 /lib/x86_64-linux-gnu/libkeyutils.so.1
-COPY --from=builder /etc/sysrepo /etc/sysrepo
-COPY --from=builder /var/run /var/run
-
-#COPY --from=builder /usr/local/etc/keystored/keys/ssh_host_rsa_key.pem /usr/local/etc/keystored/keys/ssh_host_rsa_key.pem
-#COPY --from=builder /usr/local/etc/keystored/keys/ssh_host_rsa_key.pem.pub /usr/local/etc/keystored/keys/ssh_host_rsa_key.pem.pub
-COPY --from=builder /usr/local/share/libnetconf2 /usr/local/share/libnetconf2
-
-RUN ldconfig
-
-COPY ./deploy/nts-manager/supervisord.conf /etc/supervisord.conf
-
-COPY ./deploy/nts-manager/docker_stats.sh /opt/dev/docker_stats.sh
-# Fix for the NETCONF notifications
-RUN \
-    echo "Fixing the NETCONF notifications..." && \
-    mkdir -p /var/run/sysrepo-subscriptions/ietf-crypto-types
-         
-ARG BUILD_DATE
-LABEL build-date=$BUILD_DATE
-
-ENV EDITOR vim
-EXPOSE 830
-
-CMD ["sh", "-c", "/usr/bin/supervisord -c /etc/supervisord.conf"]
diff --git a/ntsimulator/deploy/nts-manager/config.json b/ntsimulator/deploy/nts-manager/config.json
new file mode 100644 (file)
index 0000000..504a016
--- /dev/null
@@ -0,0 +1,26 @@
+{
+    "docker-rules": {
+        "excluded-modules": [],
+        "excluded-features": ["faults-status"]
+    },
+    
+    "populate-rules" : {
+        "excluded-modules": [
+            "sysrepo",
+            "sysrepo-monitoring",
+            "ietf-yang-library",
+            "ietf-netconf-acm",
+            "ietf-netconf-monitoring",
+            "nc-notifications",
+            "ietf-keystore",
+            "ietf-truststore",
+            "ietf-system",
+            "ietf-netconf-server",
+            "nts-network-function",
+            "nts-manager"
+        ],
+        
+        "default-list-instances": 1,
+        "custom-list-instances" : []
+    }
+}
\ No newline at end of file
diff --git a/ntsimulator/deploy/nts-manager/docker_stats.sh b/ntsimulator/deploy/nts-manager/docker_stats.sh
deleted file mode 100755 (executable)
index 317d3ce..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/bin/bash
-################################################################################
-#
-# Copyright 2020 highstreet technologies GmbH and others
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-# 
-#     http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-################################################################################
-
-# This script is used to complete the output of the docker stats command.
-# The docker stats command does not compute the total amount of resources (RAM or CPU)
-
-# Get the output of the docker stat command. Will be displayed at the end
-# Without modifying the special variable IFS the ouput of the docker stats command won't have
-
-CPU_CORES=`nproc`
-# the new lines thus resulting in a failure when using awk to process each line
-IFS=;
-mapfile -t DOCKER_PS_RESULT < <(/usr/bin/docker ps --all --format "{{.ID}}" --filter "label=NTS_Manager=$1")
-
-CONTAINERS=""
-
-if [ ${#DOCKER_PS_RESULT[@]} -gt 0 ]
-then
-
-       for container in "${DOCKER_PS_RESULT[@]}"
-       do
-               CONTAINERS="$CONTAINERS $container"
-       done
-fi
-
-if [ -z "$CONTAINERS" ]
-then
-       CPU_SCALED=0
-       SUM_RAM=0
-else
-       DOCKER_STATS_COMMAND="/usr/bin/docker stats --no-stream --format \"table {{.CPUPerc}}\t{{.MemUsage}}\" ${CONTAINERS}"
-       DOCKER_STATS_COMMAND_RESULT=$(eval "$DOCKER_STATS_COMMAND")
-
-       SUM_CPU=`echo $DOCKER_STATS_COMMAND_RESULT | tail -n +2 | sed "s/%//g" | awk '{s+=$1} END {print s}'`
-       SUM_RAM=`echo $DOCKER_STATS_COMMAND_RESULT | tail -n +2 | sed "s/%//g" | awk '{s+=$2} END {print s}'`
-
-       CPU_SCALED=$(echo "scale=2; $SUM_CPU/$CPU_CORES" | bc)
-fi
-
-# Output the result
-echo -e "CPU=${CPU_SCALED}%;RAM=${SUM_RAM}MiB"
\ No newline at end of file
diff --git a/ntsimulator/deploy/nts-manager/model-install.sh.in b/ntsimulator/deploy/nts-manager/model-install.sh.in
deleted file mode 100755 (executable)
index 11e5c6a..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/bin/bash
-
-set -eu -o pipefail
-
-shopt -s failglob
-
-: ${SYSREPOCTL:=sysrepoctl}
-: ${SYSREPOCFG:=sysrepocfg}
-: ${SYSREPOCTL_ROOT_PERMS:=-o root:root -p 600}
-: ${YANG_DIR:=@CMAKE_CURRENT_SOURCE_DIR@/yang/nts-manager}
-
-is_yang_module_installed() {
-    module=$1
-
-    $SYSREPOCTL -l | grep --count "^$module [^|]*|[^|]*| Installed .*$" > /dev/null
-}
-
-install_yang_module() {
-    module=$1
-
-    if ! is_yang_module_installed $module; then
-        echo "- Installing module $module..."
-        $SYSREPOCTL -i -g ${YANG_DIR}/$module.yang $SYSREPOCTL_ROOT_PERMS
-    else
-        echo "- Module $module already installed."
-    fi
-}
-
-uninstall_yang_module() {
-    module=$1
-
-    if is_yang_module_installed $module; then
-        echo "- Uninstalling module $module..."
-        $SYSREPOCTL -u -m $module
-    else
-        echo "- Module $module is not installed."
-    fi
-}
-
-enable_yang_module_feature() {
-    module=$1
-    feature=$2
-
-    if ! $SYSREPOCTL -l | grep --count "^$module [^|]*|[^|]*|[^|]*|[^|]*|[^|]*|[^|]*|.* $feature.*$" > /dev/null; then
-        echo "- Enabling feature $feature in $module..."
-        $SYSREPOCTL -m $module -e $feature
-    else
-        echo "- Feature $feature in $module already enabled."
-    fi
-}
-
-echo "- Installing network-topology-simulator..."
-install_yang_module network-topology-simulator
-
-echo "- Adding startup datastore in network-topology-simulator..."
-$SYSREPOCFG -d startup -i $YANG_DIR/network-topology-simulator.xml -f xml network-topology-simulator
index 127b6c4..9e0ca99 100644 (file)
@@ -3,26 +3,20 @@ nodaemon=true
 logfile=/var/log/supervisord.log
 loglevel=debug
 
-[program:sysrepod]
-command=/usr/local/bin/sysrepod -d
-autorestart=true
-redirect_stderr=true
-priority=1
-
-[program:sysrepo-plugind]
-command=/usr/local/bin/sysrepo-plugind -d
+[program:netopeer2-server]
+command=/usr/local/bin/netopeer2-server -d
 autorestart=true
 redirect_stderr=true
 priority=2
 
-[program:netopeer2-server]
-command=/usr/local/bin/netopeer2-server -d
+[program:sshd]
+command=/usr/sbin/sshd -D
 autorestart=true
 redirect_stderr=true
 priority=3
 
-[program:ntsimulator-manager]
-command=/usr/local/bin/ntsimulator-manager
-autorestart=true
+[program:ntsim-ng]
+command=/opt/dev/ntsim-ng/ntsim-ng -w /opt/dev/ntsim-ng -n -m
+autorestart=false
 redirect_stderr=true
-priority=4
\ No newline at end of file
+priority=4
diff --git a/ntsimulator/deploy/nts-manager/ubuntu.Dockerfile b/ntsimulator/deploy/nts-manager/ubuntu.Dockerfile
new file mode 100644 (file)
index 0000000..a119cce
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# Copyright 2020 highstreet technologies GmbH and others
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+################
+#### DEVICE ####
+################
+
+FROM o-ran-sc/nts-ng-base:latest
+LABEL maintainer="alexandru.stancu@highstreet-technologies.com / adrian.lita@highstreet-technologies.com"
+
+# ntsim-ng configuration and deployment
+COPY ./yang /opt/dev/deploy/yang
+COPY ./config.json /opt/dev/ntsim-ng/config/config.json
+
+# ntsim-ng init docker
+RUN /opt/dev/ntsim-ng/ntsim-ng --docker-init -w /opt/dev/ntsim-ng
+
+# supervisor configuration
+COPY ./supervisord.conf /etc/supervisord.conf
+
+# finishing container build
+ARG BUILD_DATE
+LABEL build-date=$BUILD_DATE
+
+# add exposed ports
+EXPOSE 830-929
+EXPOSE 21-22
+
+# host IP address to bind to
+ENV NETCONF_NTS_HOST_IP=127.0.0.1
+# starting port for host allocation
+ENV NETCONF_NTS_HOST_BASE_PORT=50000
+
+ENV DOCKER_ENGINE_VERSION=1.40
+
+# run
+WORKDIR /opt/dev/workspace
+CMD ["sh", "-c", "/usr/bin/supervisord -c /etc/supervisord.conf"]
diff --git a/ntsimulator/deploy/nts-manager/yang/nts-manager.yang b/ntsimulator/deploy/nts-manager/yang/nts-manager.yang
new file mode 100644 (file)
index 0000000..36691b6
--- /dev/null
@@ -0,0 +1,202 @@
+module nts-manager {
+  yang-version 1.1;
+  namespace "urn:o-ran-sc:params:xml:ns:yang:nts:manager";
+  prefix nts-mng;
+
+  import ietf-inet-types {
+    prefix inet;
+  }
+
+  import nts-common {
+    prefix ntsc;
+    revision-date 2020-10-22;
+  }
+
+  organization
+    "O-RAN-SC";
+  contact
+    " Web: <https://wiki.o-ran-sc.org/display/SIM/SIM>
+        Editors:  
+        Alex Stancu <mailto:alexandru.stancu@highstreet-technologies.com>
+        Adrian Lita <mailto:adrian.lita@highstreet-technologies.com>
+        Martin Skorupski <mailto:martin.skorupski@highstreet-technologies.com>";
+  description
+    "This module contains YANG definitions for the Network Topology Simulator - Manager.";
+
+  revision 2020-10-06 {
+    description
+      "Initial revision for the Network Topology Simulator - Next Generation";
+    reference
+      "O-RAN-SC SIM project";
+  }
+
+  typedef percent {
+    type decimal64 {
+      fraction-digits 2;
+      range "0 .. 100";
+    }
+    description
+      "Percentage";
+  }
+
+  grouping instance-g {
+      leaf name {
+        type string;
+        description
+          "The name of the running instance. It is the same as the docker container name which exposes this network function.";
+      }
+      container networking {
+          leaf docker-ip {
+              type inet:ip-address;
+              description
+                "The IP address of the docker container implementing the network function instance.";
+          }
+          leaf-list docker-port {
+              type inet:port-number;
+              description
+                "The ports which are exposed inside the docker container implementing the network function instance.";
+          }
+          leaf host-ip {
+              type inet:ip-address;
+              description
+                "The Host machine IP address pointing to the docker container implementing the network function instance.";
+          }
+          leaf-list host-port {
+              type inet:port-number;
+              description
+                "The Host machine ports mapped to the docker container implementing the network function instance.";
+          }
+          description
+            "Groups the details about networking information.";
+      }
+      description
+        "An instance of a network function which is running. The equivalent on the host machine is a docker container.";
+  }
+  grouping network-function-g {
+      leaf function-type {
+          type identityref {
+              base ntsc:NTS_FUNCTION_TYPE_BASE;
+          }
+          description "Type of network function to be simulated.";
+      }
+      leaf started-instances {
+          type uint16;
+          mandatory true;
+          description
+            "How many instances of this type are started.";
+      }
+      leaf mounted-instances {
+          type uint16;
+          must '. <= ../started-instances' {
+              error-message
+                "The number of mounted instances cannot be greater that the number of started instances.";
+          }
+          mandatory true;
+          description
+            "How many instances of this type are mounted in the SDN Controller.";
+      }
+
+      uses ntsc:mount-point-details-g;
+
+      leaf docker-instance-name {
+          type string;
+          mandatory true;
+          description
+            "The prefix of each docker container being started.";
+      }
+
+      leaf docker-version-tag {
+          type string;
+          mandatory true;
+          description
+            "The version tag of the docker image to be started.";
+      }
+
+      leaf docker-repository {
+          type string;
+          mandatory true;
+          description
+            "The prefix containing the docker repository information, if needed.";
+      }
+      uses ntsc:faults-g;
+      uses ntsc:netconf-config-g;
+      uses ntsc:ves-config-g;
+      container instances {
+          config false;
+          list instance {
+            key "name";
+            uses ntsc:mount-point-details-g;
+            uses instance-g;            
+            description
+              "Describes a running instance.";
+          }
+          description 
+            "Groups details about instances which are running.";
+      }
+      description
+        "Contains all the details of a simulated device.";
+  }
+  grouping simulation-information-g {
+      leaf base-port {
+          type inet:port-number;
+          config false;
+          description
+            "The base Host machine port from where the simulation can allocate ports incrementally.";
+      }
+      leaf ssh-connections {
+          type uint8;
+          config false;
+          description
+            "The number of SSH Endpoints each network function instance exposes.";
+      }
+      leaf tls-connections {
+          type uint8;
+          config false;
+          description
+            "The number of TLS Endpoints each network function instance exposes.";
+      }
+      leaf cpu-usage {
+        type percent;
+        config false;
+        description
+          "Specifies the CPU load generated by the simulation.";
+      }
+      leaf mem-usage {
+        type uint32;
+        config false;
+        description
+          "Specifies the RAM in MB used by the simulation.";
+      }
+      description
+        "Groups information about the simulation status.";
+  }
+
+  container simulation {
+      container network-functions {
+          list network-function {
+            key "function-type";
+            unique "docker-instance-name";
+            uses network-function-g;
+            description
+              "List containing different simulated network function types and their details.";
+          }
+          description
+            "Container which encompasses all simulated network functions.";
+      }
+      container sdn-controller {
+          uses ntsc:controller-g;
+          description
+            "Groups details about the SDN Controller.";
+      }
+      container ves-endpoint {
+          uses ntsc:ves-endpoint-g;
+          description
+            "Groups details about the VES Collector endpoint.";
+      }
+      uses simulation-information-g;
+      description
+        "Root level container which controls the NTS.";
+  }
+
+
+} //end module
\ No newline at end of file
diff --git a/ntsimulator/deploy/nts-manager/yang/nts-o-ran-pac.yang b/ntsimulator/deploy/nts-manager/yang/nts-o-ran-pac.yang
new file mode 100644 (file)
index 0000000..6e949c3
--- /dev/null
@@ -0,0 +1,37 @@
+module nts-o-ran-pac {
+  yang-version 1.1;
+  namespace "urn:o-ran-sc:params:xml:ns:yang:nts:o-ran";
+  prefix nts-o-ran;
+
+  import nts-common {
+      prefix ntsc;
+      revision-date 2020-10-22;
+  }
+
+  organization
+    "O-RAN-SC";
+  contact
+    " Web: <https://wiki.o-ran-sc.org/display/SIM/SIM>
+        Editors:  
+        Alex Stancu <mailto:alexandru.stancu@highstreet-technologies.com>
+        Adrian Lita <mailto:adrian.lita@highstreet-technologies.com>
+        Martin Skorupski <mailto:martin.skorupski@highstreet-technologies.com>";
+  description
+    "This module contains YANG definitions for the Network Topology Simulator - O-RAN extensions.";
+
+  revision 2020-10-26 {
+    description
+      "Initial revision for the Network Topology Simulator - Next Generation";
+    reference
+      "O-RAN implementation";
+  }
+
+  identity NTS_FUNCTION_TYPE_O_RAN_FH {
+    base ntsc:NTS_FUNCTION_TYPE_BASE;
+    description
+      "The simulated network function implements O-RAN FrontHaul (O1) YANG models.";
+    reference
+      "nts-ng-o-ran-fh";
+  }
+
+} //end module
\ No newline at end of file
diff --git a/ntsimulator/deploy/nts-manager/yang/nts-x-ran-pac.yang b/ntsimulator/deploy/nts-manager/yang/nts-x-ran-pac.yang
new file mode 100644 (file)
index 0000000..ac9fea5
--- /dev/null
@@ -0,0 +1,37 @@
+module nts-x-ran-pac {
+  yang-version 1.1;
+  namespace "urn:o-ran-sc:params:xml:ns:yang:nts:x-ran";
+  prefix nts-x-ran;
+
+  import nts-common {
+      prefix ntsc;
+      revision-date 2020-10-22;
+  }
+
+  organization
+    "O-RAN-SC";
+  contact
+    " Web: <https://wiki.o-ran-sc.org/display/SIM/SIM>
+        Editors:  
+        Alex Stancu <mailto:alexandru.stancu@highstreet-technologies.com>
+        Adrian Lita <mailto:adrian.lita@highstreet-technologies.com>
+        Martin Skorupski <mailto:martin.skorupski@highstreet-technologies.com>";
+  description
+    "This module contains YANG definitions for the Network Topology Simulator - X-RAN extensions.";
+
+  revision 2020-10-26 {
+    description
+      "Initial revision for the Network Topology Simulator - Next Generation";
+    reference
+      "X-RAN implementation";
+  }
+
+  identity NTS_FUNCTION_TYPE_X_RAN {
+    base ntsc:NTS_FUNCTION_TYPE_BASE;
+    description
+      "The simulated device implements X-RAN YANG models.";
+    reference
+      "nts-ng-x-ran";
+  }
+
+} //end module
\ No newline at end of file
diff --git a/ntsimulator/deploy/o-ran-sc/o-ran-ru/CMakeLists.txt b/ntsimulator/deploy/o-ran-sc/o-ran-ru/CMakeLists.txt
deleted file mode 100644 (file)
index 8eabadd..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-set(UTILS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/utils")
-
-include_directories(
-    "${PROJECT_SOURCE_DIR}/inc/utils" 
-    "/usr/include"
-)
-
-add_subdirectory(generic-notifications)
-
-# sources
-set (UTILS_SOURCES
-    ${UTILS_DIR}/utils.c
-)
-
-add_library(utils STATIC ${UTILS_SOURCES})
-set_property(TARGET utils PROPERTY COMPILE_FLAGS "-fPIC")
-target_link_libraries(utils m)
-target_link_libraries(utils cjson)
\ No newline at end of file
diff --git a/ntsimulator/deploy/o-ran-sc/o-ran-ru/Dockerfile b/ntsimulator/deploy/o-ran-sc/o-ran-ru/Dockerfile
deleted file mode 100644 (file)
index 7129884..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-FROM ubuntu:18.04 AS builder
-
-LABEL maintainer="alexandru.stancu@highstreet-technologies.com"
-
-RUN \
-      apt-get update && apt-get install -y \
-      # general tools
-      git \
-      cmake \
-      build-essential \
-      vim \
-      supervisor \
-      # libyang
-      libpcre3-dev \
-      pkg-config \
-      # sysrepo
-      libavl-dev \
-      libev-dev \
-      libprotobuf-c-dev \
-      protobuf-c-compiler \
-      # netopeer2 \
-      libssh-dev \
-      libssl-dev \
-      # bindings
-      swig \
-      python-dev \
-      libcurl4 \
-      libcurl4-openssl-dev \
-      curl \
-      bc
-
-RUN \
-      apt-get install -y \
-      python-setuptools \
-      python-pip
-
-# pyang dependencies
-RUN pip install rstr && \
-    pip install exrex && \
-    pip install ipaddress && \
-    pip install lxml
-
-# add netconf user
-RUN \
-      adduser --system netconf && \
-      echo "netconf:netconf" | chpasswd
-
-# generate ssh keys for netconf user
-RUN \
-      mkdir -p /home/netconf/.ssh && \
-      ssh-keygen -A && \
-      ssh-keygen -t dsa -P '' -f /home/netconf/.ssh/id_dsa && \
-      cat /home/netconf/.ssh/id_dsa.pub > /home/netconf/.ssh/authorized_keys && \
-#echo "Host *\n    StrictHostKeyChecking accept-new" >> /home/netconf/.ssh/config
-      echo "    StrictHostKeyChecking no" >> /etc/ssh/ssh_config && \
-      mkdir -p /root/.ssh && \
-      cat /home/netconf/.ssh/id_dsa.pub > /root/.ssh/authorized_keys
-       
-# use /opt/dev as working directory
-RUN mkdir /opt/dev
-WORKDIR /opt/dev
-
-# libcjson
-RUN \
-      git clone https://github.com/Melacon/cJSON.git && \
-      cd cJSON && mkdir build && cd build && \
-      cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_CJSON_TEST=Off -DCMAKE_INSTALL_PREFIX=/usr .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# libyang
-RUN \
-      git clone https://github.com/Melacon/libyang.git && \
-      cd libyang && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_BUILD_TESTS=OFF .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# sysrepo
-RUN \
-      git clone https://github.com/Melacon/sysrepo.git && \
-      sed -i 's/#define MAX_BLOCKS_AVAIL_FOR_ALLOC    3/#define MAX_BLOCKS_AVAIL_FOR_ALLOC    6/g' ./sysrepo/src/common/sr_mem_mgmt.h && \
-      cd sysrepo && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_TESTS=OFF -DREPOSITORY_LOC:PATH=/etc/sysrepo -DREQUEST_TIMEOUT=60 -DOPER_DATA_PROVIDE_TIMEOUT=60 .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# libnetconf2
-RUN \
-      git clone https://github.com/Melacon/libnetconf2.git && \
-      cd libnetconf2 && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_BUILD_TESTS=OFF .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# keystore
-RUN \
-      git clone https://github.com/Melacon/Netopeer2.git && \
-      cd Netopeer2 && \
-      cd keystored && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# netopeer2
-RUN \
-      cd /opt/dev/Netopeer2/server && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" .. && \
-      make -j2 && \
-      make install && \
-      cd ../../cli && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" .. && \
-      make -j2 && \
-      make install
-
-# pyang
-RUN \
-      git clone https://github.com/Melacon/pyang.git && \
-       cd pyang && python setup.py build && python setup.py install
-
-# NTSimulator device
-COPY . /opt/dev/ntsimulator
-COPY ./deploy/o-ran-sc/o-ran-ru/CMakeLists.txt /opt/dev/ntsimulator/src/CMakeLists.txt
-RUN \
-      cd /opt/dev/ntsimulator && mkdir build  && cd build && \
-      cmake .. && \
-      make -j2 && \
-      make install
-
-# Second stage
-FROM ubuntu:18.04  
-
-LABEL maintainer="alexandru.stancu@highstreet-technologies.com"
-
-RUN \
-      apt-get update && apt-get install -y supervisor
-
-# add netconf user
-RUN \
-      adduser --system netconf && \
-      echo "netconf:netconf" | chpasswd
-
-# generate ssh keys for netconf user
-RUN \
-      mkdir -p /home/netconf/.ssh
-
-COPY --from=builder /home/netconf/.ssh /home/netconf/.ssh
-COPY --from=builder /usr/local/lib /usr/local/lib
-COPY --from=builder /usr/local/bin /usr/local/bin
-COPY --from=builder /usr/local/include /usr/local/include
-COPY --from=builder /usr/lib/libavl.so /usr/lib/libavl.so
-COPY --from=builder /usr/lib/libavl.so.1 /usr/lib/libavl.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libev.so /usr/lib/x86_64-linux-gnu/libev.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libev.so.4 /usr/lib/x86_64-linux-gnu/libev.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcurl.so.4 /usr/lib/x86_64-linux-gnu/libcurl.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcurl.so /usr/lib/x86_64-linux-gnu/libcurl.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcjson_utils.so.1 /usr/lib/x86_64-linux-gnu/libcjson_utils.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcjson_utils.so /usr/lib/x86_64-linux-gnu/libcjson_utils.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcjson.so.1 /usr/lib/x86_64-linux-gnu/libcjson.so.1 
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcjson.so /usr/lib/x86_64-linux-gnu/libcjson.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libprotobuf.so.10 /usr/lib/x86_64-linux-gnu/libprotobuf.so.10
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.1 /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libprotobuf-c.so /usr/lib/x86_64-linux-gnu/libprotobuf-c.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libssh_threads.so.4 /usr/lib/x86_64-linux-gnu/libssh_threads.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libssh_threads.so /usr/lib/x86_64-linux-gnu/libssh_threads.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libssh.so.4 /usr/lib/x86_64-linux-gnu/libssh.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libssh.so /usr/lib/x86_64-linux-gnu/libssh.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libnghttp2.so.14 /usr/lib/x86_64-linux-gnu/libnghttp2.so.14
-COPY --from=builder /usr/lib/x86_64-linux-gnu/librtmp.so.1 /usr/lib/x86_64-linux-gnu/librtmp.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libpsl.so.5 /usr/lib/x86_64-linux-gnu/libpsl.so.5
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2 /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2 /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2
-COPY --from=builder /usr/lib/x86_64-linux-gnu/liblber-2.4.so.2 /usr/lib/x86_64-linux-gnu/liblber-2.4.so.2
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libkrb5.so.3 /usr/lib/x86_64-linux-gnu/libkrb5.so.3
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libk5crypto.so.3 /usr/lib/x86_64-linux-gnu/libk5crypto.so.3
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libkrb5support.so.0 /usr/lib/x86_64-linux-gnu/libkrb5support.so.0
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libsasl2.so.2 /usr/lib/x86_64-linux-gnu/libsasl2.so.2
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libgssapi.so.3 /usr/lib/x86_64-linux-gnu/libgssapi.so.3
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libheimntlm.so.0 /usr/lib/x86_64-linux-gnu/libheimntlm.so.0
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libkrb5.so.26 /usr/lib/x86_64-linux-gnu/libkrb5.so.26
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libasn1.so.8 /usr/lib/x86_64-linux-gnu/libasn1.so.8
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libhcrypto.so.4 /usr/lib/x86_64-linux-gnu/libhcrypto.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libroken.so.18 /usr/lib/x86_64-linux-gnu/libroken.so.18
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libwind.so.0 /usr/lib/x86_64-linux-gnu/libwind.so.0
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libheimbase.so.1 /usr/lib/x86_64-linux-gnu/libheimbase.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libhx509.so.5 /usr/lib/x86_64-linux-gnu/libhx509.so.5
-
-COPY --from=builder /lib/x86_64-linux-gnu/libkeyutils.so.1 /lib/x86_64-linux-gnu/libkeyutils.so.1
-COPY --from=builder /etc/sysrepo /etc/sysrepo
-COPY --from=builder /var/run /var/run
-
-COPY --from=builder /usr/local/etc/keystored/keys/ssh_host_rsa_key.pem /usr/local/etc/keystored/keys/ssh_host_rsa_key.pem
-COPY --from=builder /usr/local/etc/keystored/keys/ssh_host_rsa_key.pem.pub /usr/local/etc/keystored/keys/ssh_host_rsa_key.pem.pub
-COPY --from=builder /usr/local/share/libnetconf2 /usr/local/share/libnetconf2
-
-RUN ldconfig
-
-WORKDIR /tmp
-RUN \
-    apt-get update && apt-get install -yqq wget \
-    openssh-client \
-    jq \
-    curl
-
-RUN mkdir py_install && cd py_install && \
-    wget https://files.pythonhosted.org/packages/b9/9a/3e9da40ea28b8210dd6504d3fe9fe7e013b62bf45902b458d1cdc3c34ed9/ipaddress-1.0.23.tar.gz && \
-    tar -xvzf ipaddress-1.0.23.tar.gz && cd ipaddress-1.0.23 && \
-    python setup.py install
-
-COPY --from=builder /etc/ssh /etc/ssh
-COPY --from=builder /root/.ssh /root/.ssh
-
-WORKDIR /opt/dev
-# run only specific programs in this image
-COPY ./deploy/o-ran-sc/o-ran-ru/supervisord.conf /etc/supervisord.conf
-
-# tls configuratoin
-COPY ./deploy/tls /home/netconf/.ssh
-
-COPY --from=builder /opt/dev/sysrepo/build/examples/application_example /opt/dev/sysrepo/build/examples/application_example
-
-# YANG models and related scripts
-COPY ./yang/o-ran-sc/o-ran-ru /opt/dev/yang
-COPY ./yang/auto-load-yangs.sh /opt/dev/yang
-COPY ./deploy/o-ran-sc/o-ran-ru/sysrepo-configuration-load.sh /opt/dev/yang
-WORKDIR /opt/dev
-RUN \
-         cd yang && \
-         ./auto-load-yangs.sh
-
-ARG BUILD_DATE
-LABEL build-date=$BUILD_DATE
-         
-ENV EDITOR vim
-EXPOSE 830-929
-
-CMD ["sh", "-c", "/usr/bin/supervisord -c /etc/supervisord.conf"]
diff --git a/ntsimulator/deploy/o-ran-sc/o-ran-ru/container-tag.yaml b/ntsimulator/deploy/o-ran-sc/o-ran-ru/container-tag.yaml
deleted file mode 100644 (file)
index 280bd51..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
----
-tag: 0.6.5
diff --git a/ntsimulator/deploy/o-ran-sc/o-ran-ru/supervisord.conf b/ntsimulator/deploy/o-ran-sc/o-ran-ru/supervisord.conf
deleted file mode 100644 (file)
index 05ab36d..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-[supervisord]
-nodaemon=true
-logfile=/var/log/supervisord.log
-loglevel=debug
-
-[program:sysrepod]
-command=/usr/local/bin/sysrepod -d
-autorestart=true
-redirect_stderr=true
-priority=1
-
-[program:sysrepo-plugind]
-command=/usr/local/bin/sysrepo-plugind -d
-autorestart=true
-redirect_stderr=true
-priority=2
-
-[program:netopeer2-server]
-command=/usr/local/bin/netopeer2-server -d
-autorestart=true
-redirect_stderr=true
-priority=3
-
-[program:enable-netconf-call-home]
-directory=/home/netconf/.ssh
-command=/home/netconf/.ssh/enable_netconf_call_home.sh
-startsecs=0
-autorestart=false
-redirect_stderr=false
-priority=4
-
-[program:enable-tls]
-directory=/home/netconf/.ssh
-command=/home/netconf/.ssh/enable_tls.sh
-startsecs=0
-autorestart=false
-redirect_stderr=false
-priority=5
-
-[program:set-nts-ip-script]
-directory=/home/netconf/.ssh
-command=/home/netconf/.ssh/set_NTS_IP.sh
-startsecs=0
-autorestart=false
-redirect_stderr=false
-priority=5
-
-[program:sysrepo-config-load]
-directory=/opt/dev/yang
-command=/opt/dev/yang/sysrepo-configuration-load.sh
-autorestart=false
-redirect_stderr=true
-startretries=1
-priority=6
diff --git a/ntsimulator/deploy/o-ran-sc/o-ran-ru/sysrepo-configuration-load.sh b/ntsimulator/deploy/o-ran-sc/o-ran-ru/sysrepo-configuration-load.sh
deleted file mode 100755 (executable)
index 34a1e79..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/bash
-
-sleep 20
-
-echo "Loading data into sysrepo..."
-
-: ${SYSREPOCFG:=sysrepocfg}
-
-pyang -f sample-xml-skeleton --sample-xml-list-entries 1 *.yang
-
-mapfile -t modelList < <(ls -S -lr *.xml | awk {'print $9'})
-
-if [ ${#modelList[@]} -eq 0 ]; then
-  echo "No modules present, nothing to do..."
-  exit 0
-else
-  for model in ${modelList[@]}
-  do
-    modelName=${model%".xml"}
-
-    echo "Importing data for module: $model"
-    $SYSREPOCFG --import=$model --format=xml $modelName
-    
-  done
-fi
-
-echo "Finished loading data into sysrepo..."
-
-exit 0
\ No newline at end of file
diff --git a/ntsimulator/deploy/o-ran/config.json b/ntsimulator/deploy/o-ran/config.json
new file mode 100644 (file)
index 0000000..a5e30c4
--- /dev/null
@@ -0,0 +1,57 @@
+{
+    "docker-rules": {
+        "excluded-modules": [],
+        "excluded-features": []
+    },
+    
+    "populate-rules" : {
+        "excluded-modules": [
+            "sysrepo",
+            "sysrepo-monitoring",
+            "ietf-yang-library",
+            "ietf-netconf-acm",
+            "ietf-netconf-monitoring",
+            "nc-notifications",
+            "ietf-keystore",
+            "ietf-truststore",
+            "ietf-system",
+            "ietf-netconf-server",
+            "nts-network-function"
+        ],
+        
+        "default-list-instances": 1,
+        "custom-list-instances" : []
+    },
+
+    "fault-rules" : {
+        "yang-notif-template" : "<alarm-notif xmlns=\"urn:o-ran:fm:1.0\"><fault-id>$$uint16_counter$$</fault-id><fault-source>%%object%%</fault-source><affected-objects><name>%%affected-object%%</name></affected-objects><fault-severity>%%fault-severity%%</fault-severity><is-cleared>%%cleared%%</is-cleared><fault-text>%%text%%</fault-text><event-time>%%date-time%%</event-time></alarm-notif>",
+        "choosing-method" : "linear",
+        "faults" : [
+            {
+                "condition" : "cod1",
+                "object"    : "obj1",
+                "severity"  : "MAJOR",
+                "date-time" : "$$time$$",
+                "specific-problem" : "sp1",
+
+                "fault-severity" : "WARNING",
+                "affected-object" : "%%object%%",
+                "cleared" : "false",
+                "text" : "ana n-are mere"
+            },
+
+            {
+                "condition" : "cod2",
+                "object"    : "obj1",
+                "severity"  : "NORMAL",
+                "date-time" : "$$time$$",
+                "specific-problem" : "sp2",
+
+                "fault-severity" : "WARNING",
+                "affected-object" : "%%object%%",
+                "cleared" : "true",
+                "text" : "ana are mere"
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/ntsimulator/deploy/o-ran/container-tag.yaml b/ntsimulator/deploy/o-ran/container-tag.yaml
new file mode 100644 (file)
index 0000000..d2806a1
--- /dev/null
@@ -0,0 +1,2 @@
+---
+1.0.0
\ No newline at end of file
diff --git a/ntsimulator/deploy/o-ran/ru-fh/CMakeLists.txt b/ntsimulator/deploy/o-ran/ru-fh/CMakeLists.txt
deleted file mode 100644 (file)
index 3cf2ed0..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-set(UTILS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/utils")
-
-include_directories(
-    "${PROJECT_SOURCE_DIR}/inc/utils" 
-    "/usr/include"
-)
-
-add_subdirectory(o-ran-notifications)
-add_subdirectory(ves-messages)
-add_subdirectory(software-management-oran)
-add_subdirectory(generic-notifications)
-
-# sources
-set (UTILS_SOURCES
-    ${UTILS_DIR}/utils.c
-)
-
-add_library(utils STATIC ${UTILS_SOURCES})
-set_property(TARGET utils PROPERTY COMPILE_FLAGS "-fPIC")
-target_link_libraries(utils m)
-target_link_libraries(utils cjson)
\ No newline at end of file
diff --git a/ntsimulator/deploy/o-ran/ru-fh/Dockerfile b/ntsimulator/deploy/o-ran/ru-fh/Dockerfile
deleted file mode 100644 (file)
index d33d1d2..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-FROM ubuntu:18.04 AS builder
-
-LABEL maintainer="alexandru.stancu@highstreet-technologies.com"
-
-RUN \
-      apt-get update && apt-get install -y \
-      # general tools
-      git \
-      cmake \
-      build-essential \
-      vim \
-      supervisor \
-      # libyang
-      libpcre3-dev \
-      pkg-config \
-      # sysrepo
-      libavl-dev \
-      libev-dev \
-      libprotobuf-c-dev \
-      protobuf-c-compiler \
-      # netopeer2 \
-      libssh-dev \
-      libssl-dev \
-      # bindings
-      swig \
-      python-dev \
-      libcurl4 \
-      libcurl4-openssl-dev \
-      curl \
-      bc
-
-RUN \
-      apt-get install -y \
-      python-setuptools \
-      python-pip
-
-# pyang dependencies
-RUN pip install rstr && \
-    pip install exrex && \
-    pip install ipaddress && \
-    pip install lxml
-
-# add netconf user
-RUN \
-      adduser --system netconf && \
-      echo "netconf:netconf" | chpasswd
-
-# generate ssh keys for netconf user
-RUN \
-      mkdir -p /home/netconf/.ssh && \
-      ssh-keygen -A && \
-      ssh-keygen -t dsa -P '' -f /home/netconf/.ssh/id_dsa && \
-      cat /home/netconf/.ssh/id_dsa.pub > /home/netconf/.ssh/authorized_keys && \
-#echo "Host *\n    StrictHostKeyChecking accept-new" >> /home/netconf/.ssh/config
-      echo "    StrictHostKeyChecking no" >> /etc/ssh/ssh_config && \
-      mkdir -p /root/.ssh && \
-      cat /home/netconf/.ssh/id_dsa.pub > /root/.ssh/authorized_keys
-       
-# use /opt/dev as working directory
-RUN mkdir /opt/dev
-WORKDIR /opt/dev
-
-# libcjson
-RUN \
-      git clone https://github.com/Melacon/cJSON.git && \
-      cd cJSON && mkdir build && cd build && \
-      cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_CJSON_TEST=Off -DCMAKE_INSTALL_PREFIX=/usr .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# libyang
-RUN \
-      git clone https://github.com/Melacon/libyang.git && \
-      cd libyang && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_BUILD_TESTS=OFF .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# sysrepo
-RUN \
-      git clone https://github.com/Melacon/sysrepo.git && \
-      sed -i 's/#define MAX_BLOCKS_AVAIL_FOR_ALLOC    3/#define MAX_BLOCKS_AVAIL_FOR_ALLOC    6/g' ./sysrepo/src/common/sr_mem_mgmt.h && \
-      cd sysrepo && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_TESTS=OFF -DREPOSITORY_LOC:PATH=/etc/sysrepo -DREQUEST_TIMEOUT=60 -DOPER_DATA_PROVIDE_TIMEOUT=60 .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# libnetconf2
-RUN \
-      git clone https://github.com/Melacon/libnetconf2.git && \
-      cd libnetconf2 && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_BUILD_TESTS=OFF .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# keystore
-RUN \
-      git clone https://github.com/Melacon/Netopeer2.git && \
-      cd Netopeer2 && \
-      cd keystored && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# netopeer2
-RUN \
-      cd /opt/dev/Netopeer2/server && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" .. && \
-      make -j2 && \
-      make install && \
-      cd ../../cli && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" .. && \
-      make -j2 && \
-      make install
-
-# pyang
-RUN \
-      git clone https://github.com/Melacon/pyang.git && \
-       cd pyang && python setup.py build && python setup.py install
-
-# NTSimulator device
-COPY . /opt/dev/ntsimulator
-COPY ./deploy/o-ran/ru-fh/CMakeLists.txt /opt/dev/ntsimulator/src/CMakeLists.txt
-RUN \
-      cd /opt/dev/ntsimulator && mkdir build  && cd build && \
-      cmake .. && \
-      make -j2 && \
-      make install
-
-# Second stage
-FROM ubuntu:18.04  
-
-LABEL maintainer="alexandru.stancu@highstreet-technologies.com"
-
-RUN \
-      apt-get update && apt-get install -y supervisor
-
-# add netconf user
-RUN \
-      adduser --system netconf && \
-      echo "netconf:netconf" | chpasswd
-
-# generate ssh keys for netconf user
-RUN \
-      mkdir -p /home/netconf/.ssh
-
-COPY --from=builder /home/netconf/.ssh /home/netconf/.ssh
-COPY --from=builder /usr/local/lib /usr/local/lib
-COPY --from=builder /usr/local/bin /usr/local/bin
-COPY --from=builder /usr/local/include /usr/local/include
-COPY --from=builder /usr/lib/libavl.so /usr/lib/libavl.so
-COPY --from=builder /usr/lib/libavl.so.1 /usr/lib/libavl.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libev.so /usr/lib/x86_64-linux-gnu/libev.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libev.so.4 /usr/lib/x86_64-linux-gnu/libev.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcurl.so.4 /usr/lib/x86_64-linux-gnu/libcurl.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcurl.so /usr/lib/x86_64-linux-gnu/libcurl.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcjson_utils.so.1 /usr/lib/x86_64-linux-gnu/libcjson_utils.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcjson_utils.so /usr/lib/x86_64-linux-gnu/libcjson_utils.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcjson.so.1 /usr/lib/x86_64-linux-gnu/libcjson.so.1 
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcjson.so /usr/lib/x86_64-linux-gnu/libcjson.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libprotobuf.so.10 /usr/lib/x86_64-linux-gnu/libprotobuf.so.10
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.1 /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libprotobuf-c.so /usr/lib/x86_64-linux-gnu/libprotobuf-c.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libssh_threads.so.4 /usr/lib/x86_64-linux-gnu/libssh_threads.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libssh_threads.so /usr/lib/x86_64-linux-gnu/libssh_threads.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libssh.so.4 /usr/lib/x86_64-linux-gnu/libssh.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libssh.so /usr/lib/x86_64-linux-gnu/libssh.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libnghttp2.so.14 /usr/lib/x86_64-linux-gnu/libnghttp2.so.14
-COPY --from=builder /usr/lib/x86_64-linux-gnu/librtmp.so.1 /usr/lib/x86_64-linux-gnu/librtmp.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libpsl.so.5 /usr/lib/x86_64-linux-gnu/libpsl.so.5
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2 /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2 /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2
-COPY --from=builder /usr/lib/x86_64-linux-gnu/liblber-2.4.so.2 /usr/lib/x86_64-linux-gnu/liblber-2.4.so.2
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libkrb5.so.3 /usr/lib/x86_64-linux-gnu/libkrb5.so.3
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libk5crypto.so.3 /usr/lib/x86_64-linux-gnu/libk5crypto.so.3
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libkrb5support.so.0 /usr/lib/x86_64-linux-gnu/libkrb5support.so.0
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libsasl2.so.2 /usr/lib/x86_64-linux-gnu/libsasl2.so.2
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libgssapi.so.3 /usr/lib/x86_64-linux-gnu/libgssapi.so.3
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libheimntlm.so.0 /usr/lib/x86_64-linux-gnu/libheimntlm.so.0
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libkrb5.so.26 /usr/lib/x86_64-linux-gnu/libkrb5.so.26
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libasn1.so.8 /usr/lib/x86_64-linux-gnu/libasn1.so.8
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libhcrypto.so.4 /usr/lib/x86_64-linux-gnu/libhcrypto.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libroken.so.18 /usr/lib/x86_64-linux-gnu/libroken.so.18
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libwind.so.0 /usr/lib/x86_64-linux-gnu/libwind.so.0
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libheimbase.so.1 /usr/lib/x86_64-linux-gnu/libheimbase.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libhx509.so.5 /usr/lib/x86_64-linux-gnu/libhx509.so.5
-
-COPY --from=builder /lib/x86_64-linux-gnu/libkeyutils.so.1 /lib/x86_64-linux-gnu/libkeyutils.so.1
-COPY --from=builder /etc/sysrepo /etc/sysrepo
-COPY --from=builder /var/run /var/run
-
-COPY --from=builder /usr/local/etc/keystored/keys/ssh_host_rsa_key.pem /usr/local/etc/keystored/keys/ssh_host_rsa_key.pem
-COPY --from=builder /usr/local/etc/keystored/keys/ssh_host_rsa_key.pem.pub /usr/local/etc/keystored/keys/ssh_host_rsa_key.pem.pub
-COPY --from=builder /usr/local/share/libnetconf2 /usr/local/share/libnetconf2
-
-RUN ldconfig
-
-WORKDIR /tmp
-RUN \
-    apt-get update && apt-get install -yqq wget \
-    openssh-client \
-    jq \
-    curl
-
-RUN mkdir py_install && cd py_install && \
-    wget https://files.pythonhosted.org/packages/b9/9a/3e9da40ea28b8210dd6504d3fe9fe7e013b62bf45902b458d1cdc3c34ed9/ipaddress-1.0.23.tar.gz && \
-    tar -xvzf ipaddress-1.0.23.tar.gz && cd ipaddress-1.0.23 && \
-    python setup.py install
-
-COPY --from=builder /etc/ssh /etc/ssh
-COPY --from=builder /root/.ssh /root/.ssh
-
-WORKDIR /opt/dev
-# run only specific programs in this image
-COPY ./deploy/o-ran/ru-fh/supervisord.conf /etc/supervisord.conf
-
-# tls configuratoin
-COPY ./deploy/tls /home/netconf/.ssh
-
-COPY --from=builder /opt/dev/sysrepo/build/examples/application_example /opt/dev/sysrepo/build/examples/application_example
-
-# YANG models and related scripts
-COPY ./yang/o-ran/ru-fh /opt/dev/yang
-COPY ./yang/auto-load-yangs.sh /opt/dev/yang
-COPY ./yang/sysrepo-configuration-load.sh /opt/dev/yang
-
-# scripts for Software Management RPCs
-COPY ./deploy/o-ran/ru-fh/edit-config-after-activate.sh /opt/dev
-COPY ./deploy/o-ran/ru-fh/edit-config-after-activate.xml /opt/dev
-COPY ./deploy/o-ran/ru-fh/edit-config-after-download.sh /opt/dev
-COPY ./deploy/o-ran/ru-fh/edit-config-after-download.xml /opt/dev
-COPY ./deploy/o-ran/ru-fh/edit-config-demo-start.sh /opt/dev
-COPY ./deploy/o-ran/ru-fh/edit-config-demo-start.xml /opt/dev
-
-WORKDIR /opt/dev
-RUN \
-         cd yang && \
-         ./auto-load-yangs.sh
-
-ARG BUILD_DATE
-LABEL build-date=$BUILD_DATE
-         
-ENV EDITOR vim
-EXPOSE 830-929
-
-CMD ["sh", "-c", "/usr/bin/supervisord -c /etc/supervisord.conf"]
diff --git a/ntsimulator/deploy/o-ran/ru-fh/container-tag.yaml b/ntsimulator/deploy/o-ran/ru-fh/container-tag.yaml
deleted file mode 100644 (file)
index 280bd51..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
----
-tag: 0.6.5
diff --git a/ntsimulator/deploy/o-ran/ru-fh/edit-config-after-activate.sh b/ntsimulator/deploy/o-ran/ru-fh/edit-config-after-activate.sh
deleted file mode 100755 (executable)
index 9881695..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-echo "Loading config data into the NETCONF Server..."
-
-result=$(netopeer2-cli <<-END
-       connect --host 127.0.0.1 --login netconf
-       user-rpc --content=/opt/dev/edit-config-after-activate.xml
-       disconnect
-END
-)
-
-echo $result
-echo "Done!"
-
-exit 0
diff --git a/ntsimulator/deploy/o-ran/ru-fh/edit-config-after-activate.xml b/ntsimulator/deploy/o-ran/ru-fh/edit-config-after-activate.xml
deleted file mode 100644 (file)
index c96e741..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
-  <target>
-    <running/>
-  </target>
-  <config>
-    <software-inventory xmlns="urn:o-ran:software-management:1.0" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0" xc:operation="merge">
-  <software-slot>
-    <name>Slot1</name>
-    <active>false</active>
-    <running>false</running>
-    <access>READ_WRITE</access>
-  </software-slot>
-  <software-slot>
-    <name>Slot2</name>
-    <active>true</active>
-    <running>true</running>
-    <access>READ_ONLY</access>
-  </software-slot>
-</software-inventory>
-  </config>
-</edit-config>
\ No newline at end of file
diff --git a/ntsimulator/deploy/o-ran/ru-fh/edit-config-after-download.sh b/ntsimulator/deploy/o-ran/ru-fh/edit-config-after-download.sh
deleted file mode 100755 (executable)
index 7989808..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-echo "Loading config data into the NETCONF Server..."
-
-result=$(netopeer2-cli <<-END
-       connect --host 127.0.0.1 --login netconf
-       user-rpc --content=/opt/dev/edit-config-after-download.xml
-       disconnect
-END
-)
-
-echo $result
-echo "Done!"
-
-exit 0
\ No newline at end of file
diff --git a/ntsimulator/deploy/o-ran/ru-fh/edit-config-after-download.xml b/ntsimulator/deploy/o-ran/ru-fh/edit-config-after-download.xml
deleted file mode 100644 (file)
index 1664ed5..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-<edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
-  <target>
-    <running/>
-  </target>
-  <config>
-  <software-inventory xmlns="urn:o-ran:software-management:1.0" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0" xc:operation="replace">
-  <software-slot>
-    <name>Slot1</name>
-    <status>VALID</status>
-    <active>true</active>
-    <running>true</running>
-    <access>READ_ONLY</access>
-    <vendor-code>SA</vendor-code>
-    <build-id>2020-01-23T14:04:23</build-id>
-    <build-name>SAMSUNG-XRAN-FH-2349-5645-32</build-name>
-    <build-version>19.7.123</build-version>
-    <files>
-      <name>manifest-v1.0.1.cfg</name>
-      <version>2349-5645-32</version>
-      <local-path>/home/system/slot1</local-path>
-      <integrity>OK</integrity>
-    </files>
-    <files>
-      <name>image-v1.0.1.swm</name>
-      <version>2349-5645-32</version>
-      <local-path>/home/system/slot1</local-path>
-      <integrity>OK</integrity>
-    </files>
-  </software-slot>
-  <software-slot>
-    <name>Slot2</name>
-    <status>VALID</status>
-    <active>false</active>
-    <running>false</running>
-    <access>READ_WRITE</access>
-    <vendor-code>SA</vendor-code>
-    <build-id>2020-02-05T09:02:33</build-id>
-    <build-name>SAMSUNG-XRAN-FH-2349-5790-44</build-name>
-    <build-version>19.7.123</build-version>
-    <files>
-      <name>manifest-v1.0.2.cfg</name>
-      <version>2349-5790-44</version>
-      <local-path>/home/system/slot2</local-path>
-      <integrity>OK</integrity>
-    </files>
-    <files>
-      <name>image-v1.0.2.swm</name>
-      <version>2349-5790-44</version>
-      <local-path>/home/system/slot2</local-path>
-      <integrity>OK</integrity>
-    </files>
-  </software-slot>
-</software-inventory> 
-  </config>
-</edit-config>
\ No newline at end of file
diff --git a/ntsimulator/deploy/o-ran/ru-fh/edit-config-demo-start.sh b/ntsimulator/deploy/o-ran/ru-fh/edit-config-demo-start.sh
deleted file mode 100755 (executable)
index 4967da1..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-echo "Loading config data into the NETCONF Server..."
-
-result=$(netopeer2-cli <<-END
-       connect --host 127.0.0.1 --login netconf
-       user-rpc --content=/opt/dev/edit-config-demo-start.xml
-       disconnect
-END
-)
-
-echo $result
-echo "Done!"
-
-exit 0
diff --git a/ntsimulator/deploy/o-ran/ru-fh/edit-config-demo-start.xml b/ntsimulator/deploy/o-ran/ru-fh/edit-config-demo-start.xml
deleted file mode 100644 (file)
index c80e463..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-<edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
-  <target>
-    <running/>
-  </target>
-  <config>
-         <performance-measurement-objects xmlns="urn:o-ran:performance-management:1.0" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0" xc:operation="replace">
-         </performance-measurement-objects>
-  <hardware xmlns="urn:ietf:params:xml:ns:yang:ietf-hardware" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0" xc:operation="merge">
-  <component>
-  <name>softwareSlot1</name>
-  <class xmlns:ianahw="urn:ietf:params:xml:ns:yang:iana-hardware">ianahw:storage-drive</class>
-  <physical-index>4207123</physical-index>
-  <description>ddesdvlkmvdfkvf</description>
-  <parent>xAxAxxAxA</parent>
-  <parent-rel-pos>33250247</parent-rel-pos>
-  <hardware-rev>12.2.3</hardware-rev>
-  <firmware-rev>7.1.2</firmware-rev>
-  <software-rev>19.7.123</software-rev>
-  <serial-num>35VU5</serial-num>
-  <mfg-name>xqxSSJSqJ</mfg-name>
-  <model-name>trttrttttrtrtttt</model-name>
-  <alias>btsWtsWstBFFWs</alias>
-  <asset-id>Q446g</asset-id>
-  <is-fru>true</is-fru>
-  <mfg-date>2020-02-06T06:06:32.3Z</mfg-date>
-  <uri>JJuaJa</uri>
-  <uri>6cc66c66cZc6</uri>
-  <uuid>d8de752d-a6ee-74ed-fdac-2c8a9c88afba</uuid>
-  <state>
-    <state-last-changed>2020-02-11T11:02:45.3Z</state-last-changed>
-    <admin-state>locked</admin-state>
-    <oper-state>disabled</oper-state>
-    <usage-state>active</usage-state>
-    <alarm-state>critical major minor warning</alarm-state>
-    <standby-state>hot-standby</standby-state>
-  </state>
-</component>
-<component>
-  <name>softwareSlot2</name>
-  <class xmlns:ianahw="urn:ietf:params:xml:ns:yang:iana-hardware">ianahw:storage-drive</class>
-  <physical-index>4207123</physical-index>
-  <description>ddesdvlkmvdfkvf</description>
-  <parent>xAxAxxAxA</parent>
-  <parent-rel-pos>12350247</parent-rel-pos>
-  <hardware-rev>12.2.3</hardware-rev>
-  <firmware-rev>7.1.2</firmware-rev>
-  <software-rev>19.2.33</software-rev>
-  <serial-num>35VU5</serial-num>
-  <mfg-name>xqxSSJSqJ</mfg-name>
-  <model-name>trttrttttrtrtttt</model-name>
-  <alias>btsWtsWstBFFWs</alias>
-  <asset-id>Q446g</asset-id>
-  <is-fru>true</is-fru>
-  <mfg-date>2020-02-06T06:06:32.3Z</mfg-date>
-  <uri>JJuaJa</uri>
-  <uri>6cc66c66cZc6</uri>
-  <uuid>d8de752d-a6ee-74ed-fdac-2c8a9c88afba</uuid>
-  <state>
-    <state-last-changed>2020-02-11T11:02:45.3Z</state-last-changed>
-    <admin-state>locked</admin-state>
-    <oper-state>disabled</oper-state>
-    <usage-state>active</usage-state>
-    <alarm-state>critical major minor warning</alarm-state>
-    <standby-state>hot-standby</standby-state>
-  </state>
-</component>
-</hardware>
-<software-inventory xmlns="urn:o-ran:software-management:1.0" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0" xc:operation="replace">
-  <software-slot>
-    <name>Slot1</name>
-    <status>VALID</status>
-    <active>true</active>
-    <running>true</running>
-    <access>READ_ONLY</access>
-    <vendor-code>SA</vendor-code>
-    <build-id>2020-01-23T14:04:23</build-id>
-    <build-name>SAMSUNG-XRAN-FH-2349-5645-32</build-name>
-    <build-version>19.7.123</build-version>
-    <files>
-      <name>manifest-v1.0.1.cfg</name>
-      <version>2349-5645-32</version>
-      <local-path>/home/system/slot1</local-path>
-      <integrity>OK</integrity>
-    </files>
-    <files>
-      <name>image-v1.0.1.swm</name>
-      <version>2349-5645-32</version>
-      <local-path>/home/system/slot1</local-path>
-      <integrity>OK</integrity>
-    </files>
-  </software-slot>
-  <software-slot>
-    <name>Slot2</name>
-    <status>VALID</status>
-    <active>false</active>
-    <running>false</running>
-    <access>READ_WRITE</access>
-    <vendor-code>SA</vendor-code>
-    <build-id>2019-07-02T14:04:23</build-id>
-    <build-name>SAMSUNG-XRAN-FH-2349-2345-44</build-name>
-    <build-version>19.2.33</build-version>
-    <files>
-      <name>manifest-v1.0.0.cfg</name>
-      <version>2349-2345-44</version>
-      <local-path>/home/system/slot2</local-path>
-      <integrity>OK</integrity>
-    </files>
-    <files>
-      <name>image-v1.0.0.swm</name>
-      <version>2349-2345-44</version>
-      <local-path>/home/system/slot2</local-path>
-      <integrity>OK</integrity>
-    </files>
-  </software-slot>
-</software-inventory>  
-</config>
-</edit-config>
\ No newline at end of file
diff --git a/ntsimulator/deploy/o-ran/ru-fh/supervisord.conf b/ntsimulator/deploy/o-ran/ru-fh/supervisord.conf
deleted file mode 100644 (file)
index 1dcba35..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-[supervisord]
-nodaemon=true
-logfile=/var/log/supervisord.log
-loglevel=debug
-
-[program:sysrepod]
-command=/usr/local/bin/sysrepod -d
-autorestart=true
-redirect_stderr=true
-priority=1
-
-[program:sysrepo-plugind]
-command=/usr/local/bin/sysrepo-plugind -d
-autorestart=true
-redirect_stderr=true
-priority=2
-
-[program:netopeer2-server]
-command=/usr/local/bin/netopeer2-server -d
-autorestart=true
-redirect_stderr=true
-priority=3
-
-[program:enable-netconf-call-home]
-directory=/home/netconf/.ssh
-command=/home/netconf/.ssh/enable_netconf_call_home.sh
-startsecs=0
-autorestart=false
-redirect_stderr=false
-priority=4
-
-[program:enable-tls]
-directory=/home/netconf/.ssh
-command=/home/netconf/.ssh/enable_tls.sh
-startsecs=0
-autorestart=false
-redirect_stderr=false
-priority=5
-
-[program:set-nts-ip-script]
-directory=/home/netconf/.ssh
-command=/home/netconf/.ssh/set_NTS_IP.sh
-startsecs=0
-autorestart=false
-redirect_stderr=false
-priority=5
-
-[program:sysrepo-config-load]
-directory=/opt/dev/yang
-command=/opt/dev/yang/sysrepo-configuration-load.sh
-autorestart=false
-redirect_stderr=true
-startretries=1
-priority=6
-
-[program:o-ran-notifications]
-command=/usr/local/bin/o-ran-notifications
-autorestart=true
-redirect_stderr=true
-priority=7
-
-[program:ves-heartbeat]
-command=/usr/local/bin/ves-heartbeat
-autorestart=true
-redirect_stderr=true
-priority=8
-
-[program:software-management]
-command=/usr/local/bin/software-management
-autorestart=true
-redirect_stderr=true
-priority=9
\ No newline at end of file
diff --git a/ntsimulator/deploy/o-ran/supervisord.conf b/ntsimulator/deploy/o-ran/supervisord.conf
new file mode 100644 (file)
index 0000000..cd7eb88
--- /dev/null
@@ -0,0 +1,22 @@
+[supervisord]
+nodaemon=true
+logfile=/var/log/supervisord.log
+loglevel=debug
+
+[program:netopeer2-server]
+command=/usr/local/bin/netopeer2-server -d
+autorestart=true
+redirect_stderr=true
+priority=2
+
+[program:sshd]
+command=/usr/sbin/sshd -D
+autorestart=true
+redirect_stderr=true
+priority=3
+
+[program:ntsim-ng]
+command=/opt/dev/ntsim-ng/ntsim-ng -w /opt/dev/ntsim-ng -n -f
+autorestart=false
+redirect_stderr=true
+priority=4
diff --git a/ntsimulator/deploy/o-ran/ubuntu.Dockerfile b/ntsimulator/deploy/o-ran/ubuntu.Dockerfile
new file mode 100644 (file)
index 0000000..329fa7f
--- /dev/null
@@ -0,0 +1,43 @@
+#
+# Copyright 2020 highstreet technologies GmbH and others
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+################
+#### DEVICE ####
+################
+
+FROM o-ran-sc/nts-ng-base:latest
+LABEL maintainer="alexandru.stancu@highstreet-technologies.com / adrian.lita@highstreet-technologies.com"
+
+# ntsim-ng configuration and deployment
+COPY ./yang /opt/dev/deploy/yang
+COPY ./config.json /opt/dev/ntsim-ng/config/config.json
+
+# ntsim-ng init docker
+RUN /opt/dev/ntsim-ng/ntsim-ng --docker-init -w /opt/dev/ntsim-ng
+
+# supervisor configuration
+COPY ./supervisord.conf /etc/supervisord.conf
+
+# finishing container build
+ARG BUILD_DATE
+LABEL build-date=$BUILD_DATE
+
+# add exposed ports
+EXPOSE 830-929
+EXPOSE 21-22
+
+# run
+WORKDIR /opt/dev/workspace
+CMD ["sh", "-c", "/usr/bin/supervisord -c /etc/supervisord.conf"]
similarity index 96%
rename from ntsimulator/yang/o-ran/ru-fh/o-ran-fm.yang
rename to ntsimulator/deploy/o-ran/yang/o-ran-fm.yang
index 27d06f3..5142418 100644 (file)
@@ -75,9 +75,6 @@ module o-ran-fm {
     }
 
     list affected-objects {
-      // [ast] Fix for list without a key
-      key name;
-      // [ast] end fix
       leaf name {
         type string {
           length "1..255";
@@ -149,9 +146,6 @@ module o-ran-fm {
 
   container active-alarm-list {
     list active-alarms {
-      // [ast] Fix for list without a key
-      key fault-id;
-      // [ast] end fix
       uses alarm;
 
       description
@@ -207,9 +207,6 @@ module o-ran-module-cap {
     }
 
     list compression-method-supported {
-      // [ast] Fix for list without a key
-      key "iq-bitwidth compression-type";
-      // [ast] end fix
       uses cf:compression-details;
 
       description
@@ -124,7 +124,8 @@ module o-ran-mplane-int {
         }
         leaf sub-interface {
           type leafref {
-            path "/if:interfaces/if:interface[if:name = current()/../interface-name]/o-ran-int:vlan-id";
+            //checkAL added o-ran-mplane-int: before interface-name, as it would not find anything otherwise
+            path "/if:interfaces/if:interface[if:name = current()/../o-ran-mplane-int:interface-name]/o-ran-int:vlan-id";
           }
           description
             "vlans used to communicate with management plane servers.";
@@ -111,14 +111,9 @@ module o-ran-operations {
 
       leaf ru-instance-id {
         type string;
-       // [ast] added extra concat, because only 3 params are accepted in NTS
-       // must "re-match(current(), concat(/hw:hardware/hw:component/hw:mfg-name,
-        //  '_', /hw:hardware/hw:component/hw:model-name, '_',
-        //  /hw:hardware/hw:component/hw:serial-num ))";
-        must "re-match(current(), concat(concat(/hw:hardware/hw:component/hw:mfg-name,
-          '_', /hw:hardware/hw:component/hw:model-name), '_',
-          /hw:hardware/hw:component/hw:serial-num))";
-       // [ast] end fix
+        must "re-match(current(), concat(/hw:hardware/hw:component/hw:mfg-name,
+            '_', /hw:hardware/hw:component/hw:model-name, '_',
+            /hw:hardware/hw:component/hw:serial-num ))";
         description
           "a unique instance identifier that may be used to identify a
           particular hardware instance, e.g., when used performing hierarchical
@@ -264,9 +264,6 @@ module o-ran-performance-management {
 
       case TRANSPORT {
         list tr-measured-result{
-         // [ast] Fix for list without key
-          key name;
-         // [ast] end fix
           leaf name{
             type leafref{
               path "/o-ran-elements:processing-elements/o-ran-elements:ru-elements/o-ran-elements:name";
@@ -294,9 +291,6 @@ module o-ran-performance-management {
 
       case EAXC_ID {
         list eaxc-measured-result {
-         // [ast] Fix for list without key
-          key eaxc-id;
-         // [ast] end fix
           leaf eaxc-id{
             type uint16;
 
@@ -180,12 +180,15 @@ module o-ran-processing-element {
           description "the interface name ";
         }
         container aliasmac-flow {
-          when "../../../transport-session-type = 'ALIASMAC-INTERFACE'";
+          when "../../../transport-session-type = 'ALIASMAC-INTERFACE'";          
           if-feature o-ran-int:ALIASMAC-BASED-CU-PLANE;
+          //checkAS add presence, because it has mandatory child
+          presence "Contains AliasMAC details.";
           description "leafs for virtual mac type data flows";
           leaf ru-aliasmac-address {
             type leafref {
-              path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:alias-macs";
+              //checkAL added o-ran-elements:  before interface-name
+              path "/if:interfaces/if:interface[if:name = current()/../../o-ran-elements:interface-name]/o-ran-int:alias-macs";
             }
             mandatory true;
             description
@@ -193,7 +196,8 @@ module o-ran-processing-element {
           }
           leaf vlan-id {
             type leafref {
-              path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:vlan-id";
+              //checkAL added o-ran-elements:  before interface-name
+              path "/if:interfaces/if:interface[if:name = current()/../../o-ran-elements:interface-name]/o-ran-int:vlan-id";
             }
             description
               "O-RU's VLAN-ID used for alias MAC based flow";
@@ -207,10 +211,13 @@ module o-ran-processing-element {
         }
         container eth-flow {
           when "../../../transport-session-type = 'ETH-INTERFACE'";
+          //checkAS add presence, because it has mandatory child
+          presence "Contains ETH details.";
           description "leafs for mac + vlan-id type data flows";
           leaf ru-mac-address {
             type leafref {
-              path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:mac-address";
+              //checkAL added o-ran-elements:  before interface-name
+              path "/if:interfaces/if:interface[if:name = current()/../../o-ran-elements:interface-name]/o-ran-int:mac-address";
             }
             mandatory true;
             description
@@ -218,7 +225,8 @@ module o-ran-processing-element {
           }
           leaf vlan-id {
             type leafref {
-              path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:vlan-id";
+              //checkAL added o-ran-elements:  before interface-name
+              path "/if:interfaces/if:interface[if:name = current()/../../o-ran-elements:interface-name]/o-ran-int:vlan-id";
             }
             mandatory true;
             description
@@ -233,17 +241,21 @@ module o-ran-processing-element {
         }
         container udpip-flow {
           when "../../../transport-session-type = 'UDPIP-INTERFACE'";
+          //checkAL added presence
+          presence "contains updip details";
           description "leafs for UDP/IP type data flows";
           choice address {
             leaf ru-ipv4-address {
               type leafref {
-                path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/ip:ipv4/ip:address/ip:ip";
+                //checkAL added o-ran-elements:  before interface-name
+                path "/if:interfaces/if:interface[if:name = current()/../../o-ran-elements:interface-name]/ip:ipv4/ip:address/ip:ip";
               }
               description "O-RU's IPv4 address";
             }
             leaf ru-ipv6-address {
               type leafref {
-                path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/ip:ipv6/ip:address/ip:ip";
+                //checkAL added o-ran-elements:  before interface-name
+                path "/if:interfaces/if:interface[if:name = current()/../../o-ran-elements:interface-name]/ip:ipv6/ip:address/ip:ip";
               }
               description "O-RU's IPv6 address";
             }
@@ -81,7 +81,8 @@ module o-ran-transceiver {
       }
       leaf port-number {
         type leafref {
-          path "/if:interfaces/if:interface[if:name = current()/../interface-name]" + "/o-ran-int:port-reference/o-ran-int:port-number";
+          //checkAL added o-ran-transceiver:  before interface-name
+          path "/if:interfaces/if:interface[if:name = current()/../o-ran-transceiver:interface-name]" + "/o-ran-int:port-reference/o-ran-int:port-number";
         }
         description
         "A number which identifies a port. In case of SFP/SFP+
@@ -1355,9 +1355,7 @@ module o-ran-uplane-conf {
       }
 
       container laa-carrier-configuration {
-        // [ast] Fix? added relative path
-        // when "../band-number = 46";
-        when "./../band-number = 46";
+        when "../band-number = 46";
         if-feature mcap:LAA;
         description "Container to specify LAA feature related carrier configuration.";
         uses laa-carrier-config;
@@ -1487,9 +1485,6 @@ module o-ran-uplane-conf {
       list capabilities {
         description
           "List of capabilities related to this tx-array";
-       // [ast] Fix for list without key
-        key max-supported-frequency-dl;
-        // [ast] end fix
         uses mcap:support-for-dl;
       }
     }
@@ -1525,9 +1520,6 @@ module o-ran-uplane-conf {
       list capabilities {
         description
           "List of capabilities related to this rx-array";
-       // [ast] Fix for list without key
-        key max-supported-frequency-ul;
-        // [ast] end fix
         uses mcap:support-for-ul;
       }
     }
@@ -127,9 +127,10 @@ module o-ran-usermgmt {
   }
 
   container users {
-    must "user/enabled='true'" {
-      error-message "At least one account needs to be enabled.";
-    }
+    // must "user/enabled='true'" {
+    //   error-message "At least one account needs to be enabled.";
+    // }
+    //checkAL - above must is commented out for installing reasons
     //TAKE NOTE - any configuration with zero enabled users is invalid.
     //This will typically be the case when using a simulated NETCONF Server
     //and so this constraint should be removed when operating in those scenarios
diff --git a/ntsimulator/deploy/supervisord.conf b/ntsimulator/deploy/supervisord.conf
deleted file mode 100644 (file)
index b4a9098..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-[supervisord]
-nodaemon=true
-logfile=/var/log/supervisord.log
-loglevel=debug
-
-[program:sysrepod]
-command=/usr/local/bin/sysrepod -d
-autorestart=true
-redirect_stderr=true
-priority=1
-
-[program:sysrepo-plugind]
-command=/usr/local/bin/sysrepo-plugind -d
-autorestart=true
-redirect_stderr=true
-priority=2
-
-[program:netopeer2-server]
-command=/usr/local/bin/netopeer2-server -d
-autorestart=true
-redirect_stderr=true
-priority=3
-
-[program:enable-ssh]
-directory=/home/netconf/.ssh
-command=/home/netconf/.ssh/enable_ssh_key.sh
-startsecs=0
-autorestart=false
-redirect_stderr=false
-priority=4
-
-[program:enable-tls]
-directory=/home/netconf/.ssh
-command=/home/netconf/.ssh/enable_tls.sh
-startsecs=0
-autorestart=false
-redirect_stderr=false
-priority=5
-
-[program:sysrepo-config-load]
-directory=/opt/dev/yang
-command=/opt/dev/yang/sysrepo-configuration-load.sh
-autorestart=false
-redirect_stderr=true
-startretries=1
-priority=6
-
-[program:o-ran-notifications]
-command=/usr/local/bin/o-ran-notifications
-autorestart=true
-redirect_stderr=true
-priority=7
-
-[program:ves-heartbeat]
-command=/usr/local/bin/ves-heartbeat
-autorestart=true
-redirect_stderr=true
-priority=8
\ No newline at end of file
diff --git a/ntsimulator/deploy/tls/ca.srl b/ntsimulator/deploy/tls/ca.srl
deleted file mode 100644 (file)
index c10d829..0000000
+++ /dev/null
@@ -1 +0,0 @@
-91390D611074ACC8
diff --git a/ntsimulator/deploy/tls/client.key b/ntsimulator/deploy/tls/client.key
deleted file mode 100644 (file)
index 7ccdab1..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEAueCQaNQWoNmFK6LKu1p8U8ZWdWg/PvDdLsJyzfzl/Qw4UA68
-SfFNaY06zZl8QB9W02nr5kWeeMY0VA3adrPgOlvfx3oWlFbkETnMaN4OT3WTQ0Wt
-6jAWZDzVfopwpJPAzRPxACDftIqFGagYcF32hZlVNqqnVdbXh0S0EViweqp/dbG4
-VDUHSNVbglc+u4UbEzNIFXMdEFsJZpkynOmSiTsIATqIhb+2srkVgLwhfkC2qkuH
-QwAHdubuB07ObM2z01UhyEdDvEYGHwtYAGDBL2TAcsI0oGeVkRyuOkV0QY0UN7UE
-FI1yTYw+xZ42HgFx3uGwApCImxhbj69GBYWFqwIDAQABAoIBAQCZN9kR8DGu6V7y
-t0Ax68asL8O5B/OKaHWKQ9LqpVrXmikZJOxkbzoGldow/CIFoU+q+Zbwu9aDa65a
-0wiP7Hoa4Py3q5XNNUrOQDyU/OYC7cI0I83WS0lJ2zOJGYj8wKae5Z81IeQFKGHK
-4lsy1OGPAvPRGh7RjUUgRavA2MCwe07rWRuDb/OJFe4Oh56UMEjwMiNBtMNtncog
-j1vr/qgRJdf9tf0zlJmLvUJ9+HSFFV9I/97LJyFhb95gAfHkjdVroLVgT3Cho+4P
-WtZaKCIGD0OwfOG2nLV4leXvRUk62/LMlB8NI9+JF7Xm+HCKbaWHNWC7mvWSLV58
-Zl4AbUWRAoGBANyJ6SFHFRHSPDY026SsdMzXR0eUxBAK7G70oSBKKhY+O1j0ocLE
-jI2krHJBhHbLlnvJVyMUaCUOTS5m0uDw9hgSsAqeSL3hL38kxVZw+KNG9Ouno1Fl
-KnE/xXHlPQyeGs/P8nAMzHZxQtEsQdQayJEhK2XXHTsy7Q3MxDisfVJ1AoGBANfD
-34gB+OMx6pwj7zk3qWbYXSX8xjCZMR0ciko+h4xeMP2N8B0oyoqC+v1ABMAtJ3wG
-sGZd0hV9gwM7OUM3SEwkn6oeg1GemWLcn4rlSmTnZc4aeVwrEWlnSNFX3s4g9l4u
-k8Ugu4MVJYqH8HuDQ5Ggl6/QAwPzMSEdCW0O+jOfAoGAIBRbegC5+t6m7Yegz4Ja
-dxV1g98K6f58x+MDsQu4tYWV4mmrQgaPH2dtwizvlMwmdpkh+LNWNtWuumowkJHc
-akIFo3XExQIFg6wYnGtQb4e5xrGa2xMpKlIJaXjb+YLiCYqJDG2ALFZrTrvuU2kV
-9a5qfqTc1qigvNolTM0iaaUCgYApmrZWhnLUdEKV2wP813PNxfioI4afxlpHD8LG
-sCn48gymR6E+Lihn7vuwq5B+8fYEH1ISWxLwW+RQUjIneNhy/jjfV8TgjyFqg7or
-0Sy4KjpiNI6kLBXOakELRNNMkeSPopGR2E7v5rr3bGD9oAD+aqX1G7oJH/KgPPYd
-Vl7+ZwKBgQDcHyWYrimjyUgKaQD2GmoO9wdcJYQ59ke9K+OuGlp4ti5arsi7N1tP
-B4f09aeELM2ASIuk8Q/Mx0jQFnm8lzRFXdewgvdPoZW/7VufM9O7dGPOc41cm2Dh
-yrTcXx/VmUBb+/fnXVEgCv7gylp/wtdTGHQBQJHR81jFBz0lnLj+gg==
------END RSA PRIVATE KEY-----
diff --git a/ntsimulator/deploy/tls/enable_connections.sh b/ntsimulator/deploy/tls/enable_connections.sh
deleted file mode 100755 (executable)
index a321f8b..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#! /bin/bash
-################################################################################
-#
-# Copyright 2020 highstreet technologies GmbH and others
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-# 
-#     http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-################################################################################
-
-int_re='^[0-9]+$'
-
-ssh_conn=`jq '.["ssh-connections"]' /opt/dev/scripts/configuration.json`
-tls_conn=`jq '.["tls-connections"]' /opt/dev/scripts/configuration.json`
-
-echo "Enabling $ssh_conn SSH connections and $tls_conn TLS connections in device..."
-
-# if [ "$#" -ne 2 ]; then
-#   echo "Usage: $0 NUM_SSH_CONNECTIONS NUM_TLS_CONNECTIONS" >&2
-#   exit 1
-# fi
-
-if ! [[ $ssh_conn =~ $int_re ]] ; then
-   echo "error: Argument '$ssh_conn' is not a number" >&2
-   exit 1
-fi
-
-if ! [[ $tls_conn =~ $int_re ]] ; then
-   echo "error: Argument '$tls_conn' is not a number" >&2
-   exit 1
-fi
-
-netconf_port=830
-
-if [ $IPv6Enabled = "true" ]; then
-    localhost_address="::"
-else
-    localhost_address="0.0.0.0"
-fi
-
-echo '<netconf-server xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-server"><listen>' > connections.xml
-
-for (( ssh_counter=0; ssh_counter<$ssh_conn; ssh_counter++ ))
-do
-  echo "<endpoint><name>MNG$ssh_counter</name><ssh><address>$localhost_address</address><port>$netconf_port</port><host-keys><host-key><name>imported SSH key</name><public-key>ssh_host_rsa_key</public-key></host-key><host-key><name>Melacon Server key</name><public-key>melacon_server_key</public-key></host-key></host-keys></ssh></endpoint>" >> connections.xml
-  ((netconf_port++))
-done
-
-for (( tls_counter=0; tls_counter<$tls_conn; tls_counter++ ))
-do
-  echo "<endpoint><name>MNGTLS$tls_counter</name><tls><address>$localhost_address</address><port>$netconf_port</port><certificates><certificate><name>melacon_server_cert</name></certificate></certificates><client-auth><trusted-ca-certs>trusted_ca_list</trusted-ca-certs><cert-maps><cert-to-name><id>1</id><fingerprint>02:E9:38:1F:F6:8B:62:DE:0A:0B:C5:03:81:A8:03:49:A0:00:7F:8B:F3</fingerprint><map-type xmlns:x509c2n=\"urn:ietf:params:xml:ns:yang:ietf-x509-cert-to-name\">x509c2n:specified</map-type><name>netconf</name></cert-to-name></cert-maps></client-auth></tls></endpoint>" >> connections.xml
-  ((netconf_port++))
-done
-
-echo '</listen></netconf-server>' >> connections.xml
-
-sysrepocfg --import=connections.xml --format=xml ietf-netconf-server
-rm connections.xml
-
-echo 'Done'
-exit 0
\ No newline at end of file
diff --git a/ntsimulator/deploy/tls/enable_netconf_call_home.sh b/ntsimulator/deploy/tls/enable_netconf_call_home.sh
deleted file mode 100755 (executable)
index 5d453ea..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-#! /bin/bash
-################################################################################
-#
-# Copyright 2020 highstreet technologies GmbH and others
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-# 
-#     http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-################################################################################
-
-sleep 20
-
-netconf_call_home=`jq '.["netconf-call-home"]' /opt/dev/scripts/configuration.json`
-
-
-if [ $netconf_call_home = "false" ] ; then
-   echo "NETCONF Call Home is disabled, nothing to do..."
-   exit 0
-else
-   echo "Enabling NETCONF Call Home in device..."
-fi
-
-controller_ip=`jq '.["controller-details"] ."controller-ip"' /opt/dev/scripts/configuration.json`
-controller_username=`jq '.["controller-details"] ."controller-username"' /opt/dev/scripts/configuration.json`
-controller_password=`jq '.["controller-details"] ."controller-password"' /opt/dev/scripts/configuration.json`
-controller_port=`jq '.["controller-details"] ."controller-port"' /opt/dev/scripts/configuration.json`
-netconf_call_home_port=`jq '.["controller-details"] ."netconf-call-home-port"' /opt/dev/scripts/configuration.json`
-
-SSH_PUB_KEY_MELACON="$(cat /home/netconf/.ssh/melacon.server.key.pub | awk '{print $2}')"
-
-payload='{
-      "odl-netconf-callhome-server:device": [
-        {
-          "odl-netconf-callhome-server:unique-id": "'$HOSTNAME'",
-          "odl-netconf-callhome-server:ssh-host-key": "'$SSH_PUB_KEY_MELACON'",
-          "odl-netconf-callhome-server:credentials": {
-            "odl-netconf-callhome-server:username": "netconf",
-            "odl-netconf-callhome-server:passwords": [
-              "netconf"
-            ]
-          }
-        }
-      ]
-}'
-
-odl_ip=`sed -e 's/^"//' -e 's/"$//' <<<"$controller_ip"`
-odl_username=`sed -e 's/^"//' -e 's/"$//' <<<"$controller_username"`
-odl_password=`sed -e 's/^"//' -e 's/"$//' <<<"$controller_password"`
-
-echo "Payload: $payload"
-
-curl -v -H 'Content-Type: application/json' -X PUT -u $odl_username:$odl_password \
--d "$payload" http://$odl_ip:$controller_port/restconf/config/odl-netconf-callhome-server:netconf-callhome-server/allowed-devices/device/$HOSTNAME
-
-echo '<netconf-server xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-server">
-        <call-home>
-          <netconf-client>
-            <name>test_ssh_ch_client</name>
-            <ssh>
-              <endpoints>
-                <endpoint>
-                  <name>test_ssh_ch_endpt</name>
-                  <address>'$odl_ip'</address>
-                  <port>'$netconf_call_home_port'</port>
-                </endpoint>
-              </endpoints>
-              <host-keys>
-                <host-key>
-                  <name>melacon server key</name>
-                  <public-key>melacon_server_key</public-key>
-                </host-key>
-              </host-keys>
-            </ssh>
-            <connection-type>
-              <persistent/>
-            </connection-type>
-          </netconf-client>
-        </call-home>
-    </netconf-server>' > connections.xml
-
-sysrepocfg --merge=connections.xml --format=xml ietf-netconf-server
-rm connections.xml
-
-echo 'Done'
-exit 0
\ No newline at end of file
diff --git a/ntsimulator/deploy/tls/enable_ssh_key.sh b/ntsimulator/deploy/tls/enable_ssh_key.sh
deleted file mode 100755 (executable)
index 45b02e6..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#! /bin/bash
-################################################################################
-#
-# Copyright 2020 highstreet technologies GmbH and others
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-# 
-#     http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-################################################################################
-# Script to enable SSH publicKey authentication in the localhost NETCONF server
-
-sleep 5
-
-SSH_PUB_KEY="$(cat /home/netconf/.ssh/id_dsa.pub| awk '{print $2}')"
-
-echo '<system xmlns="urn:ietf:params:xml:ns:yang:ietf-system"><authentication><user><name>netconf</name><authorized-key><name>ssh_key</name><algorithm>ssh-dss</algorithm>' >> load_auth_pubkey.xml
-echo '<key-data>'"$SSH_PUB_KEY"'</key-data></authorized-key></user></authentication></system>' >> load_auth_pubkey.xml
-
-sysrepocfg --merge=load_auth_pubkey.xml --format=xml ietf-system
-rm load_auth_pubkey.xml
-
-ssh-keyscan -p 830 127.0.0.1 >> ~/.ssh/known_hosts
-
-echo 'Done'
-exit 0
\ No newline at end of file
diff --git a/ntsimulator/deploy/tls/enable_tls.sh b/ntsimulator/deploy/tls/enable_tls.sh
deleted file mode 100755 (executable)
index 97ba4c2..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-#! /bin/bash
-################################################################################
-#
-# Copyright 2020 highstreet technologies GmbH and others
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-# 
-#     http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-################################################################################
-
-sleep 10
-
-openssl genrsa -out melacon.server.key 2048
-
-openssl req -new -sha256 -key melacon.server.key -subj "/C=US/ST=CA/O=MeLaCon, Inc./CN=melacon.com" -out melacon.server.csr
-openssl x509 -req -in melacon.server.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out melacon.server.crt -days 500 -sha256
-rm melacon.server.csr
-ssh-keygen -y -f melacon.server.key > melacon.server.key.pub
-
-SSH_PUB_KEY="$(cat /home/netconf/.ssh/id_dsa.pub| awk '{print $2}')"
-SSH_PUB_KEY_MELACON="$(cat melacon.server.key.pub | awk '{print $2}')"
-
-echo '<system xmlns="urn:ietf:params:xml:ns:yang:ietf-system"><authentication><user><name>netconf</name>'  >> load_auth_pubkey.xml
-echo '<authorized-key><name>ssh_key</name><algorithm>ssh-dss</algorithm>' >> load_auth_pubkey.xml
-echo '<key-data>'"$SSH_PUB_KEY"'</key-data></authorized-key>' >> load_auth_pubkey.xml
-echo '<authorized-key><name>melacon_server_key</name><algorithm>ssh-rsa</algorithm>' >> load_auth_pubkey.xml
-echo '<key-data>'"$SSH_PUB_KEY_MELACON"'</key-data></authorized-key></user></authentication></system>' >> load_auth_pubkey.xml
-
-sysrepocfg --merge=load_auth_pubkey.xml --format=xml ietf-system
-rm load_auth_pubkey.xml
-
-if [ $IPv6Enabled = "true" ]; then
-   ssh-keyscan -p 830 :: >> ~/.ssh/known_hosts
-fi
-ssh-keyscan -p 830 127.0.0.1 >> /root/.ssh/known_hosts
-
-MELACON_SERVER_KEY="$(sed '1d;$d' melacon.server.key)"
-
-echo '<action xmlns="urn:ietf:params:xml:ns:yang:1"><keystore xmlns="urn:ietf:params:xml:ns:yang:ietf-keystore"><private-keys><load-private-key><name>melacon_server_key</name>' >> load_private_key.xml
-echo '<private-key>'"$MELACON_SERVER_KEY"'</private-key></load-private-key></private-keys></keystore></action>' >> load_private_key.xml
-
-netopeer2-cli <<END
-auth pref publickey 1000
-auth keys add /home/netconf/.ssh/id_dsa.pub /home/netconf/.ssh/id_dsa
-connect --host 127.0.0.1 --login netconf
-user-rpc --content=load_private_key.xml
-disconnect
-END
-
-rm load_private_key.xml
-
-MELACON_CERT="$(sed '1d;$d' melacon.server.crt)"
-CA_CERT="$(sed '1d;$d' ca.pem)"
-
-echo '<keystore xmlns="urn:ietf:params:xml:ns:yang:ietf-keystore"><private-keys><private-key><name>melacon_server_key</name><certificate-chains><certificate-chain><name>melacon_server_cert</name>' >> load_server_certs.xml
-echo '<certificate>'"$MELACON_CERT"'</certificate></certificate-chain></certificate-chains></private-key></private-keys><trusted-certificates><name>trusted_ca_list</name><trusted-certificate><name>ca</name>' >> load_server_certs.xml
-echo '<certificate>'"$CA_CERT"'</certificate></trusted-certificate></trusted-certificates></keystore>' >> load_server_certs.xml
-
-sysrepocfg --merge=load_server_certs.xml --format=xml ietf-keystore
-rm load_server_certs.xml
-
-# enable the SSH and TLS connections, according to the configuration file
-./enable_connections.sh
-
-echo 'Done'
-exit 0
\ No newline at end of file
diff --git a/ntsimulator/deploy/tls/netconf_browser.crt b/ntsimulator/deploy/tls/netconf_browser.crt
deleted file mode 100644 (file)
index 687579d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDGDCCAgACCQCROQ1hEHSsyDANBgkqhkiG9w0BAQsFADCBjDELMAkGA1UEBhMC
-Q1oxFjAUBgNVBAgMDVNvdXRoIE1vcmF2aWExDTALBgNVBAcMBEJybm8xDzANBgNV
-BAoMBkNFU05FVDEMMAoGA1UECwwDVE1DMRMwEQYDVQQDDApleGFtcGxlIENBMSIw
-IAYJKoZIhvcNAQkBFhNleGFtcGxlY2FAbG9jYWxob3N0MB4XDTE5MDYxNzEyNDMy
-N1oXDTIwMTAyOTEyNDMyN1owDzENMAsGA1UEAwwEdGVzdDCCASIwDQYJKoZIhvcN
-AQEBBQADggEPADCCAQoCggEBAIKxdFmW7Cr4x7txXrHgaIZYpfsI9QwkwX+3q4h9
-kbY1QVaram/AlGWgXe/42q1z0UVRGGSsnwZvIv+daT4XE47Q/7JfUcYyo1EdGORc
-ym++D+gmIy37cUzB1oe9zZrxJ3zSZnwcQV13kZMwyOAs5DT1MpqPSypclv8t3c0Z
-H0mdzpcF4sJXBg14MoQqZSwSeZZrg9tAe36hhyrKhIVXReY+Lse0X72XS/qwCnA9
-26hjm//8d7j9nskzou9xOLeBh/umZUXHkUVmY1iGQ4jt7HAvg0yZ+2zg02YyZNfY
-Xb21jGB21qy1Jf2roFCn2+7bAjqpI8+Y4C8nm+fl/sScugUCAwEAATANBgkqhkiG
-9w0BAQsFAAOCAQEAX1Gf0xZDTrUVHITSc/sRC03e+Ju658p4fx9BlP2KqqnoZHdh
-zJhmps05FAnvHx/7c4tIABBt3puLl6CofznaE2+QAUxeCiTv2vm/4O3nLU4As5jP
-udfKU+XgVI5PTEorDgVsHnv3/JBmZUxuR4VM63hBJtBvSl4QvNXRtpXjjkljwPvJ
-r+Ea9z712F2dw48c/tzRLUIp7n/py0zhSLiBLBmwsT8fkr5hKmhenqqgY5Vkfa36
-UmfEeOVhhdy5tfs2jwxy9gNFNIryijbn4HMBJEy0zEfva8VEmrYqDJQ5AYX/xcwf
-8D0Sgg3582eQgbQR7eYl0DMlv2JUn5I4AjUutg==
------END CERTIFICATE-----
diff --git a/ntsimulator/deploy/tls/netconf_browser.csr b/ntsimulator/deploy/tls/netconf_browser.csr
deleted file mode 100644 (file)
index 61d8a4c..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
------BEGIN CERTIFICATE REQUEST-----
-MIICVDCCATwCAQAwDzENMAsGA1UEAwwEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQAD
-ggEPADCCAQoCggEBAIKxdFmW7Cr4x7txXrHgaIZYpfsI9QwkwX+3q4h9kbY1QVar
-am/AlGWgXe/42q1z0UVRGGSsnwZvIv+daT4XE47Q/7JfUcYyo1EdGORcym++D+gm
-Iy37cUzB1oe9zZrxJ3zSZnwcQV13kZMwyOAs5DT1MpqPSypclv8t3c0ZH0mdzpcF
-4sJXBg14MoQqZSwSeZZrg9tAe36hhyrKhIVXReY+Lse0X72XS/qwCnA926hjm//8
-d7j9nskzou9xOLeBh/umZUXHkUVmY1iGQ4jt7HAvg0yZ+2zg02YyZNfYXb21jGB2
-1qy1Jf2roFCn2+7bAjqpI8+Y4C8nm+fl/sScugUCAwEAAaAAMA0GCSqGSIb3DQEB
-CwUAA4IBAQB4mtqz9WtRqU4IBn+FNFQGBuX6uDSfDhC2Qo6mQB1kdErEnbdL6TYn
-gkgZradYwMAaBPKDwAx74YpWs6C4HgkORP1KPweDIjZNcpEAY0HwtXdUQHzMWFOh
-gdCjVYd7WdWg7CFl01lAx1HHzakIvW6ZxjjKoPm4SaFSGvyKzj0CyH01BoSM7pgt
-ZBbQcFkV6ZYItXPZR6Bi5hJnUkNu/K8rPEQ2Fr/wXUUz3PZhO+ZGG+WZbMFuo64V
-QUMEBwWNNf1I6r9EsLiar6Y1q22P6tLmjcY9Nbca/pD+3pplZ+/j6wpnufLM8ati
-dvWZorvVAKwQim5RFnCZ7VSmqKIaywIO
------END CERTIFICATE REQUEST-----
diff --git a/ntsimulator/deploy/tls/set_NTS_IP.sh b/ntsimulator/deploy/tls/set_NTS_IP.sh
deleted file mode 100755 (executable)
index 151e996..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-################################################################################
-#
-# Copyright 2020 highstreet technologies GmbH and others
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-# 
-#     http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-################################################################################
-
-sleep 30
-
-if [ "$K8S_DEPLOYMENT" = "true" ]; then
-   NTS_IP=""
-   while true
-    do
-        echo "Trying to set the NTS_IP env var..."
-        if [ -z "$NTS_IP" ]; then
-            s=$HOSTNAME
-            count="$(cut -d'-' -f2 <<<"$s")"
-            id="NTSIM_${count}_SERVICE_HOST"
-            export NTS_IP=$(echo ${!id})
-            echo "NTS_IP=$NTS_IP"
-        else
-            echo "export NTS_IP=$NTS_IP" >> /root/.bashrc
-            source /root/.bashrc
-        fi
-        sleep 10
-    done
-else
-  echo "Non k8s deployment, not doing anything for the NTS_IP..."
-fi
-
-exit 0
diff --git a/ntsimulator/deploy/x-ran/CMakeLists.txt b/ntsimulator/deploy/x-ran/CMakeLists.txt
deleted file mode 100644 (file)
index e8d6bf1..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-set(UTILS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/utils")
-
-include_directories(
-    "${PROJECT_SOURCE_DIR}/inc/utils" 
-    "/usr/include"
-)
-
-add_subdirectory(ves-messages)
-add_subdirectory(software-management-xran)
-add_subdirectory(generic-notifications)
-
-# sources
-set (UTILS_SOURCES
-    ${UTILS_DIR}/utils.c
-)
-
-add_library(utils STATIC ${UTILS_SOURCES})
-set_property(TARGET utils PROPERTY COMPILE_FLAGS "-fPIC")
-target_link_libraries(utils m)
-target_link_libraries(utils cjson)
\ No newline at end of file
diff --git a/ntsimulator/deploy/x-ran/Dockerfile b/ntsimulator/deploy/x-ran/Dockerfile
deleted file mode 100644 (file)
index 355ae78..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-FROM ubuntu:18.04 AS builder
-
-LABEL maintainer="alexandru.stancu@highstreet-technologies.com"
-
-RUN \
-      apt-get update && apt-get install -y \
-      # general tools
-      git \
-      cmake \
-      build-essential \
-      vim \
-      supervisor \
-      # libyang
-      libpcre3-dev \
-      pkg-config \
-      # sysrepo
-      libavl-dev \
-      libev-dev \
-      libprotobuf-c-dev \
-      protobuf-c-compiler \
-      # netopeer2 \
-      libssh-dev \
-      libssl-dev \
-      # bindings
-      swig \
-      python-dev \
-      libcurl4 \
-      libcurl4-openssl-dev \
-      curl \
-      bc
-
-RUN \
-      apt-get install -y \
-      python-setuptools \
-      python-pip
-
-# pyang dependencies
-RUN pip install rstr && \
-    pip install exrex && \
-    pip install ipaddress && \
-    pip install lxml
-
-# add netconf user
-RUN \
-      adduser --system netconf && \
-      echo "netconf:netconf" | chpasswd
-
-# generate ssh keys for netconf user
-RUN \
-      mkdir -p /home/netconf/.ssh && \
-      ssh-keygen -A && \
-      ssh-keygen -t dsa -P '' -f /home/netconf/.ssh/id_dsa && \
-      cat /home/netconf/.ssh/id_dsa.pub > /home/netconf/.ssh/authorized_keys && \
-#echo "Host *\n    StrictHostKeyChecking accept-new" >> /home/netconf/.ssh/config
-      echo "    StrictHostKeyChecking no" >> /etc/ssh/ssh_config && \
-      mkdir -p /root/.ssh && \
-      cat /home/netconf/.ssh/id_dsa.pub > /root/.ssh/authorized_keys
-       
-# use /opt/dev as working directory
-RUN mkdir /opt/dev
-WORKDIR /opt/dev
-
-# libcjson
-RUN \
-      git clone https://github.com/Melacon/cJSON.git && \
-      cd cJSON && mkdir build && cd build && \
-      cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_CJSON_TEST=Off -DCMAKE_INSTALL_PREFIX=/usr .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# libyang
-RUN \
-      git clone https://github.com/Melacon/libyang.git && \
-      cd libyang && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_BUILD_TESTS=OFF .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# sysrepo
-RUN \
-      git clone https://github.com/Melacon/sysrepo.git && \
-      sed -i 's/#define MAX_BLOCKS_AVAIL_FOR_ALLOC    3/#define MAX_BLOCKS_AVAIL_FOR_ALLOC    6/g' ./sysrepo/src/common/sr_mem_mgmt.h && \
-      cd sysrepo && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_TESTS=OFF -DREPOSITORY_LOC:PATH=/etc/sysrepo -DREQUEST_TIMEOUT=60 -DOPER_DATA_PROVIDE_TIMEOUT=60 .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# libnetconf2
-RUN \
-      git clone https://github.com/Melacon/libnetconf2.git && \
-      cd libnetconf2 && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" -DENABLE_BUILD_TESTS=OFF .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# keystore
-RUN \
-      git clone https://github.com/Melacon/Netopeer2.git && \
-      cd Netopeer2 && \
-      cd keystored && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" .. && \
-      make -j2 && \
-      make install && \
-      ldconfig
-
-# netopeer2
-RUN \
-      cd /opt/dev/Netopeer2/server && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" .. && \
-      make -j2 && \
-      make install && \
-      cd ../../cli && mkdir build && cd build && \
-      cmake -DCMAKE_BUILD_TYPE:String="Release" .. && \
-      make -j2 && \
-      make install
-
-# pyang
-RUN \
-      git clone https://github.com/Melacon/pyang.git && \
-       cd pyang && python setup.py build && python setup.py install
-
-# NTSimulator device
-COPY . /opt/dev/ntsimulator
-COPY ./deploy/x-ran/CMakeLists.txt /opt/dev/ntsimulator/src/CMakeLists.txt
-RUN \
-      cd /opt/dev/ntsimulator && mkdir build  && cd build && \
-      cmake .. && \
-      make -j2 && \
-      make install
-
-# Second stage
-FROM ubuntu:18.04  
-
-LABEL maintainer="alexandru.stancu@highstreet-technologies.com"
-
-RUN \
-      apt-get update && apt-get install -y supervisor
-
-# add netconf user
-RUN \
-      adduser --system netconf && \
-      echo "netconf:netconf" | chpasswd
-
-# generate ssh keys for netconf user
-RUN \
-      mkdir -p /home/netconf/.ssh
-
-COPY --from=builder /home/netconf/.ssh /home/netconf/.ssh
-COPY --from=builder /usr/local/lib /usr/local/lib
-COPY --from=builder /usr/local/bin /usr/local/bin
-COPY --from=builder /usr/local/include /usr/local/include
-COPY --from=builder /usr/lib/libavl.so /usr/lib/libavl.so
-COPY --from=builder /usr/lib/libavl.so.1 /usr/lib/libavl.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libev.so /usr/lib/x86_64-linux-gnu/libev.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libev.so.4 /usr/lib/x86_64-linux-gnu/libev.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcurl.so.4 /usr/lib/x86_64-linux-gnu/libcurl.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcurl.so /usr/lib/x86_64-linux-gnu/libcurl.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcjson_utils.so.1 /usr/lib/x86_64-linux-gnu/libcjson_utils.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcjson_utils.so /usr/lib/x86_64-linux-gnu/libcjson_utils.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcjson.so.1 /usr/lib/x86_64-linux-gnu/libcjson.so.1 
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libcjson.so /usr/lib/x86_64-linux-gnu/libcjson.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libprotobuf.so.10 /usr/lib/x86_64-linux-gnu/libprotobuf.so.10
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.1 /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libprotobuf-c.so /usr/lib/x86_64-linux-gnu/libprotobuf-c.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libssh_threads.so.4 /usr/lib/x86_64-linux-gnu/libssh_threads.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libssh_threads.so /usr/lib/x86_64-linux-gnu/libssh_threads.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libssh.so.4 /usr/lib/x86_64-linux-gnu/libssh.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libssh.so /usr/lib/x86_64-linux-gnu/libssh.so
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libnghttp2.so.14 /usr/lib/x86_64-linux-gnu/libnghttp2.so.14
-COPY --from=builder /usr/lib/x86_64-linux-gnu/librtmp.so.1 /usr/lib/x86_64-linux-gnu/librtmp.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libpsl.so.5 /usr/lib/x86_64-linux-gnu/libpsl.so.5
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2 /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2 /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2
-COPY --from=builder /usr/lib/x86_64-linux-gnu/liblber-2.4.so.2 /usr/lib/x86_64-linux-gnu/liblber-2.4.so.2
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libkrb5.so.3 /usr/lib/x86_64-linux-gnu/libkrb5.so.3
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libk5crypto.so.3 /usr/lib/x86_64-linux-gnu/libk5crypto.so.3
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libkrb5support.so.0 /usr/lib/x86_64-linux-gnu/libkrb5support.so.0
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libsasl2.so.2 /usr/lib/x86_64-linux-gnu/libsasl2.so.2
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libgssapi.so.3 /usr/lib/x86_64-linux-gnu/libgssapi.so.3
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libheimntlm.so.0 /usr/lib/x86_64-linux-gnu/libheimntlm.so.0
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libkrb5.so.26 /usr/lib/x86_64-linux-gnu/libkrb5.so.26
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libasn1.so.8 /usr/lib/x86_64-linux-gnu/libasn1.so.8
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libhcrypto.so.4 /usr/lib/x86_64-linux-gnu/libhcrypto.so.4
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libroken.so.18 /usr/lib/x86_64-linux-gnu/libroken.so.18
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libwind.so.0 /usr/lib/x86_64-linux-gnu/libwind.so.0
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libheimbase.so.1 /usr/lib/x86_64-linux-gnu/libheimbase.so.1
-COPY --from=builder /usr/lib/x86_64-linux-gnu/libhx509.so.5 /usr/lib/x86_64-linux-gnu/libhx509.so.5
-
-COPY --from=builder /lib/x86_64-linux-gnu/libkeyutils.so.1 /lib/x86_64-linux-gnu/libkeyutils.so.1
-COPY --from=builder /etc/sysrepo /etc/sysrepo
-COPY --from=builder /var/run /var/run
-
-COPY --from=builder /usr/local/etc/keystored/keys/ssh_host_rsa_key.pem /usr/local/etc/keystored/keys/ssh_host_rsa_key.pem
-COPY --from=builder /usr/local/etc/keystored/keys/ssh_host_rsa_key.pem.pub /usr/local/etc/keystored/keys/ssh_host_rsa_key.pem.pub
-COPY --from=builder /usr/local/share/libnetconf2 /usr/local/share/libnetconf2
-
-RUN ldconfig
-
-WORKDIR /tmp
-RUN \
-    apt-get update && apt-get install -yqq wget \
-    openssh-client \
-    jq \
-    curl
-
-RUN mkdir py_install && cd py_install && \
-    wget https://files.pythonhosted.org/packages/b9/9a/3e9da40ea28b8210dd6504d3fe9fe7e013b62bf45902b458d1cdc3c34ed9/ipaddress-1.0.23.tar.gz && \
-    tar -xvzf ipaddress-1.0.23.tar.gz && cd ipaddress-1.0.23 && \
-    python setup.py install
-
-COPY --from=builder /etc/ssh /etc/ssh
-COPY --from=builder /root/.ssh /root/.ssh
-
-WORKDIR /opt/dev
-# run only specific programs in this image
-COPY ./deploy/x-ran/supervisord.conf /etc/supervisord.conf
-
-# tls configuratoin
-COPY ./deploy/tls /home/netconf/.ssh
-
-COPY --from=builder /opt/dev/sysrepo/build/examples/application_example /opt/dev/sysrepo/build/examples/application_example
-
-# YANG models and related scripts
-COPY ./yang/x-ran /opt/dev/yang
-COPY ./yang/auto-load-yangs.sh /opt/dev/yang
-COPY ./yang/sysrepo-configuration-load.sh /opt/dev/yang
-
-# scripts for Software Management RPCs
-COPY ./deploy/x-ran/edit-config-after-activate.sh /opt/dev
-COPY ./deploy/x-ran/edit-config-after-activate.xml /opt/dev
-COPY ./deploy/x-ran/edit-config-after-download.sh /opt/dev
-COPY ./deploy/x-ran/edit-config-after-download.xml /opt/dev
-COPY ./deploy/x-ran/edit-config-demo-start.sh /opt/dev
-COPY ./deploy/x-ran/edit-config-demo-start.xml /opt/dev
-
-WORKDIR /opt/dev
-RUN \
-         cd yang && \
-         ./auto-load-yangs.sh
-
-ARG BUILD_DATE
-LABEL build-date=$BUILD_DATE
-         
-ENV EDITOR vim
-EXPOSE 830-929
-
-CMD ["sh", "-c", "/usr/bin/supervisord -c /etc/supervisord.conf"]
diff --git a/ntsimulator/deploy/x-ran/config.json b/ntsimulator/deploy/x-ran/config.json
new file mode 100644 (file)
index 0000000..c088a54
--- /dev/null
@@ -0,0 +1,25 @@
+{
+    "docker-rules": {
+        "excluded-modules": [],
+        "excluded-features": []
+    },
+    
+    "populate-rules" : {
+        "excluded-modules": [
+            "sysrepo",
+            "sysrepo-monitoring",
+            "ietf-yang-library",
+            "ietf-netconf-acm",
+            "ietf-netconf-monitoring",
+            "nc-notifications",
+            "ietf-keystore",
+            "ietf-truststore",
+            "ietf-system",
+            "ietf-netconf-server",
+            "nts-network-function"
+        ],
+        
+        "default-list-instances": 1,
+        "custom-list-instances" : []
+    }
+}
\ No newline at end of file
diff --git a/ntsimulator/deploy/x-ran/edit-config-after-activate.sh b/ntsimulator/deploy/x-ran/edit-config-after-activate.sh
deleted file mode 100755 (executable)
index 9881695..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-echo "Loading config data into the NETCONF Server..."
-
-result=$(netopeer2-cli <<-END
-       connect --host 127.0.0.1 --login netconf
-       user-rpc --content=/opt/dev/edit-config-after-activate.xml
-       disconnect
-END
-)
-
-echo $result
-echo "Done!"
-
-exit 0
diff --git a/ntsimulator/deploy/x-ran/edit-config-after-activate.xml b/ntsimulator/deploy/x-ran/edit-config-after-activate.xml
deleted file mode 100644 (file)
index df249c3..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
-  <target>
-    <running/>
-  </target>
-  <config>
-    <software-inventory xmlns="urn:xran:software-management:1.0" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0" xc:operation="merge">
-  <software-slot>
-    <name>Slot1</name>
-    <active>false</active>
-    <running>false</running>
-    <access>READ_WRITE</access>
-  </software-slot>
-  <software-slot>
-    <name>Slot2</name>
-    <active>true</active>
-    <running>true</running>
-    <access>READ_ONLY</access>
-  </software-slot>
-</software-inventory>
-  </config>
-</edit-config>
\ No newline at end of file
diff --git a/ntsimulator/deploy/x-ran/edit-config-after-download.sh b/ntsimulator/deploy/x-ran/edit-config-after-download.sh
deleted file mode 100755 (executable)
index 7989808..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-echo "Loading config data into the NETCONF Server..."
-
-result=$(netopeer2-cli <<-END
-       connect --host 127.0.0.1 --login netconf
-       user-rpc --content=/opt/dev/edit-config-after-download.xml
-       disconnect
-END
-)
-
-echo $result
-echo "Done!"
-
-exit 0
\ No newline at end of file
diff --git a/ntsimulator/deploy/x-ran/edit-config-after-download.xml b/ntsimulator/deploy/x-ran/edit-config-after-download.xml
deleted file mode 100644 (file)
index 7613d58..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-<edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
-  <target>
-    <running/>
-  </target>
-  <config>
-  <software-inventory xmlns="urn:xran:software-management:1.0" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0" xc:operation="replace">
-  <software-slot>
-    <name>Slot1</name>
-    <status>VALID</status>
-    <active>true</active>
-    <running>true</running>
-    <access>READ_ONLY</access>
-    <vendor-code>SA</vendor-code>
-    <build-id>2020-01-23T14:04:23</build-id>
-    <build-name>SAMSUNG-XRAN-FH-2349-5645-32</build-name>
-    <build-version>19.7.123</build-version>
-    <files>
-      <name>manifest-v1.0.1.cfg</name>
-      <version>2349-5645-32</version>
-      <local-path>/home/system/slot1</local-path>
-      <integrity>OK</integrity>
-    </files>
-    <files>
-      <name>image-v1.0.1.swm</name>
-      <version>2349-5645-32</version>
-      <local-path>/home/system/slot1</local-path>
-      <integrity>OK</integrity>
-    </files>
-  </software-slot>
-  <software-slot>
-    <name>Slot2</name>
-    <status>VALID</status>
-    <active>false</active>
-    <running>false</running>
-    <access>READ_WRITE</access>
-    <vendor-code>SA</vendor-code>
-    <build-id>2020-02-05T09:02:33</build-id>
-    <build-name>SAMSUNG-XRAN-FH-2349-5790-44</build-name>
-    <build-version>19.7.123</build-version>
-    <files>
-      <name>manifest-v1.0.2.cfg</name>
-      <version>2349-5790-44</version>
-      <local-path>/home/system/slot2</local-path>
-      <integrity>OK</integrity>
-    </files>
-    <files>
-      <name>image-v1.0.2.swm</name>
-      <version>2349-5790-44</version>
-      <local-path>/home/system/slot2</local-path>
-      <integrity>OK</integrity>
-    </files>
-  </software-slot>
-</software-inventory> 
-  </config>
-</edit-config>
\ No newline at end of file
diff --git a/ntsimulator/deploy/x-ran/edit-config-demo-start.sh b/ntsimulator/deploy/x-ran/edit-config-demo-start.sh
deleted file mode 100755 (executable)
index 4967da1..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-echo "Loading config data into the NETCONF Server..."
-
-result=$(netopeer2-cli <<-END
-       connect --host 127.0.0.1 --login netconf
-       user-rpc --content=/opt/dev/edit-config-demo-start.xml
-       disconnect
-END
-)
-
-echo $result
-echo "Done!"
-
-exit 0
diff --git a/ntsimulator/deploy/x-ran/edit-config-demo-start.xml b/ntsimulator/deploy/x-ran/edit-config-demo-start.xml
deleted file mode 100644 (file)
index 8b77f15..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-<edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
-  <target>
-    <running/>
-  </target>
-  <config>
-         <performance-measurement-objects xmlns="urn:xran:performance-management:1.0" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0" xc:operation="replace">
-         </performance-measurement-objects>
-  <hardware xmlns="urn:ietf:params:xml:ns:yang:ietf-hardware" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0" xc:operation="merge">
-  <component>
-  <name>softwareSlot1</name>
-  <class xmlns:ianahw="urn:ietf:params:xml:ns:yang:iana-hardware">ianahw:storage-drive</class>
-  <physical-index>4207123</physical-index>
-  <description>ddesdvlkmvdfkvf</description>
-  <parent>xAxAxxAxA</parent>
-  <parent-rel-pos>33250247</parent-rel-pos>
-  <hardware-rev>12.2.3</hardware-rev>
-  <firmware-rev>7.1.2</firmware-rev>
-  <software-rev>19.7.123</software-rev>
-  <serial-num>35VU5</serial-num>
-  <mfg-name>xqxSSJSqJ</mfg-name>
-  <model-name>trttrttttrtrtttt</model-name>
-  <alias>btsWtsWstBFFWs</alias>
-  <asset-id>Q446g</asset-id>
-  <is-fru>true</is-fru>
-  <mfg-date>2020-02-06T06:06:32.3Z</mfg-date>
-  <uri>JJuaJa</uri>
-  <uri>6cc66c66cZc6</uri>
-  <uuid>d8de752d-a6ee-74ed-fdac-2c8a9c88afba</uuid>
-  <state>
-    <state-last-changed>2020-02-11T11:02:45.3Z</state-last-changed>
-    <admin-state>locked</admin-state>
-    <oper-state>disabled</oper-state>
-    <usage-state>active</usage-state>
-    <alarm-state>critical major minor warning</alarm-state>
-    <standby-state>hot-standby</standby-state>
-  </state>
-</component>
-<component>
-  <name>softwareSlot2</name>
-  <class xmlns:ianahw="urn:ietf:params:xml:ns:yang:iana-hardware">ianahw:storage-drive</class>
-  <physical-index>4207123</physical-index>
-  <description>ddesdvlkmvdfkvf</description>
-  <parent>xAxAxxAxA</parent>
-  <parent-rel-pos>12350247</parent-rel-pos>
-  <hardware-rev>12.2.3</hardware-rev>
-  <firmware-rev>7.1.2</firmware-rev>
-  <software-rev>19.2.33</software-rev>
-  <serial-num>35VU5</serial-num>
-  <mfg-name>xqxSSJSqJ</mfg-name>
-  <model-name>trttrttttrtrtttt</model-name>
-  <alias>btsWtsWstBFFWs</alias>
-  <asset-id>Q446g</asset-id>
-  <is-fru>true</is-fru>
-  <mfg-date>2020-02-06T06:06:32.3Z</mfg-date>
-  <uri>JJuaJa</uri>
-  <uri>6cc66c66cZc6</uri>
-  <uuid>d8de752d-a6ee-74ed-fdac-2c8a9c88afba</uuid>
-  <state>
-    <state-last-changed>2020-02-11T11:02:45.3Z</state-last-changed>
-    <admin-state>locked</admin-state>
-    <oper-state>disabled</oper-state>
-    <usage-state>active</usage-state>
-    <alarm-state>critical major minor warning</alarm-state>
-    <standby-state>hot-standby</standby-state>
-  </state>
-</component>
-</hardware>
-<software-inventory xmlns="urn:xran:software-management:1.0" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0" xc:operation="replace">
-  <software-slot>
-    <name>Slot1</name>
-    <status>VALID</status>
-    <active>true</active>
-    <running>true</running>
-    <access>READ_ONLY</access>
-    <vendor-code>SA</vendor-code>
-    <build-id>2020-01-23T14:04:23</build-id>
-    <build-name>SAMSUNG-XRAN-FH-2349-5645-32</build-name>
-    <build-version>19.7.123</build-version>
-    <files>
-      <name>manifest-v1.0.1.cfg</name>
-      <version>2349-5645-32</version>
-      <local-path>/home/system/slot1</local-path>
-      <integrity>OK</integrity>
-    </files>
-    <files>
-      <name>image-v1.0.1.swm</name>
-      <version>2349-5645-32</version>
-      <local-path>/home/system/slot1</local-path>
-      <integrity>OK</integrity>
-    </files>
-  </software-slot>
-  <software-slot>
-    <name>Slot2</name>
-    <status>VALID</status>
-    <active>false</active>
-    <running>false</running>
-    <access>READ_WRITE</access>
-    <vendor-code>SA</vendor-code>
-    <build-id>2019-07-02T14:04:23</build-id>
-    <build-name>SAMSUNG-XRAN-FH-2349-2345-44</build-name>
-    <build-version>19.2.33</build-version>
-    <files>
-      <name>manifest-v1.0.0.cfg</name>
-      <version>2349-2345-44</version>
-      <local-path>/home/system/slot2</local-path>
-      <integrity>OK</integrity>
-    </files>
-    <files>
-      <name>image-v1.0.0.swm</name>
-      <version>2349-2345-44</version>
-      <local-path>/home/system/slot2</local-path>
-      <integrity>OK</integrity>
-    </files>
-  </software-slot>
-</software-inventory>  
-</config>
-</edit-config>
\ No newline at end of file
index fbc35d5..cd7eb88 100644 (file)
@@ -3,64 +3,20 @@ nodaemon=true
 logfile=/var/log/supervisord.log
 loglevel=debug
 
-[program:sysrepod]
-command=/usr/local/bin/sysrepod -d
-autorestart=true
-redirect_stderr=true
-priority=1
-
-[program:sysrepo-plugind]
-command=/usr/local/bin/sysrepo-plugind -d
+[program:netopeer2-server]
+command=/usr/local/bin/netopeer2-server -d
 autorestart=true
 redirect_stderr=true
 priority=2
 
-[program:netopeer2-server]
-command=/usr/local/bin/netopeer2-server -d
+[program:sshd]
+command=/usr/sbin/sshd -D
 autorestart=true
 redirect_stderr=true
 priority=3
 
-[program:enable-netconf-call-home]
-directory=/home/netconf/.ssh
-command=/home/netconf/.ssh/enable_netconf_call_home.sh
-startsecs=0
+[program:ntsim-ng]
+command=/opt/dev/ntsim-ng/ntsim-ng -w /opt/dev/ntsim-ng -n -f
 autorestart=false
-redirect_stderr=false
-priority=4
-
-[program:enable-tls]
-directory=/home/netconf/.ssh
-command=/home/netconf/.ssh/enable_tls.sh
-startsecs=0
-autorestart=false
-redirect_stderr=false
-priority=5
-
-[program:set-nts-ip-script]
-directory=/home/netconf/.ssh
-command=/home/netconf/.ssh/set_NTS_IP.sh
-startsecs=0
-autorestart=false
-redirect_stderr=false
-priority=5
-
-[program:sysrepo-config-load]
-directory=/opt/dev/yang
-command=/opt/dev/yang/sysrepo-configuration-load.sh
-autorestart=false
-redirect_stderr=true
-startretries=1
-priority=6
-
-[program:ves-heartbeat]
-command=/usr/local/bin/ves-heartbeat
-autorestart=true
 redirect_stderr=true
-priority=7
-
-[program:software-management]
-command=/usr/local/bin/software-management
-autorestart=true
-redirect_stderr=true
-priority=8
\ No newline at end of file
+priority=4
diff --git a/ntsimulator/deploy/x-ran/ubuntu.Dockerfile b/ntsimulator/deploy/x-ran/ubuntu.Dockerfile
new file mode 100644 (file)
index 0000000..329fa7f
--- /dev/null
@@ -0,0 +1,43 @@
+#
+# Copyright 2020 highstreet technologies GmbH and others
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+################
+#### DEVICE ####
+################
+
+FROM o-ran-sc/nts-ng-base:latest
+LABEL maintainer="alexandru.stancu@highstreet-technologies.com / adrian.lita@highstreet-technologies.com"
+
+# ntsim-ng configuration and deployment
+COPY ./yang /opt/dev/deploy/yang
+COPY ./config.json /opt/dev/ntsim-ng/config/config.json
+
+# ntsim-ng init docker
+RUN /opt/dev/ntsim-ng/ntsim-ng --docker-init -w /opt/dev/ntsim-ng
+
+# supervisor configuration
+COPY ./supervisord.conf /etc/supervisord.conf
+
+# finishing container build
+ARG BUILD_DATE
+LABEL build-date=$BUILD_DATE
+
+# add exposed ports
+EXPOSE 830-929
+EXPOSE 21-22
+
+# run
+WORKDIR /opt/dev/workspace
+CMD ["sh", "-c", "/usr/bin/supervisord -c /etc/supervisord.conf"]
@@ -109,7 +109,8 @@ module xran-mplane-int {
         }
         leaf sub-interface {
           type leafref {
-            path "/if:interfaces/if:interface[if:name = current()/../interface-name]/xran-int:vlan-id";
+            //checkAL added prefix to interface-name
+            path "/if:interfaces/if:interface[if:name = current()/../xran-mplane-int:interface-name]/xran-int:vlan-id";
           }
           description
             "vlans used to communicate with management plane servers.";
@@ -136,11 +136,14 @@ module xran-processing-element {
         }
         container aliasmac-flow {
           when "derived-from(../../../transport-session-type, 'ALIASMAC-INTERFACE')";
+          //checkAL added presence
+          presence "contains aliasmac details";
           if-feature xran-int:ALIASMAC-BASED-CU-PLANE;
           description "leafs for virtual mac type data flows";
           leaf ru-aliasmac-address {
             type leafref {
-              path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/xran-int:alias-macs";
+              //checkAL added prefix to interface-name
+              path "/if:interfaces/if:interface[if:name = current()/../../xran-elements:interface-name]/xran-int:alias-macs";
             }
             config false;
             mandatory true;
@@ -149,7 +152,8 @@ module xran-processing-element {
           }
           leaf vlan-id {
             type leafref {
-              path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/xran-int:vlan-id";
+              //checkAL added prefix to interface-name
+              path "/if:interfaces/if:interface[if:name = current()/../../xran-elements:interface-name]/xran-int:vlan-id";
             }
             description
               "RU's VLAN-ID used for alias MAC based flow";
@@ -163,10 +167,13 @@ module xran-processing-element {
         }
         container eth-flow {
           when "derived-from(../../../transport-session-type, 'ETH-INTERFACE')";
+          //checkAL added presence
+          presence "contains eth details";
           description "leafs for mac + vlan-id type data flows";
           leaf ru-mac-address {
             type leafref {
-              path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/xran-int:mac-address";
+              //checkAL added prefix to interface-name
+              path "/if:interfaces/if:interface[if:name = current()/../../xran-elements:interface-name]/xran-int:mac-address";
             }
             mandatory true;
             description
@@ -174,7 +181,8 @@ module xran-processing-element {
           }
           leaf vlan-id {
             type leafref {
-              path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/xran-int:vlan-id";
+              //checkAL added prefix to interface-name
+              path "/if:interfaces/if:interface[if:name = current()/../../xran-elements:interface-name]/xran-int:vlan-id";
             }
             mandatory true;
             description
@@ -189,18 +197,22 @@ module xran-processing-element {
         }
         container udpip-flow {
           when "derived-from(../../../transport-session-type, 'UDPIP-INTERFACE')";
+          //checkAL added presence
+          presence "contains updip details";
           if-feature xran-int:UDPIP-BASED-CU-PLANE;
           description "leafs for UDP/IP type data flows";
           choice address {
             leaf ru-ipv4-address {
               type leafref {
-                path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/ip:ipv4/ip:address/ip:ip";
+                //checkAL added prefix to interface-name
+                path "/if:interfaces/if:interface[if:name = current()/../../xran-elements:interface-name]/ip:ipv4/ip:address/ip:ip";
               }
               description "RU's IPv4 address";
             }
             leaf ru-ipv6-address {
               type leafref {
-                path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/ip:ipv6/ip:address/ip:ip";
+                //checkAL added prefix to interface-name
+                path "/if:interfaces/if:interface[if:name = current()/../../xran-elements:interface-name]/ip:ipv6/ip:address/ip:ip";
               }
               description "RU's IPv6 address";
             }
@@ -72,7 +72,8 @@ module xran-transceiver {
       }
       leaf port-number {
         type leafref {
-          path "/if:interfaces/if:interface[if:name = current()/../interface-name]/xran-int:port-reference/xran-int:xran-port-number";
+          //checkAL added prefix to interface-name
+          path "/if:interfaces/if:interface[if:name = current()/../xran-transceiver:interface-name]/xran-int:port-reference/xran-int:xran-port-number";
         }
         description
         "A number which identifies a port. In case of SFP/SFP+
similarity index 96%
rename from ntsimulator/yang/x-ran/xran-usermgmt.yang
rename to ntsimulator/deploy/x-ran/yang/xran-usermgmt.yang
index 9de1d90..2a0369e 100644 (file)
@@ -91,9 +91,9 @@ module xran-usermgmt {
     uses extended-xran-groups;
     leaf enabled {
       type boolean;
-      must "count(../enabled='true') > 0" {
-        error-message "At least one account needs to be enabled.";
-      }
+      // must "count(../enabled='true') > 0" {
+      //  error-message "At least one account needs to be enabled.";
+      // }
       description
         "Indicates whether an account is enabled or disabled.";
     }
diff --git a/ntsimulator/docker-build-nts-manager.sh b/ntsimulator/docker-build-nts-manager.sh
deleted file mode 100755 (executable)
index ad6152b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-docker build -t o-ran-sc/ntsim-manager -f deploy/nts-manager/Dockerfile .
diff --git a/ntsimulator/docker-build-nts-o-ran-ru-fh.sh b/ntsimulator/docker-build-nts-o-ran-ru-fh.sh
deleted file mode 100755 (executable)
index 47f328d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-docker build -t o-ran-sc/ntsim-o-ran-ru-fh -f deploy/o-ran/ru-fh/Dockerfile .
diff --git a/ntsimulator/docker-build-nts-o-ran-sc-o-ran-ru.sh b/ntsimulator/docker-build-nts-o-ran-sc-o-ran-ru.sh
deleted file mode 100755 (executable)
index 4449cb9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-docker build -t o-ran-sc/ntsim-o-ran-sc-o-ran-ru -f deploy/o-ran-sc/o-ran-ru/Dockerfile .
diff --git a/ntsimulator/docker-build-nts-xran.sh b/ntsimulator/docker-build-nts-xran.sh
deleted file mode 100755 (executable)
index f983cd7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-docker build -t o-ran-sc/ntsim-x-ran -f deploy/x-ran/Dockerfile .
diff --git a/ntsimulator/inc/utils/utils.h b/ntsimulator/inc/utils/utils.h
deleted file mode 100644 (file)
index 61ce1e3..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*************************************************************************
-*
-* Copyright 2019 highstreet technologies GmbH and others
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*     http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-***************************************************************************/
-
-#ifndef EXAMPLES_NTSIMULATOR_UTILS_H_
-#define EXAMPLES_NTSIMULATOR_UTILS_H_
-
-#include "sysrepo.h"
-#include "sysrepo/values.h"
-#include "sysrepo/xpath.h"
-
-#include <curl/curl.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <cjson/cJSON.h>
-
-#define TRUE 1
-#define FALSE 0
-
-#define NETCONF_CONNECTIONS_PER_DEVICE (getSshConnectionsFromConfigJson() + getTlsConnectionsFromConfigJson())
-#define SSH_CONNECTIONS_PER_DEVICE getSshConnectionsFromConfigJson()
-#define TLS_CONNECTIONS_PER_DEVICE getTlsConnectionsFromConfigJson()
-
-#define PREPARE_ADD_NEW_VALUE(v, num)  {\
-                                                                               num++;\
-                                                                               }
-
-#define CREATE_NEW_VALUE(rc, v, num)   {\
-                                                                               rc = sr_realloc_values(num, num+1, &v);\
-                                                                               if (SR_ERR_OK != rc) {\
-                                                                                       return rc;\
-                                                                               }\
-                                                                               num++;\
-                                                                               }
-
-typedef struct
-{
-       int normal;
-       int warning;
-       int minor;
-       int major;
-       int critical;
-} counterAlarms;
-
-void           set_curl_common_info_ves(CURL *curl);
-
-long           random_at_most(long max);
-void           getCurrentDateAndTime(char *date_and_time);
-int            getSecondsFromLastQuarterInterval(void);
-int            getSecondsFromLastDayInterval(void);
-void           getPreviousQuarterInterval(int number_of_intervals, char *date_and_time);
-void           getPreviousDayPmTimestamp(int number_of_intervals, char *date_and_time);
-long int       getMicrosecondsSinceEpoch(void);
-void           prepare_ves_message_curl(CURL *curl);
-
-cJSON* vesCreateCommonEventHeader(char *domain, char *event_type, char *source_name, int seq_id);
-cJSON* vesCreateHeartbeatFields(int heartbeat_interval);
-cJSON* vesCreatePnfRegistrationFields(int port, bool is_tls);
-cJSON* vesCreateFaultFields(char *alarm_condition, char *alarm_object, char *severity, char *date_time, char *specific_problem);
-
-char*  readConfigFileInString(void);
-void   writeConfigFile(char *config);
-int    writeSkeletonConfigFile(void);
-
-int    getFaultNotificationDelayPeriodFromConfigJson(int *period_array, int *count);
-int    getVesHeartbeatPeriodFromConfigJson(void);
-char*  getVesAuthMethodFromConfigJson(void);
-char*  getVesIpFromConfigJson(void);
-char*  getVesUsernameFromConfigJson(void);
-char*  getVesPasswordFromConfigJson(void);
-int    getVesPortFromConfigJson(void);
-int    getVesRegistrationFromConfigJson(void);
-int    getNetconfAvailableFromConfigJson(void);
-int    getVesAvailableFromConfigJson(void);
-int     getSshConnectionsFromConfigJson(void);
-int     getTlsConnectionsFromConfigJson(void);
-
-void   generateRandomMacAddress(char *mac_address);
-
-int    writeSkeletonStatusFile(void);
-char*  readStatusFileInString(void);
-
-int     writeStatusNotificationCounters(counterAlarms ves_counter, counterAlarms netconf_counter);
-void    writeStatusFile(char *status);
-int     removeDeviceEntryFromStatusFile(char *deviceName);
-
-cJSON*  getDeviceListFromStatusFile(void);
-int     compute_notifications_count(counterAlarms *ves_counter, counterAlarms *netconf_counter);
-int     getDeviceCounters(char *containerId, counterAlarms *ves_counter, counterAlarms *netconf_counter);
-
-int     getIntFromString(char *string, int def_value);
-
-#endif /* EXAMPLES_NTSIMULATOR_UTILS_H_ */
diff --git a/ntsimulator/nts-ng-docker-image-build-ubuntu.yaml b/ntsimulator/nts-ng-docker-image-build-ubuntu.yaml
new file mode 100644 (file)
index 0000000..051da85
--- /dev/null
@@ -0,0 +1,58 @@
+#
+# Copyright 2020 highstreet technologies GmbH and others
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+version: "2.4"
+services:
+  ###################################################
+  ####### Base docker image containing the framework
+  ###################################################
+  nts-ng-base:
+    image: o-ran-sc/nts-ng-base
+    build: 
+      context: .
+      dockerfile: ./deploy/base/ubuntu.Dockerfile
+  
+  ###################################################
+  ####### NTS-NG Manager
+  ###################################################
+  nts-ng-manager:
+    image: o-ran-sc/nts-ng-manager
+    build:
+      context: ./deploy/nts-manager
+      dockerfile: ubuntu.Dockerfile
+      args: 
+        - BUILD_DATE
+
+  ###################################################
+  ####### O-RAN FH
+  ###################################################
+  nts-ng-o-ran-fh:
+    image: o-ran-sc/nts-ng-o-ran-fh
+    build:
+      context: ./deploy/o-ran
+      dockerfile: ubuntu.Dockerfile
+      args: 
+        - BUILD_DATE
+
+  ###################################################
+  ####### X-RAN
+  ###################################################
+  nts-ng-x-ran:
+    image: o-ran-sc/nts-ng-x-ran
+    build:
+      context: ./deploy/x-ran
+      dockerfile: ubuntu.Dockerfile
+      args: 
+        - BUILD_DATE
diff --git a/ntsimulator/ntsim-ng/core/app/manager.c b/ntsimulator/ntsim-ng/core/app/manager.c
new file mode 100644 (file)
index 0000000..60b8006
--- /dev/null
@@ -0,0 +1,673 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "manager.h"
+#include "utils/log_utils.h"
+#include "utils/sys_utils.h"
+#include <stdio.h>
+#include <assert.h>
+
+#include <sysrepo.h>
+#include <sysrepo/values.h>
+
+#include "core/framework.h"
+#include "core/session.h"
+#include "core/context.h"
+#include "core/docker.h"
+
+#define NTS_MANAGER_MODULE                          "nts-manager"
+#define NTS_SIMULATION_SCHEMA_XPATH                 "/nts-manager:simulation"
+#define NTS_FUNCTION_LIST_SCHEMA_XPATH              "/nts-manager:simulation/network-functions/network-function"
+#define NTS_SDN_CONTROLLER_CONFIG_XPATH             "/nts-manager:simulation/sdn-controller"
+#define NTS_VES_ENDPOINT_CONFIG_XPATH               "/nts-manager:simulation/ves-endpoint"
+
+static manager_network_function_type *manager_context = 0;
+static int manager_installed_function_types_count = 0;
+
+static int manager_populate_sysrepo_network_function_list(void);
+static int manager_populate_static_status(void);
+
+static void manager_context_free(manager_network_function_type *context);
+
+static int manager_process_change(int context_index, manager_network_function_type *new_context);
+static int manager_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data);
+static int manager_instances_get_items_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data);
+static int manager_stats_get_items_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data);
+
+int manager_run(void) {
+    assert_session();
+
+    log_message(1, LOG_COLOR_BOLD_YELLOW"\nrunning as MANAGER daemon...\n"LOG_COLOR_RESET);
+
+    manager_operations_init();
+    docker_device_init();
+
+    //get installed function types
+    struct lys_node_leaf *elem = (struct lys_node_leaf *)ly_ctx_get_node(session_context, 0, NTS_FUNCTION_LIST_SCHEMA_XPATH"/function-type", 0);
+    if(elem == 0) {
+        log_error("ly_ctx_get_node failed for xpath: %s", NTS_FUNCTION_LIST_SCHEMA_XPATH"/function-type");
+        return NTS_ERR_FAILED;
+    }
+
+    struct lys_ident **found = 0;
+    manager_installed_function_types_count = context_get_identity_leafs_of_type(elem->type.info.ident.ref[0], &found);
+    if(!manager_installed_function_types_count) {
+        log_error("error network functions");
+        return NTS_ERR_FAILED;
+    }
+
+    //initial list population
+    manager_context = (manager_network_function_type *)malloc(sizeof(manager_network_function_type) * manager_installed_function_types_count);
+    for(int i = 0; i < manager_installed_function_types_count; i++) {
+        manager_context[i].instance = 0;
+
+        manager_context[i].function_type = found[i];
+        asprintf(&manager_context[i].function_type_string, "%s:%s", found[i]->module->name, found[i]->name);
+        manager_context[i].docker_image_name = manager_context[i].function_type->ref;
+        manager_context[i].started_instances = 0;
+        manager_context[i].mounted_instances = 0;
+        manager_context[i].mount_point_addressing_method = strdup("docker-mapping");
+        manager_context[i].docker_instance_name = strdup(manager_context[i].function_type->name);
+        manager_context[i].docker_version_tag = strdup("");
+        manager_context[i].docker_repository = strdup("");
+    }
+    free(found);
+
+    //do initial sysrepo list population
+    int rc = manager_populate_sysrepo_network_function_list();
+    if(rc != NTS_ERR_OK) {
+        log_error("manager_populate_sysrepo_network_function_list failed");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = manager_populate_static_status();
+    if(rc != NTS_ERR_OK) {
+        log_error("manager_populate_static_status failed");
+        return NTS_ERR_FAILED;
+    }
+    
+    //subscribe to any changes on the list
+    rc = sr_module_change_subscribe(session_running, NTS_MANAGER_MODULE, NTS_SIMULATION_SCHEMA_XPATH, manager_change_cb, NULL, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
+    if(rc != SR_ERR_OK) {
+        log_error("could not subscribe to simulation changes");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = sr_oper_get_items_subscribe(session_running, NTS_MANAGER_MODULE, NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_instances_get_items_cb, NULL, SR_SUBSCR_CTX_REUSE, &session_subscription);
+    if(rc != SR_ERR_OK) {
+        log_error("could not subscribe to oper faults");
+        return 0;
+    }
+
+    rc = sr_oper_get_items_subscribe(session_running, NTS_MANAGER_MODULE, NTS_SIMULATION_SCHEMA_XPATH, manager_stats_get_items_cb, NULL, SR_SUBSCR_CTX_REUSE, &session_subscription);
+    if(rc != SR_ERR_OK) {
+        log_error("could not subscribe to oper faults");
+        return 0;
+    }
+
+    //daemonize
+    while(!framework_sigint) {
+        sleep(1);
+    }
+
+    for(int i = 0; i < manager_installed_function_types_count; i++) {
+        while(manager_context[i].started_instances) {
+            manager_stop_instance(&manager_context[i]);
+        }
+        manager_context_free(&manager_context[i]);
+    }
+
+    free(manager_context);
+
+    return NTS_ERR_OK;
+}
+
+static int manager_populate_sysrepo_network_function_list(void) {
+    //check whether everything is already populated, read and update (if previously ran)
+    sr_val_t *values = 0;
+    size_t value_count = 0;
+    int rc = sr_get_items(session_running, NTS_FUNCTION_LIST_SCHEMA_XPATH, 0, 0, &values, &value_count);
+    if(rc != SR_ERR_OK) {
+        log_error("get items failed");
+        return NTS_ERR_FAILED;
+    }
+
+    //either get values, or if data inconclusive, delete everything
+    if(value_count) {
+        log_message(2, "nts-manager instances found (%d). cleaning up for fresh start...\n", value_count);
+
+        for(int i = 0; i < value_count; i++) {           
+            rc = sr_delete_item(session_running, values[i].xpath, 0);
+            if(rc != SR_ERR_OK) {
+                log_error("sr_delete_item failed");
+                return NTS_ERR_FAILED;
+            }
+        }
+        rc = sr_apply_changes(session_running, 0, 0);
+        if(rc != SR_ERR_OK) {
+            log_error("sr_apply_changes failed");
+            return NTS_ERR_FAILED;
+        }
+    }
+
+    //populate everything if needed
+    for(int i = 0; i < manager_installed_function_types_count; i++) {
+        char *xpath = 0;
+
+        asprintf(&xpath, "%s[function-type='%s']/function-type", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type_string);
+        rc = sr_set_item_str(session_running, xpath, (const char *)manager_context[i].function_type_string, 0, 0);
+        if(rc != SR_ERR_OK) {
+            log_error("sr_set_item_str failed");
+            return NTS_ERR_FAILED;
+        }
+        free(xpath);
+
+        asprintf(&xpath, "%s[function-type='%s']/started-instances", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type_string);
+        rc = sr_set_item_str(session_running, xpath, "0", 0, 0);
+        if(rc != SR_ERR_OK) {
+            log_error("sr_set_item_str failed");
+            return NTS_ERR_FAILED;
+        }
+        free(xpath);
+
+        asprintf(&xpath, "%s[function-type='%s']/mounted-instances", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type_string);
+        rc = sr_set_item_str(session_running, xpath, "0", 0, 0);
+        if(rc != SR_ERR_OK) {
+            log_error("sr_set_item_str failed");
+            return NTS_ERR_FAILED;
+        }
+        free(xpath);
+
+        asprintf(&xpath, "%s[function-type='%s']/mount-point-addressing-method", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type_string);
+        rc = sr_set_item_str(session_running, xpath, (const char*)manager_context[i].mount_point_addressing_method, 0, 0);
+        if(rc != SR_ERR_OK) {
+            log_error("sr_set_item_str failed");
+            return NTS_ERR_FAILED;
+        }
+        free(xpath);
+
+        asprintf(&xpath, "%s[function-type='%s']/docker-instance-name", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type_string);
+        rc = sr_set_item_str(session_running, xpath, (const char*)manager_context[i].docker_instance_name, 0, 0);
+        if(rc != SR_ERR_OK) {
+            log_error("sr_set_item_str failed");
+            return NTS_ERR_FAILED;
+        }
+        free(xpath);
+
+        asprintf(&xpath, "%s[function-type='%s']/docker-version-tag", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type_string);
+        rc = sr_set_item_str(session_running, xpath, (const char*)manager_context[i].docker_version_tag, 0, 0);
+        if(rc != SR_ERR_OK) {
+            log_error("sr_set_item_str failed");
+            return NTS_ERR_FAILED;
+        }
+        free(xpath);
+
+        asprintf(&xpath, "%s[function-type='%s']/docker-repository", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type_string);
+        rc = sr_set_item_str(session_running, xpath, (const char*)manager_context[i].docker_repository, 0, 0);
+        if(rc != SR_ERR_OK) {
+            log_error("sr_set_item_str failed");
+            return NTS_ERR_FAILED;
+        }
+        free(xpath);
+    }
+
+    char int_to_str[30];
+
+    //setup sdn-controller defaults
+    rc = sr_set_item_str(session_running, NTS_SDN_CONTROLLER_CONFIG_XPATH"/controller-ip", (const char*)framework_environment.sdn_controller_ip, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("sr_set_item_str failed");
+        return NTS_ERR_FAILED;
+    }
+
+    sprintf(int_to_str, "%d", framework_environment.sdn_controller_port);
+    rc = sr_set_item_str(session_running, NTS_SDN_CONTROLLER_CONFIG_XPATH"/controller-port", (const char*)int_to_str, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("sr_set_item_str failed");
+        return NTS_ERR_FAILED;
+    }
+
+    sprintf(int_to_str, "%d", framework_environment.sdn_controller_callhome_port);
+    rc = sr_set_item_str(session_running, NTS_SDN_CONTROLLER_CONFIG_XPATH"/controller-netconf-call-home-port", (const char*)int_to_str, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("sr_set_item_str failed");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = sr_set_item_str(session_running, NTS_SDN_CONTROLLER_CONFIG_XPATH"/controller-username", (const char*)framework_environment.sdn_controller_username, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("sr_set_item_str failed");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = sr_set_item_str(session_running, NTS_SDN_CONTROLLER_CONFIG_XPATH"/controller-password", (const char*)framework_environment.sdn_controller_password, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("sr_set_item_str failed");
+        return NTS_ERR_FAILED;
+    }
+
+    //setup ves-endpoint details
+    rc = sr_set_item_str(session_running, NTS_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-protocol", (const char*)framework_environment.ves_endpoint_protocol, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("sr_set_item_str failed");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = sr_set_item_str(session_running, NTS_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-ip", (const char*)framework_environment.ves_endpoint_ip, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("sr_set_item_str failed");
+        return NTS_ERR_FAILED;
+    }
+
+    sprintf(int_to_str, "%d", framework_environment.ves_endpoint_port);
+    rc = sr_set_item_str(session_running, NTS_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-port", (const char*)int_to_str, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("sr_set_item_str failed");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = sr_set_item_str(session_running, NTS_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-auth-method", (const char*)framework_environment.ves_endpoint_auth_method, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("sr_set_item_str failed");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = sr_set_item_str(session_running, NTS_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-username", (const char*)framework_environment.ves_endpoint_username, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("sr_set_item_str failed");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = sr_set_item_str(session_running, NTS_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-password", (const char*)framework_environment.ves_endpoint_password, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("sr_set_item_str failed");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = sr_set_item_str(session_running, NTS_VES_ENDPOINT_CONFIG_XPATH"/ves-endpoint-certificate", (const char*)framework_environment.ves_endpoint_certificate, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("sr_set_item_str failed");
+        return NTS_ERR_FAILED;
+    }
+
+    //apply all changes
+    rc = sr_apply_changes(session_running, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("sr_apply_changes failed");
+        return NTS_ERR_FAILED;
+    }
+
+    return NTS_ERR_OK;
+}
+
+static int manager_populate_static_status(void) {
+    assert_session();
+
+    char int_to_str[30];
+
+    //setup sdn-controller defaults
+    sprintf(int_to_str, "%d", framework_environment.host_base_port);
+    int rc = sr_set_item_str(session_operational, NTS_SIMULATION_SCHEMA_XPATH"/base-port", (const char*)int_to_str, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("sr_set_item_str failed");
+        return NTS_ERR_FAILED;
+    }
+
+    sprintf(int_to_str, "%d", framework_environment.ssh_connections);
+    rc = sr_set_item_str(session_operational, NTS_SIMULATION_SCHEMA_XPATH"/ssh-connections", (const char*)int_to_str, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("sr_set_item_str failed");
+        return NTS_ERR_FAILED;
+    }
+
+    sprintf(int_to_str, "%d", framework_environment.tls_connections);
+    rc = sr_set_item_str(session_operational, NTS_SIMULATION_SCHEMA_XPATH"/tls-connections", (const char*)int_to_str, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("sr_set_item_str failed");
+        return NTS_ERR_FAILED;
+    }
+
+    //apply all changes
+    rc = sr_apply_changes(session_operational, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("sr_apply_changes failed");
+        return NTS_ERR_FAILED;
+    }
+
+    return NTS_ERR_OK;
+}
+
+static void manager_context_free(manager_network_function_type *context) {
+    assert(context);
+
+    free(context->function_type_string);
+    free(context->mount_point_addressing_method);
+    free(context->docker_instance_name);
+    free(context->docker_version_tag);
+    free(context->docker_repository);
+}
+
+//take note that this happens in the sysrepo thread
+static int manager_process_change(int context_index, manager_network_function_type *new_context) {
+    assert(context_index < manager_installed_function_types_count);
+    assert(new_context);
+
+    manager_network_function_type *current_context = &manager_context[context_index];
+    int rc = 0;
+
+    current_context->data_changed |= new_context->data_changed;
+    
+    //process changes, and update data in current_context to resemble new_context
+    if(new_context->docker_instance_name != 0) {
+        free(current_context->docker_instance_name);
+        current_context->docker_instance_name = strdup(new_context->docker_instance_name);
+    }
+
+    if(new_context->docker_version_tag != 0) {
+        free(current_context->docker_version_tag);
+        current_context->docker_version_tag = strdup(new_context->docker_version_tag);
+    }
+
+    if(new_context->docker_repository != 0) {
+        free(current_context->docker_repository);
+        current_context->docker_repository = strdup(new_context->docker_repository);
+    }
+
+    if(new_context->mount_point_addressing_method != 0) {
+        free(current_context->mount_point_addressing_method);
+        current_context->mount_point_addressing_method = strdup(new_context->mount_point_addressing_method);
+    }
+
+    if(new_context->started_instances != -1) {
+        if(new_context->started_instances < current_context->started_instances) {
+            //remove started instances
+            while(current_context->started_instances > new_context->started_instances) {
+                log_message(2, "stopping instance of type %s\n", current_context->function_type_string);
+                rc = manager_stop_instance(current_context);
+                if(rc != NTS_ERR_OK) {
+                    log_error("manager_stop_instance failed");
+                    return NTS_ERR_FAILED;
+                }
+            }
+        }
+        else if(new_context->started_instances > current_context->started_instances) {
+            //add started instances
+            while(current_context->started_instances < new_context->started_instances) {
+                log_message(2, "staring instance of type %s\n", current_context->function_type_string);
+                rc = manager_start_instance(current_context);
+                if(rc != NTS_ERR_OK) {
+                    log_error("manager_start_instance failed");
+                    return NTS_ERR_FAILED;
+                }
+            }
+        }
+    }
+
+    if(new_context->mounted_instances != -1) {
+        if(new_context->mounted_instances < current_context->mounted_instances) {
+            //remove mounted instances
+            while(current_context->mounted_instances > new_context->mounted_instances) {
+                log_message(2, "unmounting instance of type %s\n", current_context->function_type_string);
+                rc = manager_unmount_instance(current_context);
+                if(rc != NTS_ERR_OK) {
+                    log_error("manager_unmount_instance failed");
+                    return NTS_ERR_FAILED;
+                }
+            }
+        }
+        else if(new_context->mounted_instances > current_context->mounted_instances) {
+            //add mounted instances
+            while(current_context->mounted_instances < new_context->mounted_instances) {
+                log_message(2, "mouting instance of type %s\n", current_context->function_type_string);
+                rc = manager_mount_instance(current_context);
+                if(rc != NTS_ERR_OK) {
+                    log_error("manager_mount_instance failed");
+                    return NTS_ERR_FAILED;
+                }
+            }
+        }
+    }
+
+    return NTS_ERR_OK;
+}
+
+static int manager_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data) {
+    sr_change_iter_t *it = 0;
+    int rc = SR_ERR_OK;
+    sr_change_oper_t oper;
+    sr_val_t *old_value = 0;
+    sr_val_t *new_value = 0;
+
+    if(event == SR_EV_CHANGE) {
+        manager_network_function_type new_context;
+        new_context.function_type = 0;          //not to be used. use only from current_context
+        new_context.function_type_string = 0;   //not to be used. use only from current_context
+        int index = -1;
+
+        rc = sr_get_changes_iter(session, NTS_FUNCTION_LIST_SCHEMA_XPATH"//.", &it);
+        if(rc != SR_ERR_OK) {
+            log_error("sr_get_changes_iter failed");
+            return SR_ERR_VALIDATION_FAILED;
+        }
+
+        while((rc = sr_get_change_next(session, it, &oper, &old_value, &new_value)) == SR_ERR_OK) {
+            char *ov = sr_val_to_str(old_value);
+            char *nv = sr_val_to_str(new_value);
+
+            //get function type and index
+            char *function_type_string = strdup(strstr(new_value->xpath, "function-type='") + 15);
+            *strchr(function_type_string, '\'') = 0;
+            
+            //if context is new
+            if((new_context.function_type_string == 0) || (strcmp(new_context.function_type_string, function_type_string) != 0)) {
+
+                if(new_context.function_type_string != 0) {
+                    if(manager_process_change(index, &new_context) != NTS_ERR_OK) {
+                        manager_context_free(&new_context);
+                        return SR_ERR_VALIDATION_FAILED;
+                    }
+
+                    manager_context_free(&new_context);
+                }
+
+                //-1 means no change
+                new_context.function_type_string = function_type_string;
+                new_context.started_instances = -1;
+                new_context.mounted_instances = -1;
+                new_context.mount_point_addressing_method = 0;
+                new_context.docker_instance_name = 0;
+                new_context.docker_version_tag = 0;
+                new_context.docker_repository = 0;
+
+                new_context.data_changed = false;
+
+                //find intex in manager_context[]
+                for(int i = 0; i < manager_installed_function_types_count; i++) {
+                    if(strcmp(function_type_string, manager_context[i].function_type_string) == 0) {
+                        index = i;
+                        break;
+                    }
+                }
+            }
+
+            char *leaf_path  = strdup(strstr(new_value->xpath, "']/") + 3);
+            if(strcmp(leaf_path, "started-instances") == 0) {
+                new_context.started_instances = new_value->data.uint16_val;
+            }
+            else if(strcmp(leaf_path, "mounted-instances") == 0) {
+                new_context.mounted_instances = new_value->data.uint16_val;
+            }
+            else if(strcmp(leaf_path, "mount-point-addressing-method") == 0) {
+                new_context.mount_point_addressing_method = strdup(nv);
+            }
+            else if(strcmp(leaf_path, "docker-instance-name") == 0) {
+                new_context.docker_instance_name = strdup(nv);
+            }
+            else if(strcmp(leaf_path, "docker-version-tag") == 0) {
+                new_context.docker_version_tag = strdup(nv);
+            }
+            else if(strcmp(leaf_path, "docker-repository") == 0) {
+                new_context.docker_repository = strdup(nv);
+            }
+            else {
+                new_context.data_changed = true;
+            }
+
+            free(leaf_path);
+            free(ov);
+            free(nv);
+            sr_free_val(old_value);
+            sr_free_val(new_value);
+        }
+
+        sr_free_change_iter(it);
+        
+        if(index != -1) {
+            if(manager_process_change(index, &new_context) != NTS_ERR_OK) {
+                manager_context_free(&new_context);
+                return SR_ERR_VALIDATION_FAILED;
+            }
+
+            manager_context_free(&new_context);
+        }
+    }
+    else if(event == SR_EV_DONE) {
+        bool global_change = true;
+
+        rc = sr_get_changes_iter(session, NTS_SIMULATION_SCHEMA_XPATH"//.", &it);
+        if(rc != SR_ERR_OK) {
+            log_error("sr_get_changes_iter failed");
+            return SR_ERR_VALIDATION_FAILED;
+        }
+
+        while((rc = sr_get_change_next(session, it, &oper, &old_value, &new_value)) == SR_ERR_OK) {
+            if(strstr(new_value->xpath, NTS_FUNCTION_LIST_SCHEMA_XPATH) == new_value->xpath) {
+                global_change = false;
+                sr_free_val(old_value);
+                sr_free_val(new_value);
+                break;
+            }
+
+            sr_free_val(old_value);
+            sr_free_val(new_value);
+        }
+
+        sr_free_change_iter(it);
+
+        // commit all updates
+        for(int i = 0; i < manager_installed_function_types_count; i++) {
+            for(int j = 0; j < manager_context[i].started_instances; j++) {
+                if(global_change || manager_context[i].data_changed || (manager_context[i].instance[j].is_configured == false)) {
+                    log_message(2, "configuring instance %d of type %s\n", j, manager_context[i].function_type_string);
+                    rc = manager_config_instance(&manager_context[i], &manager_context[i].instance[j]);
+                    if(rc != NTS_ERR_OK) {
+                        log_error("manager_config_instance failed");
+                    }
+                }
+            }
+
+            manager_context[i].data_changed = false;
+        }
+        global_change = false;
+    }
+
+    return SR_ERR_OK;
+}
+
+static int manager_instances_get_items_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data) {
+    
+    char value[100];
+
+    *parent = lyd_new_path(NULL, sr_get_context(sr_session_get_connection(session)), NTS_FUNCTION_LIST_SCHEMA_XPATH, 0, 0, 0);
+    if(*parent == 0) {
+        return SR_ERR_OPERATION_FAILED;
+    }
+
+    for(int i = 0; i < manager_installed_function_types_count; i++) {
+        char *ftype_path = 0;
+        asprintf(&ftype_path, "%s[function-type='%s']/instances/instance", NTS_FUNCTION_LIST_SCHEMA_XPATH, manager_context[i].function_type_string);
+        for(int j = 0; j < manager_context[i].started_instances; j++) {
+            char *instance_path = 0;
+            asprintf(&instance_path, "%s[name='%s']", ftype_path, manager_context[i].instance[j].name);
+
+            char *full_path = 0;
+
+            asprintf(&full_path, "%s/mount-point-addressing-method", instance_path);
+            if(lyd_new_path(*parent, NULL, full_path, manager_context[i].instance[j].mount_point_addressing_method, 0, 0) == 0) {
+                return SR_ERR_OPERATION_FAILED;
+            }
+            free(full_path);
+
+            asprintf(&full_path, "%s/networking/docker-ip", instance_path);
+            if(lyd_new_path(*parent, NULL, full_path, manager_context[i].instance[j].docker_ip, 0, 0) == 0) {
+                return SR_ERR_OPERATION_FAILED;
+            }
+            free(full_path);
+
+            asprintf(&full_path, "%s/networking/docker-port", instance_path);
+            sprintf(value, "%d", manager_context[i].instance[j].docker_port);
+            if(lyd_new_path(*parent, NULL, full_path, value, 0, 0) == 0) {
+                return SR_ERR_OPERATION_FAILED;
+            }
+            free(full_path);
+
+            asprintf(&full_path, "%s/networking/host-ip", instance_path);
+            if(lyd_new_path(*parent, NULL, full_path, manager_context[i].instance[j].host_ip, 0, 0) == 0) {
+                return SR_ERR_OPERATION_FAILED;
+            }
+            free(full_path);
+
+            asprintf(&full_path, "%s/networking/host-port", instance_path);
+            sprintf(value, "%d", manager_context[i].instance[j].host_port);
+            if(lyd_new_path(*parent, NULL, full_path, value, 0, 0) == 0) {
+                return SR_ERR_OPERATION_FAILED;
+            }
+            free(full_path);
+
+            free(instance_path);
+        }
+        free(ftype_path);
+    }
+
+    return SR_ERR_OK;
+}
+
+static int manager_stats_get_items_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data) {
+    
+    char value[128];
+
+    *parent = lyd_new_path(NULL, sr_get_context(sr_session_get_connection(session)), NTS_SIMULATION_SCHEMA_XPATH, 0, 0, 0);
+    if(*parent == 0) {
+        return SR_ERR_OPERATION_FAILED;
+    }
+
+    docker_usage_t usage = docker_usage_get(manager_context, manager_installed_function_types_count);
+
+    sprintf(value, "%.2f", usage.cpu);
+    if(lyd_new_path(*parent, NULL, NTS_SIMULATION_SCHEMA_XPATH"/cpu-usage", value, 0, 0) == 0) {
+        return SR_ERR_OPERATION_FAILED;
+    }
+
+    sprintf(value, "%.0f", usage.mem);
+    if(lyd_new_path(*parent, NULL, NTS_SIMULATION_SCHEMA_XPATH"/mem-usage", value, 0, 0) == 0) {
+        return SR_ERR_OPERATION_FAILED;
+    }
+
+    return SR_ERR_OK;
+}
diff --git a/ntsimulator/ntsim-ng/core/app/manager.h b/ntsimulator/ntsim-ng/core/app/manager.h
new file mode 100644 (file)
index 0000000..ad1f0a9
--- /dev/null
@@ -0,0 +1,70 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <libyang/libyang.h>
+
+typedef struct {
+    //meta-data
+    char *docker_id;
+    bool is_configured;
+    bool is_mounted;
+
+    //yang data
+    char *name;
+    char *mount_point_addressing_method;
+    char *docker_ip;
+    uint16_t docker_port;
+    char *host_ip;
+    uint16_t host_port;
+} manager_network_function_instance_t;
+
+typedef struct {
+    //manager_docker data
+    manager_network_function_instance_t *instance;
+    bool data_changed;
+
+    //meta-data, constant
+    struct lys_ident *function_type;
+    char *function_type_string;
+    const char *docker_image_name;
+
+    //yang data
+    int started_instances;
+    int mounted_instances;
+    
+    char *docker_instance_name;
+    char *docker_version_tag;
+    char *docker_repository;
+
+    char *mount_point_addressing_method;
+} manager_network_function_type;
+
+//manager.c
+int manager_run(void);
+
+//manager_operations.c
+void manager_operations_init(void);
+
+int manager_start_instance(manager_network_function_type *function_type);
+int manager_config_instance(manager_network_function_type *function_type, manager_network_function_instance_t *instance);
+int manager_stop_instance(manager_network_function_type *function_type);
+int manager_mount_instance(manager_network_function_type *function_type);
+int manager_unmount_instance(manager_network_function_type *function_type);
diff --git a/ntsimulator/ntsim-ng/core/app/manager_operations.c b/ntsimulator/ntsim-ng/core/app/manager_operations.c
new file mode 100644 (file)
index 0000000..3d2245c
--- /dev/null
@@ -0,0 +1,356 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "manager.h"
+#include "utils/log_utils.h"
+#include "utils/sys_utils.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "core/framework.h"
+#include "core/docker.h"
+#include "core/session.h"
+#include "utils/nc_client.h"
+#include "utils/http_client.h"
+#include "utils/nts_utils.h"
+
+static uint16_t manager_start_port = 0;
+static uint8_t manager_port[65536];
+
+void manager_operations_init(void) {
+    manager_start_port = framework_environment.host_base_port;
+    for(int i = 0; i < 65536; i++) {
+        manager_port[i] = 0;
+    }
+}
+
+int manager_start_instance(manager_network_function_type *function_type) {
+    assert(function_type);
+    assert_session();
+
+    function_type->started_instances++;
+    function_type->instance = (manager_network_function_instance_t *)realloc(function_type->instance, sizeof(manager_network_function_instance_t) * function_type->started_instances);
+    if(function_type->instance == 0) {
+        log_error("realloc failed");
+        return NTS_ERR_FAILED;
+    }
+
+    manager_network_function_instance_t *instance = &function_type->instance[function_type->started_instances - 1];
+    instance->is_configured = false;
+    instance->is_mounted = false;
+    
+    asprintf(&instance->name, "%s-%d", function_type->docker_instance_name, function_type->started_instances - 1);
+
+    instance->mount_point_addressing_method = strdup(function_type->mount_point_addressing_method);
+
+    instance->docker_port = STANDARD_NETCONF_PORT;
+    instance->host_ip = strdup(framework_environment.host_ip);
+    instance->host_port = 0;
+
+    //find start host port
+    for(int i = manager_start_port; i < 65536 - (framework_environment.ssh_connections + framework_environment.tls_connections + framework_environment.ftp_connections + framework_environment.sftp_connections); i += (framework_environment.ssh_connections + framework_environment.tls_connections + framework_environment.ftp_connections + framework_environment.sftp_connections)) {
+        if(manager_port[i] == 0) {
+            manager_port[i] = 1;
+            instance->host_port = i;
+            break;
+        }
+    }
+
+    if(instance->host_port == 0) {
+        log_error("no ports available for operation");
+        return NTS_ERR_FAILED;
+    }
+
+    int rc = docker_device_start(function_type, instance);
+    if(rc != NTS_ERR_OK) {
+        log_error("docker_device_start failed");
+        return NTS_ERR_FAILED;
+    }
+
+    return NTS_ERR_OK;
+}
+
+int manager_config_instance(manager_network_function_type *function_type, manager_network_function_instance_t *instance) {
+    assert(function_type);
+    assert(instance);
+
+    //first wait for the nc server to be up and running
+    while(check_port_open(instance->docker_ip, instance->docker_port) == false) {
+        usleep(10000);
+    }
+
+    //populate sdn-controller and ves-endpoint
+    struct lyd_node *local_tree = 0;
+    int rc = lyd_utils_dup(session_running, "/nts-manager:simulation/sdn-controller", "/nts-network-function:simulation/sdn-controller", &local_tree);
+    if(rc != NTS_ERR_OK) {
+        log_error("lyd_utils_dup failed");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = lyd_utils_dup(session_running, "/nts-manager:simulation/ves-endpoint", "/nts-network-function:simulation/ves-endpoint", &local_tree);
+    if(rc != NTS_ERR_OK) {
+        log_error("lyd_utils_dup failed");
+        return NTS_ERR_FAILED;
+    }
+
+    char *xpath_s = 0;
+    asprintf(&xpath_s, "/nts-manager:simulation/network-functions/network-function[function-type='%s']", function_type->function_type_string);
+    rc = lyd_utils_dup(session_running, xpath_s, "/nts-network-function:simulation/network-function", &local_tree);
+    if(rc != NTS_ERR_OK) {
+        log_error("lyd_utils_dup failed");
+        return NTS_ERR_FAILED;
+    }
+    free(xpath_s);
+
+    nc_client_t *nc_client = nc_client_ssh_connect(instance->docker_ip, instance->docker_port, "netconf", "netconf");
+    if(nc_client == 0) {
+        log_error("nc_client_ssh_connect");
+        return NTS_ERR_FAILED;
+    }
+
+    rc += nc_client_edit_batch(nc_client, local_tree, 1000);
+    if(rc != NTS_ERR_OK) {
+        log_error("nc_client_edit_batch failed %d\n", rc);
+        return NTS_ERR_FAILED;
+    }
+    lyd_free_withsiblings(local_tree);
+
+    
+    if(instance->is_configured == false) {
+        //run datastore-random-populate rpc
+        struct lyd_node *rpc_node = 0;
+        struct lyd_node *rpcout = 0;
+        rpc_node = lyd_new_path(0, session_context, "/nts-network-function:datastore-random-populate", 0, 0, 0);
+        if(rpc_node == 0) {
+            log_error("failed to create rpc node");
+            return NTS_ERR_FAILED;
+        }
+
+        rpcout = nc_client_send_rpc(nc_client, rpc_node, 5000);
+        if(rpcout == 0) {
+            log_error("datastore-random-populate rpc failed");
+            return NTS_ERR_FAILED;
+        }
+        else {
+            lyd_free_withsiblings(rpcout);
+        }
+        lyd_free_withsiblings(rpc_node);
+
+        //run feature-control rpc
+        rpc_node = lyd_new_path(0, session_context, "/nts-network-function:feature-control/features", "ves-file-ready ves-heartbeat ves-pnf-registration manual-notification-generation netconf-call-home", 0, 0);
+        if(rpc_node == 0) {
+            log_error("failed to create rpc node");
+            return NTS_ERR_FAILED;
+        }
+
+        rpcout = nc_client_send_rpc(nc_client, rpc_node, 1000);
+        if(rpcout == 0) {
+            log_error("feature-control rpc failed");
+            return NTS_ERR_FAILED;
+        }
+        else {
+            lyd_free_withsiblings(rpcout);
+        }
+        lyd_free_withsiblings(rpc_node);
+    }
+
+    instance->is_configured = true;
+
+    nc_client_disconnect(nc_client);
+
+    return NTS_ERR_OK;
+}
+
+int manager_stop_instance(manager_network_function_type *function_type) {
+    assert(function_type);
+
+    manager_network_function_instance_t *instance = &function_type->instance[function_type->started_instances - 1];
+
+    if(instance->is_mounted) {
+        if(manager_unmount_instance(function_type) != NTS_ERR_OK) {
+            return NTS_ERR_FAILED;
+        }
+    }
+
+    int rc = docker_device_stop(instance);
+    if(rc != NTS_ERR_OK) {
+        log_error("docker_device_stop failed");
+        return NTS_ERR_FAILED;
+    }
+
+    //clear unused ports
+    manager_port[instance->host_port] = 0;
+
+    free(instance->mount_point_addressing_method);
+    free(instance->docker_id);
+    free(instance->name);
+    free(instance->docker_ip);
+    free(instance->host_ip);
+
+    function_type->started_instances--;
+    if(function_type->started_instances) {
+        function_type->instance = (manager_network_function_instance_t *)realloc(function_type->instance, sizeof(manager_network_function_instance_t) * function_type->started_instances);
+        if(function_type->instance == 0) {
+            log_error("realloc failed");
+            return NTS_ERR_FAILED;
+        }
+    }
+    else {
+        free(function_type->instance);
+        function_type->instance = 0;
+    }
+    return NTS_ERR_OK;
+}
+
+int manager_mount_instance(manager_network_function_type *function_type) {
+    assert(function_type);
+
+    manager_network_function_instance_t *instance = &function_type->instance[function_type->mounted_instances];
+
+    if(instance->is_mounted == true) {
+        return NTS_ERR_FAILED;
+    }
+
+    controller_details_t *controller;
+    controller = controller_details_get(0);
+    if(controller == 0) {
+        log_error("could not get controller detailes");
+        return NTS_ERR_FAILED;
+    }
+
+    for(int i = 0; i < (framework_environment.ssh_connections + framework_environment.tls_connections); i++) {
+        char *protocol;
+        char *protocol_data;
+        if(i < framework_environment.ssh_connections) {
+            protocol = "SSH";
+            protocol_data = "\
+            \"network-topology:netconf-node-topology:username\": \"netconf\",\
+            \"network-topology:netconf-node-topology:password\": \"netconf\"";
+
+        }
+        else {
+            protocol = "TLS";
+            protocol_data = "\
+            \"netconf-node-topology:key-based\" : {\
+                \"netconf-node-topology:username\" : \"netconf\",\
+                \"netconf-node-topology:key-id\" : \""KS_KEY_NAME"\"\
+            }";
+        }
+
+        char *json_template = "\
+        {\
+            \"network-topology:node\": [{\
+                    \"network-topology:node-id\": \"%s\",\
+                    \"network-topology:netconf-node-topology:host\": \"%s\",\
+                    \"network-topology:netconf-node-topology:port\": \"%d\",\
+                    \"network-topology:netconf-node-topology:tcp-only\": \"false\",\
+                    \"network-topology:netconf-node-topology:protocol\": {\
+                        \"network-topology:netconf-node-topology:name\": \"%s\"\
+                    },\
+                    %s,\
+                    \"network-topology:netconf-node-topology:connection-timeout-millis\": \"20000\",\
+                    \"network-topology:netconf-node-topology:default-request-timeout-millis\": \"60000\",\
+                    \"network-topology:netconf-node-topology:max-connection-attempts\": \"3\"\
+            }]\
+        }";
+
+        char *json = 0;
+        uint16_t port = 0;
+        char *ip = 0;
+        if(instance->mount_point_addressing_method[0] == 'd') {
+            ip = instance->docker_ip;
+            port = instance->docker_port + i;
+        }
+        else {
+            ip = instance->host_ip;
+            port = instance->host_port + i;
+        }
+        char *node_id = 0;
+        asprintf(&node_id, "%s-%d", instance->name, port);
+        asprintf(&json, json_template, node_id, ip, port, protocol, protocol_data);
+
+        char *url = 0;
+        asprintf(&url, "%s/rests/data/network-topology:network-topology/topology=topology-netconf/node=%s", controller->base_url, node_id);
+        int rc = http_request(url, controller->username, controller->password, "PUT", json, 0, 0);
+        if(rc != NTS_ERR_OK) {
+            log_error("http_request failed");
+            return NTS_ERR_FAILED;
+        }
+
+        free(url);
+        free(node_id);
+        free(json);
+    }
+
+    controller_details_free(controller);
+
+    instance->is_mounted = true;
+    function_type->mounted_instances++;
+
+    return NTS_ERR_OK;
+}
+
+int manager_unmount_instance(manager_network_function_type *function_type) {
+    assert(function_type);
+
+    manager_network_function_instance_t *instance = &function_type->instance[function_type->mounted_instances - 1];
+
+    if(instance->is_mounted == false) {
+        log_error("tried to unmount an unmounted instance");
+        return NTS_ERR_FAILED;
+    }
+
+    controller_details_t *controller;
+    controller = controller_details_get(0);
+    if(controller == 0) {
+        log_error("could not get controller detailes");
+        return NTS_ERR_FAILED;
+    }
+
+    for(int i = 0; i < (framework_environment.ssh_connections + framework_environment.tls_connections); i++) {
+        uint16_t port = 0;
+        if(function_type->mount_point_addressing_method[0] == 'd') {
+            port = instance->docker_port + i;
+        }
+        else {
+            port = instance->host_port + i;
+        }
+        char *node_id = 0;
+        asprintf(&node_id, "%s-%d", instance->name, port);
+
+        char *url = 0;
+        asprintf(&url, "%s/rests/data/network-topology:network-topology/topology=topology-netconf/node=%s", controller->base_url, node_id);
+        int rc = http_request(url, controller->username, controller->password, "DELETE", "", 0, 0);
+        if(rc != NTS_ERR_OK) {
+            log_error("http_request failed");
+            return NTS_ERR_FAILED;
+        }
+
+        free(url);
+        free(node_id);
+    }
+
+    controller_details_free(controller);
+
+    function_type->mounted_instances--;
+    function_type->instance[function_type->mounted_instances].is_mounted = false;
+
+    return NTS_ERR_OK;
+}
diff --git a/ntsimulator/ntsim-ng/core/app/network_function.c b/ntsimulator/ntsim-ng/core/app/network_function.c
new file mode 100644 (file)
index 0000000..fbd2478
--- /dev/null
@@ -0,0 +1,452 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "network_function.h"
+#include "utils/log_utils.h"
+#include "utils/sys_utils.h"
+#include <stdio.h>
+#include <pthread.h>
+#include <assert.h>
+
+#include <sysrepo.h>
+#include <sysrepo/values.h>
+
+#include "core/framework.h"
+#include "core/context.h"
+#include "core/session.h"
+#include "core/datastore/populate.h"
+
+#include "core/faults/faults.h"
+
+#include "features/ves_pnf_registration/ves_pnf_registration.h"
+#include "features/ves_heartbeat/ves_heartbeat.h"
+#include "features/ves_file_ready/ves_file_ready.h"
+#include "features/manual_notification/manual_notification.h"
+#include "features/netconf_call_home/netconf_call_home.h"
+
+#define POPULATE_RPC_SCHEMA_XPATH           "/nts-network-function:datastore-random-populate"
+#define FEATURE_CONTROL_SCHEMA_XPATH        "/nts-network-function:feature-control"
+#define FAULTS_CLEAR_SCHEMA_XPATH           "/nts-network-function:clear-fault-counters"
+#define FAULTS_LIST_SCHEMA_XPATH            "/nts-network-function:simulation/network-function/fault-generation"
+#define FAULTS_COUNT_LIST_SCHEMA_XPATH      "/nts-network-function:simulation/network-function/fault-generation/fault-count"
+#define FAULTS_NC_ENABLED_SCHEMA_XPATH      "/nts-network-function:simulation/network-function/netconf/faults-enabled"
+#define FAULTS_VES_ENABLED_SCHEMA_XPATH     "/nts-network-function:simulation/network-function/ves/faults-enabled"
+
+static int network_function_populate_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data);
+static int network_function_feature_control_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data);
+static int network_function_faults_clear_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data);
+static int network_function_faults_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data);
+static int network_function_faults_count_get_items_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data);
+
+static int faults_update_config(sr_session_ctx_t *session);                 //not protected by lock
+static void *faults_thread_routine(void *arg);
+
+static pthread_mutex_t nf_function_control_lock;
+static char *nf_function_control_string = 0;
+
+static pthread_t faults_thread;
+static pthread_mutex_t faults_lock;
+
+int network_function_run(void) {
+    assert_session();
+
+    log_message(1, LOG_COLOR_BOLD_YELLOW"\nrunning as NETWORK FUNCTION daemon...\n"LOG_COLOR_RESET);
+
+    if(pthread_mutex_init(&nf_function_control_lock, NULL) != 0) { 
+        log_error("mutex init has failed"); 
+        return NTS_ERR_FAILED; 
+    }
+
+    //populate
+    int rc = sr_rpc_subscribe(session_running, POPULATE_RPC_SCHEMA_XPATH, network_function_populate_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
+    if(rc != SR_ERR_OK) {
+        log_error("error from sr_rpc_subscribe: %s", sr_strerror(rc));
+        return NTS_ERR_FAILED;
+    }
+
+    //feature control
+    rc = sr_rpc_subscribe(session_running, FEATURE_CONTROL_SCHEMA_XPATH, network_function_feature_control_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
+    if(rc != SR_ERR_OK) {
+        log_error("error from sr_rpc_subscribe: %s", sr_strerror(rc));
+        return NTS_ERR_FAILED;
+    }
+
+    //faults
+    rc = sr_module_change_subscribe(session_running, "nts-network-function", FAULTS_LIST_SCHEMA_XPATH, network_function_faults_change_cb, NULL, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
+    if(rc != SR_ERR_OK) {
+        log_error("could not subscribe to faults");
+        return 0;
+    }
+
+    rc = sr_oper_get_items_subscribe(session_running, "nts-network-function", FAULTS_COUNT_LIST_SCHEMA_XPATH, network_function_faults_count_get_items_cb, NULL, SR_SUBSCR_CTX_REUSE, &session_subscription);
+    if(rc != SR_ERR_OK) {
+        log_error("could not subscribe to oper faults: %s", sr_strerror(rc));
+        return 0;
+    }
+
+    rc = sr_rpc_subscribe(session_running, FAULTS_CLEAR_SCHEMA_XPATH, network_function_faults_clear_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
+    if(rc != SR_ERR_OK) {
+        log_error("error from sr_rpc_subscribe: %s", sr_strerror(rc));
+        return NTS_ERR_FAILED;
+    }
+
+    rc = faults_init();
+    if(rc != NTS_ERR_OK) {
+        log_error("faults_init error", sr_strerror(rc));
+        return NTS_ERR_FAILED;
+    }
+
+    if(pthread_mutex_init(&faults_lock, NULL) != 0) { 
+        log_error("mutex init has failed"); 
+        return NTS_ERR_FAILED; 
+    }
+
+    if(pthread_create(&faults_thread, 0, faults_thread_routine, 0)) {
+        log_error("could not create thread for heartbeat");
+        return NTS_ERR_FAILED;
+    }
+
+    while(!framework_sigint) {
+
+        pthread_mutex_lock(&nf_function_control_lock);
+        if(nf_function_control_string) {
+            if(strstr(nf_function_control_string, "ves-file-ready") != 0) {
+                // start feature for handling the fileReady VES message
+                rc = ves_file_ready_feature_start(session_running);
+                if(rc != 0) {
+                    log_error("ves_file_ready_feature_start() failed");
+                }
+            }
+
+            if(strstr(nf_function_control_string, "ves-pnf-registration") != 0) {
+                // check if PNF registration is enabled and send PNF registration message if so
+                rc = ves_pnf_registration_feature_start(session_running);
+                if(rc != 0) {
+                    log_error("ves_pnf_registration_feature_start() failed");
+                }
+            }
+
+            if(strstr(nf_function_control_string, "ves-heartbeat") != 0) {
+                // start feature for handling the heartbeat VES message
+                rc = ves_heartbeat_feature_start(session_running);
+                if(rc != 0) {
+                    log_error("ves_heartbeat_feature_start() failed");
+                }
+            }
+
+            if(strstr(nf_function_control_string, "manual-notification-generation") != 0) {
+                // start feature for manual notification
+                rc = manual_notification_feature_start(session_running);
+                if(rc != 0) {
+                    log_error("manual_notification_feature_start() failed");
+                }
+            }
+
+            if(strstr(nf_function_control_string, "netconf-call-home") != 0) {
+                // start feature for NETCONF Call Home
+                rc = netconf_call_home_feature_start(session_running);
+                if(rc != 0) {
+                    log_error("netconf_call_home_feature_start() failed");
+                }
+            }
+
+            free(nf_function_control_string);
+            nf_function_control_string = 0;
+        }
+        pthread_mutex_unlock(&nf_function_control_lock);
+
+        sleep(1);
+    }
+
+    faults_free();
+
+    return NTS_ERR_OK;
+}
+
+static int network_function_populate_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) {
+    int rc;
+
+    *output_cnt = 1;
+    rc = sr_new_values(*output_cnt, output);
+    if(SR_ERR_OK != rc) {
+        return rc;
+    }
+
+    rc = sr_val_set_xpath(output[0], POPULATE_RPC_SCHEMA_XPATH"/status");
+    if(SR_ERR_OK != rc) {
+        return rc;
+    }
+
+    rc = schema_populate();
+    if(rc != NTS_ERR_OK) {
+        rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "ERROR");
+    }
+    else {
+        rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
+    }
+
+    return rc;
+}
+
+static int network_function_feature_control_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) {
+    int rc;
+    int total_errors = 0;
+
+    *output_cnt = 1;
+    rc = sr_new_values(*output_cnt, output);
+    if(SR_ERR_OK != rc) {
+        return rc;
+    }
+
+    rc = sr_val_set_xpath(output[0], FEATURE_CONTROL_SCHEMA_XPATH"/status");
+    if(SR_ERR_OK != rc) {
+        return rc;
+    }
+
+    if(total_errors != 0) {
+        rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "ERROR");
+    }
+    else {
+        rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
+    }
+
+    pthread_mutex_lock(&nf_function_control_lock);
+    nf_function_control_string = strdup(input[0].data.bits_val);
+    pthread_mutex_unlock(&nf_function_control_lock);
+
+    return rc;
+}
+
+static int network_function_faults_clear_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) {
+    int rc;
+
+    *output_cnt = 1;
+    rc = sr_new_values(*output_cnt, output);
+    if(SR_ERR_OK != rc) {
+        return rc;
+    }
+
+    rc = sr_val_set_xpath(output[0], FAULTS_CLEAR_SCHEMA_XPATH"/status");
+    if(SR_ERR_OK != rc) {
+        return rc;
+    }
+
+    pthread_mutex_lock(&faults_lock);
+    faults_counters_clear();
+    pthread_mutex_unlock(&faults_lock);
+
+    rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
+    return rc;
+}
+
+static int network_function_faults_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data) {
+    int rc = SR_ERR_OK;
+
+    if(event == SR_EV_DONE) {
+        pthread_mutex_lock(&faults_lock);
+        rc = faults_update_config(session);
+        pthread_mutex_unlock(&faults_lock);
+        if(rc != NTS_ERR_OK) {
+            log_error("faults_update_config failed");
+            return SR_ERR_VALIDATION_FAILED;
+        }
+    }
+
+    return SR_ERR_OK;
+}
+
+static int network_function_faults_count_get_items_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data) {
+    pthread_mutex_lock(&faults_lock);
+    fault_counters_t counters = faults_counters_get();
+    pthread_mutex_unlock(&faults_lock);
+    char value[20];
+
+    *parent = lyd_new_path(NULL, sr_get_context(sr_session_get_connection(session)), FAULTS_COUNT_LIST_SCHEMA_XPATH, 0, 0, 0);
+    if(*parent == 0) {
+        return SR_ERR_OPERATION_FAILED;
+    }
+
+    sprintf(value, "%d", counters.normal);
+    if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/normal", value, 0, 0) == 0) {
+        return SR_ERR_OPERATION_FAILED;
+    }
+
+    sprintf(value, "%d", counters.warning);
+    if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/warning", value, 0, 0) == 0) {
+        return SR_ERR_OPERATION_FAILED;
+    }
+
+    sprintf(value, "%d", counters.minor);
+    if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/minor", value, 0, 0) == 0) {
+        return SR_ERR_OPERATION_FAILED;
+    }
+
+    sprintf(value, "%d", counters.major);
+    if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/major", value, 0, 0) == 0) {
+        return SR_ERR_OPERATION_FAILED;
+    }
+
+    sprintf(value, "%d", counters.critical);
+    if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/critical", value, 0, 0) == 0) {
+        return SR_ERR_OPERATION_FAILED;
+    }
+
+    return SR_ERR_OK;
+}
+
+static int faults_update_config(sr_session_ctx_t *session) {
+    assert(session);
+    assert_session();
+
+    int ret = NTS_ERR_OK;
+    
+    int rc;
+    struct lyd_node *data;
+    rc = sr_get_subtree(session, FAULTS_LIST_SCHEMA_XPATH, 0, &data);
+    if(rc != SR_ERR_OK) {
+        log_error("sr_get_subtree failed");
+        ret = NTS_ERR_FAILED;
+    }
+
+    faults_fault_list_clear();
+    faults_counters_clear();
+    if(data->child == 0) {
+        goto faults_update_config_free;
+    }
+
+    struct lyd_node *chd = 0;
+    LY_TREE_FOR(data->child, chd) {
+        if(strcmp(chd->schema->name, "fault-delay-list") == 0) {
+            struct lyd_node *delay_list_entry = 0;
+            LY_TREE_FOR(chd->child, delay_list_entry) {
+                if(strcmp(delay_list_entry->schema->name, "delay-period") == 0) {
+                    rc = faults_fault_list_add(((const struct lyd_node_leaf_list *)delay_list_entry)->value.uint16);
+                    if(rc != NTS_ERR_OK) {
+                        log_error("faults_fault_list_add failed");
+                        ret = NTS_ERR_FAILED;
+                        goto faults_update_config_free;
+                    }
+                }
+            }
+        }
+        
+    }
+    
+    faults_update_config_free:
+    lyd_free(data);
+
+    return ret;
+}
+
+static void *faults_thread_routine(void *arg) {
+    int rc = 0;
+
+    sr_session_ctx_t *current_session_running = 0;
+    rc = sr_session_start(session_connection, SR_DS_RUNNING, &current_session_running);
+    if (rc != SR_ERR_OK) {
+        log_error("sr_session_start failed");
+        return 0;
+    }
+
+    sr_session_ctx_t *current_session_operational = 0;
+    rc = sr_session_start(session_connection, SR_DS_OPERATIONAL, &current_session_operational);
+    if (rc != SR_ERR_OK) {
+        log_error("sr_session_start failed");
+        return 0;
+    }
+
+    pthread_mutex_lock(&faults_lock);
+    rc = faults_update_config(current_session_running);
+    if(rc != NTS_ERR_OK) {
+        log_error("faults_update_config failed");
+        return 0;
+    }
+    pthread_mutex_unlock(&faults_lock);
+
+    while(!framework_sigint) {
+        pthread_mutex_lock(&faults_lock);
+        if(faults_fault_list_not_empty()) {
+            uint16_t new_delay = faults_fault_list_get_next();
+
+            fault_details_t *fault = faults_generate_fault();
+            if(fault == 0) {
+                log_error("faults_generate_fault failed");
+                pthread_mutex_unlock(&faults_lock);
+                sleep(1);
+                continue;
+            }
+
+            rc = faults_counters_increase(fault->severity);
+            if(rc != NTS_ERR_OK) {
+                log_error("faults_counters_increase failed");
+            }
+            pthread_mutex_unlock(&faults_lock);
+
+            sr_val_t *val = 0;
+            bool nc_fault_enabled = false;
+            bool ves_fault_enabled = false;
+
+            rc = sr_get_item(current_session_running, FAULTS_NC_ENABLED_SCHEMA_XPATH, 0, &val);
+            if(rc == SR_ERR_OK) {
+                nc_fault_enabled = val->data.bool_val;
+                sr_free_val(val);
+            }
+
+            rc = sr_get_item(current_session_running, FAULTS_VES_ENABLED_SCHEMA_XPATH, 0, &val);
+            if(rc == SR_ERR_OK) {
+                ves_fault_enabled = val->data.bool_val;
+                sr_free_val(val);
+            }
+
+            if(nc_fault_enabled) {
+                struct lyd_node *notif = 0;
+                notif = lyd_parse_mem(session_context, fault->yang_notif_processed, LYD_XML, LYD_OPT_NOTIF, 0);
+                if(notif == 0) {
+                    log_error("lyd_parse_mem failed");
+                    goto fault_send_ves;
+                }
+                
+                rc = sr_event_notif_send_tree(current_session_running, notif);
+                lyd_free(notif);
+                if(rc != SR_ERR_OK) {
+                    log_error("sr_event_notif_send_tree failed");
+                }
+            }
+
+            fault_send_ves:
+            if(ves_fault_enabled) {
+                rc = faults_ves_message_send(current_session_running, fault->condition, fault->object, fault->severity, fault->date_time, fault->specific_problem);
+                if(rc != NTS_ERR_OK) {
+                    log_error("faults_ves_message_send failed");
+                }
+            }
+
+            sleep(new_delay);
+        }
+        else {
+            pthread_mutex_unlock(&faults_lock);
+            sleep(1);
+        }
+    }
+
+    sr_session_stop(current_session_running);
+    sr_session_stop(current_session_operational);
+
+    return 0;
+}
diff --git a/ntsimulator/ntsim-ng/core/app/network_function.h b/ntsimulator/ntsim-ng/core/app/network_function.h
new file mode 100644 (file)
index 0000000..5bfcdf0
--- /dev/null
@@ -0,0 +1,20 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+int network_function_run(void);
diff --git a/ntsimulator/ntsim-ng/core/context.c b/ntsimulator/ntsim-ng/core/context.c
new file mode 100644 (file)
index 0000000..9bc57f2
--- /dev/null
@@ -0,0 +1,370 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "context.h"
+#include "utils/log_utils.h"
+#include "utils/sys_utils.h"
+#include <sysrepo.h>
+#include "core/session.h"
+#include <dirent.h>
+#include <libgen.h>
+#include <assert.h>
+
+//private variables for context state
+struct lys_ident_with_childcount {
+    struct lys_ident *ident;
+    int children;
+};
+static struct lys_ident_with_childcount *identities;
+static int identities_size;                 //number of found identities
+
+struct features_with_info {
+    char *name;
+    bool enabled;
+};
+static struct features_with_info *features;
+static int features_size;
+
+
+//private functions
+static bool check_identity_of_type(const struct lys_ident *ident, const struct lys_ident *type);
+static int identity_get_id(const struct lys_ident *ident);
+
+int context_init(const struct ly_ctx *ly_ctx) {
+    log_message(2, "context_init() begin\n");
+
+    identities = 0;
+    identities_size = 0;
+
+    features = 0;
+    features_size = 0;
+
+    log_message(2, "loading modules\n");
+    uint32_t idx = 0;
+    struct lys_module *module;
+    while((module = (struct lys_module *)ly_ctx_get_module_iter(ly_ctx, &idx)) != 0) {
+        log_message(2, "MODULE %s\n", module->name);
+        log_message(2, "  prefix: %s\n", module->prefix);
+        log_message(2, "  namespace: %s\n", module->ns);
+        log_message(2, "  imports [%d]", module->imp_size);
+        if(module->imp_size) {
+            log_message(2, ": ");
+            for(int i = 0; i < module->imp_size; i++) {
+                log_message(2, "%s(%s), ", module->imp[i].module->name, module->imp[i].module->prefix);
+            }
+        }
+        log_message(2, "\n");
+        log_message(2, "  implemented: %d\n", module->implemented);
+        
+        if(module->implemented) {
+            log_message(2, "  IDENT count: %d\n", module->ident_size);
+            if(module->ident_size) {
+                //add to list of identities
+                identities = (struct lys_ident_with_childcount *)realloc(identities, sizeof(struct lys_ident_with_childcount) * (identities_size + module->ident_size));
+                if(!identities) {
+                    log_error("bad realloc");
+                    return 1;
+                }
+
+                for(int i = 0; i < module->ident_size; i++) {
+                    identities[identities_size].ident = &module->ident[i];
+                    identities[identities_size].children = 0;
+                    identities_size++;
+
+                    if(module->ident[i].base_size) {
+                        log_message(2, "  IDENT[%d]  %s with base %s:%s\n", i, module->ident[i].name, module->ident[i].base[0]->module->name, module->ident[i].base[0]->name);
+                        int id = identity_get_id(module->ident[i].base[0]);
+                        if(id != -1) {
+                            identities[id].children++;
+                        }
+                    }
+                    else {
+                        log_message(2, "  IDENT[%d]  %s as base\n", i, module->ident[i].name);
+                    }
+                }
+            }
+
+
+            log_message(2, "  FEATURES count: %d\n", module->features_size);
+            if(module->features_size) {
+                //add to list of features
+                features = (struct features_with_info *)realloc(features, sizeof(struct features_with_info) * (features_size + module->features_size));
+                if(!features) {
+                    log_error("bad realloc");
+                    return 1;
+                }
+
+                for(int i = 0; i < module->features_size; i++) {
+                    asprintf(&features[features_size].name, "%s:%s", module->name, module->features[i].name);
+                    features[features_size].enabled = (lys_features_state(module, module->features[i].name) == 1);
+                    log_message(2, "  FEATURE[%d]  %s iffeature_size=%d enabled=%d\n", i, module->features[i].name, module->features[i].iffeature_size, features[features_size].enabled);
+                    features_size++;
+                }
+            }
+        }
+        else {
+            log_message(2, "Module not implemented, skipping...\n");
+        }
+
+        log_message(2, " ----\n");
+    }
+
+    log_message(2, "context_init() finished\n");
+
+    return 0;
+}
+
+void context_free(void) {
+    log_message(2, "context_free()... ");
+    free(identities);
+    identities_size = 0;
+
+    for(int i = 0; i < features_size; i++) {
+        free(features[i].name);
+    }
+    free(features);   
+    log_message(2, "done\n");
+}
+
+int context_get_identity_leafs_of_type(const struct lys_ident *ident, struct lys_ident ***found) {
+
+    *found = (struct lys_ident **)malloc(sizeof(struct lys_ident *) * identities_size);
+    if(!*found) {
+        log_error("bad malloc");
+    }
+
+    int count = 0;
+    for(int i = 0; i < identities_size; i++) {
+        if(check_identity_of_type(identities[i].ident, ident)) {
+            if(identities[i].children == 0) {
+                (*found)[count] = identities[i].ident;
+                count++;
+            }
+        }
+    }
+
+    if(count == 0) {
+        log_error("no identities found");
+    }
+    else {
+        *found = (struct lys_ident **)realloc(*found, sizeof(struct lys_ident *) * count);
+    }
+
+    return count;
+}
+
+int context_get_features(char ***found_features) {
+    char **ftrs = (char **)malloc(sizeof(char *) * features_size);
+    if(!ftrs) {
+        log_error("could not alloc");
+        return 0;
+    }
+
+    for(int i = 0; i < features_size; i++) {
+        ftrs[i] = (char *)malloc(sizeof(char) * (strlen(features[i].name) + 1));
+        if(!ftrs) {
+            log_error("could not alloc");
+            return 0;
+        }
+
+        strcpy(ftrs[i], features[i].name);
+    }
+
+    *found_features = ftrs;
+    return features_size;
+}
+
+bool context_get_feature_enabled(const char *feature) {
+    for(int i = 0; i < features_size; i++) {
+        if(strcmp(feature, features[i].name) == 0) {
+            return features[i].enabled;
+        }
+    }
+    return false;
+}
+
+bool context_feature_enable(const char *feature) {
+    assert(feature);
+
+    char mod[96];
+    char feat[96];
+
+    mod[0] = 0;
+    feat[0] = 0;
+
+    int i = 0;
+    int j = 0;
+    while((i < strlen(feature)) && (feature[i] != ':')) {
+        mod[j] = feature[i];
+        j++;
+        i++;
+    }
+    mod[j] = 0;
+    
+    i++;
+    j = 0;
+    while(i < strlen(feature)) {
+        feat[j] = feature[i];
+        j++;
+        i++;
+    }
+    feat[j] = 0;
+
+    int rc;
+    if((rc = sr_enable_module_feature(session_connection, mod, feat)) != SR_ERR_OK) {
+        return false;
+    }
+    
+    return true;
+}
+
+bool context_module_install(const char *name, const char *path) {
+    assert(name);
+    assert(path);
+
+    char *searchpath = strdup(path);
+    int rc = sr_install_module(session_connection, path, dirname(searchpath), 0, 0);
+    free(searchpath);
+    if(rc != SR_ERR_OK) {
+        /* succeed if the module is already installed */
+        if(rc != SR_ERR_EXISTS) {
+            return false;
+        }
+    }
+
+    char *data_path = str_replace(path, ".yang", ".xml");
+    if(file_exists(data_path)) {
+        rc = sr_install_module_data(session_connection, name, 0, data_path, LYD_XML);
+        if(rc != SR_ERR_OK) {
+            log_message(1, " xml error    ");
+            sr_remove_module(session_connection, name);
+            context_apply_changes();
+            return false;
+        }
+    }
+    free(data_path);
+
+    //apply changes
+    if(!context_apply_changes()) {
+        sr_remove_module(session_connection, name);
+        context_apply_changes();
+        return false;
+    }
+
+    return true;
+}
+
+bool context_module_set_access(const char *module_name) {
+    assert(module_name);
+
+    if(sr_set_module_access(session_connection, module_name, "root", "root", 0666) != SR_ERR_OK) {
+        return false;
+    }
+
+    return true;
+}
+
+bool context_apply_changes(void) {
+    int rc;
+    uint32_t connection_count = 0;
+
+    session_context = 0;
+    sr_disconnect(session_connection);
+    session_connection = 0;
+
+    /* get connection count */
+    if((rc = sr_connection_count(&connection_count)) != SR_ERR_OK) {
+        log_error("sr_connection_count() failed to get connection count");
+        return false;
+    }
+
+    if(connection_count) {
+        log_error("cannot apply changes because of existing connections");
+        return false;
+    }
+
+    if((rc = sr_connect(SR_CONN_ERR_ON_SCHED_FAIL, &session_connection)) != SR_ERR_OK) {
+        if((rc = sr_connect(0, &session_connection)) != SR_ERR_OK) {
+            log_error("failed to reconnect to sysrepo");
+        }
+        return false;
+    }
+
+    /* get context */
+    session_context = (struct ly_ctx *)sr_get_context(session_connection);
+    if(session_context == 0) {
+        log_error("sr_get_context failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool context_yang_is_module(const char *path) {
+    assert(path);
+
+    bool ret = false;
+    struct ly_ctx *ctx = ly_ctx_new(0, 0);
+    if(!ctx) {
+        log_error("ly_ctx_new failed");
+    }
+
+    char *searchpath = strdup(path);
+    ly_ctx_set_searchdir(ctx, dirname(searchpath));
+    const struct lys_module *mod = lys_parse_path(ctx, path, LYS_YANG);
+    if((!mod) && (ly_vecode(ctx) == LYVE_SUBMODULE)) {
+        ret = true;
+    }
+
+    free(searchpath);
+    ly_ctx_destroy(ctx, 0);
+    return ret;
+}
+
+
+static bool check_identity_of_type(const struct lys_ident *ident, const struct lys_ident *type) {
+    assert(type);
+
+    if((ident->name == type->name) && (ident->module->name == type->module->name)) {
+        return true;
+    }
+    else if(ident->base_size != 0) {
+        bool result = false;
+        for(int i = 0; i < ident->base_size; i++) {
+            result |= check_identity_of_type(ident->base[i], type);
+        }
+        return result;
+    }
+    else {
+        return false;
+    }
+
+}
+
+static int identity_get_id(const struct lys_ident *ident) {
+    assert(ident);
+
+    for(int i = 0; i < identities_size; i++) {
+        if((ident->name == identities[i].ident->name) && (ident->module->name == identities[i].ident->module->name)) {
+            return i;
+        }
+    }
+
+    return -1;
+}
diff --git a/ntsimulator/ntsim-ng/core/context.h b/ntsimulator/ntsim-ng/core/context.h
new file mode 100644 (file)
index 0000000..0d26b70
--- /dev/null
@@ -0,0 +1,38 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <libyang/libyang.h>
+
+int context_init(const struct ly_ctx *ly_ctx);
+void context_free(void);
+
+int context_get_identity_leafs_of_type(const struct lys_ident *ident, struct lys_ident ***found);
+
+//context_features (feature expressed as in module:feature)
+int context_get_features(char ***found_features);
+bool context_get_feature_enabled(const char *feature);
+bool context_feature_enable(const char *feature);                       //enable feature 
+
+bool context_module_install(const char *name, const char *path);        //install module. module needs to be present in yang/ folder as module_name.yang
+bool context_yang_is_module(const char *path);                          //check whether the file only has submodules, and no modules. function assumes that installing has failed every round
+bool context_module_set_access(const char *module_name);                //set root permissions for module
+bool context_apply_changes(void);                                       //used after installing modules mainly
diff --git a/ntsimulator/ntsim-ng/core/datastore/populate.c b/ntsimulator/ntsim-ng/core/datastore/populate.c
new file mode 100644 (file)
index 0000000..19f6ee9
--- /dev/null
@@ -0,0 +1,469 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "populate.h"
+#include "utils/log_utils.h"
+#include "utils/rand_utils.h"
+#include "utils/type_utils.h"
+#include <stdio.h>
+#include <assert.h>
+
+#include "core/session.h"
+#include "core/framework.h"
+
+#include "core/datastore/schema.h"
+
+static int schema_populate_late_resolve(populate_job_t *job);
+static int schema_populate_validate(populate_instance_t *instance, int count);
+static int schema_populate_commit_to_datastore(populate_job_t *job);
+
+int schema_populate(void) {
+    assert_session();
+
+    log_message(1, LOG_COLOR_BOLD_YELLOW"schema_populate() begin\n"LOG_COLOR_RESET);
+
+    char **xpaths = 0;
+    int instance_count = schema_get_xpaths(&xpaths);
+    if(instance_count < 0) {
+        log_error("schema_get_xpaths failed");
+        return NTS_ERR_FAILED;
+    }
+
+    populate_job_t job;
+    job.operational = 0;
+    job.running = 0;
+    job.late_resolve_count = 0;
+    job.late_resolve_instance = 0;
+    job.late_resolve_schema = 0;
+    job.late_resolve_parent_o = 0;
+    job.late_resolve_parent_r = 0;
+    job.late_resolving = false;
+
+    populate_instance_t *instance = (populate_instance_t *)malloc(sizeof(populate_instance_t) * instance_count);
+    if(!instance) {
+        log_error("bad malloc");
+        return NTS_ERR_FAILED;
+    }
+    
+    //populate everything
+    for(int i = 0; i < instance_count; i++) {
+        log_message(1, "populating "LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET" with data...\n", xpaths[i]);
+
+        struct lys_node *schema_node = (struct lys_node *)ly_ctx_get_node(session_context, 0, xpaths[i], 0);
+        if(schema_node == 0) {
+            log_error("ly_ctx_get_node failed for %s", xpaths[i]);
+            return NTS_ERR_FAILED;
+        }
+
+        if(schema_node == 0) {
+            log_message(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET);
+            log_error("ly_ctx_get_node failed for %s", xpaths[i]);
+            return NTS_ERR_FAILED;
+        }
+
+        if(!schema_node->module->implemented) {
+            log_message(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET);
+            log_error("module is not implemented for %s", xpaths[i]);
+            return NTS_ERR_FAILED;
+        }
+
+        if((schema_node->flags & LYS_STATUS_DEPRC) != 0) {
+            log_message(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET);
+            log_error("module is deprecated for %s", xpaths[i]);
+            return NTS_ERR_FAILED;
+        }
+
+        //populate current instance vals
+        instance[i].init = 0;
+        instance[i].xpath = strdup(xpaths[i]);
+        instance[i].modules = 0;
+        instance[i].mod_count = 0;
+        instance[i].operational = 0;
+        instance[i].running = 0;
+        
+        //do the actual population
+        int rc = schema_populate_recursive(&job, &instance[i], schema_node, 0, 0);
+        if(rc != NTS_ERR_OK) {
+            log_error("schema_populate_recursive failed instance %d with xpath %s", i, instance[i].xpath);
+            return rc;
+        }
+    }
+
+    //link everything so we would be able to find everything in late-resolve
+    log_message(1, LOG_COLOR_BOLD_YELLOW"schema_populate() done populating, now linking... (%d root nodes)\n"LOG_COLOR_RESET, instance_count);
+    for(int i = 0; i < instance_count; i++) {
+
+        if(instance[i].operational) {
+            if(job.operational) {
+                int rc = lyd_insert_sibling(&job.operational, instance[i].operational);
+                if(rc != 0) {
+                    log_error("lyd_insert_sibling");
+                    return NTS_ERR_FAILED;
+                }
+            }
+            else {
+                job.operational = instance[i].operational;
+            }
+        }
+
+        if(instance[i].running) {
+            if(job.running) {
+                int rc = lyd_insert_sibling(&job.running, instance[i].running);
+                if(rc != 0) {
+                    log_error("lyd_insert_sibling");
+                    return NTS_ERR_FAILED;
+                }
+            }
+            else {
+                job.running = instance[i].running;
+            }
+        }
+    }
+
+    //late-resolve
+    log_message(1, LOG_COLOR_BOLD_YELLOW"schema_populate() starting late-resolve process...\n"LOG_COLOR_RESET);
+    if(job.late_resolve_count) {
+        int rc = schema_populate_late_resolve(&job);
+        if(rc != NTS_ERR_OK) {
+            log_error("schema_populate_late_resolve failed");
+            return rc;
+        }
+    }
+    
+    //validate data and remove invalid nodes
+    log_message(1, LOG_COLOR_BOLD_YELLOW"schema_populate() validating\n"LOG_COLOR_RESET);
+    int rc = schema_populate_validate(instance, instance_count);
+    if(rc != NTS_ERR_OK) {
+        log_error("schema_populate_commit_to_datastore failed");
+        return rc;
+    }
+
+    //commit to datastore
+    log_message(1, LOG_COLOR_BOLD_YELLOW"schema_populate() commiting to datastore\n"LOG_COLOR_RESET);
+    rc = schema_populate_commit_to_datastore(&job);
+    if(rc != NTS_ERR_OK) {
+        log_error("schema_populate_commit_to_datastore failed");
+        return rc;
+    }
+
+    //cleanup
+    log_message(1, LOG_COLOR_BOLD_YELLOW"schema_populate() cleaning up... "LOG_COLOR_RESET);
+    for(int i = 0; i < instance_count; i++) {
+        log_message(1, "%d ", i);
+
+        free(instance[i].modules);
+        free(instance[i].xpath);
+
+        free(xpaths[i]);
+    }
+    free(xpaths);
+    free(job.late_resolve_instance);
+    free(job.late_resolve_schema);
+    free(job.late_resolve_parent_o);
+    free(job.late_resolve_parent_r);
+
+    lyd_free_withsiblings(job.operational);
+    lyd_free_withsiblings(job.running);
+        
+    log_message(1, "\n");
+    log_message(1, LOG_COLOR_BOLD_GREEN"schema_populate() finished\n"LOG_COLOR_RESET);
+    
+    return NTS_ERR_OK;
+}
+
+static int schema_populate_late_resolve(populate_job_t *job) {
+    assert(job);
+
+    job->late_resolving = true;
+    for(int i = 0; i < job->late_resolve_count; i++) {
+        log_message(1, LOG_COLOR_BOLD_YELLOW"late-populating "LOG_COLOR_RESET": ");
+        int rc = schema_populate_add_leaf(job, job->late_resolve_instance[i], job->late_resolve_schema[i], job->late_resolve_parent_o[i], job->late_resolve_parent_r[i]);
+        if(rc != NTS_ERR_OK) {
+            log_error("schema_populate_add_leaf failed on late-resolve");
+            return rc;
+        }
+    }
+    job->late_resolving = false;
+
+    return NTS_ERR_OK;
+}
+
+static int schema_populate_validate(populate_instance_t *instance, int count) {
+    assert_session();
+    assert(instance);
+
+    int rc = 0;
+    int commit_ok = NTS_ERR_OK;
+
+    for(int i = 0; i < count; i++) {
+        if(instance[i].operational) {
+            log_message(2, "available modules:");
+            for(int j = 0; j < instance[i].mod_count; j++) {
+                log_message(2, " %s", instance[i].modules[j]->name);
+            }
+            log_message(2, "\n");
+            log_message(1, "validating OPERATIONAL for [%d] : %s... ", i, instance[i].xpath);
+
+            int solved_instance_errors = 1;
+            int solved_errors = 0;
+            bool success = false;
+            while(instance[i].operational && solved_instance_errors) {
+                solved_instance_errors = 0;
+                rc = lyd_validate_modules(&instance[i].operational, instance[i].modules, instance[i].mod_count, LYD_OPT_DATA, 0);
+                if(rc == 0) {
+                    log_message(1, LOG_COLOR_BOLD_GREEN"success (%d)\n"LOG_COLOR_RESET, solved_errors);
+                    success = true;
+                    break;
+                }
+                else {
+                    log_message(2, "\n");
+
+                    struct ly_err_item *err = ly_err_first(session_context);
+                    while(err) {
+                        if((err->vecode == LYVE_NOWHEN) || (err->vecode == LYVE_NOMUST) || (err->vecode == LYVE_NOCONSTR) || (err->vecode == LYVE_NOLEAFREF) || (err->vecode == LYVE_NOMIN) || (err->vecode == LYVE_INVAL)) {
+                            struct ly_set *set = lyd_find_path(instance[i].operational, err->path);
+                            if(set && set->number) {
+                                log_message(2, "operational error code %d on path %s with msg %s\n", err->vecode, err->path, err->msg);
+                                log_message(2, LOG_COLOR_BOLD_RED"  [WHEN-DELETE O]"LOG_COLOR_RESET" %s ... ", err->path);
+
+                                bool mandatory = false;
+                                if((set->set.d[0]->schema->flags & LYS_MAND_TRUE) != 0) {
+                                    mandatory = true;
+                                }
+
+                                if((set->set.d[0]->schema->parent) && (set->set.d[0]->schema->parent->nodetype == LYS_CASE)) {
+                                    if((set->set.d[0]->schema->parent->flags & LYS_MAND_TRUE) != 0) {
+                                        mandatory = true;
+                                    }
+                                }
+
+                                if((set->set.d[0]->dflt != 0) || (lys_is_key((const struct lys_node_leaf *)set->set.d[0]->schema, 0)) || (mandatory) || (err->vecode == LYVE_NOMIN)) {
+                                    //delete whole parent
+                                    log_message(2, "deleted parent : %s\n", lyd_path(set->set.d[0]->parent));
+                                    struct lyd_node *p = set->set.d[0]->parent;
+                                    lyd_free_withsiblings(set->set.d[0]);
+                                    lyd_free(p);
+                                    if(p == instance[i].operational) {
+                                        log_message(1, "instance became empty "LOG_COLOR_BOLD_GREEN"success\n"LOG_COLOR_RESET);
+                                        success = true;
+                                        instance[i].operational = 0;
+                                        break;
+                                    }
+                                }
+                                else {
+                                    //delete THIS node only
+                                    lyd_free(set->set.d[0]);
+                                    log_message(2, "deleted\n");
+                                    if(set->set.d[0] == instance[i].operational) {
+                                        log_message(1, "instance became empty "LOG_COLOR_BOLD_GREEN"success\n"LOG_COLOR_RESET);
+                                        success = true;
+                                        instance[i].operational = 0;
+                                        break;
+                                    }
+                                }
+                                solved_instance_errors++;
+
+                                ly_set_free(set);
+                            }
+                        }
+                        else if((err->vecode != 0) && (err->vecode != 29)) {
+                            log_message(2, "operational error code %d on path %s with msg %s\n", err->vecode, err->path, err->msg);
+                        }
+
+                        err = err->next;
+                    }
+                    ly_err_clean(session_context, 0);
+                }
+
+                solved_errors += solved_instance_errors;
+            }
+
+            if(!success) {
+                if(!solved_errors) {
+                    log_message(1, LOG_COLOR_BOLD_YELLOW"failed"LOG_COLOR_RESET"\n%s\n", ly_errmsg(session_context));
+                }
+                else {
+                    log_message(1, LOG_COLOR_BOLD_YELLOW"partially solved (%d)"LOG_COLOR_RESET"\n", solved_errors);
+                }
+            }
+        }
+
+        if(instance[i].running) {
+            log_message(1, "validating RUNNING... for [%d] : %s... ", i, instance[i].xpath);
+
+            int solved_instance_errors = 1;
+            int solved_errors = 0;
+            bool success = false;
+            while(instance[i].running && solved_instance_errors) {
+                solved_instance_errors = 0;
+                rc = lyd_validate_modules(&instance[i].running, instance[i].modules, instance[i].mod_count, LYD_OPT_CONFIG, 0);
+                if(rc == 0) {
+                    log_message(1, LOG_COLOR_BOLD_GREEN"success (%d)\n"LOG_COLOR_RESET, solved_errors);
+                    success = true;
+                    break;
+                }
+                else {
+                    log_message(2, "\n");
+
+                    struct ly_err_item *err = ly_err_first(session_context);
+                    while(err) {
+                        if((err->vecode == LYVE_NOWHEN) || (err->vecode == LYVE_NOMUST) || (err->vecode == LYVE_NOCONSTR) || (err->vecode == LYVE_NOLEAFREF) || (err->vecode == LYVE_NOMIN) || (err->vecode == LYVE_INVAL)) {
+                            struct ly_set *set = lyd_find_path(instance[i].running, err->path);
+                            if(set && set->number) {
+                                log_message(2, "running error code %d on path %s with msg %s\n", err->vecode, err->path, err->msg);
+                                log_message(2, LOG_COLOR_BOLD_RED"  [WHEN-DELETE R]"LOG_COLOR_RESET" %s ... ", err->path);
+
+                                bool mandatory = false;
+                                if((set->set.d[0]->schema->flags & LYS_MAND_TRUE) != 0) {
+                                    mandatory = true;
+                                }
+
+                                if((set->set.d[0]->schema->parent) && (set->set.d[0]->schema->parent->nodetype == LYS_CASE)) {
+                                    if((set->set.d[0]->schema->parent->flags & LYS_MAND_TRUE) != 0) {
+                                        mandatory = true;
+                                    }
+                                }
+
+                                if((set->set.d[0]->dflt != 0) || (lys_is_key((const struct lys_node_leaf *)set->set.d[0]->schema, 0)) || (mandatory) || (err->vecode == LYVE_NOMIN))  {
+                                    //delete whole parent
+                                    log_message(2, "deleted parent : %s\n", lyd_path(set->set.d[0]->parent));
+                                    struct lyd_node *p = set->set.d[0]->parent;
+                                    lyd_free_withsiblings(set->set.d[0]);
+                                    lyd_free(p);
+
+                                    if(p == instance[i].running) {
+                                        log_message(1, "instance became empty "LOG_COLOR_BOLD_GREEN"success\n"LOG_COLOR_RESET);
+                                        success = true;
+                                        instance[i].running = 0;
+                                        break;
+                                    }
+                                }
+                                else {
+                                    //delete THIS node only
+                                    lyd_free(set->set.d[0]);
+                                    log_message(2, "deleted\n");
+                                    if(set->set.d[0] == instance[i].running) {
+                                        log_message(1, "instance became empty "LOG_COLOR_BOLD_GREEN"success\n"LOG_COLOR_RESET);
+                                        success = true;
+                                        instance[i].running = 0;
+                                        break;
+                                    }
+                                }
+                                solved_instance_errors++;
+
+                                ly_set_free(set);
+                            }
+                        }
+                        else if((err->vecode != 0) && (err->vecode != 29)) {
+                            log_message(2, "running error code %d on path %s with msg %s\n", err->vecode, err->path, err->msg);
+                        }
+
+                        err = err->next;
+                    }
+                    ly_err_clean(session_context, 0);
+                }
+
+                solved_errors += solved_instance_errors;
+            }
+
+            if(!success) {
+                if(!solved_errors) {
+                    log_message(1, LOG_COLOR_BOLD_YELLOW"failed"LOG_COLOR_RESET"\n%s\n", ly_errmsg(session_context));
+                }
+                else {
+                    log_message(1, LOG_COLOR_BOLD_YELLOW"partially solved (%d)"LOG_COLOR_RESET"\n", solved_errors);
+                }
+            }
+        }
+    }
+
+    return commit_ok;
+}
+
+static int schema_populate_commit_to_datastore(populate_job_t *job) {
+    assert_session();
+    assert(job);
+
+    int rc = 0;
+    int commit_ok = 0;
+
+    if(job->operational) {
+        rc = SR_ERR_OK;
+        log_message(1, "editing batch for OPERATIONAL... ");
+        rc = sr_edit_batch(session_operational, job->operational, "merge");
+        if (rc != SR_ERR_OK) {
+            log_message(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET);
+            commit_ok = NTS_ERR_FAILED;
+        }
+        else {
+            log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
+        }
+
+        rc = SR_ERR_OK;
+        log_message(1, "appling changes to OPERATIONAL... ");
+        rc = sr_apply_changes(session_operational, 0, 0);
+        if (rc != SR_ERR_OK) {
+            sr_discard_changes(session_operational);
+            commit_ok = NTS_ERR_FAILED;
+            log_message(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET);
+        }
+        else {
+            log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
+        }
+    }
+
+    if(job->running) {
+        // or you can do it like this, but will replace the WHOLE datastore
+        // rc = SR_ERR_OK;
+        // log_message(1, "editing batch for RUNNING...");
+        // rc = sr_replace_config(session_running, 0, job->running, 0, 0);
+        // if (rc != SR_ERR_OK) {
+        //     log_message(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET);
+        //     commit_ok = NTS_ERR_FAILED;
+        // }
+        // else {
+        //     log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
+        // }
+
+        rc = SR_ERR_OK;
+        log_message(1, "editing batch for RUNNING...");
+        rc = sr_edit_batch(session_running, job->running, "merge");
+        if (rc != SR_ERR_OK) {
+            log_message(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET);
+            commit_ok = NTS_ERR_FAILED;
+        }
+        else {
+            log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
+        }
+
+        rc = SR_ERR_OK;
+        log_message(1, "appling changes to RUNNING... ");
+        rc = sr_apply_changes(session_running, 0, 0);
+        if (rc != SR_ERR_OK) {
+            sr_discard_changes(session_running);
+            commit_ok = NTS_ERR_FAILED;
+            log_message(1, LOG_COLOR_BOLD_RED"failed\n"LOG_COLOR_RESET);
+        }
+        else {
+            log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
+        }
+    }
+
+    return commit_ok;
+}
diff --git a/ntsimulator/ntsim-ng/core/datastore/populate.h b/ntsimulator/ntsim-ng/core/datastore/populate.h
new file mode 100644 (file)
index 0000000..3df3693
--- /dev/null
@@ -0,0 +1,54 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <libyang/libyang.h>
+
+typedef struct {
+    int init;
+
+    char *xpath;
+
+    const struct lys_module **modules;
+    int mod_count;
+
+    struct lyd_node *operational;
+    struct lyd_node *running;
+} populate_instance_t;
+
+typedef struct {
+    struct lyd_node *operational;
+    struct lyd_node *running;
+    bool late_resolving;
+
+    int late_resolve_count;
+    struct lys_node **late_resolve_schema;
+    struct lyd_node **late_resolve_parent_o;
+    struct lyd_node **late_resolve_parent_r;
+    populate_instance_t **late_resolve_instance;
+} populate_job_t;
+
+//populate.c
+int schema_populate(void);                     //populate all available root nodes (taking into consideration excluded, deprecated and unimplemented)
+
+//populate_rec.c
+int schema_populate_recursive(populate_job_t *job, populate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r);
+int schema_populate_add_leaf(populate_job_t *job, populate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r);
diff --git a/ntsimulator/ntsim-ng/core/datastore/populate_rec.c b/ntsimulator/ntsim-ng/core/datastore/populate_rec.c
new file mode 100644 (file)
index 0000000..d185083
--- /dev/null
@@ -0,0 +1,584 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "populate.h"
+#include "utils/log_utils.h"
+#include "utils/rand_utils.h"
+#include "utils/type_utils.h"
+#include <stdio.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "core/session.h"
+#include "core/framework.h"
+
+#define SCHEMA_LEAFREF_TOTAL_ENTRIES      11
+
+static int schema_instance_add_module(populate_instance_t *instance, const struct lys_module *module);
+static int schema_populate_late_resolve_add_leaf(populate_job_t *job, populate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r);
+static const char* schema_leafref_temp_val(int index);
+
+int schema_populate_recursive(populate_job_t *job, populate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r) {
+    assert_session();
+    assert(job);
+    assert(schema);
+    assert(instance);
+    
+    char *resolved_schema_path = lys_path(schema, LYS_PATH_FIRST_PREFIX);
+    bool schema_operational = ((schema->flags & LYS_CONFIG_W) == 0);
+
+    schema_populate_rerun_switch:
+    switch(schema->nodetype) {
+        //for container, just add it to the xpath, and iterate it's childeren to further traverse the tree
+        case LYS_CONTAINER: {
+            //add container
+
+            struct lyd_node *new_parent_o = parent_o;
+            struct lyd_node *new_parent_r = parent_r;
+
+            new_parent_o = lyd_new(parent_o, schema->module, schema->name);
+            if(!new_parent_o) {
+                log_error("error creating container operational -> %s", schema->name);
+                log_error("ly_error: %s\n", ly_errmsg(session_context));
+                return NTS_ERR_FAILED;
+            }
+
+            if(!schema_operational && !framework_arguments.operational_only) {
+                new_parent_r = lyd_new(parent_r, schema->module, schema->name);
+                if(!new_parent_r) {
+                    log_error("error creating container running -> %s", schema->name);
+                    log_error("ly_error: %s\n", ly_errmsg(session_context));
+                    return NTS_ERR_FAILED;
+                }
+            }
+
+            if(!instance->init) {
+                instance->init = true;
+                instance->operational = new_parent_o;
+                instance->running = new_parent_r;
+            }
+
+            char mandatory = ' ';
+            if((schema->flags & LYS_MAND_TRUE) != 0) {
+                mandatory = 'M';
+            }
+            if((schema->parent) && (schema->parent->nodetype == LYS_CASE)) {
+                if((schema->parent->flags & LYS_MAND_TRUE) != 0) {
+                    mandatory = 'M';
+                }
+            }
+            bool node_operational = ((schema->flags & LYS_CONFIG_W) == 0);
+            char *xpath = lyd_path(new_parent_o);
+            log_message(1, LOG_COLOR_BOLD_MAGENTA"[%15s] "LOG_COLOR_BOLD_YELLOW"[%c%c]"LOG_COLOR_RESET" %s\n", "CONTAINER", node_operational ? 'O' : 'R', mandatory, xpath);
+            free(xpath);
+
+            int rc = schema_instance_add_module(instance, schema->module);
+            if(rc != NTS_ERR_OK) {
+                log_error("schema_instance_add_module failed");
+                return rc;
+            }
+
+            struct lys_node *child = 0;
+            LY_TREE_FOR(schema->child, child) {
+                int rc = schema_populate_recursive(job, instance, child, new_parent_o, new_parent_r);
+                if(rc != NTS_ERR_OK) {
+                    log_error("schema_populate_recursive failed");
+                    return rc;
+                }
+            }
+        } break;
+
+        //choice does not appear into the data path. get all the avalable choices, and choose a random one
+        case LYS_CHOICE: {
+            int choice_no = 0;
+            struct lys_node_case *choice = (struct lys_node_case *)schema->child;
+            while(choice) {
+                choice_no++;
+                choice = (struct lys_node_case *)choice->next;
+            }
+
+            //select a random choice
+            choice_no = rand_uint16() % choice_no;
+
+            int i = 0;
+            choice = (struct lys_node_case *)schema->child;
+            while(i < choice_no) {
+                i++;
+                choice = (struct lys_node_case *)choice->next;
+            }
+
+            //after the choice was made, rerun the adding without other tree-searching (will run into a CASE)
+            schema = (struct lys_node *)choice;
+            goto schema_populate_rerun_switch;
+        } break;
+
+        //the actual "case" is this node's child, so we skip directly to that
+        case LYS_CASE:
+            //case contains mandatory
+            if(schema->child) {
+                schema = schema->child;
+                goto schema_populate_rerun_switch;
+            }
+            else {
+                //blank case
+                return NTS_ERR_OK;
+            }
+            break;
+
+        //populate a list
+        case LYS_LIST: {
+            //get min-max for current list
+            struct lys_node_list *list = (struct lys_node_list *)schema;
+            int min_added = list->min ? list->min : 1;
+            int max_added = list->max ? list->max : 65536;
+            
+            int populating_times = framework_populate_get_instance_count(resolved_schema_path);
+            if(populating_times != 0) {
+                if(min_added < populating_times) {
+                    min_added = populating_times;
+                }
+                if(min_added > max_added) {
+                    min_added = max_added;
+                    log_error("min-elements exceeds max-elements for path %s. truncated to %d", resolved_schema_path, max_added);
+                }
+                log_message(2, "populating %d times list '%s'\n", min_added, resolved_schema_path);
+
+                //populate node with the intended number of values
+                while(min_added) {
+                    //add list
+
+                    struct lyd_node *new_parent_o = parent_o;
+                    struct lyd_node *new_parent_r = parent_r;
+
+                    new_parent_o = lyd_new(parent_o, schema->module, schema->name);
+                    if(!new_parent_o) {
+                        log_error("error creating list operational -> %s", schema->name);
+                        log_error("ly_error: %s\n", ly_errmsg(session_context));
+                        return NTS_ERR_FAILED;
+                    }
+
+                    if(!schema_operational && !framework_arguments.operational_only) {
+                        new_parent_r = lyd_new(parent_r, schema->module, schema->name);
+                        if(!new_parent_r) {
+                            log_error("error creating container running -> %s", schema->name);
+                            log_error("ly_error: %s\n", ly_errmsg(session_context));
+                            return NTS_ERR_FAILED;
+                        }
+                    }
+
+                    if(!instance->init) {
+                        instance->init = true;
+                        instance->operational = new_parent_o;
+                        instance->running = new_parent_r;
+                    }
+
+                    char mandatory = ' ';
+                    if((schema->flags & LYS_MAND_TRUE) != 0) {
+                        mandatory = 'M';
+                    }
+                    if((schema->parent) && (schema->parent->nodetype == LYS_CASE)) {
+                        if((schema->parent->flags & LYS_MAND_TRUE) != 0) {
+                            mandatory = 'M';
+                        }
+                    }
+                    bool node_operational = ((schema->flags & LYS_CONFIG_W) == 0);
+                    char *xpath = lyd_path(new_parent_o);
+                    log_message(1, LOG_COLOR_BOLD_MAGENTA"[%15s] "LOG_COLOR_BOLD_YELLOW"[%c%c]"LOG_COLOR_RESET" %s\n", "LIST", node_operational ? 'O' : 'R', mandatory, xpath);
+                    free(xpath);
+
+                    int rc = schema_instance_add_module(instance, schema->module);
+                    if(rc != NTS_ERR_OK) {
+                        log_error("schema_instance_add_module failed");
+                        return rc;
+                    }
+
+                    //populate all list elements below in the tree
+                    struct lys_node *child = 0;
+                    LY_TREE_FOR(schema->child, child) {
+                        int rc = schema_populate_recursive(job, instance, child, new_parent_o, new_parent_r);
+                        if(rc != NTS_ERR_OK) {
+                            log_error("schema_populate_recursive failed");
+                            return rc;
+                        }
+                    }
+
+                    min_added--;
+                }
+            }
+            else {
+                log_message(2, "not populating list '%s'\n", resolved_schema_path);
+            }
+        } break;
+
+        //populate the leaf
+        case LYS_LEAF: {
+            if(schema_populate_add_leaf(job, instance, schema, parent_o, parent_r) != NTS_ERR_OK) {
+                return NTS_ERR_FAILED;
+            }            
+        } break;
+
+        //leaflist is treated the same as a LEAF, but with min/max characteristics of a LIST
+        case LYS_LEAFLIST: {
+            //get min-max for the current leaflist
+            struct lys_node_leaflist *list = (struct lys_node_leaflist *)schema;
+            int min_added = list->min ? list->min : 1;
+            int max_added = list->max ? list->max : 65536;
+            
+            int populating_times = framework_populate_get_instance_count(resolved_schema_path);
+            if(populating_times != 0) {
+                if(min_added < populating_times) {
+                    min_added = populating_times;
+                }
+                if(min_added > max_added) {
+                    min_added = max_added;
+                    log_error("min-elements exceeds max-elements for path %s truncated to %d", resolved_schema_path, max_added);
+                }
+                log_message(2, "populating %d times leaflist '%s'\n", min_added, resolved_schema_path);
+
+                //add the leafs
+                while(min_added) {
+                    if(schema_populate_add_leaf(job, instance, schema, parent_o, parent_r) != NTS_ERR_OK) {
+                        return NTS_ERR_FAILED;
+                    }   
+                    min_added--;
+                }
+            }
+            else {
+                log_message(2, "not populating leaflist '%s'\n", resolved_schema_path);
+            }
+        } break;
+
+        case LYS_ACTION:
+        case LYS_INPUT:
+        case LYS_OUTPUT:
+        case LYS_NOTIF:
+            //don't do anything, since we don't want to add this or go further down the tree when we meet them
+            break;
+
+        //other node types (grouping, uses, augment, etc just traverse)
+        default:
+            log_message(1, "[%15s]      %s\n", typeutils_yang_nodetype_to_str(schema->nodetype), resolved_schema_path);
+
+            //traverse the tree down for any other node types, without adding anything to the path
+            struct lys_node *child = 0;
+            LY_TREE_FOR(schema->child, child) {
+                int rc = schema_populate_recursive(job, instance, child, parent_o, parent_r);
+                if(rc != NTS_ERR_OK) {
+                    return rc;
+                }
+            }
+            break;
+    }
+
+    free(resolved_schema_path);
+
+    return NTS_ERR_OK;
+}
+
+int schema_populate_add_leaf(populate_job_t *job, populate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r) {
+    assert_session();
+    assert(job);
+    assert(schema);
+    assert(parent_o);
+
+    int rc = schema_instance_add_module(instance, schema->module);
+    if(rc != NTS_ERR_OK) {
+        log_error("bad schema_instance_add module");
+        return rc;
+    }
+
+    struct lys_type *type = &((struct lys_node_leaf *)schema)->type;
+    
+    char *data_xpath = lyd_path(parent_o);
+    data_xpath = (char *)realloc(data_xpath, sizeof(char) * (strlen(data_xpath) + 1 + strlen(schema->name) + 1));
+    if(!data_xpath) {
+        log_error("lyd_path failed");
+        return NTS_ERR_FAILED;
+    }
+    strcat(data_xpath, "/");
+    strcat(data_xpath, schema->name);
+
+    //check whether the value is MANDATORY or not (for logging purposes)
+    char mandatory = ' ';
+    if((schema->flags & LYS_MAND_TRUE) != 0) {
+        mandatory = 'M';
+    }
+
+    if((schema->parent) && (schema->parent->nodetype == LYS_CASE)) {
+        if((schema->parent->flags & LYS_MAND_TRUE) != 0) {
+            mandatory = 'M';
+        }
+    }
+
+    bool node_operational = ((schema->flags & LYS_CONFIG_W) == 0);
+    log_message(1, LOG_COLOR_BOLD_MAGENTA"[%15s] "LOG_COLOR_BOLD_YELLOW"[%c%c]"LOG_COLOR_RESET" %s <-- ", typeutils_yang_type_to_str(type->base), node_operational ? 'O' : 'R', mandatory, data_xpath);
+    free(data_xpath);
+
+
+    char *resolved_schema_path = lys_path(schema, LYS_PATH_FIRST_PREFIX);
+    char *value = framework_populate_get_restrict_schema(resolved_schema_path);
+    free(resolved_schema_path);
+
+    schema_populate_add_leaf_rerun_switch:
+    switch(type->base) {
+        case LY_TYPE_UNION:
+            if((type->info.uni.count == 0) && (type->der != 0)) {
+                type = &type->der->type;
+            }
+
+            type = &type->info.uni.types[0];
+            goto schema_populate_add_leaf_rerun_switch;
+            break;
+
+        case LY_TYPE_INST: {
+            struct lyd_node *parent = parent_o;
+            while(parent->parent) {
+                parent = parent->parent;
+            }
+
+            if(value == 0) {
+                value = lyd_path(parent);
+            }
+
+            goto schema_populate_add_leaf_actual_add;
+        } break;
+
+        case LY_TYPE_EMPTY:
+            if(rand_bool()) {   //if present, add it
+                log_message(1, LOG_COLOR_CYAN"present"LOG_COLOR_RESET"\n");
+                goto schema_populate_add_leaf_actual_add;
+            }
+            else {
+                log_message(1, LOG_COLOR_CYAN"empty"LOG_COLOR_RESET"\n");
+                return NTS_ERR_OK;
+            }
+            break;
+
+        case LY_TYPE_LEAFREF: {
+            if(value == 0) {
+                int index = 0;
+                struct lyd_node *new_node = 0;
+                while((new_node == 0) && (index < SCHEMA_LEAFREF_TOTAL_ENTRIES)) {
+                    new_node = lyd_new_leaf(parent_o, schema->module, schema->name, schema_leafref_temp_val(index));
+                    index++;
+                }
+
+                if(new_node == 0) {
+                    log_error("error on lyd_new_leaf schema %s. didn't work with any temp val", schema->name);
+                    return NTS_ERR_FAILED;
+                }
+
+                //based on the new_node's path, try to find elements of relative path for the leafref
+                struct ly_set *set = lyd_find_path(new_node, type->info.lref.path);
+                lyd_free(new_node);
+
+                if(set && set->number) {
+                    //choose a random schema and get its value
+                    static int set_number = 0;  //checkAL aici trebuia oare random ?
+                    set_number++;
+                    if(set_number >= set->number) {
+                        set_number = 0;
+                    }
+                    asprintf(&value, "%s", ((struct lyd_node_leaf_list *)set->set.d[set_number])->value_str);
+                    if(!value) {
+                        log_error("bad asprintf");
+                        return NTS_ERR_FAILED;
+                    }
+
+                    int rc = schema_instance_add_module(instance, set->set.d[set_number]->schema->module);
+                    if(rc != NTS_ERR_OK) {
+                        log_error("bad schema_instance_add module");
+                        return rc;
+                    }
+
+                    ly_set_free(set);
+
+                    goto schema_populate_add_leaf_actual_add;
+                }
+                else {
+                    //adding to late-resolve list, as we don't have any nodes in the leafref path
+                    int rc = schema_populate_late_resolve_add_leaf(job, instance, schema, parent_o, parent_r);
+                    if(rc != NTS_ERR_OK) {
+                        return rc;
+                    }
+
+                    if(!job->late_resolving) {
+                        log_message(1, LOG_COLOR_BOLD_YELLOW"added to late-resolve list...\n"LOG_COLOR_RESET);
+                    }
+                    else {
+                        log_message(1, LOG_COLOR_BOLD_YELLOW"REadded to late-resolve list...\n"LOG_COLOR_RESET);
+                    }
+
+                    return NTS_ERR_OK;
+                }
+            }
+        } break;
+      
+        default:
+            if(value == 0) {
+                value = rand_get_populate_value(type);
+            }
+            goto schema_populate_add_leaf_actual_add;
+            break;
+    }
+
+    schema_populate_add_leaf_actual_add: {
+        //add schema to operational
+        struct lyd_node *new_node = lyd_new_leaf(parent_o, schema->module, schema->name, value);
+        if(new_node == 0) {
+            log_error("error on lyd_new_leaf operational: %s", ly_errmsg(session_context));
+            return NTS_ERR_FAILED;
+        }
+        
+        //print out the value
+        if(value) {
+            log_message(1, LOG_COLOR_CYAN"'%s'"LOG_COLOR_RESET"\n",  value);
+        }
+        else {
+            log_message(1, "\n");
+        }
+
+        //if it fits the case, add it also to running
+        if(!node_operational && !framework_arguments.operational_only) {
+            struct lyd_node *new_node = lyd_new_leaf(parent_r, schema->module, schema->name, value);
+            if(new_node == 0) {
+                log_error("error on lyd_new_leaf running: %s", ly_errmsg(session_context));
+                return NTS_ERR_FAILED;
+            }
+        }
+        
+        free(value);
+    }
+
+    return NTS_ERR_OK;
+}
+
+static int schema_instance_add_module(populate_instance_t *instance, const struct lys_module *module) {
+    assert(module);
+    assert(instance);
+
+    for(int i = 0; i < instance->mod_count; i++) {
+        if(instance->modules[i] == module) {
+            return NTS_ERR_OK;
+        }
+    }
+
+    instance->modules = (const struct lys_module **)realloc(instance->modules, sizeof(const struct lys_module *) * (instance->mod_count + 1));
+    if(!instance->modules) {
+        log_error("bad realloc");
+        return NTS_ERR_FAILED;
+    }
+    instance->modules[instance->mod_count] = module;
+    instance->mod_count++;
+
+    return NTS_ERR_OK;
+}
+
+static int schema_populate_late_resolve_add_leaf(populate_job_t *job, populate_instance_t *instance, struct lys_node *schema, struct lyd_node *parent_o, struct lyd_node *parent_r) {
+    assert(job);
+    assert(instance);
+
+    job->late_resolve_schema = (struct lys_node **)realloc(job->late_resolve_schema, (job->late_resolve_count + 1) * sizeof(struct lys_node *));
+    if(!job->late_resolve_schema) {
+        log_error("bad realloc");
+        return NTS_ERR_FAILED;
+    }
+    job->late_resolve_schema[job->late_resolve_count] = schema;
+
+    job->late_resolve_parent_o = (struct lyd_node **)realloc(job->late_resolve_parent_o, (job->late_resolve_count + 1) * sizeof(struct lyd_node *));
+    if(!job->late_resolve_parent_o) {
+        log_error("bad realloc");
+        return NTS_ERR_FAILED;
+    }
+    job->late_resolve_parent_o[job->late_resolve_count] = parent_o;
+
+    job->late_resolve_parent_r = (struct lyd_node **)realloc(job->late_resolve_parent_r, (job->late_resolve_count + 1) * sizeof(struct lyd_node *));
+    if(!job->late_resolve_parent_r) {
+        log_error("bad realloc");
+        return NTS_ERR_FAILED;
+    }
+    job->late_resolve_parent_r[job->late_resolve_count] = parent_r;
+
+    job->late_resolve_instance = (populate_instance_t **)realloc(job->late_resolve_instance, (job->late_resolve_count + 1) * sizeof(populate_instance_t *));
+    if(!job->late_resolve_instance) {
+        log_error("bad realloc");
+        return NTS_ERR_FAILED;
+    }
+    job->late_resolve_instance[job->late_resolve_count] = instance;
+
+    job->late_resolve_count++;
+
+    return NTS_ERR_OK;
+}
+
+static const char* schema_leafref_temp_val(int index) {
+    switch(index) {
+        case 0:
+            return "1";
+            break;
+
+        case 1:
+            return "1.1.1.1";
+            break;
+
+        case 2:
+            return "Fd:4D:63:A5:21:C5";
+            break;
+
+        case 3:
+            return "";
+            break;
+
+        case 4:
+            return "::1";
+            break;
+
+        case 5:
+            return "false";
+            break;
+
+        case 6:
+            return "TDD";
+            break;
+
+        case 7:
+            return "NR";
+            break;
+
+        case 8:
+            return "best-effort";
+            break;
+
+        case 9:
+            return "yes-fault:o-ran-sc-alarm-type";
+            break;
+
+        case 10:
+            return "";
+            break;
+
+        
+
+
+        default:
+            log_error("index out of bounds");
+            return 0;
+            break;
+    }
+}
diff --git a/ntsimulator/ntsim-ng/core/datastore/schema.c b/ntsimulator/ntsim-ng/core/datastore/schema.c
new file mode 100644 (file)
index 0000000..93ae199
--- /dev/null
@@ -0,0 +1,252 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "utils/log_utils.h"
+#include "utils/type_utils.h"
+#include <stdio.h>
+#include <time.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include <libyang/libyang.h>
+#include "core/session.h"
+#include "core/framework.h"
+
+static int schema_print_recursive(struct lys_node *root);
+
+int schema_get_xpaths(char ***root_xpath) {
+    assert_session();
+    assert(root_xpath);
+
+    const struct lys_module *module;
+    const struct lys_node *root;
+    uint32_t idx = 0;
+    char **list = 0;
+    int total = 0;
+
+    while((module = ly_ctx_get_module_iter(session_context, &idx)) != 0) {
+        if(!framework_is_populate_excluded_module(module->name) && (module->implemented)) {
+            LY_TREE_FOR(module->data, root) {
+                if(((root->nodetype == LYS_CONTAINER) || (root->nodetype == LYS_LIST)) && ((root->flags & LYS_STATUS_DEPRC) == 0)) {
+                    list = (char **)realloc(list, sizeof(char *) * (total + 1));
+                    if(!list) {
+                        log_error("bad realloc");
+                        return NTS_ERR_FAILED;
+                    }
+                    asprintf(&list[total], "/%s:%s", module->name, root->name);
+                    if(!list[total]) {
+                        log_error("bad asprintf");
+                        return NTS_ERR_FAILED;
+                    }
+                    total++; 
+                }
+                else if(root->nodetype == LYS_USES) {
+                    struct lys_node *chd;
+                    LY_TREE_FOR(root->child, chd) {
+                        if(((chd->nodetype == LYS_CONTAINER) || (chd->nodetype == LYS_LIST)) && ((chd->flags & LYS_STATUS_DEPRC) == 0)) {
+                            list = (char **)realloc(list, sizeof(char *) * (total + 1));
+                            if(!list) {
+                                log_error("bad realloc");
+                                return NTS_ERR_FAILED;
+                            }
+                            asprintf(&list[total], "/%s:%s", module->name, chd->name);                            
+                            if(!list[total]) {
+                                log_error("bad asprintf");
+                                return NTS_ERR_FAILED;
+                            }
+                            total++;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    *root_xpath = list;
+    return total;
+}
+
+int schema_print_root_paths(void) {
+    assert_session();
+
+    struct lys_module *module;
+    struct lys_node *root;
+    uint32_t idx = 0;
+
+    while((module = (struct lys_module *)ly_ctx_get_module_iter(session_context, &idx)) != 0) {
+        log_message(2, "looking into module "LOG_COLOR_BOLD_MAGENTA"%s"LOG_COLOR_RESET"\n", module->name);
+
+        char flags[10];
+        strcpy(flags, "[     ]");
+        flags[1] = (module->implemented == 0) ? 'i' : ' ';
+        flags[3] = framework_is_populate_excluded_module(module->name) ? 'E' : ' ';
+
+        LY_TREE_FOR(module->data, root) {
+            log_message(2, "   found "LOG_COLOR_CYAN"%s"LOG_COLOR_RESET" with name "LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET"\n", typeutils_yang_nodetype_to_str(root->nodetype), root->name);
+            if((root->nodetype == LYS_CONTAINER) || (root->nodetype == LYS_LIST)) {
+                flags[2] = ((root->flags & LYS_STATUS_DEPRC) != 0) ? 'D' : ' ';
+                flags[4] = ((root->flags & LYS_CONFIG_W) == 0) ? 'O' : 'R';
+                flags[5] = (root->nodetype == LYS_CONTAINER) ? 'C' : 'L';
+                log_message(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_CYAN" /%s:%s\n"LOG_COLOR_RESET, flags, module->name, root->name);
+            }
+            else if(root->nodetype == LYS_USES) {
+                struct lys_node *chd;
+                LY_TREE_FOR(root->child, chd) {
+                    log_message(2, "   - found "LOG_COLOR_CYAN"%s"LOG_COLOR_RESET" with name "LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET"\n", typeutils_yang_nodetype_to_str(chd->nodetype), chd->name);
+                    if((chd->nodetype == LYS_CONTAINER) || (chd->nodetype == LYS_LIST)) {
+                        flags[2] = ((chd->flags & LYS_STATUS_DEPRC) != 0) ? 'D' : ' ';
+                        flags[4] = ((chd->flags & LYS_CONFIG_W) == 0) ? 'O' : 'R';
+                        flags[5] = (chd->nodetype == LYS_CONTAINER) ? 'C' : 'L';
+                        log_message(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_CYAN" /%s:%s\n"LOG_COLOR_RESET, flags, module->name, chd->name);
+                    }
+                }
+            }
+        }
+    }
+
+    log_message(1, "\n   "LOG_COLOR_BOLD_YELLOW"i"LOG_COLOR_RESET" - not implemented | "LOG_COLOR_BOLD_YELLOW"D"LOG_COLOR_RESET" - deprecated | "LOG_COLOR_BOLD_YELLOW"E"LOG_COLOR_RESET" - excluded by config | "LOG_COLOR_BOLD_YELLOW"O"LOG_COLOR_RESET" - operational datastore | "LOG_COLOR_BOLD_YELLOW"R"LOG_COLOR_RESET" - running datastore | "LOG_COLOR_BOLD_YELLOW"C"LOG_COLOR_RESET" - container | "LOG_COLOR_BOLD_YELLOW"L"LOG_COLOR_RESET" - list\n\n");
+    return NTS_ERR_OK;
+}
+
+int schema_print_xpath(const char *xpath) {
+    assert_session();
+    assert(xpath);
+
+    if(xpath == 0) {
+        log_error("xpath is null");
+        return NTS_ERR_FAILED;
+    }
+    log_message(1, "printing out data structure for xpath: "LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET"\n", xpath);
+    
+    struct lys_node *elem = (struct lys_node *)ly_ctx_get_node(session_context, 0, xpath, 0);
+    if(elem == 0) {
+        log_error("ly_ctx_get_node failed for xpath: %s", xpath);
+        return NTS_ERR_FAILED;
+    }
+
+    struct lys_module *module = lys_node_module(elem);
+    if(module == 0) {
+        log_error("lys_node_module failed for xpath: %s", xpath);
+        return NTS_ERR_FAILED;
+    }
+
+
+    log_message(2, "module is %s @ revision %s\n", module->name, module->rev[0].date);
+
+    int rc = schema_print_recursive(elem);
+    if(rc != NTS_ERR_OK) {
+        log_error("schema_print_recursive failed for xpath: %s", xpath);
+        return NTS_ERR_FAILED;
+    }
+
+    log_message(1, "\n   "LOG_COLOR_BOLD_YELLOW"R"LOG_COLOR_RESET" - read only | "LOG_COLOR_BOLD_YELLOW"W"LOG_COLOR_RESET" - writeable | "LOG_COLOR_BOLD_YELLOW"*"LOG_COLOR_RESET" - key | "LOG_COLOR_BOLD_YELLOW"M"LOG_COLOR_RESET" - mandatory | "LOG_COLOR_BOLD_YELLOW"D"LOG_COLOR_RESET" - deprecated | "LOG_COLOR_BOLD_YELLOW"O"LOG_COLOR_RESET" - obsolete\n\n");
+    log_message(2, "schema_print() finished\n");
+
+    return NTS_ERR_OK;
+
+}
+
+static int schema_print_recursive(struct lys_node *root) {
+    assert(root);
+
+    char my_status[] = "[    ]";
+    my_status[1] = ((root->flags & LYS_CONFIG_W) == 0) ? 'R' : 'W';
+    my_status[2] = ((root->flags & LYS_MAND_TRUE) != 0) ? 'M' : ' ';
+    my_status[3] = ((root->flags & LYS_STATUS_DEPRC) != 0) ? 'D' : ' ';
+    my_status[4] = ((root->flags & LYS_STATUS_OBSLT) != 0) ? 'O' : ' ';
+
+    if(((root->parent) && (root->parent->nodetype == LYS_CASE)) && ((root->parent->flags & LYS_MAND_TRUE) != 0)) {
+        my_status[2] = 'M';
+    }
+
+    char *path = lys_data_path(root);
+    if((root->nodetype != LYS_CHOICE) && (root->nodetype != LYS_CASE)) {
+        log_message(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET" %-100s ", my_status, path);
+
+        if(root->nodetype == LYS_LIST) {
+            struct lys_node_list *list = (struct lys_node_list *)root;
+            log_message(1, LOG_COLOR_CYAN"%s "LOG_COLOR_MAGENTA"(m: %d M: %d)"LOG_COLOR_RESET, 4 + typeutils_yang_nodetype_to_str(root->nodetype), list->min, list->max); //+4 to skip "LYS_"
+        }
+        else if(root->nodetype == LYS_LEAFLIST) {
+            struct lys_node_leaflist *list = (struct lys_node_leaflist *)root;
+            log_message(1, LOG_COLOR_CYAN"%s "LOG_COLOR_MAGENTA"(m: %d M: %d)"LOG_COLOR_RESET, 4 + typeutils_yang_nodetype_to_str(root->nodetype), list->min, list->max); //+4 to skip "LYS_"
+        }
+        else {
+            log_message(1, LOG_COLOR_CYAN"%-20s"LOG_COLOR_RESET, 4 + typeutils_yang_nodetype_to_str(root->nodetype)); //+4 to skip "LYS_"
+        }
+    }
+    free(path);
+
+    switch(root->nodetype) {
+        case LYS_LEAF:
+        case LYS_LEAFLIST: {            
+            struct lys_type *type = &((struct lys_node_leaf *)root)->type;
+            if(lys_is_key((const struct lys_node_leaf *)root, 0) != 0) {
+                log_message(1, LOG_COLOR_BOLD_YELLOW"[*]"LOG_COLOR_RESET);
+            }
+            else {
+                log_message(1, "   ");
+            }
+
+            char *typestr = typeutils_type_to_str(type);
+            log_message(1, "[%s]", typestr);
+            free(typestr);
+            
+            if(root->parent) {
+                if(root->parent->nodetype == LYS_CASE) {
+                    log_message(1, " is a "LOG_COLOR_BLUE"CASE"LOG_COLOR_RESET" of "LOG_COLOR_CYAN"%s"LOG_COLOR_RESET, root->parent->parent->name);
+                }
+            }
+            
+            if(type->base == LY_TYPE_LEAFREF) {
+                log_message(1, " path: "LOG_COLOR_GREEN"%s"LOG_COLOR_RESET" ", type->info.lref.path);
+            }
+            else if(type->base == LY_TYPE_UNION) {
+                if((type->info.uni.count == 0) && (type->der != 0)) {
+                    type = &type->der->type;
+                }
+
+                log_message(1, " available union types (%d):"LOG_COLOR_GREEN, type->info.uni.count);
+                for(int i = 0; i < type->info.uni.count; i++) {
+                    char *typestr = typeutils_type_to_str(&type->info.uni.types[i]);
+                    log_message(1, " %s", typestr);
+                    free(typestr);
+                }
+                log_message(1, LOG_COLOR_RESET);
+            }
+        } break;
+
+        default:
+            break;
+    }
+  
+    if((root->nodetype != LYS_CHOICE) && (root->nodetype != LYS_CASE)) {
+        log_message(1, "\n");
+    }
+
+    struct lys_node *child = 0;
+    LY_TREE_FOR(root->child, child) {
+        int rc = schema_print_recursive(child);
+        if(rc != NTS_ERR_OK) {
+            return rc;
+        }
+    }
+
+    return NTS_ERR_OK;
+}
similarity index 61%
rename from ntsimulator/src/ves-messages/heartbeat.h
rename to ntsimulator/ntsim-ng/core/datastore/schema.h
index 6750112..490c3ba 100644 (file)
@@ -1,6 +1,6 @@
 /*************************************************************************
 *
-* Copyright 2019 highstreet technologies GmbH and others
+* Copyright 2020 highstreet technologies GmbH and others
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * limitations under the License.
 ***************************************************************************/
 
-#ifndef SRC_VES_MESSAGES_HEARTBEAT_H_
-#define SRC_VES_MESSAGES_HEARTBEAT_H_
+#pragma once
 
-#include <curl/curl.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <cjson/cJSON.h>
+#include <string.h>
+#include <stdint.h>
 
-#define CURL_MEM_SIZE 2048
+int schema_get_xpaths(char ***root_xpath);  //returns number of xpaths, 0 if none, -1 if error
 
-/**
- * cURL utilities
-*/
-
-struct MemoryStruct {
-  char *memory;
-  size_t size;
-};
-
-int _init_curl(void);
-int cleanup_curl(void);
-
-#endif /* SRC_VES_MESSAGES_HEARTBEAT_H_ */
+int schema_print_root_paths(void);
+int schema_print_xpath(const char *xpath);
diff --git a/ntsimulator/ntsim-ng/core/docker.c b/ntsimulator/ntsim-ng/core/docker.c
new file mode 100644 (file)
index 0000000..40f2bff
--- /dev/null
@@ -0,0 +1,756 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "docker.h"
+#include "utils/log_utils.h"
+#include "utils/sys_utils.h"
+#include "utils/http_client.h"
+#include "core/framework.h"
+#include "core/session.h"
+#include "core/context.h"
+#include <sysrepo.h>
+#include <dirent.h>
+#include <assert.h>
+#include <sys/sysinfo.h>
+
+#include <cjson/cJSON.h>
+
+#define DOCKER_SOCK_FNAME       "/var/run/docker.sock"
+
+static cJSON *docker_network_info = 0;
+
+struct installable_module {
+    char *name;
+    char *fullpath;
+    bool installed;
+    bool submodule;
+};
+
+typedef struct {
+    char *name;
+    char *value;
+} environment_var_t;
+
+static environment_var_t *docker_environment_var;
+static int docker_environment_var_count = 0;
+
+static int get_installable_modules(struct installable_module **modules);    //list available modules for install
+static void list_yangs(const char *path, struct installable_module **modules, int *total);
+
+static char *docker_parse_json_message(const char *json_string);
+
+static int docker_container_create(const char *image, manager_network_function_instance_t *instance);
+static int docker_container_start(manager_network_function_instance_t *instance);
+static int docker_container_inspect(manager_network_function_instance_t *instance);
+
+
+bool docker_container_init(void) {
+    int rc;
+
+    sr_log_stderr(SR_LL_NONE);
+    log_message(1, "Entering container-init mode...\n");
+
+    // connect to sysrepo
+    rc = sr_connect(0, &session_connection);
+    if(SR_ERR_OK != rc) {
+        log_error("sr_connect failed");
+        return false;
+    }
+
+    /* get context */
+    session_context = (struct ly_ctx *)sr_get_context(session_connection);
+    if(session_context == 0) {
+        log_error("sr_get_context failed");
+        return false;
+    }
+
+    /* install yang files */
+    log_message(1, "Installing yang files...\n");
+    struct installable_module *modules;
+    int total_modules = get_installable_modules(&modules);
+    log_message(1, "Found total modules: %d\n", total_modules);
+
+    int old_failed_installations = 1;
+    int failed_installations = 0;
+    int install_round = 0;
+    while(failed_installations != old_failed_installations) {
+        old_failed_installations = failed_installations;
+        failed_installations = 0;
+        install_round++;
+        for(int i = 0; i < total_modules; i++) {
+            if(!modules[i].installed) {
+                modules[i].submodule = context_yang_is_module(modules[i].fullpath);
+                if(!modules[i].submodule) {
+                    if(!framework_is_docker_excluded_module(modules[i].name)) {
+                        log_message(1, "[round %d] trying to install module %s from %s... ", install_round, modules[i].name, modules[i].fullpath);
+                        if(!context_module_install(modules[i].name, modules[i].fullpath)) {
+                            failed_installations++;
+                            log_message(1, LOG_COLOR_BOLD_YELLOW"failed"LOG_COLOR_RESET"\n");
+                        }
+                        else {
+                            log_message(1, LOG_COLOR_BOLD_GREEN"done"LOG_COLOR_RESET"\n");
+                            modules[i].installed = true;
+                        }
+                    }
+                    else {
+                        log_message(1, "[round %d] not installing module %s as it's excluded in config.\n", install_round, modules[i].name);
+                        modules[i].installed = true;
+                    }
+                }
+                else {
+                    log_message(1, "[round %d] %s is a submodule... "LOG_COLOR_BOLD_YELLOW"skipping"LOG_COLOR_RESET"\n", install_round, modules[i].name);
+                    modules[i].installed = true;
+                }
+            }
+        }
+    }
+
+    if(failed_installations != 0) {
+        log_error("Failed to install all modules in %d rounds...", install_round);
+        return false;
+    }
+    else {
+        log_message(1, LOG_COLOR_BOLD_GREEN"successfully"LOG_COLOR_RESET" installed "LOG_COLOR_BOLD_GREEN"ALL"LOG_COLOR_RESET" modules in "LOG_COLOR_BOLD_YELLOW"%d"LOG_COLOR_RESET" rounds\n", (install_round - 1));
+    }
+
+    //set access for all installed modules
+    log_message(1, "Setting access configuration for installed modules... ");
+    for(int i = 0; i < total_modules; i++) {
+        if((!framework_is_docker_excluded_module(modules[i].name)) && (!modules[i].submodule)) {
+            if(!context_module_set_access(modules[i].name)) {
+                log_error("Failed to set access to module %s...", modules[i].name);
+                return false;
+            }
+        }
+    }
+    log_message(1, LOG_COLOR_BOLD_GREEN"done"LOG_COLOR_RESET"\n");
+
+    //cleanup module-install used memory
+    for(int i = 0; i < total_modules; i++) {
+        free(modules[i].name);
+        free(modules[i].fullpath);
+    }
+    free(modules);
+
+    //get context
+    session_context = (struct ly_ctx *)sr_get_context(session_connection);
+    if(session_context == 0) {
+        log_error("sr_get_context failed");
+        return false;
+    }
+
+    //init context so we can see all the available modules, features, etc
+    rc = context_init(session_context);
+    if(rc != 0) {
+        log_error("context_init() failed");
+        return false;
+    }
+
+    /* enable features */
+    log_message(1, "Enabling yang features...\n");
+    char **available_features;
+    int total_available_features;
+    total_available_features = context_get_features(&available_features);
+    log_message(1, "Found total features: %d\n", total_available_features);
+    for(int i = 0; i < total_available_features; i++) {
+        log_message(1, "feature %s: ", available_features[i]);
+
+        if(!context_get_feature_enabled(available_features[i])) {
+            if(!framework_is_docker_excluded_feature(available_features[i])) {
+                if(context_feature_enable(available_features[i])) {
+                    log_message(1, "enabling... "LOG_COLOR_BOLD_GREEN"done"LOG_COLOR_RESET"\n");
+                }
+                else {
+                    log_error("enabling... failed\n");
+                }
+            }
+            else {
+                log_message(1, "excluded in config, skipping\n");
+            }
+        }
+        else {
+            log_message(1, "already "LOG_COLOR_BOLD_GREEN"enabled"LOG_COLOR_RESET", skipping.\n");
+        }
+    }
+    for(int i = 0; i < total_available_features; i++) {
+        free(available_features[i]);
+    }
+    free(available_features);
+
+    sr_disconnect(session_connection);
+    context_free();
+
+    log_message(1, LOG_COLOR_BOLD_GREEN"ntsim successfully initialized Docker container"LOG_COLOR_RESET"\n");
+    return true;
+}
+
+static int get_installable_modules(struct installable_module **modules) {
+    int total = 0;
+    *modules = 0;
+    list_yangs("/opt/dev/deploy/yang", modules, &total);
+    return total;
+}
+
+static void list_yangs(const char *path, struct installable_module **modules, int *total) {
+    DIR *d;
+    struct dirent *dir;
+    d = opendir(path);
+    if(d) {
+        while((dir = readdir(d)) != NULL) {
+            if(dir->d_type == DT_DIR) {
+                if(strcmp(dir->d_name, ".") != 0 && strcmp(dir->d_name, "..") != 0)
+                {
+                    char new_path[1024];
+                    snprintf(new_path, sizeof(new_path), "%s/%s", path, dir->d_name);
+                    list_yangs(new_path, modules, total);
+                }
+            } else {
+                if(strstr(dir->d_name, ".yang") != 0) {
+                    *modules = (struct installable_module *)realloc(*modules, sizeof(struct installable_module) * (*total + 1));
+                    if(!*modules) {
+                        log_error("could not realloc");
+                        return;
+                    }
+
+                    (*modules)[*total].name = (char*)malloc(sizeof(char) * (strlen(dir->d_name) + 1));
+                    if(!(*modules)[*total].name) {
+                        log_error("could not alloc");
+                        return;
+                    }
+                    strcpy((*modules)[*total].name, dir->d_name);
+                    (*modules)[*total].name[strlen(dir->d_name) - 5] = 0;   //extract ".yang"
+                    char *rev = strstr((*modules)[*total].name, "@");
+                    if(rev) { //extract revision, if exists
+                        *rev = 0;
+                    }
+
+                    (*modules)[*total].fullpath = (char*)malloc(sizeof(char) * (strlen(path) + 1 + strlen(dir->d_name) + 1));
+                    if(!(*modules)[*total].fullpath) {
+                        log_error("could not alloc");
+                        return;
+                    }
+                    sprintf((*modules)[*total].fullpath, "%s/%s", path, dir->d_name);
+
+                    (*modules)[*total].installed = false;
+                    (*modules)[*total].submodule = false;
+
+                    (*total)++;
+                }
+            }
+        }
+        closedir(d);
+    }
+}
+
+int docker_device_init(void) {
+    char *response = 0;
+    char *url = 0;
+    asprintf(&url, "http://v%s/containers/%s/json", framework_environment.docker_engine_version, framework_environment.hostname);
+
+    int rc = http_socket_request(url, DOCKER_SOCK_FNAME, "GET", 0, 0, &response);
+    if(rc != NTS_ERR_OK) {
+        log_error("http_socket_request failed");
+        return NTS_ERR_FAILED;
+    }
+
+    cJSON *json_response = cJSON_Parse(response);
+    free(response);
+
+    if(json_response == 0) {
+        log_error("could not parse JSON response for url=\"%s\"", url);
+        return NTS_ERR_FAILED;
+    }
+
+    cJSON *hostConfig = cJSON_GetObjectItemCaseSensitive(json_response, "HostConfig");
+    if(hostConfig == 0) {
+        log_error("could not get HostConfig object");
+        return NTS_ERR_FAILED;
+    }
+
+    cJSON *networkMode = cJSON_GetObjectItemCaseSensitive(hostConfig, "NetworkMode");
+    if(networkMode == 0) {
+        log_error("could not get NetworkMode object");
+        return NTS_ERR_FAILED;
+    }
+
+    docker_network_info = cJSON_Duplicate(networkMode, 1);
+    cJSON_Delete(json_response);
+
+    log_message(2, "finished parsing docker inspect...\n");
+
+
+    docker_environment_var_count = 5;
+    docker_environment_var = (environment_var_t *)malloc(sizeof(environment_var_t) * docker_environment_var_count);
+    if(docker_environment_var == 0) {
+        log_error("malloc failed");
+        return NTS_ERR_FAILED;
+    }
+    
+    //set env variables for network functions
+    docker_environment_var[0].name = ENV_VAR_SSH_CONNECTIONS;
+    asprintf(&docker_environment_var[0].value, "%d", framework_environment.ssh_connections);
+    docker_environment_var[1].name = ENV_VAR_TLS_CONNECTIONS;
+    asprintf(&docker_environment_var[1].value, "%d", framework_environment.tls_connections);
+    docker_environment_var[2].name = ENV_VAR_IPV6ENABLED;
+    docker_environment_var[2].value = framework_environment.ip_v6_enabled ? "true" : "false";
+    docker_environment_var[3].name = ENV_VAR_HOST_IP;
+    docker_environment_var[3].value = framework_environment.host_ip;
+    docker_environment_var[4].name = ENV_VAR_HOST_BASE_PORT;
+    // docker_environment_var[4].value = will be updated by docker_create...
+
+    return NTS_ERR_OK;
+}
+
+int docker_device_start(const manager_network_function_type *function_type, manager_network_function_instance_t *instance) {
+    assert(function_type);
+    assert(instance);
+    assert(docker_network_info);
+
+    char *image = 0;
+    if(function_type->docker_version_tag && (function_type->docker_version_tag[0] != 0)) {
+        if(function_type->docker_repository && (function_type->docker_repository[0] != 0)) {
+            asprintf(&image, "%s/%s:%s", function_type->docker_repository, function_type->docker_image_name, function_type->docker_version_tag);    
+        }
+        else {
+            asprintf(&image, "%s:%s", function_type->docker_image_name, function_type->docker_version_tag);
+        }
+    }
+    else {
+        if(function_type->docker_repository && (function_type->docker_repository[0] != 0)) {
+            asprintf(&image, "%s/%s:latest", function_type->docker_repository, function_type->docker_image_name);    
+        }
+        else {
+            asprintf(&image, "%s:latest", function_type->docker_image_name);
+        }
+    }
+
+    int rc = docker_container_create(image, instance);
+    if(rc != NTS_ERR_OK) {
+        log_error("docker_container_create failed");
+        return NTS_ERR_FAILED;
+    }
+    free(image);
+
+    rc = docker_container_start(instance);
+    if(rc != NTS_ERR_OK) {
+        log_error("docker_container_start failed");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = docker_container_inspect(instance);
+    if(rc != NTS_ERR_OK) {
+        log_error("docker_container_inspect failed");
+        return NTS_ERR_FAILED;
+    }
+
+    log_message(2, "docker_device_start: docker_id: %s | name: %s | docker_ip: %s | host_port: %d\n", instance->docker_id, instance->name, instance->docker_ip, instance->host_port);
+
+    return NTS_ERR_OK;
+}
+
+int docker_device_stop(manager_network_function_instance_t *instance) {
+    assert(instance);
+
+    char *url = 0;
+    asprintf(&url, "http://v%s/containers/%s?force=true", framework_environment.docker_engine_version, instance->docker_id);
+
+    int rc = http_socket_request(url, DOCKER_SOCK_FNAME, "DELETE", "", 0, 0);
+    free(url);
+    if(rc != NTS_ERR_OK) {
+        log_error("http_socket_request failed");
+        return NTS_ERR_FAILED;
+    }
+
+    return NTS_ERR_OK;
+}
+
+docker_usage_t docker_usage_get(const manager_network_function_type *function_type, int function_type_count) {
+    docker_usage_t ret;
+    ret.cpu = 0;
+    ret.mem = 0;
+
+    char buffer[1024];
+    char full_text[1024 * 1024];
+    FILE* pipe = popen("docker stats --no-stream --format \"table {{.ID}}|{{.CPUPerc}}|{{.MemUsage}}|\"", "r");
+    if (!pipe) {
+        log_error("popen() failed");
+        return ret;
+    }
+
+    int n = 1;
+    int k = 0;
+    while(n != 0) {
+        n = fread(buffer, 1, sizeof(buffer), pipe);
+        for(int i = 0; i < n; i++) {
+            full_text[k++] = buffer[i];
+        }
+    }
+    pclose(pipe);
+    full_text[k] = 0;
+
+    char *c = full_text;
+    
+    c = strstr(c, "\n");
+    while(c) {
+        char line[1024];
+        line[0] = 0;
+
+        char *d = strstr(c + 1, "\n");
+        if(d) {
+            for(char *i = c + 1; i < d; i++) {
+                line[i - c - 1] = *i;
+                line[i - c] = 0;
+            }
+
+            char container_name[1024];
+            char buff[1024];
+            float cpu = 0.0;
+            float mem = 0.0;
+
+            char *x = strstr(line, "|");
+            for(char *i = line; i < x; i++) {
+                container_name[i - line] = *i;
+                container_name[i - line + 1] = 0;
+            }
+
+            char *start = x + 1;
+            x = strstr(start, "|");
+            for(char *i = start; i < x; i++) {
+                if(((*i >= '0') && (*i <= '9')) || (*i == '.')) {
+                    buff[i - start] = *i;
+                }
+                else {
+                    buff[i - start] = 0;
+                    break;
+                }
+            }
+
+            cpu = strtof(buff, 0);
+
+            int mul = 1;
+            start = x + 1;
+            x = strstr(start, "|");
+            for(char *i = start; i < x; i++) {
+                if(((*i >= '0') && (*i <= '9')) || (*i == '.')) {
+                    buff[i - start] = *i;
+                }
+                else {
+                    if(*i == 'G') {
+                        mul = 1024;
+                    }
+                    buff[i - start] = 0;
+                    break;
+                }
+            }
+
+            mem = strtof(buff, 0) * mul;
+            
+            
+            if(strcmp(container_name, framework_environment.hostname) == 0) {
+                ret.cpu += cpu;
+                ret.mem += mem;
+            }
+            else {
+                for(int i = 0; i < function_type_count; i++) {
+                    for(int j = 0; j < function_type[i].started_instances; j++) {
+                        
+                        if(strcmp(container_name, function_type[i].instance[j].docker_id) == 0) {
+                            ret.cpu += cpu;
+                            ret.mem += mem;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        
+        c = d;
+    }
+
+
+    ret.cpu /= get_nprocs();
+
+    return ret;
+}
+
+static char *docker_parse_json_message(const char *json_string) {
+    assert(json_string);
+
+    cJSON *json_response = cJSON_Parse(json_string);
+    if(json_response == 0) {
+        log_error("cJSON_Parse failed");
+        return 0;
+    }
+
+    cJSON *message;
+    message = cJSON_GetObjectItem(json_response, "message");
+    if(message == 0) {
+        log_error("json parsing failed");
+        return 0;
+    }
+
+    char *ret = strdup(message->valuestring);
+    cJSON_Delete(json_response);
+    return ret;
+}
+
+static int docker_container_create(const char *image, manager_network_function_instance_t *instance) {
+    assert(image);
+    assert(instance);
+
+    cJSON *postDataJson = cJSON_CreateObject();
+    if(cJSON_AddStringToObject(postDataJson, "Image", image) == 0) {
+        log_error("could not create JSON object: Image");
+        return NTS_ERR_FAILED;
+    }
+
+    if(cJSON_AddStringToObject(postDataJson, "Hostname", instance->name) == 0) {
+        log_error("could not create JSON object: Hostname");
+        return NTS_ERR_FAILED;
+    }    
+
+    cJSON *hostConfig = cJSON_CreateObject();
+    if(hostConfig == 0) {
+        log_error("could not create JSON object: HostConfig");
+        return NTS_ERR_FAILED;
+    }
+    cJSON_AddItemToObject(postDataJson, "HostConfig", hostConfig);
+
+    cJSON *portBindings = cJSON_CreateObject();
+    if(portBindings == 0) {
+        printf("could not create JSON object: PortBindings");
+        return NTS_ERR_FAILED;
+    }
+    cJSON_AddItemToObject(hostConfig, "PortBindings", portBindings);
+    
+    for(int i = 0; i < (framework_environment.ssh_connections + framework_environment.tls_connections + framework_environment.ftp_connections + framework_environment.sftp_connections); ++i) {
+        cJSON *port = cJSON_CreateArray();
+        if(port == 0) {
+            log_error("could not create JSON object: port");
+            return NTS_ERR_FAILED;
+        }
+
+        char dockerContainerPort[20];
+        if(i < framework_environment.ssh_connections + framework_environment.tls_connections) {
+            sprintf(dockerContainerPort, "%d/tcp", STANDARD_NETCONF_PORT + i);
+        }
+        else if(i < (framework_environment.ssh_connections + framework_environment.tls_connections + framework_environment.ftp_connections)) {
+            sprintf(dockerContainerPort, "%d/tcp", STANDARD_FTP_PORT);
+        }
+        else if(i < (framework_environment.ssh_connections + framework_environment.tls_connections + framework_environment.ftp_connections + framework_environment.sftp_connections)) {
+            sprintf(dockerContainerPort, "%d/tcp", STANDARD_SFTP_PORT);
+        }
+        cJSON_AddItemToObject(portBindings, dockerContainerPort, port);
+
+        cJSON *hostPort = cJSON_CreateObject();
+        if(hostPort == 0) {
+            log_error("could not create JSON object: HostPort");
+            return NTS_ERR_FAILED;
+        }
+
+        char dockerHostPort[20];
+        sprintf(dockerHostPort, "%d", instance->host_port + i);
+        if(cJSON_AddStringToObject(hostPort, "HostPort", dockerHostPort) == 0) {
+            log_error("could not create JSON object: HostPortString");
+            return NTS_ERR_FAILED;
+        }
+
+        if(cJSON_AddStringToObject(hostPort, "HostIp", "0.0.0.0") == 0) {   //instance->host_ip
+            log_error("could not create JSON object: HostIpString");
+            return NTS_ERR_FAILED;
+        }
+
+        cJSON_AddItemToArray(port, hostPort);
+    }
+
+    
+    //environment vars start
+    asprintf(&docker_environment_var[4].value, "%d", instance->host_port);
+
+    cJSON *env_variables_array = cJSON_CreateArray();
+    if (env_variables_array == 0) {
+        log_error("Could not create JSON object: Env array");
+        return NTS_ERR_FAILED;
+    }
+    cJSON_AddItemToObject(postDataJson, "Env", env_variables_array);
+
+    for(int i = 0; i < docker_environment_var_count; i++) {
+        char *environment_var = 0;
+        asprintf(&environment_var, "%s=%s", docker_environment_var[i].name, docker_environment_var[i].value);
+
+        cJSON *env_var_obj = cJSON_CreateString(environment_var);
+        if(env_var_obj == 0) {
+            log_error("could not create JSON object");
+            return NTS_ERR_FAILED;
+        }
+        cJSON_AddItemToArray(env_variables_array, env_var_obj);
+
+        free(environment_var);
+    }
+
+    free(docker_environment_var[4].value);
+    //environment vars finished
+
+
+    cJSON *netMode = cJSON_Duplicate(docker_network_info, 1);
+    cJSON_AddItemToObject(hostConfig, "NetworkMode", netMode);
+
+    char *post_data_string = 0;
+    post_data_string = cJSON_PrintUnformatted(postDataJson);
+    cJSON_Delete(postDataJson);
+
+    char *url = 0;
+    asprintf(&url, "http:/v%s/containers/create?name=%s", framework_environment.docker_engine_version, instance->name);
+
+    char *response = 0;
+    int response_code = 0;
+    int rc = http_socket_request(url, DOCKER_SOCK_FNAME, "POST", post_data_string, &response_code, &response);
+    if(rc != NTS_ERR_OK) {
+        log_error("http_socket_request failed");
+        return NTS_ERR_FAILED;
+    }
+    free(url);
+
+    if(response_code != 201) {
+        char *message = docker_parse_json_message(response);
+        log_error("docker_container_create failed (%d): %s", response_code, message);
+        free(message);
+        free(response);
+        return NTS_ERR_FAILED;
+    }
+    else {
+        cJSON *json_response = cJSON_Parse(response);
+        free(response);
+        const cJSON *container_id = 0;
+
+        container_id = cJSON_GetObjectItemCaseSensitive(json_response, "Id");
+
+        if(cJSON_IsString(container_id) && (container_id->valuestring != 0)) {
+            char container_id_short[13];
+            memset(container_id_short, '\0', sizeof(container_id_short));
+            strncpy(container_id_short, container_id->valuestring, 12);
+
+            instance->docker_id = strdup(container_id_short);
+
+            cJSON_Delete(json_response);
+            return NTS_ERR_OK;
+        }
+        else {
+            cJSON_Delete(json_response);
+            return NTS_ERR_FAILED;
+        }
+    }
+}
+
+static int docker_container_start(manager_network_function_instance_t *instance) {
+    assert(instance);
+
+    char *url = 0;
+    asprintf(&url, "http://v%s/containers/%s/start", framework_environment.docker_engine_version, instance->docker_id);
+
+    char *response = 0;
+    int response_code = 0;
+    int rc = http_socket_request(url, DOCKER_SOCK_FNAME, "POST", "", &response_code, &response);
+    free(url);
+    if(rc != NTS_ERR_OK) {
+        log_error("http_socket_request failed");
+        return NTS_ERR_FAILED;
+    }
+    else {
+        if(response_code == 304) {
+            log_error("docker_container_start failed (%d): container already started\n", response_code);
+            free(response);
+            return NTS_ERR_FAILED;
+        }
+        else if(response_code != 204) {
+            char *message = docker_parse_json_message(response);
+            log_error("docker_container_start failed (%d): %s", response_code, message);
+            free(message);
+            free(response);
+            return NTS_ERR_FAILED;
+        }
+        
+    }
+
+    return NTS_ERR_OK;
+}
+
+static int docker_container_inspect(manager_network_function_instance_t *instance) {
+    assert(instance);
+
+    char *url = 0;
+    asprintf(&url, "http://v%s/containers/%s/json", framework_environment.docker_engine_version, instance->docker_id);
+
+    char *response = 0;    
+    int rc = http_socket_request(url, DOCKER_SOCK_FNAME, "GET", "", 0, &response);
+    free(url);
+    if(rc != NTS_ERR_OK) {
+        log_error("http_socket_request failed");
+        return NTS_ERR_FAILED;
+    }
+
+    cJSON *json_response = cJSON_Parse(response);
+    free(response);
+    if(json_response == 0) {
+        log_error("cJSON_Parse failed");
+        return NTS_ERR_FAILED;
+    }
+
+
+    cJSON *main_node = cJSON_GetObjectItem(json_response, "NetworkSettings");
+    if(main_node == 0) {
+        log_error("json parsing failed");
+        return NTS_ERR_FAILED;
+    }
+
+    cJSON *node = cJSON_GetObjectItem(main_node, "Networks");
+    if(node == 0) {
+        log_error("json parsing failed");
+        return NTS_ERR_FAILED;
+    }
+        
+    node = node->child;   //get info from the first in array
+    if(node == 0) {
+        log_error("json parsing failed");
+        return NTS_ERR_FAILED;
+    }
+
+    char *ipv6_env_var = getenv("IPv6_ENABLED");
+    if(ipv6_env_var == 0) {
+        log_error("could not get the IPv6 Enabled env variable");
+        return NTS_ERR_FAILED;
+    }
+
+    cJSON *element = cJSON_GetObjectItem(node, "IPAddress");
+    if(strcmp(ipv6_env_var, "true") == 0) {
+        element = cJSON_GetObjectItem(node, "GlobalIPv6Address");
+    }
+    else {
+        element = cJSON_GetObjectItem(node, "IPAddress");
+    } 
+
+    if(element == 0) {
+        log_error("json parsing failed");
+        return NTS_ERR_FAILED;
+    }
+    instance->docker_ip = strdup(element->valuestring);
+
+    cJSON_Delete(json_response);
+    return NTS_ERR_OK;
+}
diff --git a/ntsimulator/ntsim-ng/core/docker.h b/ntsimulator/ntsim-ng/core/docker.h
new file mode 100644 (file)
index 0000000..0185594
--- /dev/null
@@ -0,0 +1,36 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <stdbool.h>
+#include "core/app/manager.h"
+
+typedef struct {
+    float cpu;
+    float mem;
+} docker_usage_t;
+
+//init current container. used *only* with --docker-init
+bool docker_container_init(void);
+
+//docker container functions for manager
+int docker_device_init(void);
+int docker_device_start(const manager_network_function_type *function_type, manager_network_function_instance_t *instance);
+int docker_device_stop(manager_network_function_instance_t *instance);
+
+docker_usage_t docker_usage_get(const manager_network_function_type *function_type, int function_type_count);
diff --git a/ntsimulator/ntsim-ng/core/faults/faults.c b/ntsimulator/ntsim-ng/core/faults/faults.c
new file mode 100644 (file)
index 0000000..12ba223
--- /dev/null
@@ -0,0 +1,103 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "faults.h"
+#include "utils/log_utils.h"
+#include "utils/rand_utils.h"
+#include "utils/nts_utils.h"
+#include "utils/sys_utils.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+static fault_settings_t *faults = 0;
+static int fault_iterator = -1;
+
+int faults_init(void) {
+    int rc = 0;
+
+    rc = faults_ves_init();
+    if(rc != NTS_ERR_OK) {
+        log_error("faults_ves_init failed"); 
+        return NTS_ERR_FAILED; 
+    }
+
+    faults_counters_clear();
+
+    char *config_contents = file_read_content("config/config.json");
+    rc = faults_change_settings(config_contents);
+    free(config_contents);
+
+    return rc;
+}
+
+void faults_free(void) {
+    faults_ves_free();
+    faults_settings_free(faults);
+}
+
+int faults_change_settings(const char *json) {
+    assert(json);
+
+    fault_settings_t *local_faults = faults_settings_read(json);
+    if(faults) {
+        faults_settings_free(faults);
+    }
+    faults = local_faults;
+
+    return NTS_ERR_OK;
+}
+
+bool faults_get_present(void) {
+    return (faults != 0);
+}
+
+fault_details_t *faults_generate_fault(void) {
+    if(faults == 0) {
+        return 0;
+    }
+
+    switch(faults->choosing_method[0]) {
+        case 'l':
+            fault_iterator++;
+            if(fault_iterator >= faults->fault_count) {
+                fault_iterator = 0;
+            }
+
+            break;
+
+        case 'r':
+            fault_iterator = rand_uint32() % faults->fault_count;
+            break;
+
+        default:
+            log_error("invalid fault choosing method");
+            return 0;
+            break;
+    }
+
+    int rc = faults_settings_process(faults, fault_iterator);
+    if(rc != NTS_ERR_OK) {
+        log_error("faults_settings_process failed");
+        faults_settings_free(faults);
+        return 0;
+    }
+
+    return &faults->fault[fault_iterator];
+}
diff --git a/ntsimulator/ntsim-ng/core/faults/faults.h b/ntsimulator/ntsim-ng/core/faults/faults.h
new file mode 100644 (file)
index 0000000..e9f9f9f
--- /dev/null
@@ -0,0 +1,85 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <sysrepo.h>
+
+typedef struct {
+    //list of all fields, including ves mandatory
+    char **field_name;
+    char **field_value;
+    int field_count;
+
+    //mandatory ves fields
+    char *condition;
+    char *object;
+    char *severity;
+    char *date_time;
+    char *specific_problem;
+
+    //output data
+    char *yang_notif_processed;
+} fault_details_t;
+
+typedef struct {
+    char *yang_notif_template;
+    char *choosing_method;
+
+    fault_details_t *fault;
+    int fault_count;
+} fault_settings_t;
+
+typedef struct {
+    uint32_t normal;
+    uint32_t warning;
+    uint32_t minor;
+    uint32_t major;
+    uint32_t critical;
+} fault_counters_t;
+
+int faults_init(void);
+void faults_free(void);
+
+int faults_change_settings(const char *json);
+bool faults_get_present(void);                      //returns wheter faults are present or not in current config
+
+fault_details_t *faults_generate_fault(void);       //does not require freeing, does not update counters
+
+//faults_processing.c
+fault_settings_t *faults_settings_read(const char *json_plain);
+void faults_settings_free(fault_settings_t *faults);
+int faults_settings_process(fault_settings_t *faults, int fault_no);
+
+//faults_counters.c
+fault_counters_t faults_counters_get(void);             //assumes faults_lock is acquired
+void faults_counters_clear(void);                       //assumes faults_lock is acquired
+int faults_counters_increase(const char *severity);     //assumes faults_lock is acquired
+
+//faults_logic.c
+void faults_fault_list_clear(void);         //assumes faults_lock is acquired
+int faults_fault_list_add(uint16_t delay);  //assumes faults_lock is acquired
+bool faults_fault_list_not_empty(void);     //assumes faults_lock is acquired
+uint16_t faults_fault_list_get_next(void);  //assumes faults_lock is acquired
+
+//faults_ves.c
+int faults_ves_init(void);
+void faults_ves_free(void);
+
+int faults_ves_message_send(sr_session_ctx_t *session, const char *condition, const char *object, const char *severity, const char *date_time, const char *specific_problem);
diff --git a/ntsimulator/ntsim-ng/core/faults/faults_counters.c b/ntsimulator/ntsim-ng/core/faults/faults_counters.c
new file mode 100644 (file)
index 0000000..9817a18
--- /dev/null
@@ -0,0 +1,67 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "faults.h"
+#include "utils/log_utils.h"
+#include "utils/rand_utils.h"
+#include "utils/sys_utils.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+static fault_counters_t fault_counters;
+
+fault_counters_t faults_counters_get(void) {
+    return fault_counters;
+}
+
+void faults_counters_clear(void) {
+    fault_counters.normal = 0;
+    fault_counters.warning = 0;
+    fault_counters.minor = 0;
+    fault_counters.major = 0;
+    fault_counters.critical = 0;
+}
+
+int faults_counters_increase(const char *severity) {
+    assert(severity);
+
+    int ret = NTS_ERR_OK;
+    if(strcmp(severity, "NORMAL") == 0) {
+        fault_counters.normal++;
+    }
+    else if(strcmp(severity, "WARNING") == 0) {
+        fault_counters.warning++;
+    }
+    else if(strcmp(severity, "MINOR") == 0) {
+        fault_counters.minor++;
+    }
+    else if(strcmp(severity, "MAJOR") == 0) {
+        fault_counters.major++;
+    }
+    else if(strcmp(severity, "CRITICAL") == 0) {
+        fault_counters.critical++;
+    }
+    else {
+        log_error("severity not found: %s", severity);
+        ret = NTS_ERR_FAILED;
+    }
+
+    return ret;
+}
diff --git a/ntsimulator/ntsim-ng/core/faults/faults_logic.c b/ntsimulator/ntsim-ng/core/faults/faults_logic.c
new file mode 100644 (file)
index 0000000..3f1688e
--- /dev/null
@@ -0,0 +1,65 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "faults.h"
+#include "utils/log_utils.h"
+#include "utils/rand_utils.h"
+#include "utils/sys_utils.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+static uint16_t *faults_fault_list = 0;
+static uint16_t faults_fault_list_len = 0;
+static uint16_t faults_fault_list_iterator = 0;
+
+void faults_fault_list_clear(void) {
+    faults_fault_list_len = 0;
+    free(faults_fault_list);
+    faults_fault_list = 0;
+    faults_fault_list_iterator = 0;
+}
+
+int faults_fault_list_add(uint16_t delay) {
+    faults_fault_list_len++;
+    faults_fault_list = (uint16_t *)realloc(faults_fault_list, sizeof(uint16_t) * (faults_fault_list_len));
+    if(faults_fault_list == 0) {
+        log_error("realloc failed");
+        return NTS_ERR_FAILED;
+    }
+    faults_fault_list[faults_fault_list_len - 1] = delay;
+
+    return NTS_ERR_OK;
+}
+
+bool faults_fault_list_not_empty(void) {
+    return (faults_fault_list_len != 0);
+}
+
+uint16_t faults_fault_list_get_next(void) {
+    assert(faults_fault_list_iterator < faults_fault_list_len);
+
+    uint16_t ret = faults_fault_list[faults_fault_list_iterator];
+    faults_fault_list_iterator++;
+    if(faults_fault_list_iterator >= faults_fault_list_len) {
+        faults_fault_list_iterator = 0;
+    }
+
+    return ret;
+}
diff --git a/ntsimulator/ntsim-ng/core/faults/faults_processing.c b/ntsimulator/ntsim-ng/core/faults/faults_processing.c
new file mode 100644 (file)
index 0000000..032f99c
--- /dev/null
@@ -0,0 +1,462 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "faults.h"
+#include "utils/log_utils.h"
+#include "utils/sys_utils.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <cjson/cJSON.h>
+
+static char *fault_process_vars(const char *template, const fault_details_t *details);
+static char *fault_process_function(const char *function);
+
+fault_settings_t *faults_settings_read(const char *json_plain) {
+    if(json_plain == 0) {
+        return 0;
+    }
+
+    fault_settings_t *ret = (fault_settings_t *)malloc(sizeof(fault_settings_t));
+    if(ret == 0) {
+        log_error("malloc failed");
+        goto faults_settings_read_failed_cleanup;
+    }
+
+    ret->yang_notif_template = 0;
+    ret->choosing_method = 0;
+    ret->fault = 0;
+    ret->fault_count = 0;
+
+    cJSON *json = cJSON_Parse(json_plain);
+    if(!json) {
+        log_error("json parsing error: %s", cJSON_GetErrorPtr());
+        goto faults_settings_read_failed_cleanup;
+    }
+
+    cJSON *main_node = cJSON_GetObjectItem(json, "fault-rules");
+    if(main_node == 0) {
+        goto faults_settings_read_failed_cleanup;
+    }
+
+    cJSON *node = cJSON_GetObjectItem(main_node, "yang-notif-template");
+    if(node && cJSON_IsString(node)) {
+        ret->yang_notif_template = strdup(node->valuestring);
+    }
+    else {
+        log_error("could not find yang-notif-template");
+        goto faults_settings_read_failed_cleanup;
+    }
+
+    node = cJSON_GetObjectItem(main_node, "choosing-method");
+    if(node && cJSON_IsString(node)) {
+        ret->choosing_method = strdup(node->valuestring);
+    }
+    else {
+        log_error("could not find choosing-method");
+        goto faults_settings_read_failed_cleanup;
+    }
+
+    node = cJSON_GetObjectItem(main_node, "faults");
+    if(node && cJSON_IsArray(node)) {
+        cJSON *fault_detail;
+        cJSON_ArrayForEach(fault_detail, node) {
+            cJSON *object;
+            ret->fault_count++;
+            ret->fault = (fault_details_t *)realloc(ret->fault, sizeof(fault_details_t)*ret->fault_count);
+            if(ret->fault == 0) {
+                ret->fault_count--;
+                log_error("realloc failed");
+                goto faults_settings_read_failed_cleanup;
+            }
+
+            ret->fault[ret->fault_count - 1].condition = 0;
+            ret->fault[ret->fault_count - 1].object = 0;
+            ret->fault[ret->fault_count - 1].severity = 0;
+            ret->fault[ret->fault_count - 1].date_time = 0;
+            ret->fault[ret->fault_count - 1].specific_problem = 0;
+            ret->fault[ret->fault_count - 1].field_name = 0;
+            ret->fault[ret->fault_count - 1].field_value = 0;
+            ret->fault[ret->fault_count - 1].field_count = 0;
+            ret->fault[ret->fault_count - 1].yang_notif_processed = 0;
+
+            cJSON_ArrayForEach(object, fault_detail) {
+                ret->fault[ret->fault_count - 1].field_count++;
+                ret->fault[ret->fault_count - 1].field_name = (char **)realloc(ret->fault[ret->fault_count - 1].field_name, sizeof(char*) * ret->fault[ret->fault_count - 1].field_count);
+                if(ret->fault[ret->fault_count - 1].field_name == 0) {
+                    ret->fault[ret->fault_count - 1].field_count--;
+                    log_error("realloc failed");
+                    goto faults_settings_read_failed_cleanup;
+                }
+
+                ret->fault[ret->fault_count - 1].field_value = (char **)realloc(ret->fault[ret->fault_count - 1].field_value, sizeof(char*) * ret->fault[ret->fault_count - 1].field_count);
+                if(ret->fault[ret->fault_count - 1].field_value == 0) {
+                    ret->fault[ret->fault_count - 1].field_count--;
+                    log_error("realloc failed");
+                    goto faults_settings_read_failed_cleanup;
+                }
+
+                asprintf(&ret->fault[ret->fault_count - 1].field_name[ret->fault[ret->fault_count - 1].field_count - 1], "%%%%%s%%%%", object->string);
+                ret->fault[ret->fault_count - 1].field_value[ret->fault[ret->fault_count - 1].field_count - 1] = strdup(object->valuestring);
+            }
+        }
+    }
+    else {
+        log_error("could not find faults list");
+        goto faults_settings_read_failed_cleanup;
+    }
+
+    cJSON_free(json);
+    return ret;
+
+    faults_settings_read_failed_cleanup:
+    faults_settings_free(ret);
+    cJSON_free(json);
+    return 0;
+}
+
+void faults_settings_free(fault_settings_t *faults) {
+    if(faults) {
+        free(faults->yang_notif_template);
+        free(faults->choosing_method);
+
+        for(int i = 0; i < faults->fault_count; i++) {
+            free(faults->fault[i].condition);
+            free(faults->fault[i].object);
+            free(faults->fault[i].severity);
+            free(faults->fault[i].date_time);
+            free(faults->fault[i].specific_problem);
+
+            for(int j = 0; j < faults->fault[i].field_count; j++) {
+                free(faults->fault[i].field_name[j]);
+                free(faults->fault[i].field_value[j]);
+            }
+            free(faults->fault[i].field_name);
+            free(faults->fault[i].field_value);
+
+            free(faults->fault[i].yang_notif_processed);
+        }
+    }
+}
+
+int faults_settings_process(fault_settings_t *faults, int fault_no) {
+    assert(faults);
+    assert(fault_no < faults->fault_count);
+
+    free(faults->fault[fault_no].condition);
+    free(faults->fault[fault_no].object);
+    free(faults->fault[fault_no].severity);
+    free(faults->fault[fault_no].date_time);
+    free(faults->fault[fault_no].specific_problem);
+    free(faults->fault[fault_no].yang_notif_processed);
+
+    faults->fault[fault_no].condition = 0;
+    faults->fault[fault_no].object = 0;
+    faults->fault[fault_no].severity = 0;
+    faults->fault[fault_no].date_time = 0;
+    faults->fault[fault_no].specific_problem = 0;
+    faults->fault[fault_no].yang_notif_processed = 0;
+    
+    for(int j = 0; j < faults->fault[fault_no].field_count; j++) {
+        if(strcmp(faults->fault[fault_no].field_name[j], "%%condition%%") == 0) {
+            faults->fault[fault_no].condition = fault_process_vars(faults->fault[fault_no].field_value[j], &faults->fault[fault_no]);
+        }
+        else if(strcmp(faults->fault[fault_no].field_name[j], "%%object%%") == 0) {
+            faults->fault[fault_no].object = fault_process_vars(faults->fault[fault_no].field_value[j], &faults->fault[fault_no]);
+        }
+        else if(strcmp(faults->fault[fault_no].field_name[j], "%%severity%%") == 0) {
+            faults->fault[fault_no].severity = fault_process_vars(faults->fault[fault_no].field_value[j], &faults->fault[fault_no]);
+        }
+        else if(strcmp(faults->fault[fault_no].field_name[j], "%%date-time%%") == 0) {
+            faults->fault[fault_no].date_time = fault_process_vars(faults->fault[fault_no].field_value[j], &faults->fault[fault_no]);
+        }
+        else if(strcmp(faults->fault[fault_no].field_name[j], "%%specific-problem%%") == 0) {
+            faults->fault[fault_no].specific_problem = fault_process_vars(faults->fault[fault_no].field_value[j], &faults->fault[fault_no]);
+        }
+    }
+
+    faults->fault[fault_no].yang_notif_processed = fault_process_vars(faults->yang_notif_template, &faults->fault[fault_no]);
+
+    if(faults->fault[fault_no].condition == 0) {
+        log_error("could not find condition in fault");
+        return NTS_ERR_FAILED;
+    }
+
+    if(faults->fault[fault_no].object == 0) {
+        log_error("could not find object in fault");
+        return NTS_ERR_FAILED;
+    }
+
+    if(faults->fault[fault_no].severity == 0) {
+        log_error("could not find severity in fault");
+        return NTS_ERR_FAILED;
+    }
+
+    if(faults->fault[fault_no].date_time == 0) {
+        log_error("could not find date_time in fault");
+        return NTS_ERR_FAILED;
+    }
+
+    if(faults->fault[fault_no].specific_problem == 0) {
+        log_error("could not find specific_problem in fault");
+        return NTS_ERR_FAILED;
+    }
+
+    if(faults->fault[fault_no].yang_notif_processed == 0) {
+        log_error("could not find yang_notif_processed in fault");
+        return NTS_ERR_FAILED;
+    }
+
+    return NTS_ERR_OK;
+}
+
+static char *fault_process_vars(const char *template, const fault_details_t *details) {
+    assert(template);
+    assert(details);
+
+    char *ret = strdup(template);
+    if(ret == 0) {
+        log_error("strdup error");
+        return 0;
+    }
+
+    //if template is blank, do not process anything, means nc notif disabled
+    if(ret[0] == 0) {
+        return ret;
+    }
+
+    char **vars = 0;
+    int vars_count = 0;
+    
+    char **funcs = 0;
+    int funcs_count = 0;
+
+    char *var = 0;
+    char *func = 0;
+
+    //do replacements until no replacement is done
+    int replaced = 1;
+    while(replaced) {
+        replaced = 0;
+
+        var = 0;
+        vars = 0;
+        vars_count = 0;
+        func = 0;
+        funcs = 0;
+        funcs_count = 0;
+
+        char *pos_start;
+
+        //look for vars
+        pos_start = strstr(ret, "%%");
+        while(pos_start) {
+            char *pos_end = strstr(pos_start + 2, "%%");
+            int var_size = pos_end - pos_start + 2;
+            var = (char *)malloc(sizeof(char) * (var_size + 1));
+            if(var == 0) {
+                log_error("bad malloc");
+                goto fault_process_vars_failed;
+            }
+
+            for(int i = 0; i < var_size; i++) {
+                var[i] = pos_start[i];
+            }
+            var[var_size] = 0;
+
+            // found var
+            vars_count++;
+            vars = (char **)realloc(vars, sizeof(char *) * vars_count);
+            if(!vars) {
+                vars_count = 0;
+                log_error("bad malloc");
+                goto fault_process_vars_failed;
+            }
+
+            vars[vars_count - 1] = strdup(var);
+            if(!vars[vars_count - 1]) {
+                vars_count--;
+                log_error("bad malloc");
+                goto fault_process_vars_failed;
+            }
+            free(var);
+            var = 0;
+
+            pos_start = strstr(pos_end + 2, "%%");
+        }
+
+        //look for functions
+        pos_start = strstr(ret, "$$");
+        while(pos_start) {
+            char *pos_end = strstr(pos_start + 2, "$$");
+            int func_size = pos_end - pos_start + 2;
+            func = (char *)malloc(sizeof(char) * (func_size + 1));
+            if(func == 0) {
+                log_error("bad malloc");
+                goto fault_process_vars_failed;
+            }
+
+            for(int i = 0; i < func_size; i++) {
+                func[i] = pos_start[i];
+            }
+            func[func_size] = 0;
+
+            // found func
+            funcs_count++;
+            funcs = (char **)realloc(funcs, sizeof(char *) * funcs_count);
+            if(!funcs) {
+                funcs_count = 0;
+                log_error("bad malloc");
+                goto fault_process_vars_failed;
+            }
+
+            funcs[funcs_count - 1] = strdup(func);
+            if(!funcs[funcs_count - 1]) {
+                funcs_count--;
+                log_error("bad malloc");
+                goto fault_process_vars_failed;
+            }
+            free(func);
+            func = 0;
+
+            pos_start = strstr(pos_end + 2, "$$");
+        }
+
+        //replace vars
+        for(int i = 0; i < vars_count; i++) {
+            char *var_value = 0;
+            for(int j = 0; j < details->field_count; j++) {
+                if(strcmp(details->field_name[j], vars[i]) == 0) {
+                    var_value = strdup(details->field_value[j]);
+                }
+            }
+
+            if(var_value == 0) {
+                log_error("value %s not found", vars[i]);
+                goto fault_process_vars_failed;
+            }
+
+            ret = str_replace(ret, vars[i], var_value);
+            if(ret == 0) {
+                free(var_value);
+                var_value = 0;
+                goto fault_process_vars_failed;
+            }
+
+            free(var_value);
+            var_value = 0;
+            replaced++;
+        }
+
+        //replace functions
+        for(int i = 0; i < funcs_count; i++) {
+            char *func_value = fault_process_function(funcs[i]);
+            if(func_value == 0) {
+                log_error("function %s not found", vars[i]);
+                goto fault_process_vars_failed;
+            }
+
+            ret = str_replace(ret, funcs[i], func_value);
+            if(ret == 0) {
+                free(func_value);
+                goto fault_process_vars_failed;
+            }
+
+            free(func_value);
+            func_value = 0;
+            replaced++;
+        }
+
+        for(int i = 0; i < vars_count; i++) {
+            free(vars[i]);
+        }
+        free(vars);
+        vars = 0;
+        vars_count = 0;
+
+        for(int i = 0; i < funcs_count; i++) {
+            free(funcs[i]);
+        }
+        free(funcs);
+        funcs = 0;
+        funcs_count = 0;
+    }
+
+
+    free(var);
+    free(func);
+    for(int i = 0; i < vars_count; i++) {
+        free(vars[i]);
+    }
+    free(vars);
+
+    for(int i = 0; i < funcs_count; i++) {
+        free(funcs[i]);
+    }
+    free(funcs);
+    return ret;
+
+    fault_process_vars_failed:
+    free(var);
+    free(func);
+
+    for(int i = 0; i < vars_count; i++) {
+        free(vars[i]);
+    }
+    free(vars);
+
+    for(int i = 0; i < funcs_count; i++) {
+        free(funcs[i]);
+    }
+    free(funcs);
+    return 0;
+}
+
+static char *fault_process_function(const char *function) {
+    assert(function);
+
+    static uint8_t uint8_counter = 0;
+    static uint16_t uint16_counter = 0;
+    static uint32_t uint32_counter = 0;
+
+    if(strcmp(function, "$$time$$") == 0) {
+        return get_current_date_and_time();
+    }
+    else if(strcmp(function, "$$uint8_counter$$") == 0) {
+        char *ret = 0;
+        asprintf(&ret, "%d", uint8_counter);
+        uint8_counter++;
+        return ret;
+    }
+    else if(strcmp(function, "$$uint16_counter$$") == 0) {
+        char *ret = 0;
+        asprintf(&ret, "%d", uint16_counter);
+        uint16_counter++;
+        return ret;
+    }
+    else if(strcmp(function, "$$uint32_counter$$") == 0) {
+        char *ret = 0;
+        asprintf(&ret, "%d", uint32_counter);
+        uint32_counter++;
+        return ret;
+    }
+
+    return 0;
+}
diff --git a/ntsimulator/ntsim-ng/core/faults/faults_ves.c b/ntsimulator/ntsim-ng/core/faults/faults_ves.c
new file mode 100644 (file)
index 0000000..e95deed
--- /dev/null
@@ -0,0 +1,236 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "faults.h"
+#include "utils/log_utils.h"
+#include "utils/rand_utils.h"
+#include "utils/nts_utils.h"
+#include "utils/sys_utils.h"
+#include "utils/http_client.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "core/framework.h"
+#include <cjson/cJSON.h>
+
+static uint32_t *fault_ves_sequence_number = 0;
+
+static cJSON *ves_create_fault_fields(const char *alarm_condition, const char *alarm_object, const char *severity, const char *date_time, const char *specific_problem);
+static int ves_message_send_internal(sr_session_ctx_t *session, const char *condition, const char *object, const char *severity, const char *date_time, const char *specific_problem, int port, uint32_t *seq_id);
+
+int faults_ves_init(void) {
+    fault_ves_sequence_number = (uint32_t *)malloc(sizeof(uint32_t) * (framework_environment.ssh_connections + framework_environment.tls_connections));
+    if(fault_ves_sequence_number == 0) {
+        log_error("malloc failed"); 
+        return NTS_ERR_FAILED; 
+    }
+
+    for(int i = 0; i < (framework_environment.ssh_connections + framework_environment.tls_connections); i++) {
+        fault_ves_sequence_number[i] = 0;
+    }
+
+    return NTS_ERR_OK;
+}
+
+void faults_ves_free(void) {
+    free(fault_ves_sequence_number);
+    fault_ves_sequence_number = 0;
+}
+
+int faults_ves_message_send(sr_session_ctx_t *session, const char *condition, const char *object, const char *severity, const char *date_time, const char *specific_problem) {
+    assert(condition);
+    assert(object);
+    assert(severity);
+    assert(date_time);
+    assert(specific_problem);
+
+    nts_mount_point_addressing_method_t mp = nts_mount_point_addressing_method_get(session);
+    if(mp == UNKNOWN_MAPPING) {
+        log_error("mount-point-addressing-method failed");
+        return NTS_ERR_FAILED;
+    }
+
+    int base_port = STANDARD_NETCONF_PORT;
+    if(mp == HOST_MAPPING) {
+        base_port = framework_environment.host_base_port;
+    }
+
+    for(int port = base_port; port < base_port + (framework_environment.ssh_connections + framework_environment.tls_connections); port++) {
+        uint32_t *seq_id = &fault_ves_sequence_number[port - base_port];
+        int rc = ves_message_send_internal(session, condition, object, severity, date_time, specific_problem, port, seq_id);
+        if(rc != NTS_ERR_OK) {
+            log_error("ves_message_send_internal failed");
+        }
+    }
+
+    return NTS_ERR_OK;
+}
+
+static cJSON *ves_create_fault_fields(const char *alarm_condition, const char *alarm_object, const char *severity, const char *date_time, const char *specific_problem) {
+    assert(alarm_condition);
+    assert(alarm_object);
+    assert(severity);
+    assert(date_time);
+    assert(specific_problem);
+    
+    cJSON *faultFields = cJSON_CreateObject();
+    if(faultFields == 0) {
+        log_error("could not create JSON object: faultFields");
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(faultFields, "faultFieldsVersion", "4.0") == 0) {
+        log_error("could not create JSON object: faultFieldsVersion");
+        cJSON_Delete(faultFields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(faultFields, "alarmCondition", alarm_condition) == 0) {
+        log_error("could not create JSON object: alarmCondition");
+        cJSON_Delete(faultFields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(faultFields, "alarmInterfaceA", alarm_object) == 0) {
+        log_error("could not create JSON object: alarmInterfaceA");
+        cJSON_Delete(faultFields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(faultFields, "eventSourceType", "O_RAN_COMPONENT") == 0) {
+        log_error("could not create JSON object: eventSourceType");
+        cJSON_Delete(faultFields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(faultFields, "specificProblem", specific_problem) == 0) {
+        log_error("could not create JSON object: specificProblem");
+        cJSON_Delete(faultFields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(faultFields, "eventSeverity", severity) == 0) {
+        log_error("could not create JSON object: eventSeverity");
+        cJSON_Delete(faultFields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(faultFields, "vfStatus", "Active") == 0) {
+        log_error("could not create JSON object: vfStatus");
+        cJSON_Delete(faultFields);
+        return 0;
+    }
+
+    cJSON *alarmAdditionalInformation = cJSON_CreateObject();
+    if(alarmAdditionalInformation == 0) {
+        log_error("could not create JSON object: alarmAdditionalInformation");
+        cJSON_Delete(faultFields);
+        return 0;
+    }
+    cJSON_AddItemToObject(faultFields, "alarmAdditionalInformation", alarmAdditionalInformation);
+
+    if(cJSON_AddStringToObject(alarmAdditionalInformation, "eventTime", date_time) == 0) {
+        log_error("could not create JSON object: eventTime");
+        cJSON_Delete(faultFields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(alarmAdditionalInformation, "equipType", "O-RAN-sim") == 0) {
+        log_error("could not create JSON object: equipType");
+        cJSON_Delete(faultFields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(alarmAdditionalInformation, "vendor", "Melacon") == 0) {
+        log_error("could not create JSON object: vendor");
+        cJSON_Delete(faultFields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(alarmAdditionalInformation, "model", "Simulated Device") == 0) {
+        log_error("could not create JSON object: model");
+        cJSON_Delete(faultFields);
+        return 0;
+    }
+
+    return faultFields;
+}
+
+static int ves_message_send_internal(sr_session_ctx_t *session, const char *condition, const char *object, const char *severity, const char *date_time, const char *specific_problem, int port, uint32_t *seq_id) {
+    assert(condition);
+    assert(object);
+    assert(severity);
+    assert(date_time);
+    assert(specific_problem);
+
+    char *hostname_string = framework_environment.hostname;
+    cJSON *post_data_json = cJSON_CreateObject();
+    if(post_data_json == 0) {
+        log_error("cJSON_CreateObject failed");
+        return NTS_ERR_FAILED;
+    }
+
+    cJSON *event = cJSON_CreateObject();
+    if(event == 0) {
+        log_error("cJSON_CreateObject failed");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+    cJSON_AddItemToObject(post_data_json, "event", event);
+
+    char *source_name = 0;
+    asprintf(&source_name, "%s-%d", hostname_string, port);
+    cJSON *common_event_header = ves_create_common_event_header("fault", "O_RAN_COMPONENT_Alarms", source_name, "Low", (*seq_id)++);
+    free(source_name);
+
+    if(common_event_header == 0) {
+        log_error("ves_create_common_event_header failed");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+    cJSON_AddItemToObject(event, "commonEventHeader", common_event_header);
+
+    cJSON *fault_fields = ves_create_fault_fields(condition, object, severity, date_time, specific_problem);
+    if(fault_fields == 0) {
+        log_error("ves_create_fault_fields failed");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+    cJSON_AddItemToObject(event, "faultFields", fault_fields);
+
+    char *post_data = cJSON_PrintUnformatted(post_data_json);
+    ves_details_t *ves_details = ves_endpoint_details_get(session);
+    if(!ves_details) {
+        log_error("ves_endpoint_details_get failed");
+        return NTS_ERR_FAILED;
+    }
+    
+    int rc = http_request(ves_details->url, ves_details->username, ves_details->password, "POST", post_data, 0, 0);
+    ves_details_free(ves_details);
+    cJSON_Delete(post_data_json);
+    free(post_data);
+    
+    if(rc != NTS_ERR_OK) {
+        log_error("http_request failed");
+        return NTS_ERR_FAILED;
+    }
+
+    return NTS_ERR_OK;
+}
diff --git a/ntsimulator/ntsim-ng/core/framework.c b/ntsimulator/ntsim-ng/core/framework.c
new file mode 100644 (file)
index 0000000..499f97d
--- /dev/null
@@ -0,0 +1,650 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "framework.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <limits.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <cjson/cJSON.h>
+
+#include "utils/sys_utils.h"
+#include "utils/log_utils.h"
+#include "utils/rand_utils.h"
+
+framework_arguments_t framework_arguments;
+framework_config_t framework_config;
+framework_environment_t framework_environment;
+
+const char *argp_program_version = "ntsim-ng v0.0.1a";
+const char *argp_program_bug_address = "<alexandru.stancu@highstreet-technologies.com> / <adrian.lita@highstreet-technologies.com>";
+static char doc[] = "ntsim - new generation";
+
+static struct argp_option options[] = {
+    // docker init functionality, independent from rest of the app
+    { "docker-init", 'i', 0, 0, "Runs initialization tasks for the Docker container that's being built. Do not run manually." },
+
+    // daemon modes (choose only one)
+    { "manager", 'm', 0, 0, "Run the daemon as manager." },
+    { "network-function", 'f', 0, 0, "Run the daemon as network function." },
+
+    // global settings, can be combined
+    { "operational-only", 'o', 0, 0, "When this is set, the RUNNING datastore is actually the OPERATIONAL one." },
+    { "fixed-rand", 'r', "SEED", 0, "Initialize RAND seed to a fixed value (for debugging purposes)." },
+    { "verbose", 'v', "LEVEL", 0, "Verbosity level for printing to stdout (logs will still save everything). LEVEL is: 0=errors only, 1=requested info(default), 2=info" },
+    { "workspace", 'w', "PATH", 0, "Initialize workspace to a different one than the current working directory." },
+
+    // test modes (choose only one)
+    { "test-mode", 't', 0, 0, "Test mode to be deleted after." },
+    { "exhaustive-test", '0', 0, 0, "Do an automated test on the whole delpoy." },
+
+    // functions, can be combined
+    { "ls", '1', 0, 0, "Print all available root paths." },
+    { "schema", '2', "XPATH", 0, "Print schema for XPATH." },
+    { "populate", '3', 0, 0, "Populate everything." },
+    { "enable-features", '4', 0, 0, "Enables features. Usually works combined with populate." },
+
+    // function settings, can be combined with functions as well
+    { "nc-server-init", 'n', 0, 0, "Sets netconf server configuration." },
+    { "loop", 'l', 0, 0, "After doing the job, don't exit until CTRL+C is pressed." },
+    { 0 } 
+};
+
+volatile sig_atomic_t framework_sigint;
+static void framework_signal_handler(int signo);
+
+static error_t parse_opt(int key, char *arg, struct argp_state *state);
+
+void framework_init(int argc, char **argv) {
+    //initialize app arguments
+    framework_arguments.container_init = false;
+    framework_arguments.nc_server_init = false;
+
+    framework_arguments.manager = false;
+    framework_arguments.network_function = false;
+    
+    framework_arguments.no_rand = false;
+    framework_arguments.fixed_seed = 0;
+    framework_arguments.operational_only = false;
+    framework_arguments.verbosity_level = 1;
+    framework_arguments.loop = false;
+    framework_arguments.test_mode = false;
+    
+    framework_arguments.exhaustive_test = false;
+    framework_arguments.print_root_paths = false;
+    framework_arguments.print_structure_xpath = 0;
+    framework_arguments.populate_all = false;
+    framework_arguments.enable_features = false;
+
+    framework_sigint = 0;
+    signal(SIGINT, framework_signal_handler);
+    signal(SIGTERM, framework_signal_handler);
+    signal(SIGKILL, framework_signal_handler);
+    signal(SIGQUIT, framework_signal_handler);
+
+    //parse provided command line arguments
+    struct argp argp = { options, parse_opt, 0, doc, 0, 0, 0 };
+    argp_parse(&argp, argc, argv, 0, 0, &framework_arguments);
+
+    //disable buffering for stdout
+    setbuf(stdout, NULL);
+
+    int status = 0;
+
+    //test whether log and config folders are ok
+    if(!dir_exists("config")) {
+        status |= 1;
+        mkdir("config", 0777);
+    }
+
+    if(!dir_exists("log")) {
+        status |= 2;
+        mkdir("log", 0777);
+    }
+
+    //init logging subsystem
+    log_init("log/log.txt");
+    log_message(2, "app was called: ");
+    for(int i = 0; i < argc; i++) {
+        log_message(2, "%s ", argv[i]);
+    }
+    log_message(2, "\n");
+
+    char cwd[PATH_MAX];
+    getcwd(cwd, sizeof(cwd));
+    log_message(2, "current working dir is: %s\n", cwd);
+
+    if(status & 1) {
+        log_message(2, "config folder wasn't found, and was created.\n");
+    }
+
+    if(status & 2) {
+        log_message(2, "log folder wasn't found, and was created.\n");
+    }
+
+    if(!file_exists("config/config.json")) {
+        log_message(2, "config.json file missing. created.\n");
+        file_touch("config/config.json", "{}");
+    }
+
+    //init rand generator if needed
+    if(framework_arguments.no_rand == false) {
+        rand_init();
+    }
+    else {
+        rand_init_fixed(framework_arguments.fixed_seed);
+    }
+
+    //init app config
+    framework_config.docker_excluded_modules = 0;
+    framework_config.docker_excluded_modules_count = 0;
+    framework_config.docker_excluded_features = 0;
+    framework_config.docker_excluded_features_count = 0;
+    framework_config.debug_max_string_size = 0;
+    framework_config.populate_excluded_modules = 0;
+    framework_config.populate_excluded_modules_count = 0;
+    framework_config.default_list_instances = 1;
+    framework_config.custom_list_instances_count = 0;
+    framework_config.custom_list_instances = 0;
+    framework_config.restrict_schema_count = 0;
+    framework_config.restrict_schema = 0;
+
+    log_message(2, "starting parsing config.json\n");
+    char *config_contents = file_read_content("config/config.json");
+    cJSON *json = cJSON_Parse(config_contents);
+    free(config_contents);
+    if(!json) {
+        log_error("config.json :%s", cJSON_GetErrorPtr());
+    }
+    else {
+        cJSON *main_node;
+        cJSON *node;
+
+        main_node = cJSON_GetObjectItem(json, "docker-rules");
+        if(main_node) {
+            node = cJSON_GetObjectItem(main_node, "excluded-modules");
+            if(node) {
+                if(cJSON_IsArray(node)) {
+                    cJSON *element;
+                    cJSON_ArrayForEach(element, node) {
+                        if(cJSON_IsString(element)) {
+                            log_message(2, "adding docker-rules/exclude-modules: %s\n", element->valuestring);
+                            framework_config.docker_excluded_modules = (char **)realloc(framework_config.docker_excluded_modules, sizeof(char*) * (framework_config.docker_excluded_modules_count + 1));
+                            if(!framework_config.docker_excluded_modules) {
+                                log_error("bad realloc");
+                            }
+                            framework_config.docker_excluded_modules[framework_config.docker_excluded_modules_count] = (char *)malloc(sizeof(char) * (strlen(element->valuestring) + 1));
+                            if(!framework_config.docker_excluded_modules[framework_config.docker_excluded_modules_count]) {
+                                log_error("bad malloc");
+                            }
+                            strcpy(framework_config.docker_excluded_modules[framework_config.docker_excluded_modules_count], element->valuestring);
+                            framework_config.docker_excluded_modules_count++;
+                        }
+                    }
+                }
+            }
+
+            node = cJSON_GetObjectItem(main_node, "excluded-features");
+            if(node) {
+                if(cJSON_IsArray(node)) {
+                    cJSON *element;
+                    cJSON_ArrayForEach(element, node) {
+                        if(cJSON_IsString(element)) {
+                            log_message(2, "adding docker-rules/excluded-features: %s\n", element->valuestring);
+                            framework_config.docker_excluded_features = (char **)realloc(framework_config.docker_excluded_features, sizeof(char*) * (framework_config.docker_excluded_features_count + 1));
+                            if(!framework_config.docker_excluded_features) {
+                                log_error("bad realloc");
+                            }
+                            framework_config.docker_excluded_features[framework_config.docker_excluded_features_count] = (char *)malloc(sizeof(char) * (strlen(element->valuestring) + 1));
+                            if(!framework_config.docker_excluded_features[framework_config.docker_excluded_features_count]) {
+                                log_error("bad malloc");
+                            }
+                            strcpy(framework_config.docker_excluded_features[framework_config.docker_excluded_features_count], element->valuestring);
+                            framework_config.docker_excluded_features_count++;
+                        }
+                    }
+                }
+            }
+        }
+
+        main_node = cJSON_GetObjectItem(json, "debug-max-string-size");
+        if(main_node) {
+            framework_config.debug_max_string_size = main_node->valueint;
+            log_message(2, "setting debug-max-string-sizes: %d\n", framework_config.debug_max_string_size);
+        }
+
+        main_node = cJSON_GetObjectItem(json, "populate-rules");
+        if(main_node) {
+            node = cJSON_GetObjectItem(main_node, "excluded-modules");
+            if(node) {
+                if(cJSON_IsArray(node)) {
+                    cJSON *element;
+                    cJSON_ArrayForEach(element, node) {
+                        if(cJSON_IsString(element)) {
+                            log_message(2, "adding populate-rules/excluded-modules: %s\n", element->valuestring);
+                            framework_config.populate_excluded_modules = (char **)realloc(framework_config.populate_excluded_modules, sizeof(char*) * (framework_config.populate_excluded_modules_count + 1));
+                            if(!framework_config.populate_excluded_modules) {
+                                log_error("bad realloc");
+                            }
+                            framework_config.populate_excluded_modules[framework_config.populate_excluded_modules_count] = (char *)malloc(sizeof(char) * (strlen(element->valuestring) + 1));
+                            if(!framework_config.populate_excluded_modules[framework_config.populate_excluded_modules_count]) {
+                                log_error("bad malloc");
+                            }
+                            strcpy(framework_config.populate_excluded_modules[framework_config.populate_excluded_modules_count], element->valuestring);
+                            framework_config.populate_excluded_modules_count++;
+                        }
+                    }
+                }
+            }
+
+            node = cJSON_GetObjectItem(main_node, "default-list-instances");
+            if(node) {
+                if(cJSON_IsNumber(node)) {
+                    framework_config.default_list_instances = node->valueint;
+                    log_message(2, "found populate-rules/default-list-instances to be: %d\n", framework_config.default_list_instances);
+                }
+            }
+
+            node = cJSON_GetObjectItem(main_node, "custom-list-instances");
+            if(node) {
+                if(cJSON_IsArray(node)) {
+                    cJSON *element;
+                    cJSON_ArrayForEach(element, node) {
+                        if(cJSON_IsObject(element)) {
+                            cJSON *object;
+                            cJSON_ArrayForEach(object, element) {
+                                char *path = object->string;
+                                int count = object->valueint;
+                                log_message(2, "adding populate-rules/custom-list-instances %s - %d\n", path, count);
+                                framework_config.custom_list_instances = (custom_list_instances_t *)realloc(framework_config.custom_list_instances, sizeof(custom_list_instances_t) * (framework_config.custom_list_instances_count + 1));
+                                if(!framework_config.custom_list_instances) {
+                                    log_error("bad realloc");
+                                }
+                                
+                                framework_config.custom_list_instances[framework_config.custom_list_instances_count].path = (char *)malloc(sizeof(char) * (strlen(path) + 1));
+                                if(!framework_config.custom_list_instances[framework_config.custom_list_instances_count].path) {
+                                    log_error("bad malloc");
+                                }
+                                strcpy(framework_config.custom_list_instances[framework_config.custom_list_instances_count].path, path);
+                                framework_config.custom_list_instances[framework_config.custom_list_instances_count].count = count;
+                                framework_config.custom_list_instances_count++;
+                            }
+                        }
+                    }
+                }
+            }
+
+            node = cJSON_GetObjectItem(main_node, "restrict-schema");
+            if(node) {
+                if(cJSON_IsArray(node)) {
+                    cJSON *element;
+                    cJSON_ArrayForEach(element, node) {
+                        if(cJSON_IsObject(element)) {
+                            cJSON *object;
+                            cJSON_ArrayForEach(object, element) {
+                                char *path = object->string;
+
+                                log_message(2, "adding populate-rules/restrict-schema: %s with values:", path);
+                                framework_config.restrict_schema = (restrict_schema_t *)realloc(framework_config.restrict_schema, sizeof(restrict_schema_t) * (framework_config.restrict_schema_count + 1));
+                                if(!framework_config.restrict_schema) {
+                                    log_error("bad realloc");
+                                }
+                                
+                                framework_config.restrict_schema[framework_config.restrict_schema_count].path = (char *)malloc(sizeof(char) * (strlen(path) + 1));
+                                if(!framework_config.restrict_schema[framework_config.restrict_schema_count].path) {
+                                    log_error("bad malloc");
+                                }
+                                strcpy(framework_config.restrict_schema[framework_config.restrict_schema_count].path, path);
+
+
+                                framework_config.restrict_schema[framework_config.restrict_schema_count].values_count = 0;
+                                framework_config.restrict_schema[framework_config.restrict_schema_count].values = 0;
+                                framework_config.restrict_schema[framework_config.restrict_schema_count].index = 0;
+                                cJSON *value;
+                                cJSON_ArrayForEach(value, object) {
+                                    if(cJSON_IsString(value)) {
+                                        framework_config.restrict_schema[framework_config.restrict_schema_count].values = (char **)realloc(framework_config.restrict_schema[framework_config.restrict_schema_count].values, sizeof(char*) * (framework_config.restrict_schema[framework_config.restrict_schema_count].values_count + 1));
+                                        if(!framework_config.restrict_schema[framework_config.restrict_schema_count].values) {
+                                            log_error("bad realloc");
+                                        }
+                                        framework_config.restrict_schema[framework_config.restrict_schema_count].values[framework_config.restrict_schema[framework_config.restrict_schema_count].values_count] = (char *)malloc(sizeof(char) * (strlen(value->valuestring) + 1));
+                                        if(!framework_config.restrict_schema[framework_config.restrict_schema_count].values[framework_config.restrict_schema[framework_config.restrict_schema_count].values_count]) {
+                                            log_error("bad malloc");
+                                        }
+                                        strcpy(framework_config.restrict_schema[framework_config.restrict_schema_count].values[framework_config.restrict_schema[framework_config.restrict_schema_count].values_count], value->valuestring);
+                                        framework_config.restrict_schema[framework_config.restrict_schema_count].values_count++;
+
+                                        log_message(2, " %s", value->valuestring);
+                                    }
+                                }
+                                log_message(2, "\n");
+
+                                framework_config.restrict_schema_count++;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        cJSON_free(json);
+        
+    }
+    log_message(2, "finished parsing config.json\n");
+
+    //environment vars
+    bool ip_ok = get_local_ips("eth0", &framework_environment.ip_v4, &framework_environment.ip_v6);
+    if(!ip_ok) {
+        log_error("could not get local IP addresses");
+    }
+
+    char *ipv6_env_var = getenv(ENV_VAR_IPV6ENABLED);
+    if(ipv6_env_var == 0) {
+        log_error("could not get the IPv6 Enabled env variable");
+    }
+    framework_environment.ip_v6_enabled = (strcmp(ipv6_env_var, "true") == 0) ? true : false;
+
+
+    framework_environment.docker_engine_version = getenv(ENV_VAR_DOCKER_ENGINE_VERSION) ? strdup(getenv(ENV_VAR_DOCKER_ENGINE_VERSION)) : strdup("1.40");
+    framework_environment.hostname = getenv(ENV_VAR_HOSTNAME) ? strdup(getenv(ENV_VAR_HOSTNAME)) : strdup("localhost");
+    framework_environment.host_ip = getenv(ENV_VAR_HOST_IP) ? strdup(getenv(ENV_VAR_HOST_IP)) : strdup("127.0.0.1");
+    framework_environment.host_base_port = get_int_from_string_with_default(getenv(ENV_VAR_HOST_BASE_PORT), 1000);
+    framework_environment.ssh_connections = get_int_from_string_with_default(getenv(ENV_VAR_SSH_CONNECTIONS), 1);
+    framework_environment.tls_connections = get_int_from_string_with_default(getenv(ENV_VAR_TLS_CONNECTIONS), 0);
+    framework_environment.ftp_connections = 1;
+    framework_environment.sftp_connections = 1;
+
+    framework_environment.sdn_controller_ip = getenv(ENV_VAR_SDN_CONTROLLER_IP) ? strdup(getenv(ENV_VAR_SDN_CONTROLLER_IP)) : strdup("127.0.0.1");
+    framework_environment.sdn_controller_port = get_int_from_string_with_default(getenv(ENV_VAR_SDN_CONTROLLER_PORT), 8181);
+    framework_environment.sdn_controller_callhome_port = get_int_from_string_with_default(getenv(ENV_VAR_SDN_CONTROLLER_CALLHOME_PORT), 6666);
+    framework_environment.sdn_controller_username = getenv(ENV_VAR_SDN_CONTROLLER_USERNAME) ? strdup(getenv(ENV_VAR_SDN_CONTROLLER_USERNAME)) : strdup("admin");
+    framework_environment.sdn_controller_password = getenv(ENV_VAR_SDN_CONTROLLER_PASSWORD) ? strdup(getenv(ENV_VAR_SDN_CONTROLLER_PASSWORD)) : strdup("admin");
+
+    framework_environment.ves_endpoint_protocol = getenv(ENV_VAR_VES_ENDPOINT_PROTOCOL) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_PROTOCOL)) : strdup("https");
+    framework_environment.ves_endpoint_ip = getenv(ENV_VAR_VES_ENDPOINT_IP) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_IP)) : strdup("127.0.0.1");
+    framework_environment.ves_endpoint_port = get_int_from_string_with_default(getenv(ENV_VAR_VES_ENDPOINT_PORT), 1234);
+    framework_environment.ves_endpoint_auth_method = getenv(ENV_VAR_VES_ENDPOINT_AUTH_METHOD) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_AUTH_METHOD)) : strdup("no-auth");
+    framework_environment.ves_endpoint_username = getenv(ENV_VAR_VES_ENDPOINT_USERNAME) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_USERNAME)) : strdup("admin");
+    framework_environment.ves_endpoint_password = getenv(ENV_VAR_VES_ENDPOINT_PASSWORD) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_PASSWORD)) : strdup("admin");
+    framework_environment.ves_endpoint_certificate = getenv(ENV_VAR_VES_ENDPOINT_CERTIFICATE) ? strdup(getenv(ENV_VAR_VES_ENDPOINT_CERTIFICATE)) : strdup("");
+
+    log_message(2, "[env] ip_v6_enabled = %s\n", framework_environment.ip_v6_enabled ? "true" : "false");
+    log_message(2, "[env] ip_v4 = %s\n", framework_environment.ip_v4);
+    log_message(2, "[env] ip_v6 = %s\n", framework_environment.ip_v6);
+    log_message(2, "[env] docker_engine_version = %s\n", framework_environment.docker_engine_version);
+    log_message(2, "[env] hostname = %s\n", framework_environment.hostname);
+    log_message(2, "[env] host_ip = %s\n", framework_environment.host_ip);
+    log_message(2, "[env] host_base_port = %d\n", framework_environment.host_base_port);
+    log_message(2, "[env] ssh_connections = %d\n", framework_environment.ssh_connections);
+    log_message(2, "[env] tls_connections = %d\n", framework_environment.tls_connections);
+    log_message(2, "[env] ftp_connections = %d\n", framework_environment.ftp_connections);
+    log_message(2, "[env] sftp_connections = %d\n", framework_environment.sftp_connections);
+
+    log_message(2, "[env] sdn_controller_ip = %s\n", framework_environment.sdn_controller_ip);
+    log_message(2, "[env] sdn_controller_port = %d\n", framework_environment.sdn_controller_port);
+    log_message(2, "[env] sdn_controller_callhome_port = %d\n", framework_environment.sdn_controller_callhome_port);
+    log_message(2, "[env] sdn_controller_username = %s\n", framework_environment.sdn_controller_username);
+    log_message(2, "[env] sdn_controller_password = %s\n", framework_environment.sdn_controller_password);
+
+    log_message(2, "[env] ves_endpoint_protocol = %s\n", framework_environment.ves_endpoint_protocol);
+    log_message(2, "[env] ves_endpoint_ip = %s\n", framework_environment.ves_endpoint_ip);
+    log_message(2, "[env] ves_endpoint_port = %d\n", framework_environment.ves_endpoint_port);
+    log_message(2, "[env] ves_endpoint_auth_method = %s\n", framework_environment.ves_endpoint_auth_method);
+    log_message(2, "[env] ves_endpoint_username = %s\n", framework_environment.ves_endpoint_username);
+    log_message(2, "[env] ves_endpoint_password = %s\n", framework_environment.ves_endpoint_password);
+    log_message(2, "[env] ves_endpoint_certificate = %s\n", framework_environment.ves_endpoint_certificate);
+
+    log_message(2, "finished environment vars\n");
+}
+
+void framework_free(void) {
+    log_message(2, "framework_free()... ");
+
+    free(framework_environment.ip_v4);
+    free(framework_environment.ip_v6);
+    free(framework_environment.docker_engine_version);
+    free(framework_environment.hostname);
+    free(framework_environment.host_ip);
+    free(framework_environment.sdn_controller_ip);
+    free(framework_environment.sdn_controller_username);
+    free(framework_environment.sdn_controller_password);
+    free(framework_environment.ves_endpoint_protocol);
+    free(framework_environment.ves_endpoint_ip);
+    free(framework_environment.ves_endpoint_auth_method);
+    free(framework_environment.ves_endpoint_username);
+    free(framework_environment.ves_endpoint_password);
+    free(framework_environment.ves_endpoint_certificate);
+
+    if(framework_arguments.print_structure_xpath) {
+        free(framework_arguments.print_structure_xpath);
+        framework_arguments.print_structure_xpath = 0;
+    }
+
+    if(framework_config.docker_excluded_modules_count) {
+        for(int i = 0; i < framework_config.docker_excluded_modules_count; i++) {
+            free(framework_config.docker_excluded_modules[i]);
+        }
+        free(framework_config.docker_excluded_modules);
+    }
+
+    if(framework_config.docker_excluded_features_count) {
+        for(int i = 0; i < framework_config.docker_excluded_features_count; i++) {
+            free(framework_config.docker_excluded_features[i]);
+        }
+        free(framework_config.docker_excluded_features);
+    }
+
+    if(framework_config.populate_excluded_modules_count) {
+        for(int i = 0; i < framework_config.populate_excluded_modules_count; i++) {
+            free(framework_config.populate_excluded_modules[i]);
+        }
+        free(framework_config.populate_excluded_modules);
+    }
+
+    for(int i = 0; i < framework_config.custom_list_instances_count; i++) {
+        free(framework_config.custom_list_instances[i].path);
+        
+    }
+    free(framework_config.custom_list_instances);
+
+    for(int i = 0; i < framework_config.restrict_schema_count; i++) {
+        free(framework_config.restrict_schema[i].path);
+        for(int j = 0; j < framework_config.restrict_schema[i].values_count; j++) {
+            free(framework_config.restrict_schema[i].values[j]);
+        }
+        free(framework_config.restrict_schema[i].values);
+    }
+    free(framework_config.restrict_schema);
+
+    log_message(2, "done\n");
+    log_close();
+    if(framework_arguments.container_init) {
+        rename("log/log.txt", "log/install_log.txt");
+        rename("log/error.txt", "log/install_error.txt");
+    }
+}
+
+bool framework_is_docker_excluded_module(const char *module) {
+    assert(module);
+
+    for(int i = 0; i < framework_config.docker_excluded_modules_count; i++) {
+        if(strstr(module, framework_config.docker_excluded_modules[i]) != 0) {
+            return true;
+        }
+    }
+    
+    return false;
+}
+
+bool framework_is_docker_excluded_feature(const char *feature) {
+    assert(feature);
+
+    for(int i = 0; i < framework_config.docker_excluded_features_count; i++) {
+        if(strstr(feature, framework_config.docker_excluded_features[i]) != 0) {
+            return true;
+        }
+    }
+    
+    return false;
+}
+
+bool framework_is_populate_excluded_module(const char *module) {
+    assert(module);
+
+    for(int i = 0; i < framework_config.populate_excluded_modules_count; i++) {
+        if(strstr(module, framework_config.populate_excluded_modules[i]) != 0) {
+            return true;
+        }
+    }
+    
+    return false;
+}
+
+int framework_populate_get_instance_count(const char *path) {
+    assert(path);
+
+    for(int i = 0; i < framework_config.custom_list_instances_count; i++) {
+        if(strcmp(path, framework_config.custom_list_instances[i].path) == 0) {
+            return framework_config.custom_list_instances[i].count;
+        }
+    }
+    return framework_config.default_list_instances;
+}
+
+char *framework_populate_get_restrict_schema(const char *path) {
+    assert(path);
+    char *ret = 0;
+
+    for(int i = 0; i < framework_config.restrict_schema_count; i++) {
+        if(strcmp(path, framework_config.restrict_schema[i].path) == 0) {
+            ret = strdup(framework_config.restrict_schema[i].values[framework_config.restrict_schema[i].index]);
+            framework_config.restrict_schema[i].index++;
+            if(framework_config.restrict_schema[i].index >= framework_config.restrict_schema[i].values_count) {
+                framework_config.restrict_schema[i].index = 0;
+            }
+            break;
+        }
+    }
+
+    return ret;
+}
+
+static void framework_signal_handler(int signo) {
+    framework_sigint = 1;
+}
+
+static error_t parse_opt(int key, char *arg, struct argp_state *state) {
+    framework_arguments_t *iter_arguments = state->input;
+    switch (key) {
+        case 'i':
+            iter_arguments->container_init = true;
+            break;
+
+        case 'n':
+            iter_arguments->nc_server_init = true;
+            break;
+
+        case 'm':
+            iter_arguments->manager = true;
+            break;
+
+        case 'f':
+            iter_arguments->network_function = true;
+            break;
+
+
+        case 'l':
+            iter_arguments->loop = true;
+            break;
+
+        case 'r':
+            iter_arguments->no_rand = true;
+            framework_arguments.fixed_seed = 0;
+            int i = 0;
+            while(arg[i]) {
+                framework_arguments.fixed_seed *= 10;
+                framework_arguments.fixed_seed += arg[i] - '0';
+                i++;
+            }
+            break;
+
+        case 'o':
+            iter_arguments->operational_only = true;
+            break;
+
+        case 't':
+            iter_arguments->test_mode = true;
+            break;
+
+        case 'v':
+            iter_arguments->verbosity_level = arg[0] - '0';
+            break;
+
+        case 'w':
+            chdir(arg);
+            break;
+
+        case '0':
+            iter_arguments->exhaustive_test = true;
+            break;
+
+        case '1':
+            iter_arguments->print_root_paths = true;
+            break;
+
+        case '2':
+            iter_arguments->print_structure_xpath = (char *)malloc(sizeof(char) * (strlen(arg) + 1));
+            if(!iter_arguments->print_structure_xpath) {
+                log_error("very bad malloc failure here");
+                return 1;
+            }
+            strcpy(iter_arguments->print_structure_xpath, arg);
+            if(arg[strlen(arg) - 1] == '/') {
+                iter_arguments->print_structure_xpath[strlen(arg) - 1] = 0;
+            }
+            break;
+
+        case '3':
+            iter_arguments->populate_all = true;
+            break;
+
+        case '4':
+            iter_arguments->enable_features = true;
+            break;
+
+        case ARGP_KEY_ARG:
+            if (state->arg_num >= 2) {
+                argp_usage(state);
+            }
+            break;
+
+        case ARGP_KEY_END:
+
+            break;
+
+        default:
+            return ARGP_ERR_UNKNOWN;
+    }
+    
+    return 0;
+}
diff --git a/ntsimulator/ntsim-ng/core/framework.h b/ntsimulator/ntsim-ng/core/framework.h
new file mode 100644 (file)
index 0000000..be44555
--- /dev/null
@@ -0,0 +1,149 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <argp.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <signal.h>
+
+#define ENV_VAR_HOSTNAME                        "HOSTNAME"
+#define ENV_VAR_DOCKER_ENGINE_VERSION           "DOCKER_ENGINE_VERSION"
+#define ENV_VAR_IPV6ENABLED                     "IPv6_ENABLED"
+#define ENV_VAR_HOST_IP                         "NETCONF_NTS_HOST_IP"
+#define ENV_VAR_HOST_BASE_PORT                  "NETCONF_NTS_HOST_BASE_PORT"
+#define ENV_VAR_SSH_CONNECTIONS                 "SSH_CONNECTIONS"
+#define ENV_VAR_TLS_CONNECTIONS                 "TLS_CONNECTIONS"
+
+#define ENV_VAR_SDN_CONTROLLER_IP               "SDN_CONTROLLER_IP"
+#define ENV_VAR_SDN_CONTROLLER_PORT             "SDN_CONTROLLER_PORT"
+#define ENV_VAR_SDN_CONTROLLER_CALLHOME_PORT    "SDN_CONTROLLER_CALLHOME_PORT"
+#define ENV_VAR_SDN_CONTROLLER_USERNAME         "SDN_CONTROLLER_USERNAME"
+#define ENV_VAR_SDN_CONTROLLER_PASSWORD         "SDN_CONTROLLER_PASSWORD"
+
+#define ENV_VAR_VES_ENDPOINT_PROTOCOL           "VES_ENDPOINT_PROTOCOL"
+#define ENV_VAR_VES_ENDPOINT_IP                 "VES_ENDPOINT_IP"
+#define ENV_VAR_VES_ENDPOINT_PORT               "VES_ENDPOINT_PORT"
+#define ENV_VAR_VES_ENDPOINT_AUTH_METHOD        "VES_ENDPOINT_AUTH_METHOD"
+#define ENV_VAR_VES_ENDPOINT_USERNAME           "VES_ENDPOINT_USERNAME"
+#define ENV_VAR_VES_ENDPOINT_PASSWORD           "VES_ENDPOINT_PASSWORD"
+#define ENV_VAR_VES_ENDPOINT_CERTIFICATE        "VES_ENDPOINT_CERTIFICATE"
+
+typedef struct {
+    char *path;
+    int count;
+} custom_list_instances_t;
+
+typedef struct {
+    char *path;
+    int values_count;
+    char **values;
+    int index;
+} restrict_schema_t;
+
+typedef struct {
+    bool container_init;
+    bool nc_server_init;
+
+    bool no_rand;
+    unsigned int fixed_seed;
+    bool operational_only;
+    int verbosity_level;
+    bool loop;
+    bool test_mode;
+
+    bool manager;
+    bool network_function;
+
+    bool exhaustive_test;
+    bool print_root_paths;
+    char *print_structure_xpath;
+    bool populate_all;
+    bool enable_features;
+} framework_arguments_t;
+
+typedef struct {
+    int docker_excluded_modules_count;
+    char **docker_excluded_modules;
+
+    int docker_excluded_features_count;
+    char **docker_excluded_features;
+
+    int debug_max_string_size;
+
+    int populate_excluded_modules_count;
+    char **populate_excluded_modules;
+
+    int default_list_instances;
+
+    int custom_list_instances_count;
+    custom_list_instances_t *custom_list_instances;
+
+    int restrict_schema_count;
+    restrict_schema_t *restrict_schema;
+} framework_config_t;
+
+typedef struct {
+    char *docker_engine_version;
+
+    char *ip_v4;
+    char *ip_v6;
+    bool ip_v6_enabled;
+
+    char *hostname;
+    char *host_ip;
+    uint16_t host_base_port;
+    uint16_t ssh_connections;
+    uint16_t tls_connections;
+    uint16_t ftp_connections;
+    uint16_t sftp_connections;
+
+    char *sdn_controller_ip;
+    uint16_t sdn_controller_port;
+    uint16_t sdn_controller_callhome_port;
+    char *sdn_controller_username;
+    char *sdn_controller_password;
+
+    char *ves_endpoint_protocol;
+    char *ves_endpoint_ip;
+    uint16_t ves_endpoint_port;
+    char *ves_endpoint_auth_method;
+    char *ves_endpoint_username;
+    char *ves_endpoint_password;
+    char *ves_endpoint_certificate;
+} framework_environment_t;
+
+extern framework_arguments_t framework_arguments;
+extern framework_config_t framework_config;
+extern framework_environment_t framework_environment;
+
+volatile sig_atomic_t framework_sigint;
+
+void framework_init(int argc, char **argv);
+void framework_free(void);
+
+//docker-related functions
+bool framework_is_docker_excluded_module(const char *module);
+bool framework_is_docker_excluded_feature(const char *feature);
+
+//populate-related functions
+bool framework_is_populate_excluded_module(const char *module);
+
+int framework_populate_get_instance_count(const char *path);
+char *framework_populate_get_restrict_schema(const char *path);     //returns null if there is no restricted entry, value otherwise. value must be freed
diff --git a/ntsimulator/ntsim-ng/core/nc_config.c b/ntsimulator/ntsim-ng/core/nc_config.c
new file mode 100644 (file)
index 0000000..43402eb
--- /dev/null
@@ -0,0 +1,620 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "nc_config.h"
+#include "utils/log_utils.h"
+#include "utils/sys_utils.h"
+#include "utils/http_client.h"
+#include <stdio.h>
+#include <assert.h>
+
+#include <libyang/libyang.h>
+#include "core/session.h"
+#include "core/framework.h"
+
+#define GEN_KEY_SCRIPT                              "/home/netconf/.ssh/generate-ssh-keys.sh"
+#define KS_CERT_NAME                                "melacon_server_cert"
+#define SERVER_PRIVATE_KEY_PATH                     "/home/netconf/.ssh/melacon.server.key"
+#define SERVER_PUBLIC_KEY_PATH                      "/home/netconf/.ssh/melacon.server.key.pub.pem"
+#define SERVER_CERT_PATH                            "/home/netconf/.ssh/melacon.server.crt"
+#define CLIENT_CERT_PATH                            "/home/netconf/.ssh/client.crt"
+#define CA_CERT_PATH                                "/home/netconf/.ssh/ca.pem"
+
+static int nc_config_netconf_port = STANDARD_NETCONF_PORT;
+
+static int load_ssh_keys(sr_session_ctx_t *session);
+static int load_trusted_certificates(sr_session_ctx_t *session);
+static int remove_nacm(sr_session_ctx_t *session);
+static int create_ssh_listen_endpoints(struct lyd_node *netconf_node, int ssh_connections);
+static int create_tls_listen_endpoints(struct lyd_node *netconf_node, int tls_connections);
+static int configure_endpoints_connections(sr_session_ctx_t *session);
+
+int netconf_configure(void) {
+    int rc = NTS_ERR_OK;
+
+    nc_config_netconf_port = STANDARD_NETCONF_PORT;
+
+    sr_session_ctx_t *current_session;
+    rc = sr_session_start(session_connection, SR_DS_RUNNING, &current_session);
+    if(rc != 0) {
+        log_error("could not start session on running datastore");
+        return NTS_ERR_FAILED;
+    }
+
+    // generate and load private keys
+    log_message(1, "ietf-keystore startup datastore configuration...");     //checkAS e ok aici ?
+    rc = load_ssh_keys(current_session);
+    if(rc != 0) {
+        log_error("could not load SSH keys");
+        return NTS_ERR_FAILED;
+    }
+    log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
+
+    // load trusted certificates
+    log_message(1, "ietf-truststore startup datastore configuration...");
+    rc = load_trusted_certificates(current_session);
+    if(rc != 0) {
+        log_error("could not load trusted certificates");
+        return NTS_ERR_FAILED;
+    }
+    log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
+
+    // remove NACM
+    log_message(1, "Removing NACM...");
+    rc = remove_nacm(current_session);
+    if(rc != 0) {
+        log_error("could not remove NACM");
+        return NTS_ERR_FAILED;
+    }
+    log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
+
+    // configure SSH connections
+    log_message(1, "Configuring connection endpoints...");
+    rc = configure_endpoints_connections(current_session);
+    if(rc != 0) {
+        log_error("could not configure endpoint connections forNETCONF Server");
+        return NTS_ERR_FAILED;
+    }
+    log_message(1, LOG_COLOR_BOLD_GREEN"done\n"LOG_COLOR_RESET);
+
+    rc = sr_session_stop(current_session);
+    if(rc != 0) {
+        log_error("could not configure stop current sysrepo session");
+        return NTS_ERR_FAILED;
+    }
+
+    return NTS_ERR_OK;
+}
+
+static int load_ssh_keys(sr_session_ctx_t *session) {
+    assert(session);
+
+    int rc = NTS_ERR_OK;
+    char xpath[500];
+    struct lyd_node *rcl = 0;
+
+    rc = system(GEN_KEY_SCRIPT);
+    if(rc != 0) {
+        log_error("could not generate the SSH keys");
+        return NTS_ERR_FAILED;
+    }
+
+    struct lys_module *module;
+    module = (struct lys_module *)ly_ctx_get_module(session_context, "ietf-keystore", 0, 0);
+    if(module == 0) {
+        log_error("could not get module %s from context", "ietf-keystore");
+        return NTS_ERR_FAILED;
+    }
+    
+    struct lyd_node *keystore_node = 0;
+    keystore_node = lyd_new(NULL, module, "keystore");
+    if(keystore_node == 0) {
+        log_error("could not create a new lyd_node");
+        return NTS_ERR_FAILED;
+    }
+
+    sprintf(xpath, "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key[name='%s']/algorithm", KS_KEY_NAME);
+    rcl = lyd_new_path(keystore_node, 0, xpath, "rsa2048", 0, LYD_PATH_OPT_NOPARENTRET);
+    if(rcl == 0) {
+        log_error("could not created yang path");
+        return NTS_ERR_FAILED;
+    }
+
+    char *private_key = read_key(SERVER_PRIVATE_KEY_PATH);
+    if(private_key == 0) {
+        log_error("could not read the private key from path=%s", SERVER_PRIVATE_KEY_PATH);
+        return NTS_ERR_FAILED;
+    }
+    log_message(2, "Private Key that was built: \n%s\n", private_key);
+
+    sprintf(xpath, "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key[name='%s']/private-key", KS_KEY_NAME);
+    rcl = lyd_new_path(keystore_node, 0, xpath, private_key, 0, LYD_PATH_OPT_NOPARENTRET);
+    if(rcl == 0) {
+        log_error("could not created yang path");
+        return NTS_ERR_FAILED;
+    }
+
+    free(private_key);
+
+    char *public_key = read_key(SERVER_PUBLIC_KEY_PATH);
+    if(public_key == 0) {
+        log_error("could not read the public key from path=%s", SERVER_PUBLIC_KEY_PATH);
+        return NTS_ERR_FAILED;
+    }
+    log_message(2, "Public Key that was built: \n%s\n", public_key);
+
+    sprintf(xpath, "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key[name='%s']/public-key", KS_KEY_NAME);
+    rcl = lyd_new_path(keystore_node, 0, xpath, public_key, 0, LYD_PATH_OPT_NOPARENTRET);
+    if(rcl == 0) {
+        log_error("could not created yang path");
+        return NTS_ERR_FAILED;
+    }
+
+    free(public_key);
+
+    char *certificate = read_key(SERVER_CERT_PATH);
+    if(certificate == 0) {
+        log_error("could not read the certificate from path=%s", SERVER_CERT_PATH);
+        return NTS_ERR_FAILED;
+    }
+    log_message(2, "Certificate that was built: \n%s\n", certificate);
+
+    sprintf(xpath, "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key[name='%s']/certificates/certificate[name='%s']/cert", KS_KEY_NAME, KS_CERT_NAME);
+    rcl = lyd_new_path(keystore_node, 0, xpath, certificate, 0, LYD_PATH_OPT_NOPARENTRET);
+    if(rcl == 0) {
+        log_error("could not created yang path");
+        return NTS_ERR_FAILED;
+    }
+
+    free(certificate);
+
+    rc = sr_edit_batch(session, keystore_node, "replace");
+    if(rc != SR_ERR_OK) {
+        log_error("could not edit batch on datastore");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = sr_validate(session, "ietf-keystore", 0);
+    if(rc != SR_ERR_OK) {
+        struct ly_err_item *err = ly_err_first(session_context);
+        log_error("sr_validate issues on STARTUP: %s", err->msg);
+        return false;
+    }
+
+    rc = sr_apply_changes(session, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("could not apply changes on datastore");
+        return NTS_ERR_FAILED;
+    }
+    
+    return NTS_ERR_OK;
+}
+
+static int load_trusted_certificates(sr_session_ctx_t *session) {
+    assert(session);
+
+    int rc = NTS_ERR_OK;
+    struct lyd_node *rcl = 0;
+
+    struct lyd_node *trusted_certificate_node = 0;
+    struct lys_module *module;
+    module = (struct lys_module *)ly_ctx_get_module(session_context, "ietf-truststore", 0, 0);
+    if(module == 0) {
+        log_error("could not get module %s from context", "ietf-truststore");
+        return NTS_ERR_FAILED;
+    }
+
+    trusted_certificate_node = lyd_new(NULL, module, "truststore");
+    if(trusted_certificate_node == 0) {
+        log_error("could not create a new lyd_node");
+        return NTS_ERR_FAILED;
+    }
+
+    char xpath[500];
+
+    sprintf(xpath, "/ietf-truststore:truststore/certificates[name='clientcerts']/certificate[name='clientcert']/cert");
+    char *client_cert = read_key(CLIENT_CERT_PATH);
+    rcl = lyd_new_path(trusted_certificate_node, 0, xpath, client_cert, 0, LYD_PATH_OPT_NOPARENTRET);
+    if(rcl == 0) {
+        log_error("could not created yang path");
+        return NTS_ERR_FAILED;
+    }
+    free(client_cert);
+
+    sprintf(xpath, "/ietf-truststore:truststore/certificates[name='cacerts']/certificate[name='cacert']/cert");
+    char *ca_cert = read_key(CA_CERT_PATH);
+    rcl = lyd_new_path(trusted_certificate_node, 0, xpath, ca_cert, 0, LYD_PATH_OPT_NOPARENTRET);
+    if(rcl == 0) {
+        log_error("could not created yang path");
+        return NTS_ERR_FAILED;
+    }
+    free(ca_cert);
+
+    rc = sr_edit_batch(session, trusted_certificate_node, "replace");
+    if(rc != SR_ERR_OK) {
+        log_error("could not edit batch on datastore");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = sr_validate(session, "ietf-truststore", 0);
+    if(rc != SR_ERR_OK) {
+        struct ly_err_item *err = ly_err_first(session_context);
+        log_error("sr_validate issues on STARTUP: %s", err->msg);
+        return NTS_ERR_FAILED;
+    }
+
+    rc = sr_apply_changes(session, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("could not apply changes on datastore");
+        return NTS_ERR_FAILED;
+    }
+    return NTS_ERR_OK;
+}
+
+static int remove_nacm(sr_session_ctx_t *session) {
+    assert(session);
+
+    int rc = NTS_ERR_OK;
+    struct lyd_node *rcl = 0;
+    char xpath[100];
+
+    struct lys_module *module = 0;
+    module = (struct lys_module *) ly_ctx_get_module(session_context, "ietf-netconf-acm", 0, 0);
+    if(module == 0) {
+        log_error("could not get module %s from context", "ietf-netconf-acm");
+        return NTS_ERR_FAILED;
+    }
+
+    struct lyd_node *nacm_node = 0;
+    nacm_node = lyd_new(NULL, module, "nacm");
+    if(nacm_node == 0) {
+        log_error("could not create a new lyd_node");
+        return NTS_ERR_FAILED;
+    }
+
+    sprintf(xpath, "/ietf-netconf-acm:nacm/enable-nacm");
+    rcl = lyd_new_path(nacm_node, 0, xpath, "false", 0, LYD_PATH_OPT_NOPARENTRET);
+    if(rcl == 0) {
+        log_error("could not created yang path");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = sr_edit_batch(session, nacm_node, "replace");
+    if(rc != SR_ERR_OK) {
+        log_error("could not edit batch on datastore");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = sr_validate(session, "ietf-netconf-acm", 0);
+    if(rc != SR_ERR_OK) {
+        struct ly_err_item *err = ly_err_first(session_context);
+        log_error("sr_validate issues on STARTUP: %s", err->msg);
+        return NTS_ERR_FAILED;
+    }
+
+    rc = sr_apply_changes(session, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("could not apply changes on datastore");
+        return NTS_ERR_FAILED;
+    }
+    
+    return NTS_ERR_OK;
+}
+
+static int create_ssh_listen_endpoints(struct lyd_node *netconf_node, int ssh_connections) {
+    assert(netconf_node);
+
+    char xpath[500];
+    char local_ip[30];
+    struct lyd_node *rcl = 0;
+
+    
+    if(framework_environment.ip_v6_enabled) {
+        sprintf(local_ip, "::");
+    }
+    else {
+        sprintf(local_ip, "0.0.0.0");
+    } 
+
+    char *public_ssh_key = read_key(SERVER_PUBLIC_SSH_KEY_PATH);
+    if(public_ssh_key == 0) {
+        log_error("could not read the public ssh key from file %s", SERVER_PUBLIC_SSH_KEY_PATH);
+        return NTS_ERR_FAILED;
+    }
+
+    char *ssh_key_string;
+
+    ssh_key_string = strtok(public_ssh_key, " ");
+    ssh_key_string = strtok(NULL, " ");
+
+    for(int i=0; i < ssh_connections; ++i) {
+        char endpoint_name[100];
+        sprintf(endpoint_name, "mng-ssh-%d", i);
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/local-address", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, local_ip, 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        char local_port[10];
+        sprintf(local_port, "%d", nc_config_netconf_port++);
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/local-port", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, local_port, 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/keepalives/idle-time", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, "1", 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/keepalives/max-probes", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, "10", 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters/keepalives/probe-interval", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, "5", 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/server-identity/host-key[name='default-key']/public-key/keystore-reference", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, KS_KEY_NAME, 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/supported-authentication-methods/publickey", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/supported-authentication-methods/passsword", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/supported-authentication-methods/other", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, "interactive", 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/users/user[name='netconf']/authorized-key[name='%s']/algorithm", endpoint_name, KS_KEY_NAME);
+        rcl = lyd_new_path(netconf_node, 0, xpath, "ssh-rsa", 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters/client-authentication/users/user[name='netconf']/authorized-key[name='%s']/key-data", endpoint_name, KS_KEY_NAME);
+        rcl = lyd_new_path(netconf_node, 0, xpath, ssh_key_string, 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+    } 
+
+    free(public_ssh_key);
+
+    return NTS_ERR_OK;
+}
+
+static int create_tls_listen_endpoints(struct lyd_node *netconf_node, int tls_connections) {
+    assert(netconf_node);
+
+    struct lyd_node *rcl = 0;
+    char xpath[500];
+    char local_ip[30];
+
+    if(framework_environment.ip_v6_enabled) {
+        sprintf(local_ip, "::");
+    }
+    else {
+        sprintf(local_ip, "0.0.0.0");
+    } 
+
+    for(int i=0; i < tls_connections; ++i) {
+        char endpoint_name[100];
+        sprintf(endpoint_name, "mng-tls-%d", i);
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/local-address", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, local_ip, 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        char local_port[10];
+        sprintf(local_port, "%d", nc_config_netconf_port++);
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/local-port", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, local_port, 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/keepalives/idle-time", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, "1", 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/keepalives/max-probes", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, "10", 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters/keepalives/probe-interval", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, "5", 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/server-identity/keystore-reference/asymmetric-key", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, KS_KEY_NAME, 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/server-identity/keystore-reference/certificate", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, KS_CERT_NAME, 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/required", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/ca-certs", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, "cacerts", 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/client-certs", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, "clientcerts", 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/cert-maps/cert-to-name[id='1']/fingerprint", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, "02:E9:38:1F:F6:8B:62:DE:0A:0B:C5:03:81:A8:03:49:A0:00:7F:8B:F3", 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/cert-maps/cert-to-name[id='1']/map-type", endpoint_name);
+        rcl = lyd_new_path(netconf_node, session_context, xpath, "ietf-x509-cert-to-name:specified", 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+
+        sprintf(xpath, "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tls-server-parameters/client-authentication/cert-maps/cert-to-name[id='1']/name", endpoint_name);
+        rcl = lyd_new_path(netconf_node, 0, xpath, "netconf-tls", 0, LYD_PATH_OPT_NOPARENTRET);
+        if(rcl == 0) {
+            log_error("could not created yang path");
+            return NTS_ERR_FAILED;
+        }
+    }
+
+    return NTS_ERR_OK;
+}
+
+static int configure_endpoints_connections(sr_session_ctx_t *session) {
+    assert(session);
+
+    int rc = NTS_ERR_OK;
+
+    struct lys_module *module = 0;
+    module = (struct lys_module *)ly_ctx_get_module(session_context, "ietf-netconf-server", 0, 0);
+    if(module == 0) {
+        log_error("could not get module %s from context", "ietf-netconf-server");
+        return NTS_ERR_FAILED;
+    }
+
+
+    struct lyd_node *netconf_node = 0;
+    netconf_node = lyd_new_path(NULL, session_context, "/ietf-netconf-server:netconf-server", 0, 0, 0);
+    if(netconf_node == 0) {
+        log_error("could not create a new lyd_node");
+        return NTS_ERR_FAILED;
+    }
+
+    // create the SSH endpoints in ietf-netconf-server
+    int ssh_connections = 0;
+    if(framework_arguments.manager) {
+        ssh_connections = 1;
+    }
+    else {
+        ssh_connections = framework_environment.ssh_connections;
+    }
+
+    if(ssh_connections == 0) {
+        log_error("ssh_connections must be at least 1");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = create_ssh_listen_endpoints(netconf_node, ssh_connections);
+    if(rc != NTS_ERR_OK) {
+        log_error("could not create %d SSH Listen endpoints on the NETCONF Server", ssh_connections);
+        return NTS_ERR_FAILED;
+    }
+
+    // create the TLS endpoints in ietf-netconf-server
+    if(framework_arguments.manager == false) {
+        rc = create_tls_listen_endpoints(netconf_node, framework_environment.tls_connections);
+        if(rc != NTS_ERR_OK) {
+            log_error("could not create %d TLS Listen endpoints on the NETCONF Server", framework_environment.tls_connections);
+            return NTS_ERR_FAILED;
+        }
+    }
+    
+    rc = sr_edit_batch(session, netconf_node, "replace");
+    if(rc != SR_ERR_OK) {
+        log_error("could not edit batch on datastore");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = sr_validate(session, "ietf-netconf-server", 0);
+    if(rc != SR_ERR_OK) {
+        struct ly_err_item *err = ly_err_first(session_context);
+        log_error("sr_validate issues on STARTUP: %s", err->msg);
+        return NTS_ERR_FAILED;
+    }
+
+    rc = sr_apply_changes(session, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("could not apply changes on datastore");
+        return NTS_ERR_FAILED;
+    }
+    
+    return NTS_ERR_OK;
+}
diff --git a/ntsimulator/ntsim-ng/core/nc_config.h b/ntsimulator/ntsim-ng/core/nc_config.h
new file mode 100644 (file)
index 0000000..1dc1f28
--- /dev/null
@@ -0,0 +1,23 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <string.h>
+#include <stdint.h>
+
+int netconf_configure(void);
diff --git a/ntsimulator/ntsim-ng/core/session.c b/ntsimulator/ntsim-ng/core/session.c
new file mode 100644 (file)
index 0000000..716bc56
--- /dev/null
@@ -0,0 +1,91 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "session.h"
+#include "core/framework.h"
+#include "utils/log_utils.h"
+#include <stdio.h>
+#include <assert.h>
+
+sr_conn_ctx_t *session_connection = 0;
+sr_session_ctx_t *session_running = 0;
+sr_session_ctx_t *session_operational = 0;
+struct ly_ctx *session_context = 0;
+sr_subscription_ctx_t *session_subscription = 0;
+
+int session_init(void) {
+    int rc = SR_ERR_OK;
+    
+    /* connect to sysrepo */
+    rc = sr_connect(0, &session_connection);
+    if(SR_ERR_OK != rc) {
+        log_error("sr_connect failed");
+        goto session_init_cleanup;
+    }
+
+    /* start session */
+    rc = sr_session_start(session_connection, SR_DS_OPERATIONAL, &session_operational);
+    if (rc != SR_ERR_OK) {
+        log_error("sr_session_start operational failed");
+        goto session_init_cleanup;
+    }
+
+    if(framework_arguments.operational_only == false) {
+        rc = sr_session_start(session_connection, SR_DS_RUNNING, &session_running);
+        if (rc != SR_ERR_OK) {
+            log_error("sr_session_start running failed");
+            goto session_init_cleanup;
+        }
+    }
+    else {
+        session_running = session_operational;
+    }
+
+
+    /* get context */
+    session_context = (struct ly_ctx *)sr_get_context(session_connection);
+    if(session_context == 0) {
+        log_error("sr_get_context failed");
+        goto session_init_cleanup;
+    }
+
+    return NTS_ERR_OK;
+
+session_init_cleanup:
+    return NTS_ERR_FAILED;
+}
+
+void session_free(void) {
+    log_message(2, "session_free()... ");
+    if(session_subscription) {
+        sr_unsubscribe(session_subscription);
+    }
+
+    sr_session_stop(session_operational);
+    if(framework_arguments.operational_only == false) {
+        sr_session_stop(session_running);
+    }
+    sr_disconnect(session_connection);
+
+    session_connection = 0;
+    session_running = 0;
+    session_operational = 0;
+    session_context = 0;
+    log_message(2, "done\n");
+}
diff --git a/ntsimulator/ntsim-ng/core/session.h b/ntsimulator/ntsim-ng/core/session.h
new file mode 100644 (file)
index 0000000..6e2bd49
--- /dev/null
@@ -0,0 +1,34 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <string.h>
+#include <stdint.h>
+#include <sysrepo.h>
+#include <libyang/libyang.h>
+
+extern sr_conn_ctx_t *session_connection;
+extern sr_session_ctx_t *session_running;
+extern sr_session_ctx_t *session_operational;
+extern struct ly_ctx *session_context;
+extern sr_subscription_ctx_t *session_subscription;
+
+#define assert_session()    assert(session_connection && session_running && session_operational && session_context) 
+
+int session_init(void);
+void session_free(void);
diff --git a/ntsimulator/ntsim-ng/core/test.c b/ntsimulator/ntsim-ng/core/test.c
new file mode 100644 (file)
index 0000000..8902984
--- /dev/null
@@ -0,0 +1,92 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "test.h"
+#include "utils/log_utils.h"
+#include "utils/rand_utils.h"
+#include "utils/type_utils.h"
+#include "utils/sys_utils.h"
+#include <stdio.h>
+#include <assert.h>
+
+#include <libyang/libyang.h>
+#include "core/session.h"
+#include "core/framework.h"
+#include "core/docker.h"
+
+#include "core/datastore/schema.h"
+#include "core/datastore/populate.h"
+
+
+int exhaustive_test_run(void) {
+    //first get all xpaths
+    char **xpaths = 0;
+    int xpaths_count = schema_get_xpaths(&xpaths);
+    if(xpaths_count < 0) {
+        log_error("schema_get_xpaths failed");
+        return NTS_ERR_FAILED;
+    }
+    else {
+        log_message(0, "schema_get_xpaths executed with "LOG_COLOR_BOLD_GREEN"success"LOG_COLOR_RESET" (%d)\n", xpaths_count);
+    }
+
+    //switching verbosity level to 0 so we don't see logs
+    int old_verbosity_level = framework_arguments.verbosity_level;
+    framework_arguments.verbosity_level = 0;
+
+    //testing schema_print_xpath()
+    for(int i = 0 ; i < xpaths_count; i++) {
+        int rc = schema_print_xpath(xpaths[i]);
+        if(rc != NTS_ERR_OK) {
+            log_error("error in schema_print_xpath");
+            return rc;
+        }
+    }
+
+    log_message(0, "schema_print_xpath executed with "LOG_COLOR_BOLD_GREEN"success"LOG_COLOR_RESET" for all paths\n");
+
+    //freeing paths
+    for(int i = 0; i < xpaths_count; i++) {
+        free(xpaths[i]);
+    }
+    free(xpaths);
+
+    //testing schema_populate
+    int rc = schema_populate();
+    if(rc != NTS_ERR_OK) {
+        log_error("error in schema_populate");
+        return rc;
+    }
+    
+    log_message(0, "schema_populate executed with "LOG_COLOR_BOLD_GREEN"success"LOG_COLOR_RESET"\n");
+
+    log_message(0, LOG_COLOR_BOLD_GREEN"ALL TESTS WENT GOOD!"LOG_COLOR_RESET"\n\n\n");
+
+    //switching back verbosity level
+    framework_arguments.verbosity_level = old_verbosity_level;
+
+    return NTS_ERR_OK;
+}
+
+int test_mode_run(void) {
+    assert_session();
+
+   
+    return NTS_ERR_OK;
+}
diff --git a/ntsimulator/ntsim-ng/core/test.h b/ntsimulator/ntsim-ng/core/test.h
new file mode 100644 (file)
index 0000000..ce9b42b
--- /dev/null
@@ -0,0 +1,24 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <string.h>
+#include <stdint.h>
+
+int exhaustive_test_run(void);
+int test_mode_run(void);
diff --git a/ntsimulator/ntsim-ng/features/manual_notification/manual_notification.c b/ntsimulator/ntsim-ng/features/manual_notification/manual_notification.c
new file mode 100644 (file)
index 0000000..e76fa61
--- /dev/null
@@ -0,0 +1,100 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "manual_notification.h"
+#include "utils/log_utils.h"
+#include "utils/sys_utils.h"
+#include "utils/rand_utils.h"
+#include "utils/http_client.h"
+#include "utils/nts_utils.h"
+#include <stdio.h>
+#include <assert.h>
+
+#include <sysrepo.h>
+#include <sysrepo/values.h>
+
+#include "core/session.h"
+#include "core/framework.h"
+
+#define MANUAL_NOTIFICATION_RPC_SCHEMA_XPATH         "/nts-network-function:invoke-notification"
+
+static int manual_notification_pm_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data);
+
+int manual_notification_feature_start(sr_session_ctx_t *current_session) {
+    assert_session();
+
+    int rc = sr_rpc_subscribe(current_session, MANUAL_NOTIFICATION_RPC_SCHEMA_XPATH, manual_notification_pm_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
+    if(rc != SR_ERR_OK) {
+        log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc));
+        return NTS_ERR_FAILED;
+    }
+
+    return NTS_ERR_OK;
+}
+
+static int manual_notification_pm_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) {
+    int rc;
+
+    *output_cnt = 1;
+    rc = sr_new_values(*output_cnt, output);
+    if(SR_ERR_OK != rc) {
+        return rc;
+    }
+
+    rc = sr_val_set_xpath(output[0], MANUAL_NOTIFICATION_RPC_SCHEMA_XPATH"/status");
+    if(SR_ERR_OK != rc) {
+        return rc;
+    }
+
+    LYD_FORMAT notif_format = LYD_UNKNOWN;
+    char *notif_object = 0;
+    for(int i = 0; i < input_cnt; i++) {
+        if(strstr(input[i].xpath, "notification-format") != 0) {
+            if(input[i].data.enum_val[0] == 'x') {
+                notif_format = LYD_XML;
+            }
+            else if(input[i].data.enum_val[0] == 'j') {
+                notif_format = LYD_JSON;
+            }
+        }
+        else if(strstr(input[i].xpath, "notification-object") != 0) {
+            notif_object = input[i].data.string_val;
+        }
+    }
+
+    struct lyd_node *notif = 0;
+    notif = lyd_parse_mem(session_context, notif_object, notif_format, LYD_OPT_NOTIF, 0);
+    if(notif) {
+        rc = sr_event_notif_send_tree(session, notif);
+    }
+    else {
+        rc = SR_ERR_VALIDATION_FAILED;
+    }
+
+    lyd_free_withsiblings(notif);
+
+    if(rc != SR_ERR_OK) {
+        rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "ERROR");
+    }
+    else {
+        rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
+    }
+
+    return rc;
+}
diff --git a/ntsimulator/ntsim-ng/features/manual_notification/manual_notification.h b/ntsimulator/ntsim-ng/features/manual_notification/manual_notification.h
new file mode 100644 (file)
index 0000000..6b2fd83
--- /dev/null
@@ -0,0 +1,22 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <sysrepo.h>
+
+int manual_notification_feature_start(sr_session_ctx_t *current_session);
diff --git a/ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.c b/ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.c
new file mode 100644 (file)
index 0000000..b3bacb0
--- /dev/null
@@ -0,0 +1,284 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "netconf_call_home.h"
+#include "utils/log_utils.h"
+#include "utils/sys_utils.h"
+#include "utils/rand_utils.h"
+#include "utils/http_client.h"
+#include "utils/nts_utils.h"
+#include <stdio.h>
+#include <assert.h>
+
+#include "core/session.h"
+#include "core/framework.h"
+
+#define NETCONF_CALLHOME_ENABLED_SCHEMA_PATH        "/nts-network-function:simulation/network-function/netconf/call-home"
+#define NETCONF_CALLHOME_CURL_SEND_PAYLOAD_FORMAT   "{\"odl-netconf-callhome-server:device\":[{\"odl-netconf-callhome-server:unique-id\":\"%s\",\"odl-netconf-callhome-server:ssh-host-key\":\"%s\",\"odl-netconf-callhome-server:credentials\":{\"odl-netconf-callhome-server:username\":\"netconf\",\"odl-netconf-callhome-server:passwords\":[\"netconf\"]}}]}"
+#define SDN_CONTROLLER_DETAILS_SCHEMA_PATH          "/nts-network-function:simulation/sdn-controller"
+
+static int create_ssh_callhome_endpoint(sr_session_ctx_t *current_session, struct lyd_node *netconf_node);
+static int create_tls_callhome_endpoint(sr_session_ctx_t *current_session, struct lyd_node *netconf_node);
+static int send_odl_callhome_configuration(sr_session_ctx_t *current_session);
+
+int netconf_call_home_feature_start(sr_session_ctx_t *current_session) {
+    assert(current_session);
+    assert_session();
+
+    sr_val_t *value = 0;
+
+    bool callhome_enabled = false;
+    int rc = sr_get_item(current_session, NETCONF_CALLHOME_ENABLED_SCHEMA_PATH, 0, &value);
+    if(rc == SR_ERR_OK) {
+        callhome_enabled = value->data.bool_val;
+        sr_free_val(value);
+    }
+
+    if(callhome_enabled == false) {
+        log_message(2, "NETCONF CallHome is not enabled, not configuring NETCONF Server.\n");
+        return NTS_ERR_OK;
+    }
+
+    struct lyd_node *netconf_node = 0;
+    netconf_node = lyd_new_path(NULL, session_context, "/ietf-netconf-server:netconf-server", 0, 0, 0);
+    if(netconf_node == 0) {
+        log_error("could not create a new lyd_node");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = create_ssh_callhome_endpoint(current_session, netconf_node);
+    if(rc != NTS_ERR_OK) {
+        log_error("could not create SSH CallHome endpoint on the NETCONF Server");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = create_tls_callhome_endpoint(current_session, netconf_node);
+    if(rc != NTS_ERR_OK) {
+        log_error("could not create TLS CallHome endpoint on the NETCONF Server");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = sr_edit_batch(current_session, netconf_node, "merge");
+    if(rc != SR_ERR_OK) {
+        log_error("could not edit batch on datastore");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = sr_validate(current_session, "ietf-netconf-server", 0);
+    if(rc != SR_ERR_OK) {
+        struct ly_err_item *err = ly_err_first(session_context);
+        log_error("sr_validate issues on STARTUP: %s", err->msg);
+        return NTS_ERR_FAILED;
+    }
+
+    rc = sr_apply_changes(current_session, 0, 0);
+    if(rc != SR_ERR_OK) {
+        log_error("could not apply changes on datastore");
+        return NTS_ERR_FAILED;
+    }
+
+    lyd_free_withsiblings(netconf_node);
+
+    return NTS_ERR_OK;
+}
+
+
+static int create_ssh_callhome_endpoint(sr_session_ctx_t *current_session, struct lyd_node *netconf_node) {
+    assert(current_session);
+    assert(netconf_node);
+
+    sr_val_t *value = 0;
+
+    bool callhome_enabled = false;
+    int rc = sr_get_item(current_session, NETCONF_CALLHOME_ENABLED_SCHEMA_PATH, 0, &value);
+    if(rc == SR_ERR_OK) {
+        callhome_enabled = value->data.bool_val;
+        sr_free_val(value);
+    }
+
+    if(callhome_enabled == false) {
+        log_message(2, "NETCONF CallHome is not enabled, not configuring NETCONF Server.\n");
+        return NTS_ERR_OK;
+    }
+
+    controller_details_t *controller = controller_details_get(current_session);
+    if(controller == 0) {
+        log_error("controller_details_get failed");
+        return NTS_ERR_FAILED;
+    }
+
+    char *controller_ip = strdup(controller->ip);
+    uint16_t controller_callhome_port = controller->nc_callhome_port;
+    controller_details_free(controller);
+
+    if(controller_ip == 0) {
+        log_error("strdup failed");
+        return NTS_ERR_FAILED;
+    }
+
+    char xpath[500];
+    sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/tcp-client-parameters/keepalives/idle-time");
+    struct lyd_node *rcl = lyd_new_path(netconf_node, 0, xpath, "1", 0, LYD_PATH_OPT_NOPARENTRET);
+    if(rcl == 0) {
+        log_error("could not created yang path");
+        free(controller_ip);
+        return NTS_ERR_FAILED;
+    }
+
+    sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/tcp-client-parameters/keepalives/max-probes");
+    rcl = lyd_new_path(netconf_node, 0, xpath, "10", 0, LYD_PATH_OPT_NOPARENTRET);
+    if(rcl == 0) {
+        log_error("could not created yang path");
+        free(controller_ip);
+        return NTS_ERR_FAILED;
+    }
+
+    sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/tcp-client-parameters/keepalives/probe-interval");
+    rcl = lyd_new_path(netconf_node, 0, xpath, "5", 0, LYD_PATH_OPT_NOPARENTRET);
+    if(rcl == 0) {
+        log_error("could not created yang path");
+        free(controller_ip);
+        return NTS_ERR_FAILED;
+    }
+
+    sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/tcp-client-parameters/remote-address");
+    rcl = lyd_new_path(netconf_node, 0, xpath, controller_ip, 0, LYD_PATH_OPT_NOPARENTRET);
+    if(rcl == 0) {
+        log_error("could not created yang path");
+        free(controller_ip);
+        return NTS_ERR_FAILED;
+    }
+    free(controller_ip);
+
+    sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/tcp-client-parameters/remote-port");
+    char port[20];
+    sprintf(port, "%d", controller_callhome_port);
+    rcl = lyd_new_path(netconf_node, 0, xpath, port, 0, LYD_PATH_OPT_NOPARENTRET);
+    if(rcl == 0) {
+        log_error("could not created yang path");
+        return NTS_ERR_FAILED;
+    }
+
+    sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/ssh-server-parameters/server-identity/host-key[name='default-key']/public-key/keystore-reference");
+    rcl = lyd_new_path(netconf_node, 0, xpath, KS_KEY_NAME, 0, LYD_PATH_OPT_NOPARENTRET);
+    if(rcl == 0) {
+        log_error("could not created yang path");
+        return NTS_ERR_FAILED;
+    }
+
+    sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/ssh-server-parameters/client-authentication/supported-authentication-methods/publickey");
+    rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET);
+    if(rcl == 0) {
+        log_error("could not created yang path");
+        return NTS_ERR_FAILED;
+    }
+
+    sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/ssh-server-parameters/client-authentication/supported-authentication-methods/passsword");
+    rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET);
+    if(rcl == 0) {
+        log_error("could not created yang path");
+        return NTS_ERR_FAILED;
+    }
+
+    sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/ssh-server-parameters/client-authentication/supported-authentication-methods/other");
+    rcl = lyd_new_path(netconf_node, 0, xpath, "interactive", 0, LYD_PATH_OPT_NOPARENTRET);
+    if(rcl == 0) {
+        log_error("could not created yang path");
+        return NTS_ERR_FAILED;
+    }
+
+    sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/ssh-server-parameters/client-authentication/users");
+    rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET);
+    if(rcl == 0) {
+        log_error("could not created yang path");
+        return NTS_ERR_FAILED;
+    }
+
+    sprintf(xpath, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/connection-type/persistent");
+    rcl = lyd_new_path(netconf_node, 0, xpath, "", 0, LYD_PATH_OPT_NOPARENTRET);
+    if(rcl == 0) {
+        log_error("could not created yang path");
+        return NTS_ERR_FAILED;
+    }
+
+    rc = send_odl_callhome_configuration(current_session);
+    if(rc != NTS_ERR_OK) {
+        log_message(2, "could not send ODL Call Home configuration.\n");
+    }
+
+    return NTS_ERR_OK;
+}
+
+static int create_tls_callhome_endpoint(sr_session_ctx_t *current_session, struct lyd_node *netconf_node) {
+    assert(current_session);
+    assert(netconf_node);
+
+    // checkAS future usage, TLS endpoint yet supported in ODL
+    
+    return NTS_ERR_OK;
+}
+
+
+static int send_odl_callhome_configuration(sr_session_ctx_t *current_session) {
+    assert(current_session);
+
+    char *public_ssh_key = read_key(SERVER_PUBLIC_SSH_KEY_PATH);
+    if(public_ssh_key == 0) {
+        log_error("could not read the public ssh key from file %s", SERVER_PUBLIC_SSH_KEY_PATH);
+        return NTS_ERR_FAILED;
+    }
+
+    char *ssh_key_string;
+    ssh_key_string = strtok(public_ssh_key, " ");
+    ssh_key_string = strtok(NULL, " ");
+
+    // checkAS we have hardcoded here the username and password of the NETCONF Server
+    char *odl_callhome_payload = 0;
+    asprintf(&odl_callhome_payload, NETCONF_CALLHOME_CURL_SEND_PAYLOAD_FORMAT, framework_environment.hostname, ssh_key_string);
+    free(public_ssh_key);
+    if(odl_callhome_payload == 0) {
+        log_error("bad asprintf");
+        return NTS_ERR_FAILED;
+    }
+
+    controller_details_t *controller = controller_details_get(current_session);
+    if(controller == 0) {
+        log_error("controller_details_get failed");
+        return NTS_ERR_FAILED;
+    }
+    
+    char *url = 0;
+    asprintf(&url, "%s/rests/data/odl-netconf-callhome-server:netconf-callhome-server/allowed-devices/device=%s", controller->base_url, framework_environment.hostname);
+    if(url == 0) {
+        log_error("bad asprintf");
+        controller_details_free(controller);
+        return NTS_ERR_FAILED;
+    }
+
+    int rc = http_request(url, controller->username, controller->password, "PUT", odl_callhome_payload, 0, 0);
+    if(rc != NTS_ERR_OK) {
+        log_error("http_request failed");
+    }
+    
+    free(url);
+    controller_details_free(controller);
+    free(odl_callhome_payload);
+
+    return rc;
+}
diff --git a/ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.h b/ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.h
new file mode 100644 (file)
index 0000000..48a9661
--- /dev/null
@@ -0,0 +1,22 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <sysrepo.h>
+
+int netconf_call_home_feature_start(sr_session_ctx_t *current_session);
diff --git a/ntsimulator/ntsim-ng/features/ves_file_ready/ves_file_ready.c b/ntsimulator/ntsim-ng/features/ves_file_ready/ves_file_ready.c
new file mode 100644 (file)
index 0000000..7cd56d5
--- /dev/null
@@ -0,0 +1,273 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "ves_file_ready.h"
+#include "utils/log_utils.h"
+#include "utils/sys_utils.h"
+#include "utils/http_client.h"
+#include "utils/nts_utils.h"
+#include <stdio.h>
+#include <assert.h>
+
+#include <sysrepo.h>
+#include <sysrepo/values.h>
+
+#include "core/framework.h"
+#include "core/session.h"
+
+#define FILE_READY_RPC_SCHEMA_XPATH         "/nts-network-function:invoke-ves-pm-file-ready"
+
+static int ves_file_ready_invoke_pm_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data);
+static int ves_file_ready_send_message(sr_session_ctx_t *session, const char *file_location);
+static cJSON* ves_create_file_ready_fields(const char* file_location);
+static void ves_file_ready_vsftp_daemon_init(void);
+
+int ves_file_ready_feature_start(sr_session_ctx_t *current_session) {
+    assert(current_session);
+    assert_session();
+
+    int rc = sr_rpc_subscribe(current_session, FILE_READY_RPC_SCHEMA_XPATH, ves_file_ready_invoke_pm_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
+    if(rc != SR_ERR_OK) {
+        log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc));
+        return NTS_ERR_FAILED;
+    }
+
+    ves_file_ready_vsftp_daemon_init();
+
+    return NTS_ERR_OK;
+}
+
+static void ves_file_ready_vsftp_daemon_init(void) {
+    system("/usr/sbin/vsftpd &");
+}
+
+static int ves_file_ready_invoke_pm_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) {
+    int rc;
+
+    *output_cnt = 1;
+    rc = sr_new_values(*output_cnt, output);
+    if(SR_ERR_OK != rc) {
+        return rc;
+    }
+
+    rc = sr_val_set_xpath(output[0], FILE_READY_RPC_SCHEMA_XPATH"/status");
+    if(SR_ERR_OK != rc) {
+        return rc;
+    }
+
+    rc = ves_file_ready_send_message(session, input[0].data.string_val);
+    if(rc != NTS_ERR_OK) {
+        rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "ERROR");
+    }
+    else {
+        rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
+    }
+
+    return rc;
+}
+
+static int ves_file_ready_send_message(sr_session_ctx_t *session, const char *file_location) {
+    assert(session);
+    assert(file_location);
+
+    int rc;
+    static int sequence_number = 0;
+
+    cJSON *post_data_json = cJSON_CreateObject();
+    if(post_data_json == 0) {
+        log_error("could not create cJSON object");
+        return NTS_ERR_FAILED;
+    }
+
+    cJSON *event = cJSON_CreateObject();
+    if(event == 0) {
+        log_error("could not create cJSON object");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+    
+    if(cJSON_AddItemToObject(post_data_json, "event", event) == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+
+    char *hostname_string = framework_environment.hostname;
+    cJSON *common_event_header = ves_create_common_event_header("notification", "Notification-gnb_Nokia-FileReady", hostname_string, "Normal", sequence_number++);
+    if(common_event_header == 0) {
+        log_error("could not create cJSON object");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+    
+    if(cJSON_AddItemToObject(event, "commonEventHeader", common_event_header) == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+
+    cJSON *file_ready_fields = ves_create_file_ready_fields(file_location);
+    if(file_ready_fields == 0) {
+        log_error("could not create cJSON object");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+    
+    if(cJSON_AddItemToObject(event, "notificationFields", file_ready_fields) == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+
+    char *post_data = cJSON_PrintUnformatted(post_data_json);
+    cJSON_Delete(post_data_json);
+    if(post_data == 0) {
+        log_error("cJSON_PrintUnformatted failed");
+        return NTS_ERR_FAILED;
+    }
+
+
+    ves_details_t *ves_details = ves_endpoint_details_get(session);
+    if(!ves_details) {
+        log_error("ves_endpoint_details_get failed");
+        free(post_data);
+        return NTS_ERR_FAILED;
+    }
+    
+    rc = http_request(ves_details->url, ves_details->username, ves_details->password, "POST", post_data, 0, 0);
+    ves_details_free(ves_details);
+    free(post_data);
+    
+    if(rc != NTS_ERR_OK) {
+        log_error("http_request failed");
+        return NTS_ERR_FAILED;
+    }
+
+    return NTS_ERR_OK;
+}
+
+static cJSON* ves_create_file_ready_fields(const char* file_location) {
+    assert(file_location);
+
+    cJSON *file_ready_fields = cJSON_CreateObject();
+    if(file_ready_fields == 0) {
+        log_error("could not create JSON object");
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(file_ready_fields, "changeIdentifier", "PM_MEAS_FILES") == 0) {
+        log_error("cJSON_AddStringToObject failed");
+        cJSON_Delete(file_ready_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(file_ready_fields, "changeType", "FileReady") == 0) {
+        log_error("cJSON_AddStringToObject failed");
+        cJSON_Delete(file_ready_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(file_ready_fields, "notificationFieldsVersion", "2.0") == 0) {
+        log_error("cJSON_AddStringToObject failed");
+        cJSON_Delete(file_ready_fields);
+        return 0;
+    }
+
+    cJSON *array_of_named_hash_map = cJSON_CreateArray();
+    if(array_of_named_hash_map == 0) {
+        log_error("could not create JSON object");
+        cJSON_Delete(file_ready_fields);
+        return 0;
+    }
+    
+    if(cJSON_AddItemToObject(file_ready_fields, "arrayOfNamedHashMap", array_of_named_hash_map) == 0) {
+        log_error("cJSON_AddStringToObject failed");
+        cJSON_Delete(file_ready_fields);
+        return 0;
+    }
+
+    cJSON *additional_fields_entry = cJSON_CreateObject();
+    if(additional_fields_entry == 0) {
+        log_error("could not create JSON object");
+        cJSON_Delete(file_ready_fields);
+        return 0;
+    }
+
+    char *filename = strrchr(file_location, '/');
+
+    if(filename == 0) {
+        if(cJSON_AddStringToObject(additional_fields_entry, "name", "dummy_file.tar.gz") == 0) {
+            log_error("cJSON_AddStringToObject failed");
+            cJSON_Delete(file_ready_fields);
+            return 0;
+        }
+    }
+    else {
+        if(cJSON_AddStringToObject(additional_fields_entry, "name", filename + 1) == 0) {
+            log_error("cJSON_AddStringToObject failed");
+            cJSON_Delete(file_ready_fields);
+            return 0;
+        }
+    }
+
+    cJSON *hash_map = cJSON_CreateObject();
+    if(hash_map == 0) {
+        log_error("could not create JSON object");
+        cJSON_Delete(file_ready_fields);
+        return 0;
+    }
+    
+    if(cJSON_AddItemToObject(additional_fields_entry, "hashMap", hash_map) == 0) {
+        log_error("cJSON_AddStringToObject failed");
+        cJSON_Delete(file_ready_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(hash_map, "location", file_location) == 0) {
+        log_error("cJSON_AddStringToObject failed");
+        cJSON_Delete(file_ready_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(hash_map, "compression", "gzip") == 0) {
+        log_error("cJSON_AddStringToObject failed");
+        cJSON_Delete(file_ready_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(hash_map, "fileFormatType", "org.3GPP.32.435#measCollec") == 0) {
+        log_error("cJSON_AddStringToObject failed");
+        cJSON_Delete(file_ready_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(hash_map, "fileFormatVersion", "V5") == 0) {
+        log_error("cJSON_AddStringToObject failed");
+        cJSON_Delete(file_ready_fields);
+        return 0;
+    }
+
+    if(cJSON_AddItemToArray(array_of_named_hash_map, additional_fields_entry) == 0) {
+        log_error("cJSON_AddStringToObject failed");
+        cJSON_Delete(file_ready_fields);
+        return 0;
+    }
+
+    return file_ready_fields;
+}
diff --git a/ntsimulator/ntsim-ng/features/ves_file_ready/ves_file_ready.h b/ntsimulator/ntsim-ng/features/ves_file_ready/ves_file_ready.h
new file mode 100644 (file)
index 0000000..67f951a
--- /dev/null
@@ -0,0 +1,22 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <sysrepo.h>
+
+int ves_file_ready_feature_start(sr_session_ctx_t *current_session);
diff --git a/ntsimulator/ntsim-ng/features/ves_heartbeat/ves_heartbeat.c b/ntsimulator/ntsim-ng/features/ves_heartbeat/ves_heartbeat.c
new file mode 100644 (file)
index 0000000..4bfc075
--- /dev/null
@@ -0,0 +1,272 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "ves_heartbeat.h"
+#include "utils/log_utils.h"
+#include "utils/sys_utils.h"
+#include "utils/http_client.h"
+#include "utils/nts_utils.h"
+#include <stdio.h>
+#include <time.h>
+#include <inttypes.h>
+#include <assert.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#include "core/session.h"
+#include "core/framework.h"
+
+#define HEARTBEAT_SCHEMA_XPATH      "/nts-network-function:simulation/network-function/ves/heartbeat-period" 
+
+static volatile int ves_heartbeat_period;
+static int ves_sequence_number;
+
+static pthread_t ves_heartbeat_thread;
+static pthread_mutex_t ves_heartbeat_lock;
+
+
+//mutex-guarded access
+static int ves_heartbeat_period_get(void);
+static void ves_heartbeat_period_set(int new_period);
+
+static int ves_heartbeat_send_ves_message(void);
+static void *ves_heartbeat_thread_routine(void *arg);
+static cJSON* ves_create_heartbeat_fields(int heartbeat_period);
+static int heartbeat_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data);
+
+int ves_heartbeat_feature_start(sr_session_ctx_t *current_session) {
+    assert_session();
+
+    sr_val_t *value = 0;
+    if(pthread_mutex_init(&ves_heartbeat_lock, NULL) != 0) { 
+        log_error("mutex init has failed"); 
+        return NTS_ERR_FAILED; 
+    }
+
+    ves_heartbeat_period = 0;
+    ves_sequence_number = 0;
+
+    int rc = sr_get_item(current_session, HEARTBEAT_SCHEMA_XPATH, 0, &value);
+    if(rc == SR_ERR_OK) {
+        ves_heartbeat_period_set(value->data.uint16_val);
+        sr_free_val(value);
+    }
+    else if(rc != SR_ERR_NOT_FOUND) {
+        log_error("sr_get_item failed");
+    }
+
+    rc = sr_module_change_subscribe(current_session, "nts-network-function", HEARTBEAT_SCHEMA_XPATH, heartbeat_change_cb, NULL, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
+    if(rc != SR_ERR_OK) {
+        log_error("could not subscribe to heartbeat");
+        return NTS_ERR_FAILED;
+    }
+
+    if(pthread_create(&ves_heartbeat_thread, 0, ves_heartbeat_thread_routine, 0)) {
+        log_error("could not create thread for heartbeat");
+        return NTS_ERR_FAILED;
+    }
+
+    return NTS_ERR_OK;
+}
+
+static int ves_heartbeat_period_get(void) {
+    pthread_mutex_lock(&ves_heartbeat_lock);
+    int ret = ves_heartbeat_period;
+    pthread_mutex_unlock(&ves_heartbeat_lock);
+    return ret;
+}
+
+static void ves_heartbeat_period_set(int new_period) {
+    pthread_mutex_lock(&ves_heartbeat_lock);
+    ves_heartbeat_period = new_period;
+    pthread_mutex_unlock(&ves_heartbeat_lock);
+}
+
+static int ves_heartbeat_send_ves_message(void) {
+    char *hostname_string = framework_environment.hostname;
+    cJSON *post_data_json = cJSON_CreateObject();
+    if(post_data_json == 0) {
+        log_error("cJSON_CreateObject failed");
+        return NTS_ERR_FAILED;
+    }
+
+    cJSON *event = cJSON_CreateObject();
+    if(event == 0) {
+        log_error("cJSON_CreateObject failed");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+    
+    if(cJSON_AddItemToObject(post_data_json, "event", event) == 0) {
+        log_error("cJOSN_AddItemToObject failed");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+
+    cJSON *common_event_header = ves_create_common_event_header("heartbeat", "Controller", hostname_string, "Low", ves_sequence_number++);
+    if(common_event_header == 0) {
+        log_error("ves_create_common_event_header failed");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+    
+    if(cJSON_AddItemToObject(event, "commonEventHeader", common_event_header) == 0) {
+        log_error("cJOSN_AddItemToObject failed");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+
+    cJSON *heartbeat_fields = ves_create_heartbeat_fields(ves_heartbeat_period_get());
+    if(heartbeat_fields == 0) {
+        log_error("ves_create_heartbeat_fields failed");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+    
+    if(cJSON_AddItemToObject(event, "heartbeatFields", heartbeat_fields) == 0) {
+        log_error("cJOSN_AddItemToObject failed");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+
+    char *post_data = cJSON_PrintUnformatted(post_data_json);
+    cJSON_Delete(post_data_json);
+    if(post_data == 0) {
+        log_error("cJSON_PrintUnformatted failed");
+        return NTS_ERR_FAILED;
+    }
+
+    ves_details_t *ves_details = ves_endpoint_details_get(0);
+    if(!ves_details) {
+        log_error("ves_endpoint_details_get failed");
+        free(post_data);
+        return NTS_ERR_FAILED;
+    }
+    
+    int rc = http_request(ves_details->url, ves_details->username, ves_details->password, "POST", post_data, 0, 0);
+    ves_details_free(ves_details);
+    free(post_data);
+    
+    if(rc != NTS_ERR_OK) {
+        log_error("http_request failed");
+        return NTS_ERR_FAILED;
+    }
+
+    return NTS_ERR_OK;
+}
+
+static void *ves_heartbeat_thread_routine(void *arg) {
+    int current_heartbeat_period = 0;
+    unsigned int timer_counter = 0;
+
+    while(!framework_sigint) {
+        current_heartbeat_period = ves_heartbeat_period_get();
+        timer_counter++;
+
+        if((timer_counter >= current_heartbeat_period) && (current_heartbeat_period > 0)) {
+            timer_counter = 0;
+
+            int rc = ves_heartbeat_send_ves_message();
+            if(rc != NTS_ERR_FAILED) {
+                log_error("could not send VES heartbeat");
+            }
+        }
+
+        sleep(1);
+    }
+
+    return 0;
+}
+
+static cJSON* ves_create_heartbeat_fields(int heartbeat_period) {
+    cJSON *heartbeat_fields = cJSON_CreateObject();
+    if(heartbeat_fields == 0) {
+        log_error("could not create JSON object");
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(heartbeat_fields, "heartbeatFieldsVersion", "3.0") == 0) {
+        log_error("cJSON_Add*ToObject failed");
+        cJSON_Delete(heartbeat_fields);
+        return 0;
+    }
+
+    if(cJSON_AddNumberToObject(heartbeat_fields, "heartbeatInterval", (double)(heartbeat_period)) == 0) {
+        log_error("cJSON_Add*ToObject failed");
+        cJSON_Delete(heartbeat_fields);
+        return 0;
+    }
+
+    cJSON *additional_fields = cJSON_CreateObject();
+    if(additional_fields == 0) {
+        log_error("could not create JSON object");
+        log_error("cJSON_Add*ToObject failed");
+        cJSON_Delete(heartbeat_fields);
+        return 0;
+    }
+    
+    if(cJSON_AddItemToObject(heartbeat_fields, "additionalFields", additional_fields) == 0) {
+        log_error("cJSON_Add*ToObject failed");
+        cJSON_Delete(heartbeat_fields);
+        return 0;
+    }
+
+    char *current_date_and_time = get_current_date_and_time();
+    if(current_date_and_time == 0) {
+        log_error("get_current_date_and_time failed");
+        cJSON_Delete(heartbeat_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(additional_fields, "eventTime", current_date_and_time) == 0) {
+        log_error("cJSON_Add*ToObject failed");
+        cJSON_Delete(heartbeat_fields);
+        free(current_date_and_time);
+        return 0;
+    }
+    free(current_date_and_time);
+
+    return heartbeat_fields;
+}
+
+static int heartbeat_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data) {
+    sr_change_iter_t *it = 0;
+    int rc = SR_ERR_OK;
+    sr_change_oper_t oper;
+    sr_val_t *old_value = 0;
+    sr_val_t *new_value = 0;
+
+    if(event == SR_EV_DONE) {
+        rc = sr_get_changes_iter(session, HEARTBEAT_SCHEMA_XPATH, &it);
+        if(rc != SR_ERR_OK) {
+            log_error("sr_get_changes_iter failed");
+            return SR_ERR_VALIDATION_FAILED;
+        }
+
+        while((rc = sr_get_change_next(session, it, &oper, &old_value, &new_value)) == SR_ERR_OK) {
+            ves_heartbeat_period_set(new_value->data.uint16_val);
+            sr_free_val(old_value);
+            sr_free_val(new_value);
+        }
+
+        sr_free_change_iter(it);
+    }
+
+    return SR_ERR_OK;
+}
diff --git a/ntsimulator/ntsim-ng/features/ves_heartbeat/ves_heartbeat.h b/ntsimulator/ntsim-ng/features/ves_heartbeat/ves_heartbeat.h
new file mode 100644 (file)
index 0000000..0cea6c7
--- /dev/null
@@ -0,0 +1,22 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <sysrepo.h>
+
+int ves_heartbeat_feature_start(sr_session_ctx_t *current_session);
diff --git a/ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.c b/ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.c
new file mode 100644 (file)
index 0000000..62ccd47
--- /dev/null
@@ -0,0 +1,379 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "ves_pnf_registration.h"
+#include "utils/log_utils.h"
+#include "utils/sys_utils.h"
+#include "utils/rand_utils.h"
+#include "utils/http_client.h"
+#include "utils/nts_utils.h"
+#include <stdio.h>
+#include <assert.h>
+
+#include "core/session.h"
+#include "core/framework.h"
+
+#define PNF_REGISTRATION_SCHEMA_XPATH               "/nts-network-function:simulation/network-function/ves/pnf-registration"
+
+static int ves_pnf_sequence_number = 0;
+
+static int ves_pnf_registration_send(sr_session_ctx_t *current_session, const char *nf_ip_address, int nf_port, bool is_tls);
+static cJSON* ves_create_pnf_registration_fields(const char *nf_ip_address, int nf_port, bool is_tls);
+
+int ves_pnf_registration_feature_start(sr_session_ctx_t *current_session) {
+    assert(current_session);
+
+    ves_pnf_sequence_number = 0;
+
+    sr_val_t *value = 0;
+    int rc = NTS_ERR_OK;
+    bool pnf_registration_enabled = false;
+    rc = sr_get_item(current_session, PNF_REGISTRATION_SCHEMA_XPATH, 0, &value);
+    if(rc == SR_ERR_OK) {
+        pnf_registration_enabled = value->data.bool_val;
+        sr_free_val(value);
+    }
+    else if(rc != SR_ERR_NOT_FOUND) {
+        log_error("sr_get_item failed");
+        return NTS_ERR_FAILED;
+    }
+
+    if(pnf_registration_enabled == false) {
+        log_message(2, "PNF registration is disabled\n");
+        return NTS_ERR_OK;
+    }
+
+    bool host_addressing_enabled = (nts_mount_point_addressing_method_get(current_session) == HOST_MAPPING);
+
+    char nf_ip_address[128];
+    int nf_port;
+
+    if(host_addressing_enabled) {
+        strcpy(nf_ip_address, framework_environment.host_ip);
+        nf_port = framework_environment.host_base_port;
+    }
+    else {
+        if(framework_environment.ip_v6_enabled) {
+            strcpy(nf_ip_address, framework_environment.ip_v6);
+        }
+        else {
+            strcpy(nf_ip_address, framework_environment.ip_v4);
+        } 
+        
+        nf_port = STANDARD_NETCONF_PORT;
+    }
+
+    int port = 0;
+    for(int i = 0; i < framework_environment.ssh_connections; ++port, ++i) {
+        rc = ves_pnf_registration_send(current_session, nf_ip_address, nf_port + port, false);
+        if(rc != NTS_ERR_OK) {
+            log_error("could not send pnfRegistration message for IP=%s and port=%d and protocol SSH", nf_ip_address, nf_port + port);
+            continue;
+        }
+    }
+
+    for(int i = 0; i < framework_environment.tls_connections; ++port, ++i) {
+        rc = ves_pnf_registration_send(current_session, nf_ip_address, nf_port + port, true);
+        if(rc != NTS_ERR_OK) {
+            log_error("could not send pnfRegistration message for IP=%s and port=%d and protocol TLS", nf_ip_address, nf_port + port);
+            continue;
+        }
+    }
+
+    return NTS_ERR_OK;
+}
+
+
+static int ves_pnf_registration_send(sr_session_ctx_t *current_session, const char *nf_ip_address, int nf_port, bool is_tls) {
+    assert(current_session);
+    assert(nf_ip_address);
+
+    cJSON *post_data_json = cJSON_CreateObject();
+    if(post_data_json == 0) {
+        log_error("could not create cJSON object");
+        return NTS_ERR_FAILED;
+    }
+
+    cJSON *event = cJSON_CreateObject();
+    if(event == 0) {
+        log_error("could not create cJSON object");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+    
+    if(cJSON_AddItemToObject(post_data_json, "event", event) == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+
+    char *hostname_string = framework_environment.hostname;
+    char source_name[100];
+       sprintf(source_name, "%s_%d", hostname_string, nf_port);
+
+    cJSON *common_event_header = ves_create_common_event_header("pnfRegistration", "EventType5G", source_name, "Normal", ves_pnf_sequence_number++);
+    if(common_event_header == 0) {
+        log_error("could not create cJSON object");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+    
+    if(cJSON_AddItemToObject(event, "commonEventHeader", common_event_header) == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+
+       cJSON *pnf_registration_fields = ves_create_pnf_registration_fields(nf_ip_address, nf_port, is_tls);
+    if(pnf_registration_fields == 0) {
+        log_error("could not create cJSON object");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+    
+    if(cJSON_AddItemToObject(event, "pnfRegistrationFields", pnf_registration_fields) == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(post_data_json);
+        return NTS_ERR_FAILED;
+    }
+
+    char *post_data = cJSON_PrintUnformatted(post_data_json);
+    cJSON_Delete(post_data_json);
+    if(post_data == 0) {
+        log_error("cJSON_PrintUnformatted failed");
+        return NTS_ERR_FAILED;
+    }
+
+
+    ves_details_t *ves_details = ves_endpoint_details_get(current_session);
+    if(!ves_details) {
+        log_error("ves_endpoint_details_get failed");
+        free(post_data);
+        return NTS_ERR_FAILED;
+    }
+    
+    int rc = http_request(ves_details->url, ves_details->username, ves_details->password, "POST", post_data, 0, 0);
+    ves_details_free(ves_details);
+    free(post_data);
+    
+    if(rc != NTS_ERR_OK) {
+        log_error("http_request failed");
+        return NTS_ERR_FAILED;
+    }
+
+    return NTS_ERR_OK;
+}
+
+static cJSON* ves_create_pnf_registration_fields(const char *nf_ip_address, int nf_port, bool is_tls) {
+    assert(nf_ip_address);
+
+    //checkAL aici n-ar trebui niste valori "adevarate" ?
+
+    cJSON *pnf_registration_fields = cJSON_CreateObject();
+    if(pnf_registration_fields == 0) {
+        log_error("could not create JSON object");
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(pnf_registration_fields, "pnfRegistrationFieldsVersion", "2.0") == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(pnf_registration_fields, "lastServiceDate", "2019-08-16") == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    char *mac_addr = rand_mac_address();
+    if(mac_addr == 0) {
+        log_error("rand_mac_address failed")
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(pnf_registration_fields, "macAddress", mac_addr) == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        free(mac_addr);
+        return 0;
+    }
+    free(mac_addr);
+
+    if(cJSON_AddStringToObject(pnf_registration_fields, "manufactureDate", "2019-08-16") == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(pnf_registration_fields, "modelNumber", "Simulated Device Melacon") == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(pnf_registration_fields, "oamV4IpAddress", nf_ip_address) == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(pnf_registration_fields, "oamV6IpAddress", "0:0:0:0:0:ffff:a0a:011") == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    char serial_number[512];
+    sprintf(serial_number, "%s-%s-%d-Simulated Device Melacon", framework_environment.hostname, nf_ip_address, nf_port);
+
+    if(cJSON_AddStringToObject(pnf_registration_fields, "serialNumber", serial_number) == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(pnf_registration_fields, "softwareVersion", "2.3.5") == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(pnf_registration_fields, "unitFamily", "Simulated Device") == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(pnf_registration_fields, "unitType", "O-RAN-sim") == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(pnf_registration_fields, "vendorName", "Melacon") == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    cJSON *additional_fields = cJSON_CreateObject();
+    if(additional_fields == 0) {
+        log_error("could not create JSON object");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+    cJSON_AddItemToObject(pnf_registration_fields, "additionalFields", additional_fields);
+
+    char port_string[10];
+    sprintf(port_string, "%d", nf_port);
+
+    if(cJSON_AddStringToObject(additional_fields, "oamPort", port_string) == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    if(is_tls) {
+        //TLS specific configuration
+        if(cJSON_AddStringToObject(additional_fields, "protocol", "TLS") == 0) {
+            log_error("cJSON_AddItemToObject failed");
+            cJSON_Delete(pnf_registration_fields);
+            return 0;
+        }
+
+        if(cJSON_AddStringToObject(additional_fields, "username", "netconf") == 0) {
+            log_error("cJSON_AddItemToObject failed");
+            cJSON_Delete(pnf_registration_fields);
+            return 0;
+        }
+
+        if(cJSON_AddStringToObject(additional_fields, "keyId", KS_KEY_NAME) == 0) {
+            log_error("cJSON_AddItemToObject failed");
+            cJSON_Delete(pnf_registration_fields);
+            return 0;
+        }
+    }
+    else {
+        //SSH specific configuration
+        if(cJSON_AddStringToObject(additional_fields, "protocol", "SSH") == 0) {
+            log_error("cJSON_AddItemToObject failed");
+            cJSON_Delete(pnf_registration_fields);
+            return 0;
+        }
+
+        if(cJSON_AddStringToObject(additional_fields, "username", "netconf") == 0) {
+            log_error("cJSON_AddItemToObject failed");
+            cJSON_Delete(pnf_registration_fields);
+            return 0;
+        }
+
+        if(cJSON_AddStringToObject(additional_fields, "password", "netconf") == 0) {
+            log_error("cJSON_AddItemToObject failed");
+            cJSON_Delete(pnf_registration_fields);
+            return 0;
+        }
+    }
+
+    if(cJSON_AddStringToObject(additional_fields, "reconnectOnChangedSchema", "false") == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(additional_fields, "sleep-factor", "1.5") == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(additional_fields, "tcpOnly", "false") == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(additional_fields, "connectionTimeout", "20000") == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(additional_fields, "maxConnectionAttempts", "100") == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(additional_fields, "betweenAttemptsTimeout", "2000") == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(additional_fields, "keepaliveDelay", "120") == 0) {
+        log_error("cJSON_AddItemToObject failed");
+        cJSON_Delete(pnf_registration_fields);
+        return 0;
+    }
+
+    return pnf_registration_fields;
+}
diff --git a/ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.h b/ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.h
new file mode 100644 (file)
index 0000000..0512ed0
--- /dev/null
@@ -0,0 +1,22 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <sysrepo.h>
+
+int ves_pnf_registration_feature_start(sr_session_ctx_t *current_session);
diff --git a/ntsimulator/ntsim-ng/main.c b/ntsimulator/ntsim-ng/main.c
new file mode 100644 (file)
index 0000000..e967d7e
--- /dev/null
@@ -0,0 +1,205 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+
+#include "utils/log_utils.h"
+#include "utils/nc_client.h"
+
+#include "core/framework.h"
+#include "core/docker.h"
+#include "core/session.h"
+#include "core/context.h"
+#include "core/test.h"
+#include "core/nc_config.h"
+
+#include "core/app/manager.h"
+#include "core/app/network_function.h"
+#include "core/datastore/schema.h"
+#include "core/datastore/populate.h"
+#include "core/faults/faults.h"
+
+#include "features/ves_pnf_registration/ves_pnf_registration.h"
+#include "features/ves_heartbeat/ves_heartbeat.h"
+#include "features/ves_file_ready/ves_file_ready.h"
+#include "features/manual_notification/manual_notification.h"
+#include "features/netconf_call_home/netconf_call_home.h"
+
+int main(int argc, char **argv) {
+    int return_code = EXIT_SUCCESS;
+
+    framework_init(argc, argv);
+
+    if(framework_arguments.container_init) {
+        if(!docker_container_init()) {
+            log_error("docker_container_init() failed");
+            return_code = EXIT_FAILURE;   
+        }
+
+        framework_free();
+        return return_code;
+    }
+    else { //not in container-init mode
+        sr_log_stderr(SR_LL_NONE);
+
+        int rc;
+        rc = session_init();
+        if(rc != 0) {
+            log_error("session_init() failed");
+            return_code = EXIT_FAILURE;
+            goto non_container_init_cleanup;
+        }
+
+        rc = context_init(session_context);
+        if(rc != 0) {
+            log_error("context_init() failed");
+            return_code = EXIT_FAILURE;
+            goto non_container_init_cleanup;
+        }
+
+        nc_client_init();
+
+        if(framework_arguments.nc_server_init) {
+            //configure local netconf server
+            rc = netconf_configure();
+            if(rc != 0) {
+                log_error("netconf_configure() failed");
+                return_code = EXIT_FAILURE;
+                goto non_container_init_cleanup;
+            }
+        }
+
+        if(framework_arguments.manager) {
+            //run in manager mode
+            if(manager_run() != NTS_ERR_OK) {
+                return_code = EXIT_FAILURE;
+                goto non_container_init_cleanup;
+            }
+        }
+        else if(framework_arguments.network_function) {
+            //run in network function mode
+            if(network_function_run() != NTS_ERR_OK) {
+                return_code = EXIT_FAILURE;
+                goto non_container_init_cleanup;
+            }
+        }
+        else {
+            if(framework_arguments.test_mode) {
+                if(test_mode_run() != NTS_ERR_OK) {
+                    return_code = EXIT_FAILURE;
+                    goto non_container_init_cleanup;
+                }
+            }
+            else if(framework_arguments.exhaustive_test) {
+                //exhaustive test
+                if(exhaustive_test_run() != NTS_ERR_OK) {
+                    return_code = EXIT_FAILURE;
+                    goto non_container_init_cleanup;
+                }
+            }
+
+            if(framework_arguments.print_root_paths) {
+                //print all root paths with their attributes
+                if(schema_print_root_paths() != NTS_ERR_OK) {
+                    return_code = EXIT_FAILURE;
+                    goto non_container_init_cleanup;
+                }
+            }
+            
+            if(framework_arguments.print_structure_xpath != 0) {
+                //print the associated structure
+                if(schema_print_xpath(framework_arguments.print_structure_xpath) != NTS_ERR_OK) {
+                    return_code = EXIT_FAILURE;
+                    goto non_container_init_cleanup;
+                }
+            }
+            
+            if(framework_arguments.populate_all) {
+                // populate all
+                if(schema_populate() != NTS_ERR_OK) {
+                    return_code = EXIT_FAILURE;
+                    goto non_container_init_cleanup;
+                }
+            }
+
+            if(framework_arguments.enable_features) {
+                // check if PNF registration is enabled and send PNF registration message if so
+                rc = ves_pnf_registration_feature_start(session_running);
+                if(rc != 0) {
+                    log_error("ves_pnf_registration_feature_start() failed");
+                    return_code = EXIT_FAILURE;
+                    goto non_container_init_cleanup;
+                }
+
+                // start feature for handling the heartbeat VES message
+                rc = ves_heartbeat_feature_start(session_running);
+                if(rc != 0) {
+                    log_error("ves_heartbeat_feature_start() failed");
+                    return_code = EXIT_FAILURE;
+                    goto non_container_init_cleanup;
+                }
+
+                // start feature for handling the fileReady VES message
+                rc = ves_file_ready_feature_start(session_running);
+                if(rc != 0) {
+                    log_error("ves_file_ready_feature_start() failed");
+                    return_code = EXIT_FAILURE;
+                    goto non_container_init_cleanup;
+                }
+
+                // start feature for manual notification
+                rc = manual_notification_feature_start(session_running);
+                if(rc != 0) {
+                    log_error("manual_notification_feature_start() failed");
+                    return_code = EXIT_FAILURE;
+                    goto non_container_init_cleanup;
+                }
+
+                // start feature for NETCONF Call Home
+                rc = netconf_call_home_feature_start(session_running);
+                if(rc != 0) {
+                    log_error("netconf_call_home_feature_start() failed");
+                    return_code = EXIT_FAILURE;
+                    goto non_container_init_cleanup;
+                }
+            }
+
+            if(framework_arguments.loop) {
+                while(!framework_sigint) {
+                    sleep(1);
+                }
+            }
+        }
+
+        non_container_init_cleanup:
+        log_message(1, LOG_COLOR_BOLD_RED"\nstopping now...\n"LOG_COLOR_RESET);
+
+        nc_client_destroy();
+        context_free();
+        session_free();
+        framework_free();
+
+        return return_code;
+    }
+
+    return EXIT_FAILURE;
+}
diff --git a/ntsimulator/ntsim-ng/utils/http_client.c b/ntsimulator/ntsim-ng/utils/http_client.c
new file mode 100644 (file)
index 0000000..245223f
--- /dev/null
@@ -0,0 +1,216 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "http_client.h"
+#include "utils/log_utils.h"
+#include "utils/sys_utils.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <curl/curl.h>
+
+struct memory {
+    char *response;
+    size_t size;
+};
+
+static size_t curl_write_cb(void *data, size_t size, size_t nmemb, void *userp);
+int http_request(const char *url, const char *username, const char* password, const char *method, const char *send_data, int *response_code, char **recv_data) {
+    assert(url);
+    assert(method);
+
+    const char *send_data_good = send_data;
+    if(!send_data_good) {
+        send_data_good = "";
+    }
+
+    CURL *curl = curl_easy_init();
+    if(curl == 0) {
+        log_error("could not initialize cURL");
+        return NTS_ERR_FAILED;
+    }
+
+    // set curl options
+    struct curl_slist *header = 0;
+    header = curl_slist_append(header, "Content-Type: application/json");
+    if(!header) {
+        log_error("curl_slist_append failed");
+        curl_easy_cleanup(curl);
+        return NTS_ERR_FAILED;
+    }
+
+    header = curl_slist_append(header, "Accept: application/json");
+    if(!header) {
+        log_error("curl_slist_append failed");
+        curl_easy_cleanup(curl);
+        return NTS_ERR_FAILED;
+    }
+
+    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
+    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 1L);     //seconds timeout for a connection
+    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 1L);            //seconds timeout for an operation
+    curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1L);
+    curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
+
+    // disable SSL verifications
+    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
+    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
+    curl_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 0L);
+    curl_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 0L);
+
+    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method);
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, send_data_good);
+    curl_easy_setopt(curl, CURLOPT_URL, url);
+
+    if((username) && (password)) {
+        char *credentials = 0;
+        asprintf(&credentials, "%s:%s", username, password);
+        if(credentials == 0) {
+            log_error("asprintf failed");
+            curl_slist_free_all(header);
+            curl_easy_cleanup(curl);
+            return NTS_ERR_FAILED;
+        }
+        curl_easy_setopt(curl, CURLOPT_USERPWD, credentials);
+        free(credentials);
+    }
+
+    struct memory response_data = {0};
+    if(recv_data) {
+        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb);
+        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response_data);
+    }
+    
+    log_message(2, "%s-ing cURL to url=\"%s\" with body=\"%s\"\n", method, url, send_data_good);
+    CURLcode res = curl_easy_perform(curl);
+    curl_slist_free_all(header);
+
+    if(res != CURLE_OK) {
+        log_message(2, "--> could not send cURL to url=%s, with error: %s\n", url, curl_easy_strerror(res));
+        curl_easy_cleanup(curl);
+        return NTS_ERR_FAILED;
+    }
+
+    if(response_code) {
+        long http_rc;
+        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_rc);
+        *response_code = http_rc;
+    }
+
+    if(recv_data) {
+        *recv_data = response_data.response;
+    }
+
+    curl_easy_cleanup(curl);
+    return NTS_ERR_OK;
+}
+
+int http_socket_request(const char *url, const char *sock_fname, const char *method, const char *send_data, int *response_code, char **recv_data) {
+    assert(url);
+    assert(sock_fname);
+    assert(method);
+
+    const char *send_data_good = send_data;
+    if(!send_data_good) {
+        send_data_good = "";
+    }
+
+    CURL *curl = curl_easy_init();
+    if(curl == 0) {
+        log_error("could not initialize cURL");
+        return NTS_ERR_FAILED;
+    }
+
+    // set curl options
+    struct curl_slist *header = 0;
+    header = curl_slist_append(header, "Content-Type: application/json");
+    if(!header) {
+        log_error("curl_slist_append failed");
+        curl_easy_cleanup(curl);
+        return NTS_ERR_FAILED;
+    }
+
+    header = curl_slist_append(header, "Accept: application/json");
+    if(!header) {
+        log_error("curl_slist_append failed");
+        curl_easy_cleanup(curl);
+        return NTS_ERR_FAILED;
+    }
+
+    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
+    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 1L);     //seconds timeout for a connection
+    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 2L);            //seconds timeout for an operation
+    curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1L);
+    curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
+
+    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method);
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, send_data_good);
+    curl_easy_setopt(curl, CURLOPT_URL, url);
+    curl_easy_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, sock_fname);
+
+    struct memory response_data = {0};
+    if(recv_data) {
+        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb);
+        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response_data);
+    }
+    
+    log_message(2, "%s-ing cURL to url=\"%s\" with body=\"%s\"\n", method, url, send_data_good);
+    CURLcode res = curl_easy_perform(curl);
+    curl_slist_free_all(header);
+
+    if(res != CURLE_OK) {
+        log_message(2, "--> could not send cURL to url=%s, with error: %s\n", url, curl_easy_strerror(res));
+        curl_easy_cleanup(curl);
+        return NTS_ERR_FAILED;
+    }
+
+    if(response_code) {
+        long http_rc;
+        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_rc);
+        *response_code = http_rc;
+    }
+
+    if(recv_data) {
+        *recv_data = response_data.response;
+    }
+
+    curl_easy_cleanup(curl);
+    return NTS_ERR_OK;
+}
+
+static size_t curl_write_cb(void *data, size_t size, size_t nmemb, void *userp) {
+    size_t realsize = size * nmemb;
+    struct memory *mem = (struct memory *)userp;
+
+    char *ptr = realloc(mem->response, mem->size + realsize + 1);
+    if(ptr == NULL) {
+        log_error("realloc failed");
+        return 0;  /* out of memory! */
+    }
+
+    mem->response = ptr;
+    memcpy(&(mem->response[mem->size]), data, realsize);
+    mem->size += realsize;
+    mem->response[mem->size] = 0;
+
+    return realsize;
+}
diff --git a/ntsimulator/ntsim-ng/utils/http_client.h b/ntsimulator/ntsim-ng/utils/http_client.h
new file mode 100644 (file)
index 0000000..98828ed
--- /dev/null
@@ -0,0 +1,23 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <stdint.h>
+
+int http_request(const char *url, const char *username, const char* password, const char *method, const char *send_data, int *response_code, char **recv_data);
+int http_socket_request(const char *url, const char *sock_fname, const char *method, const char *send_data, int *response_code, char **recv_data);
diff --git a/ntsimulator/ntsim-ng/utils/log_utils.c b/ntsimulator/ntsim-ng/utils/log_utils.c
new file mode 100644 (file)
index 0000000..7624036
--- /dev/null
@@ -0,0 +1,162 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "log_utils.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <time.h>
+#include <assert.h>
+
+#include <core/framework.h>
+
+static int instances = 0;
+static int errors = 0;
+static FILE* logfile = 0;
+
+static char *extract_format(const char *format);
+
+void log_init(const char *logfilename) {
+    assert(instances == 0);
+    instances++;
+
+    logfile = fopen(logfilename, "w");
+
+    assert(logfile);
+
+    time_t t = time(NULL);
+    struct tm tm = *localtime(&t);
+    fprintf(logfile, "started at: %d-%02d-%02d %02d:%02d:%02d\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
+    fprintf(stdout, LOG_COLOR_BOLD_RED"started at: %d-%02d-%02d %02d:%02d:%02d\n"LOG_COLOR_RESET, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
+}
+
+void log__message(char const * const filename, uint32_t location, const int verbose_level, const char *format, ...) {
+    va_list arg;
+
+    char *format2 = 0;
+    asprintf(&format2, "[%s:%u] %s", filename, location, format);
+    if(format2 == 0) {
+        fprintf(stderr, LOG_COLOR_BOLD_RED"bad malloc in log system\n"LOG_COLOR_RESET);
+        format2 = (char *)format;
+    }
+
+    va_start(arg, format);
+    char *new_format = extract_format(format2);
+    vfprintf(logfile, new_format, arg);
+
+    if(new_format != format2) {
+        free(new_format);
+    }
+
+    if(format2 != format) {
+        free(format2);
+    }
+    fflush(logfile);
+    va_end(arg);
+
+    if(verbose_level <= framework_arguments.verbosity_level) {
+        va_start(arg, format);
+        vfprintf(stdout, format, arg);
+        va_end(arg);
+    }
+}
+
+void log__error(char const * const function, uint32_t location, const char *format, ...) {
+    va_list arg;
+    bool has_newline = false;
+    if(format[strlen(format) - 1] == '\n') {
+        has_newline = true;
+    }
+
+    errors++;
+    char *new_format = extract_format(format);
+    fprintf(logfile, "[error in %s():%d] ", function, location);
+    va_start(arg, format);
+    vfprintf(logfile, new_format, arg);
+    if(new_format != format) {
+        free(new_format);
+    }
+    if(!has_newline) {
+        fprintf(logfile, "\n");
+    }
+    fflush(logfile);
+    va_end(arg);
+
+    fprintf(stderr, "["LOG_COLOR_RED"error in "LOG_COLOR_BOLD_RED"%s()"LOG_COLOR_RED":"LOG_COLOR_BOLD_CYAN"%d"LOG_COLOR_RESET"] ", function, location);
+    va_start(arg, format);
+    vfprintf(stderr, format, arg);
+    if(!has_newline) {
+        fprintf(stderr, "\n");
+    }
+    va_end(arg);
+}
+
+void log_close(void) {
+    time_t t = time(NULL);
+    struct tm tm = *localtime(&t);
+    fprintf(logfile, "finished at: %d-%02d-%02d %02d:%02d:%02d\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
+    fclose(logfile);
+
+    if(errors) {
+        fprintf(stderr, "-------- !!!!!! ERRORS WERE PRESENT, CHECK ERROR FILE !!!!!! ------------\n\n\n\n");
+    }
+}
+
+static char *extract_format(const char *format) {
+    assert(format);
+
+    int l = strlen(format);
+    char *ret = (char *)malloc(sizeof(char) * (l + 1));
+    if(ret == 0) {
+        fprintf(stderr, LOG_COLOR_BOLD_RED"bad malloc in log system\n"LOG_COLOR_RESET);
+        return (char *)format;
+    }
+
+    int s = 0;
+    int d = 0;
+    bool in_escape = false;
+
+    while(s < l) {
+        if(!in_escape) {
+            //escape char
+            if(format[s] == 27) {
+                in_escape = true;
+                s++;
+            }
+        }
+        else {
+            if(format[s] == 'm') {
+                in_escape = false;
+                s++;
+            }
+        }
+
+
+        if(!in_escape) {
+            ret[d++] = format[s];
+        }
+
+        s++;
+    }
+
+    ret[d] = 0;
+  
+    return ret;
+}
diff --git a/ntsimulator/ntsim-ng/utils/log_utils.h b/ntsimulator/ntsim-ng/utils/log_utils.h
new file mode 100644 (file)
index 0000000..59fd277
--- /dev/null
@@ -0,0 +1,51 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <string.h>
+#include <stdint.h>
+
+#define LOG_COLOR_RESET         "\033[0m"
+#define LOG_COLOR_RED           "\033[0;31m"
+#define LOG_COLOR_BOLD_RED      "\033[1;31m"
+#define LOG_COLOR_GREEN         "\033[0;32m"
+#define LOG_COLOR_BOLD_GREEN    "\033[1;32m"
+#define LOG_COLOR_YELLOW        "\033[0;33m"
+#define LOG_COLOR_BOLD_YELLOW   "\033[01;33m"
+#define LOG_COLOR_BLUE          "\033[0;34m"
+#define LOG_COLOR_BOLD_BLUE     "\033[1;34m"
+#define LOG_COLOR_MAGENTA       "\033[0;35m"
+#define LOG_COLOR_BOLD_MAGENTA  "\033[1;35m"
+#define LOG_COLOR_CYAN          "\033[0;36m"
+#define LOG_COLOR_BOLD_CYAN     "\033[1;36m"
+
+#define NTS_ERR_OK                             (0)
+#define NTS_ERR_FAILED                         (-1)
+
+void log_init(const char *logfilename);
+void log_message(const int verbose_level, const char *format, ...);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wvariadic-macros"
+#define log_message(verbose_level, format, args...)  log__message(__FILE__, (uint32_t)__LINE__, verbose_level, format, ## args);
+#define log_error(format, args...)  log__error(__func__, (uint32_t)__LINE__, format, ## args);
+#pragma GCC diagnostic pop
+void log_close(void);
+
+//use log_error instead
+void log__error(char const * const function, uint32_t location, const char *format, ...);
+void log__message(char const * const filename, uint32_t location, const int verbose_level, const char *format, ...);
diff --git a/ntsimulator/ntsim-ng/utils/nc_client.c b/ntsimulator/ntsim-ng/utils/nc_client.c
new file mode 100644 (file)
index 0000000..f3cb997
--- /dev/null
@@ -0,0 +1,352 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "nc_client.h"
+#include "utils/log_utils.h"
+#include "utils/sys_utils.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "core/session.h"
+
+#include <libnetconf2/session.h>
+#include <libnetconf2/session_client.h>
+#include <libnetconf2/messages_client.h>
+
+static char *nc_client_pass_cb(const char *username, const char *hostname, void *priv) {
+    nc_client_t *client = (nc_client_t *)priv;
+    return strdup(client->password);
+}
+
+static int nc_client_auth_hostkey_check(const char *hostname, ssh_session session, void *priv) {
+    return 0;   //auto-authorize
+}
+
+nc_client_t *nc_client_ssh_connect(const char *host, uint16_t port, const char *username, const char *password) {
+    assert(host);
+    assert(port > 20);
+    assert(username);
+    assert(password);
+
+    nc_client_t *client = (nc_client_t *)malloc(sizeof(nc_client_t));
+    if(client == 0) {
+        return 0;
+    }
+
+    client->edit_batch_root = 0;
+
+    nc_client_init();
+
+    nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, 3);
+    nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, -1);
+    nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, -1);
+
+    nc_client_ssh_set_username(username);
+    client->password = strdup(password);
+    if(client->password == 0) {
+        free(client);
+    }
+
+    nc_client_ssh_set_auth_password_clb(nc_client_pass_cb, client);
+    nc_client_ssh_set_auth_hostkey_check_clb(nc_client_auth_hostkey_check, 0);
+
+    client->session = nc_connect_ssh(host, port, 0);
+    if(client->session == 0) {
+        log_error("nc_connect_ssh failed");
+        free(client->password);
+        free(client);
+        return 0;
+    }
+
+    return client;
+}
+
+int nc_client_disconnect(nc_client_t *client) {
+    assert(client);
+    
+    nc_session_free(client->session, 0);
+    free(client->password);
+    free(client);
+
+    return NTS_ERR_OK;
+}
+
+struct lyd_node *nc_client_send_rpc(nc_client_t *client, struct lyd_node *data, int timeout) {
+    assert(client);
+    assert(data);
+
+    struct nc_rpc *rpc;
+    struct nc_reply *reply;
+    NC_MSG_TYPE send_ret;
+    NC_MSG_TYPE reply_ret;
+    uint64_t msg_id;
+
+    char *xmldata = 0;
+    if(lyd_print_mem(&xmldata, data, LYD_XML, 0) != 0) {
+        log_error("lyd_print_mem failed");
+        return 0;
+    }
+
+    rpc = nc_rpc_act_generic_xml(xmldata, NC_PARAMTYPE_CONST);
+    if(rpc == 0) {
+        log_error("could not create rpc");
+        free(xmldata);
+        return 0;
+    }
+
+    msg_id = 0;
+    send_ret = nc_send_rpc(client->session, rpc, timeout, &msg_id);
+    if(send_ret != NC_MSG_RPC) {
+        log_error("could not send rpc");
+        free(xmldata);
+        nc_rpc_free(rpc);
+        return 0;
+    }
+
+    repeat_nc_recv_reply:
+    reply_ret = nc_recv_reply(client->session, rpc, msg_id, timeout, LYD_OPT_DESTRUCT | LYD_OPT_NOSIBLINGS, &reply);
+    if(reply_ret != NC_MSG_REPLY) {
+        if(reply_ret == NC_MSG_NOTIF) {
+            goto repeat_nc_recv_reply;
+        }
+
+        log_error("could not get rpc reply");
+        free(xmldata);
+        nc_rpc_free(rpc);
+        return 0;
+    }
+
+    if(reply->type != NC_RPL_DATA) {
+        log_error("reply has no data");
+        free(xmldata);
+        nc_rpc_free(rpc);
+        nc_reply_free(reply);
+        return 0;
+    }
+
+    char *ret_data_xml = strdup("");    //libyang does not support having the parent RPC in XML
+    struct lyd_node *chd = 0;
+    LY_TREE_FOR(((struct nc_reply_data *)reply)->data->child, chd) {
+        char *temp_xml = 0;
+        if(lyd_print_mem(&temp_xml, chd, LYD_XML, 0) != 0) {
+            log_error("lyd_print_mem failed");
+            free(ret_data_xml);
+            free(xmldata);
+            nc_rpc_free(rpc);
+            nc_reply_free(reply);
+            return 0;
+        }
+
+        ret_data_xml = (char *)realloc(ret_data_xml, sizeof(char) * (strlen(ret_data_xml) + strlen(temp_xml) + 1));
+        strcat(ret_data_xml, temp_xml);
+        free(temp_xml);
+    }
+    
+    free(xmldata);
+    nc_reply_free(reply);
+    nc_rpc_free(rpc);
+
+    struct lyd_node *ret_data = lyd_parse_mem(session_context, ret_data_xml, LYD_XML, LYD_OPT_RPCREPLY | LYD_OPT_NOEXTDEPS, data, 0);
+    free(ret_data_xml);
+    return ret_data;
+}
+
+struct lyd_node *nc_client_get_batch(nc_client_t *client, const char *xpath, int timeout) {
+    assert(client);
+    assert(xpath);
+
+    struct nc_rpc *rpc;
+    struct nc_reply *reply;
+    NC_MSG_TYPE send_ret;
+    NC_MSG_TYPE reply_ret;
+    uint64_t msg_id;
+
+    rpc = nc_rpc_get(xpath, NC_WD_UNKNOWN, NC_PARAMTYPE_CONST);
+    if(rpc == 0) {
+        log_error("could not create rpc");
+        return 0;
+    }
+
+    msg_id = 0;
+    send_ret = nc_send_rpc(client->session, rpc, timeout, &msg_id);
+    if(send_ret != NC_MSG_RPC) {
+        log_error("could not send rpc");
+        nc_rpc_free(rpc);
+        return 0;
+    }
+
+    repeat_nc_recv_reply:
+    reply_ret = 0;
+    reply_ret = nc_recv_reply(client->session, rpc, msg_id, timeout, LYD_OPT_DESTRUCT | LYD_OPT_NOSIBLINGS, &reply);
+    if(reply_ret != NC_MSG_REPLY) {
+        if(reply_ret == NC_MSG_NOTIF) {
+            goto repeat_nc_recv_reply;
+        }
+
+        log_error("could not get rpc reply");
+        nc_rpc_free(rpc);
+        return 0;
+    }
+
+    if(reply->type != NC_RPL_DATA) {
+        log_error("reply has no data");
+        nc_rpc_free(rpc);
+        nc_reply_free(reply);
+        return 0;
+    }
+
+    char *ret_data_xml = 0;
+    if(lyd_print_mem(&ret_data_xml, ((struct nc_reply_data *)reply)->data, LYD_XML, 0) != 0) {
+        log_error("lyd_print_mem failed");
+        nc_reply_free(reply);
+        nc_rpc_free(rpc);
+        return 0;
+    }
+    
+    nc_reply_free(reply);
+    nc_rpc_free(rpc);
+
+    struct lyd_node *ret_data = lyd_parse_mem(session_context, ret_data_xml, LYD_XML, LYD_OPT_DATA | LYD_OPT_NOSIBLINGS);
+    free(ret_data_xml);
+    return ret_data;
+}
+
+int nc_client_edit_batch(nc_client_t *client, struct lyd_node *data, int timeout) {
+    assert(client);
+    assert(data);
+
+    struct nc_rpc *rpc;
+    struct nc_reply *reply;
+    NC_MSG_TYPE send_ret;
+    NC_MSG_TYPE reply_ret;
+    uint64_t msg_id;
+
+    char *content = 0;
+    int rc = lyd_print_mem(&content, data, LYD_XML, 0);
+    if(rc != 0) {
+        log_error("lyd_print_mem failed");
+        return NTS_ERR_FAILED;
+    }
+
+    rpc = nc_rpc_edit(NC_DATASTORE_RUNNING, NC_RPC_EDIT_DFLTOP_MERGE, NC_RPC_EDIT_TESTOPT_SET, NC_RPC_EDIT_ERROPT_STOP, content, NC_PARAMTYPE_CONST);
+    if(rpc == 0) {
+        log_error("could not create rpc");
+        free(content);
+        return NTS_ERR_FAILED;
+    }
+    
+    msg_id = 0;
+    send_ret = nc_send_rpc(client->session, rpc, timeout, &msg_id);
+    if(send_ret != NC_MSG_RPC) {
+        log_error("could not send rpc");
+        free(content);
+        nc_rpc_free(rpc);
+        return NTS_ERR_FAILED;
+    }
+
+    reply_ret = nc_recv_reply(client->session, rpc, msg_id, timeout, LYD_OPT_DESTRUCT | LYD_OPT_NOSIBLINGS, &reply);
+    if((reply_ret != NC_MSG_REPLY) || (reply->type != NC_RPL_OK)) {
+        log_error("could not get rpc reply");
+
+        free(content);
+        nc_rpc_free(rpc);
+        return NTS_ERR_FAILED;
+    }
+    
+    free(content);
+    nc_reply_free(reply);
+    nc_rpc_free(rpc);
+
+    return NTS_ERR_OK;
+}
+
+int nc_client_set_item_str(nc_client_t *client, const char *xpath, const char *value) {
+    assert(client);
+    assert(xpath);
+    assert(value);
+
+    if(client->edit_batch_root) {
+        struct lyd_node *n = lyd_new_path(client->edit_batch_root, 0, xpath, (void*)value, LYD_ANYDATA_CONSTSTRING, 0);
+        if(n == 0) {
+            log_error("lyd_new_path error");
+            return NTS_ERR_FAILED;
+        }
+    }
+    else {
+        client->edit_batch_root = lyd_new_path(0, session_context, xpath, (void*)value, LYD_ANYDATA_CONSTSTRING, 0);
+        if(client->edit_batch_root == 0) {
+            log_error("lyd_new_path error");
+            return NTS_ERR_FAILED;
+        }
+    }
+
+    return NTS_ERR_OK;
+}
+
+int nc_client_edit_apply_changes(nc_client_t *client, int timeout) {
+    assert(client);
+    assert(client->edit_batch_root);
+
+    int rc = nc_client_edit_batch(client, client->edit_batch_root, timeout);
+    lyd_free_withsiblings(client->edit_batch_root);
+    client->edit_batch_root = 0;
+    return rc;
+}
+
+int lyd_utils_dup(sr_session_ctx_t *session, const char *xpath_s, const char *xpath_d, struct lyd_node **tree) {
+    assert(session);
+    assert(xpath_s);
+    assert(xpath_d);
+    assert(tree);
+
+    if(*tree == 0) {
+        *tree = lyd_new_path(0, session_context, xpath_d, 0, LYD_ANYDATA_CONSTSTRING, 0);
+        if(*tree == 0) {
+            return NTS_ERR_FAILED;
+        }
+    }
+
+    struct lyd_node *data_s = 0;
+    int rc = sr_get_data(session, xpath_s, 0, 0, 0, &data_s);
+    if(rc != SR_ERR_OK) {
+        log_error("could not get value for xPath=%s from the datastore\n", xpath_s);
+        lyd_free(*tree);
+        return NTS_ERR_FAILED;
+    }
+
+    struct lyd_node *next = 0;
+    struct lyd_node *snode = 0;
+    LY_TREE_DFS_BEGIN(data_s, next, snode) {
+        char *xpath_c = lyd_path(snode);
+        if((snode->schema->nodetype == LYS_LEAF) || (snode->schema->nodetype == LYS_LEAFLIST)) {
+            const char *value = ((struct lyd_node_leaf_list*)snode)->value_str;
+            char *new_xpath = str_replace(xpath_c, xpath_s, xpath_d);
+            
+            ly_log_options(0);
+            lyd_new_path(*tree, 0, new_xpath, (void*)value, LYD_ANYDATA_CONSTSTRING, 0);
+            free(xpath_c);
+            free(new_xpath);
+        }
+        LY_TREE_DFS_END(data_s, next, snode);
+    }
+
+    lyd_free(data_s);
+    return NTS_ERR_OK;
+}
diff --git a/ntsimulator/ntsim-ng/utils/nc_client.h b/ntsimulator/ntsim-ng/utils/nc_client.h
new file mode 100644 (file)
index 0000000..c5f66b3
--- /dev/null
@@ -0,0 +1,47 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#define NC_ENABLED_SSH
+#include <libyang/libyang.h>
+#include <libnetconf2/session.h>
+#include <libnetconf2/session_client.h>
+#include <sysrepo.h>
+
+// void nc_client_init(void);   --imported from libnetconf2, must be called on app init
+// void nc_client_destroy(void);   --imported from libnetconf2, must be called on app deinit
+
+typedef struct {
+    struct nc_session *session;
+    struct lyd_node *edit_batch_root;
+
+    char *password;
+} nc_client_t;
+
+nc_client_t *nc_client_ssh_connect(const char *host, uint16_t port, const char *username, const char *password);
+int nc_client_disconnect(nc_client_t *client);
+
+struct lyd_node *nc_client_send_rpc(nc_client_t *client, struct lyd_node *data, int timeout);
+
+struct lyd_node *nc_client_get_batch(nc_client_t *client, const char *xpath, int timeout);
+int nc_client_edit_batch(nc_client_t *client, struct lyd_node *data, int timeout);
+
+int nc_client_set_item_str(nc_client_t *client, const char *xpath, const char *value);
+int nc_client_edit_apply_changes(nc_client_t *client, int timeout);
+
+int lyd_utils_dup(sr_session_ctx_t *session, const char *xpath_s, const char *xpath_d, struct lyd_node **tree);
diff --git a/ntsimulator/ntsim-ng/utils/nts_utils.c b/ntsimulator/ntsim-ng/utils/nts_utils.c
new file mode 100644 (file)
index 0000000..b3c7d5d
--- /dev/null
@@ -0,0 +1,425 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "nts_utils.h"
+#include "utils/log_utils.h"
+#include "utils/sys_utils.h"
+#include "core/framework.h"
+#include "core/session.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+#define MOUNT_POINT_ADDRESSING_METHOD_SCHEMA_XPATH  "/nts-network-function:simulation/network-function/mount-point-addressing-method"
+
+cJSON* ves_create_common_event_header(const char *domain, const char *event_type, const char *source_name, const char *priority, int seq_id) {
+    assert(domain);
+    assert(event_type);
+    assert(source_name);
+    assert(priority);
+
+    char *eventId = 0;
+    long useconds = get_microseconds_since_epoch();
+
+    asprintf(&eventId, "%s-%d", event_type, seq_id);
+    if(eventId == 0) {
+        log_error("asprintf failed");
+        return 0;
+    }
+
+    cJSON *common_event_header = cJSON_CreateObject();
+    if(common_event_header == 0) {
+        log_error("could not create JSON object");
+        free(eventId);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(common_event_header, "domain", domain) == 0) {
+        log_error("cJSON AddStringToObject error");
+        free(eventId);
+        cJSON_Delete(common_event_header);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(common_event_header, "eventId", eventId) == 0) {
+        log_error("cJSON AddStringToObject error");
+        free(eventId);
+        cJSON_Delete(common_event_header);
+        return 0;
+    }
+
+    free(eventId);
+
+    if(cJSON_AddStringToObject(common_event_header, "eventName", event_type) == 0) {
+        log_error("cJSON AddStringToObject error");
+        cJSON_Delete(common_event_header);
+        return 0;
+    }
+
+    if(cJSON_AddNumberToObject(common_event_header, "sequence", (double)(seq_id)) == 0) {
+        log_error("cJSON AddNumberToObject error");
+        cJSON_Delete(common_event_header);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(common_event_header, "priority", priority) == 0) {
+        log_error("cJSON AddStringToObject error");
+        cJSON_Delete(common_event_header);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(common_event_header, "reportingEntityId", "") == 0) {
+        log_error("cJSON AddStringToObject error");
+        cJSON_Delete(common_event_header);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(common_event_header, "reportingEntityName", source_name) == 0) {
+        log_error("cJSON AddStringToObject error");
+        cJSON_Delete(common_event_header);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(common_event_header, "sourceId", "") == 0) {
+        log_error("cJSON AddStringToObject error");
+        cJSON_Delete(common_event_header);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(common_event_header, "sourceName", source_name) == 0) {
+        log_error("cJSON AddStringToObject error");
+        cJSON_Delete(common_event_header);
+        return 0;
+    }
+
+    if(cJSON_AddNumberToObject(common_event_header, "startEpochMicrosec", (double)(useconds)) == 0) {
+        log_error("cJSON AddNumberToObject error");
+        cJSON_Delete(common_event_header);
+        return 0;
+    }
+
+    if(cJSON_AddNumberToObject(common_event_header, "lastEpochMicrosec", (double)(useconds)) == 0) {
+        log_error("cJSON AddNumberToObject error");
+        cJSON_Delete(common_event_header);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(common_event_header, "nfNamingCode", "sdn controller") == 0) {
+        log_error("cJSON AddStringToObject error");
+        cJSON_Delete(common_event_header);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(common_event_header, "nfVendorName", "sdn") == 0) {
+        log_error("cJSON AddStringToObject error");
+        cJSON_Delete(common_event_header);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(common_event_header, "timeZoneOffset", "+00:00") == 0) {
+        log_error("cJSON AddStringToObject error");
+        cJSON_Delete(common_event_header);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(common_event_header, "version", "4.1") == 0) {
+        log_error("cJSON AddStringToObject error");
+        cJSON_Delete(common_event_header);
+        return 0;
+    }
+
+    if(cJSON_AddStringToObject(common_event_header, "vesEventListenerVersion", "7.2") == 0) {
+        log_error("cJSON AddStringToObject error");
+        cJSON_Delete(common_event_header);
+        return 0;
+    }
+
+    return common_event_header;
+}
+
+nts_mount_point_addressing_method_t nts_mount_point_addressing_method_get(sr_session_ctx_t *current_session) {
+    assert_session();
+
+    nts_mount_point_addressing_method_t ret = UNKNOWN_MAPPING;
+
+    int rc;
+    bool session_started = false;
+    if(current_session == 0) {
+        rc = sr_session_start(session_connection, SR_DS_RUNNING, &current_session);
+        if(rc != SR_ERR_OK) {
+            log_error("could not start sysrepo session");
+            return ret;
+        }
+        session_started = true;
+    }
+
+    sr_val_t *value = 0;
+    rc = sr_get_item(session_running, MOUNT_POINT_ADDRESSING_METHOD_SCHEMA_XPATH, 0, &value);
+    if(rc == SR_ERR_OK) {
+        if(strcmp(value->data.enum_val, "host-mapping") == 0) {
+            ret = HOST_MAPPING;
+        }
+        else {
+            ret = DOCKER_MAPPING;
+        }
+        sr_free_val(value);
+    }
+
+    if(session_started) {
+        rc = sr_session_stop(current_session);
+        if(rc != SR_ERR_OK) {
+            log_error("could not stop sysrepo session");
+            return ret;
+        }
+    }
+
+    return ret;
+}
+
+// checkAS authentication via certificate not supported yet
+ves_details_t *ves_endpoint_details_get(sr_session_ctx_t *current_session) {
+    assert_session();
+
+    int rc;
+    bool session_started = false;
+    if(current_session == 0) {
+        rc = sr_session_start(session_connection, SR_DS_RUNNING, &current_session);
+        if(rc != SR_ERR_OK) {
+            log_error("could not start sysrepo session");
+            return 0;
+        }
+        session_started = true;
+    }
+
+    struct lyd_node *data = 0;
+    char *xpath_to_get;
+
+    if(framework_arguments.manager) {
+        xpath_to_get = "/nts-manager:simulation/ves-endpoint";
+    }
+    else {
+        xpath_to_get = "/nts-network-function:simulation/ves-endpoint";
+    }
+
+    rc = sr_get_subtree(current_session, xpath_to_get, 0, &data);
+    if(rc != SR_ERR_OK) {
+        log_error("could not get value for xPath=%s from the running datastore\n", xpath_to_get);
+        if(session_started) {
+            sr_session_stop(current_session);
+        }
+        return 0;
+    }
+
+    if(session_started) {
+        rc = sr_session_stop(current_session);
+        if(rc != SR_ERR_OK) {
+            log_error("could not stop sysrepo session");
+            lyd_free(data);
+            return 0;
+        }
+    }
+
+    if(data->child == 0) {
+        log_error("ves-endpoint probably not set yet\n", xpath_to_get);
+        lyd_free(data);
+        return 0;
+    }
+
+    ves_details_t *ret = (ves_details_t *)malloc(sizeof(ves_details_t));
+    if(!ret) {
+        log_error("malloc failed");
+        lyd_free(data);
+        return 0;
+    }
+
+    ret->protocol = 0;
+    ret->ip = 0;
+    ret->port = 0;
+    ret->auth_method = 0;
+    ret->username = 0;
+    ret->password = 0;
+
+    struct lyd_node *chd = 0;
+    LY_TREE_FOR(data->child, chd) {
+        const char *val = ((const struct lyd_node_leaf_list *)chd)->value_str;
+
+        if(strcmp(chd->schema->name, "ves-endpoint-protocol") == 0) {
+            ret->protocol = strdup(val);
+        }
+        else if(strcmp(chd->schema->name, "ves-endpoint-ip") == 0) {
+            ret->ip = strdup(val);
+        }
+        else if(strcmp(chd->schema->name, "ves-endpoint-port") == 0) {
+            ret->port = ((const struct lyd_node_leaf_list *)chd)->value.uint16;
+        }
+        else if(strcmp(chd->schema->name, "ves-endpoint-auth-method") == 0) {
+            ret->auth_method = strdup(val);
+        }
+        else if(strcmp(chd->schema->name, "ves-endpoint-username") == 0) {
+            ret->username = strdup(val);
+        }
+        else if(strcmp(chd->schema->name, "ves-endpoint-password") == 0) {
+            ret->password = strdup(val);
+        }
+    }
+    lyd_free(data);
+
+    asprintf(&ret->url, "%s://%s:%d/eventListener/v7", ret->protocol, ret->ip, ret->port);
+    if((ret->protocol == 0) || (ret->ip == 0) || (ret->auth_method == 0) || (ret->username == 0) || (ret->password == 0) || (ret->url == 0)) {
+        free(ret->protocol);
+        free(ret->ip);
+        free(ret->auth_method);
+        free(ret->username);
+        free(ret->password);
+        free(ret->url);
+        free(ret);
+        ret = 0;
+    }
+
+    return ret;
+}
+
+void ves_details_free(ves_details_t *instance) {
+    assert(instance);
+
+    free(instance->protocol);
+    free(instance->ip);
+    free(instance->url);
+    free(instance->auth_method);
+    free(instance->username);
+    free(instance->password);
+    free(instance);
+}
+
+
+// checkAS authentication via certificate not supported yet
+controller_details_t *controller_details_get(sr_session_ctx_t *current_session) {
+    assert_session();
+
+    int rc;
+    bool session_started = false;
+    if(current_session == 0) {
+        rc = sr_session_start(session_connection, SR_DS_RUNNING, &current_session);
+        if(rc != SR_ERR_OK) {
+            log_error("could not start sysrepo session");
+            return 0;
+        }
+        session_started = true;
+    }
+
+    struct lyd_node *data = 0;
+    char *xpath_to_get;
+
+    if(framework_arguments.manager) {
+        xpath_to_get = "/nts-manager:simulation/sdn-controller";
+    }
+    else {
+        xpath_to_get = "/nts-network-function:simulation/sdn-controller";
+    }
+
+    rc = sr_get_subtree(current_session, xpath_to_get, 0, &data);
+    if(rc != SR_ERR_OK) {
+        log_error("could not get value for xPath=%s from the running datastore\n", xpath_to_get);
+        if(session_started) {
+            sr_session_stop(current_session);
+        }
+        return 0;
+    }
+
+    if(session_started) {
+        rc = sr_session_stop(current_session);
+        if(rc != SR_ERR_OK) {
+            log_error("could not stop sysrepo session");
+            lyd_free(data);
+            return 0;
+        }
+    }
+
+    if(data->child == 0) {
+        log_error("sdn-controller probably not set yet\n");
+        lyd_free(data);
+        return 0;
+    }
+
+    controller_details_t *ret = (controller_details_t *)malloc(sizeof(controller_details_t));
+    if(!ret) {
+        log_error("malloc failed");
+        lyd_free(data);
+        return 0;
+    }
+
+    ret->protocol = 0;
+    ret->ip = 0;
+    ret->port = 0;
+    ret->nc_callhome_port = 0;
+    ret->auth_method = 0;
+    ret->username = 0;
+    ret->password = 0;
+
+    ret->protocol = strdup("http");
+    ret->auth_method = strdup("basic");
+
+    struct lyd_node *chd = 0;
+    LY_TREE_FOR(data->child, chd) {
+        const char *val = ((const struct lyd_node_leaf_list *)chd)->value_str;
+
+        if(strcmp(chd->schema->name, "controller-ip") == 0) {
+            ret->ip = strdup(val);
+        }
+        else if(strcmp(chd->schema->name, "controller-port") == 0) {
+            ret->port = ((const struct lyd_node_leaf_list *)chd)->value.uint16;
+        }
+        else if(strcmp(chd->schema->name, "controller-netconf-call-home-port") == 0) {
+            ret->nc_callhome_port = ((const struct lyd_node_leaf_list *)chd)->value.uint16;
+        }
+        else if(strcmp(chd->schema->name, "controller-username") == 0) {
+            ret->username = strdup(val);
+        }
+        else if(strcmp(chd->schema->name, "controller-password") == 0) {
+            ret->password = strdup(val);
+        }
+    }
+    lyd_free(data);
+
+    asprintf(&ret->base_url, "%s://%s:%d", ret->protocol, ret->ip, ret->port);
+    if((ret->protocol == 0) || (ret->ip == 0) || (ret->auth_method == 0) || (ret->username == 0) || (ret->password == 0) || (ret->base_url == 0)) {
+        free(ret->protocol);
+        free(ret->ip);
+        free(ret->auth_method);
+        free(ret->username);
+        free(ret->password);
+        free(ret->base_url);
+        free(ret);
+        ret = 0;
+    }
+
+    return ret;
+}
+
+void controller_details_free(controller_details_t *instance) {
+    assert(instance);
+
+    free(instance->protocol);
+    free(instance->ip);
+    free(instance->base_url);
+    free(instance->auth_method);
+    free(instance->username);
+    free(instance->password);
+    free(instance);
+}
diff --git a/ntsimulator/ntsim-ng/utils/nts_utils.h b/ntsimulator/ntsim-ng/utils/nts_utils.h
new file mode 100644 (file)
index 0000000..29f3944
--- /dev/null
@@ -0,0 +1,61 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <stdint.h>
+#include <cjson/cJSON.h>
+#include <sysrepo.h>
+
+typedef enum {
+    UNKNOWN_MAPPING = 0,
+    DOCKER_MAPPING = 1,
+    HOST_MAPPING = 2,
+} nts_mount_point_addressing_method_t;
+
+typedef struct {
+    char *protocol;
+    char *ip;
+    uint16_t port;
+    char *auth_method;
+    char *username;
+    char *password;
+
+    char *url;
+} ves_details_t;
+
+typedef struct {    
+    char *ip;
+    uint16_t port;
+    uint16_t nc_callhome_port;
+    char *username;
+    char *password;
+
+    char *protocol;
+    char *base_url;
+    char *auth_method;
+} controller_details_t;
+
+cJSON* ves_create_common_event_header(const char *domain, const char *event_type, const char *source_name, const char *priority, int seq_id);
+
+nts_mount_point_addressing_method_t nts_mount_point_addressing_method_get(sr_session_ctx_t *current_session);
+
+ves_details_t *ves_endpoint_details_get(sr_session_ctx_t *current_session);
+void ves_details_free(ves_details_t *instance);
+
+controller_details_t *controller_details_get(sr_session_ctx_t *current_session);
+void controller_details_free(controller_details_t *instance);
diff --git a/ntsimulator/ntsim-ng/utils/rand_utils.c b/ntsimulator/ntsim-ng/utils/rand_utils.c
new file mode 100644 (file)
index 0000000..28222e6
--- /dev/null
@@ -0,0 +1,920 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "rand_utils.h"
+#include "log_utils.h"
+#include "sys_utils.h"  //for b64_encode
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <inttypes.h>
+#include <assert.h>
+#include <math.h>
+
+#include "core/context.h"       //for context_get_identity_leafs_of_type
+#include "core/framework.h"     //to check for no_rand
+
+//private definitions
+typedef struct __rand_range {
+    union {
+        int64_t num;
+        double dec;
+    } value;
+
+    union {
+        int64_t num;
+        double dec;
+    } min;
+
+    union {
+        int64_t num;
+        double dec;
+    } max;
+} rand_range_t;
+
+//private functions
+static char *rand_string(int min_length, int max_length);
+static struct lys_ident *rand_identity(struct lys_ident *type);
+
+//random based on ranges
+static int64_t rand_range_type_int_min(LY_DATA_TYPE type);
+static int64_t rand_range_type_int_max(LY_DATA_TYPE type);
+static rand_range_t rand_range(const char *range, const LY_DATA_TYPE type);
+
+//for the following functions, the result should be freed by the user
+static char *rand_date_and_time(void);
+static char *rand_ipv4_address(void);
+static char *rand_ipv6_address(void);
+static char *rand_uuid(void);
+
+
+void rand_init(void) {
+    unsigned int seed;
+
+    FILE* urandom = fopen("/dev/urandom", "r");
+    if(urandom == 0) {
+        log_error("failed to open /dev/urandom");
+    }
+    else {
+        fread(&seed, sizeof(int), 1, urandom);
+        fclose(urandom);
+    }
+
+    srand(seed);
+    srandom(seed);
+
+    log_message(2, "rand_init() was called and seed was initialized to %u\n", seed);
+    if(RAND_MAX < 65536) {
+        log_error("RAND_MAX is too low: %d", RAND_MAX);
+    }
+}
+
+void rand_init_fixed(unsigned int seed) {
+    srand(seed);
+    srandom(seed);
+
+    log_message(2, "rand_init_fixed() was called and seed was initialized to %u\n", seed);
+
+    if(RAND_MAX < 65536) {
+        log_error("RAND_MAX is too low: %d", RAND_MAX);
+    }
+}
+
+char *rand_get_populate_value(const struct lys_type *type) {
+    assert(type);
+
+    char *ret = 0;
+
+    if(type->der->module) {
+        char *full_type = 0;
+        
+        asprintf(&full_type, "%s:%s", type->der->module->name, type->der->name);
+        if(full_type == 0) {
+            log_error("bad malloc");
+            return 0;
+        }
+
+        if(strstr(full_type, "ietf-yang-types:date-and-time") != 0) {
+            ret = rand_date_and_time();
+        }
+        else if(strstr(full_type, "ietf-inet-types:ipv4-address") != 0) {
+            ret = rand_ipv4_address();
+        }
+        else if(strstr(full_type, "ietf-inet-types:ipv6-address") != 0) {
+            ret = rand_ipv6_address();
+        }
+        else if((strstr(full_type, "ietf-yang-types:mac-address") != 0) || (strstr(full_type, "ietf-yang-types:phys-address") != 0)) {
+            ret = rand_mac_address();
+        }
+        else if(strstr(full_type, "universal-id") != 0) {
+            ret = rand_uuid();
+        }
+        
+        free(full_type);
+        if(ret) {
+            return ret;
+        }
+    }
+
+    switch(type->base) {
+        case LY_TYPE_EMPTY:
+        case LY_TYPE_BOOL:
+            if(rand_bool()) {
+                asprintf(&ret, "true");
+                return ret;
+            }
+            else {
+                asprintf(&ret, "false");
+                return ret;
+            }
+            break;
+
+        case LY_TYPE_DER:
+            return rand_get_populate_value(&type->der->type);
+            break;
+
+        case LY_TYPE_ENUM:
+            if(type->info.enums.count) {
+                int i = rand_uint16() % type->info.enums.count; 
+                asprintf(&ret, "%s", type->info.enums.enm[i].name);
+                return ret;
+            }
+            else {
+                return rand_get_populate_value(&type->der->type);
+            }
+            break;
+
+        case LY_TYPE_IDENT: {
+            while(!type->info.ident.ref) {
+                type = &type->der->type;
+            }
+            struct lys_ident *ident = rand_identity(type->info.ident.ref[0]);
+            if(ident == 0) {
+                log_error("rand_identity failed");
+                return 0;
+            }
+
+            asprintf(&ret, "%s:%s", ident->module->name, ident->name);
+            return ret;    
+        } break;
+
+        case LY_TYPE_STRING: {
+            int min_length = 1;
+            int max_length = 255;
+            char *expression = 0;
+            bool found_length = false;
+
+            do {
+                if(type->info.str.length && !found_length) {
+                    rand_range_t vals = rand_range(type->info.str.length->expr, LY_TYPE_UINT8);
+                    min_length = vals.min.num;
+                    max_length = vals.max.num;
+                    if(min_length == 0) {
+                        min_length = 1;
+                    }
+
+                    found_length = true;
+                }
+
+                if(type->info.str.pat_count) {
+                    //checkAL aici de fapt trebuie sa facem AND si NOT intre toate expresiile, in functie de modifier
+                    // int modifier = type->info.str.patterns[i].expr[0];
+                    if(expression) {
+                        free(expression);
+                        expression = 0;
+                    }
+                    expression = strdup((char*)(type->info.str.patterns[0].expr + 1));
+                }
+
+                if(type->der) {
+                    type = &type->der->type;
+                }
+                else {
+                    break;
+                }
+            } while(1);
+
+            if(expression) {
+                char *ret = rand_regex(expression);
+                if(ret == 0) {
+                    log_error("rand_regex failed");
+                    free(expression);
+                    return 0;
+                }
+
+                while(strlen(ret) < min_length) {
+                    char *add = rand_regex(expression);
+                    if(add == 0) {
+                        log_error("rand_regex failed");
+                        free(expression);
+                        free(ret);
+                        return 0;
+                    }
+
+                    char *newret = 0;
+                    asprintf(&newret, "%s%s", ret, add);
+                    free(add);
+                    free(ret);
+                    ret = newret;
+                }
+                free(expression);
+
+                if(ret == 0) {
+                    log_error("rand_regex failed");
+                    return 0;
+                }
+
+                if(max_length && (strlen(ret) > max_length)) {
+                    ret[max_length] = 0;
+                }
+
+                return ret;
+            }
+            else {
+                return rand_string(min_length, max_length);
+            }
+        } break;
+
+        case LY_TYPE_INT8:
+        case LY_TYPE_UINT8:
+        case LY_TYPE_INT16:
+        case LY_TYPE_UINT16:
+        case LY_TYPE_INT32:
+        case LY_TYPE_UINT32:
+        case LY_TYPE_INT64:
+        case LY_TYPE_UINT64: {
+            const char *expr = 0;
+            
+            do {
+                if(type->info.num.range) {
+                    expr = type->info.num.range->expr;
+                }    
+
+                if(type->der) {
+                    type = &type->der->type;
+                }
+                else {
+                    break;
+                }
+            } while(1);
+
+            int64_t r = rand_range(expr, type->base).value.num;
+            if(type->base == LY_TYPE_UINT8) {
+                asprintf(&ret, "%"PRIu8, (uint8_t)r);
+            }
+            else if(type->base == LY_TYPE_UINT16) {
+                asprintf(&ret, "%"PRIu16, (uint16_t)r);
+            }
+            else if(type->base == LY_TYPE_UINT32) {
+                asprintf(&ret, "%"PRIu32, (uint32_t)r);
+            }
+            else if(type->base == LY_TYPE_UINT64) {
+                asprintf(&ret, "%"PRIu64, (uint64_t)r);
+            }
+            else if(type->base == LY_TYPE_INT8) {
+                asprintf(&ret, "%"PRId8, (int8_t)r);
+            }
+            else if(type->base == LY_TYPE_INT16) {
+                asprintf(&ret, "%"PRId16, (int16_t)r);
+            }
+            else if(type->base == LY_TYPE_INT32) {
+                asprintf(&ret, "%"PRId32, (int32_t)r);
+            }
+            else if(type->base == LY_TYPE_INT64) {
+                asprintf(&ret, "%"PRId64, (int64_t)r);
+            }
+
+            return ret;
+        } break;
+
+        case LY_TYPE_DEC64: {
+            const char *expr = 0;
+            int digits = -1;
+            char fmt[10];
+            char *ret = 0;
+            
+            do {
+                if(type->info.dec64.range) {
+                    expr = type->info.dec64.range->expr;
+                }
+
+                if(digits == -1) {
+                    digits = type->info.dec64.dig;
+                }
+
+                if(type->der) {
+                    type = &type->der->type;
+                }
+                else {
+                    break;
+                }
+            } while(1);
+
+            rand_range_t dr = rand_range(expr, LY_TYPE_DEC64);
+            sprintf(fmt, "%%.%df", digits);
+
+            //19 digits total, including decimal part
+            int intdig = 19 - digits;
+            double max_val = 9.223372036854775807;
+
+            while(fabs(dr.value.dec) > (pow(10, intdig - 1) * max_val)) {
+                dr.value.dec /= 10;
+            }
+
+            asprintf(&ret, fmt, dr.value.dec);
+            return ret;
+        } break;
+
+        case LY_TYPE_BITS:
+            ret = (char*)malloc(1);
+            if(ret == 0) {
+                log_error("malloc failed");
+                return 0;
+            }
+            ret[0] = 0;
+
+            for(int i = 0; i < type->info.bits.count; i++) {
+                if(rand_bool()) {
+                    const char *val = type->info.bits.bit[i].name;
+                    bool first = (ret == 0);
+                    ret = (char*)realloc(ret, sizeof(char) * (strlen(ret) + 1 + strlen(val) + 1));
+                    if(ret == 0) {
+                        log_error("malloc failed");
+                        return 0;
+                    }
+
+                    if(!first) {
+                        strcat(ret, " ");
+                    }
+                    strcat(ret, val);
+                }
+            }
+            return ret;
+            break;
+
+        case LY_TYPE_BINARY: {
+            int length = 1;
+            char *ret = 0;
+
+            do {
+                if(type->info.binary.length) {
+                    rand_range_t vals = rand_range(type->info.binary.length->expr, LY_TYPE_UINT16);
+                    length = vals.min.num;
+                    if(length == 0) {
+                        length = 1;
+                    }
+                }
+
+                if(type->der) {
+                    type = &type->der->type;
+                }
+                else {
+                    break;
+                }
+            } while(1);
+
+            uint8_t *data = (uint8_t *)malloc(sizeof(uint8_t) * length);
+            if(!data) {
+                log_error("bad malloc");
+                return 0;
+            }
+
+            for(int i = 0; i < length; i++) {
+                data[i] = rand_uint8();
+            }
+
+            ret = b64_encode(data, length);
+            free(data);
+            return ret;
+        } break;
+
+        case LY_TYPE_LEAFREF:
+        case LY_TYPE_UNION:
+        case LY_TYPE_INST:
+            asprintf(&ret, "{late_resolve_%s}", type->der->name);
+            log_error("needed: %s", ret);
+            assert(0);
+            return ret;
+            break;
+
+        case LY_TYPE_UNKNOWN:
+        default:
+            asprintf(&ret, "{unimplemented_%s}", type->der->name);
+            log_error("can't generate random for: %s", type->der->name);
+            assert(0);
+            return ret;
+            break;
+    }
+}
+
+uint8_t rand_uint8(void) {
+    return rand() % 256;
+}
+
+int8_t rand_int8(void) {
+    return (int8_t)rand_uint8();
+}
+
+uint16_t rand_uint16(void) {
+    return rand() % 65536;
+}
+
+int16_t rand_int16(void) {
+    return (int16_t)rand_uint16();
+}
+
+uint32_t rand_uint32(void) {
+    uint32_t x = rand_uint16();
+    x <<= 16;
+    x += rand_uint16();
+    return x;
+}
+
+int32_t rand_int32(void) {
+    return (int32_t)rand_uint32();
+}
+
+uint64_t rand_uint64(void) {
+    uint64_t x = rand_uint32();
+    x <<= 32;
+    x += rand_uint32();
+    return x;
+}
+
+int64_t rand_int64(void) {
+    return (int64_t)rand_uint64();
+}
+
+bool rand_bool(void) {
+    return ((rand() & 0x01) == 1);
+}
+
+char *rand_regex(const char *regexp) {
+    assert(regexp);
+
+    char buffer[8192];
+    char *cmd = 0;
+    static int run_time = 0;
+
+    if(framework_arguments.no_rand) {
+        run_time++;
+        asprintf(&cmd, "regxstring %d '%s'", run_time, regexp);
+    }
+    else {
+        asprintf(&cmd, "regxstring '%s'", regexp);
+    }
+
+    FILE* pipe = popen(cmd, "r");
+    free(cmd);
+
+    if (!pipe) {
+        log_error("popen() failed");
+        return 0;
+    }
+
+    fgets(buffer, sizeof(buffer), pipe);
+    pclose(pipe);
+    
+    char *ret = strdup(buffer);
+    ret[strlen(ret) - 1] = 0;   //remove trailing \n
+
+    return ret;
+}
+
+char *rand_mac_address(void) {
+    char *ret = 0;
+
+    asprintf(&ret, "%02x:%02x:%02x:%02x:%02x:%02x", rand_uint8(), rand_uint8(), rand_uint8(), rand_uint8(), rand_uint8(), rand_uint8());
+    return ret;
+}
+
+static char *rand_string(int min_length, int max_length) {
+    assert(min_length >= 0);
+    assert(min_length <= max_length);
+
+    char charset[] = "0123456789"
+                     "abcdefghijklmnopqrstuvwxyz"
+                     "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+    int length = 1;
+    if(min_length == max_length) {
+        length = min_length;
+    }
+    else {
+        if((framework_config.debug_max_string_size) && (framework_config.debug_max_string_size < max_length)) {
+            max_length = framework_config.debug_max_string_size;
+        }
+
+        length = min_length + rand_uint16() % (max_length - min_length);
+    }
+
+    char *ret = (char *)malloc(length + 1);
+    if(!ret) {
+        log_error("bad malloc");
+        return 0;
+    }
+
+    for(int i = 0; i < length; i++) {
+        ret[i] = charset[(rand_uint8() % (sizeof(charset) - 1))];
+    }
+    ret[length] = 0;
+    return ret;
+}
+
+static struct lys_ident *rand_identity(struct lys_ident *type) {
+    assert(type);
+
+    struct lys_ident **found_identities;
+    int total = context_get_identity_leafs_of_type(type, &found_identities);
+    if(total == 0) {
+        return 0;
+    }
+
+    int chosen = rand_uint16() % total;
+    struct lys_ident *ret = found_identities[chosen];
+    free(found_identities);
+
+    return ret;
+}
+
+
+static int64_t rand_range_type_int_min(LY_DATA_TYPE type) {
+    switch (type) {
+        case LY_TYPE_UINT8:
+            return 0;
+            break;
+
+        case LY_TYPE_INT8:
+            return INT8_MIN;
+            break;
+
+        case LY_TYPE_UINT16:
+            return 0;
+            break;
+
+        case LY_TYPE_INT16:
+            return INT16_MIN;
+            break;
+
+        case LY_TYPE_UINT32:
+            return 0;
+            break;
+
+        case LY_TYPE_INT32:
+            return INT32_MIN;
+            break;
+
+        case LY_TYPE_UINT64:
+            return 0;
+            break;
+
+        case LY_TYPE_INT64:
+            return INT64_MIN;
+            break;
+
+        default:
+            return 0;
+            assert(0);
+            break;
+    }
+}
+
+static int64_t rand_range_type_int_max(LY_DATA_TYPE type) {
+    switch (type) {
+        case LY_TYPE_UINT8:
+            return UINT8_MAX;
+            break;
+
+        case LY_TYPE_INT8:
+            return INT8_MAX;
+            break;
+
+        case LY_TYPE_UINT16:
+            return UINT16_MAX;
+            break;
+
+        case LY_TYPE_INT16:
+            return INT16_MAX;
+            break;
+
+        case LY_TYPE_UINT32:
+            return UINT32_MAX;
+            break;
+
+        case LY_TYPE_INT32:
+            return INT32_MAX;
+            break;
+
+        case LY_TYPE_UINT64:
+            return INT64_MAX;   //yes, intended
+            break;
+
+        case LY_TYPE_INT64:
+            return INT64_MAX;
+            break;
+
+        default:
+            return 0;
+            assert(0);
+            break;
+    }
+}
+
+static rand_range_t rand_range(const char *range, const LY_DATA_TYPE type) {
+    char *working_range = 0;
+    rand_range_t ret;
+    ret.value.num = 0;
+    ret.min.num = 0;
+    ret.max.num = 0;
+
+    if (range) {
+        //remove spaces
+        char *rrange = (char*)malloc(sizeof(char) * (strlen(range) + 1));
+        if (!rrange) {
+            log_error("bad malloc");
+            return ret;
+        }
+
+        int i = 0;
+        int j = 0;
+        while (range[i]) {
+            if ((range[i] != ' ') && (range[i] != '\r') && (range[i] != '\n')) {
+                rrange[j] = range[i];
+                j++;
+            }
+            i++;
+        }
+        rrange[j] = 0;
+        //split the range into OR ranges
+        //first count how many different ranges exist
+        int chosen_range = 1;
+        char *search = strchr(rrange, '|');
+        while (search) {
+            chosen_range++;
+            search = strchr(search + 1, '|');
+        }
+
+        //choose a random one
+        chosen_range = rand_uint16() % chosen_range;
+        int current_range = 0;
+        char *token;
+        token = strtok(rrange, "|");
+        while (token) {
+            if (current_range == chosen_range) {
+                working_range = strdup(token);
+            }
+            current_range++;
+            token = strtok(0, "|");
+        }
+        free(rrange);
+    }
+
+    //now parse working_range according to type
+    if (type == LY_TYPE_DEC64) {
+        double min = -922337203685477580.8;
+        double max = 922337203685477580.7;
+        bool negative = false;
+
+        if (working_range) {
+            min = 0;
+            max = 0;
+
+            int i = 0;
+            if ((working_range[i] == 'm') || (working_range[i] == 'M')) {
+                min = -922337203685477580.8;
+                while (working_range[i] != '.') {
+                    i++;
+                }
+            }
+            else {
+                if (working_range[i] == '-') {
+                    negative = true;
+                    i++;
+                }
+
+                while ((working_range[i] >= '0') && (working_range[i] <= '9')) {
+                    min *= 10;
+                    min += working_range[i] - '0';
+                    i++;
+                }
+            }
+
+            //working_range[i...] is either '.', ".." or \0
+            if (working_range[i] == '.') {
+                if (working_range[i + 1] != '.') {
+                    i++;
+                    int power = 0;
+                    while ((working_range[i] >= '0') && (working_range[i] <= '9')) {
+                        power--;
+                        min += (working_range[i] - '0') * pow(10, power);
+                        i++;
+                    }
+                }
+                else {
+                    i += 2;    //skip ".."
+                }
+            }
+
+            if (negative) {
+                min *= -1;
+                negative = false;
+            }
+            
+            if (working_range[i] == 0) {
+                //single value
+                max = min;
+            }
+            else {
+                //there's also an upper value
+                if ((working_range[i] == 'm') || (working_range[i] == 'M')) {
+                    max = 922337203685477580.7;
+                }
+                else {
+                    if (working_range[i] == '-') {
+                        negative = true;
+                        i++;
+                    }
+
+                    while ((working_range[i] >= '0') && (working_range[i] <= '9')) {
+                        max *= 10;
+                        max += working_range[i] - '0';
+                        i++;
+                    }
+                }
+
+                //working_range[i...] is either '.', or \0
+                if (working_range[i] == '.') {
+                    i++;
+                    int power = 0;
+                    while ((working_range[i] >= '0') && (working_range[i] <= '9')) {
+                        power--;
+                        max += (working_range[i] - '0') * pow(10, power);
+                        i++;
+                    }
+                }
+
+                if (negative) {
+                    max *= -1;
+                    negative = false;
+                }
+            }
+        }
+
+        ret.value.dec = rand() / 1.0 / RAND_MAX;
+        ret.value.dec = (max - min) * ret.value.dec + min;
+        ret.min.dec = min;
+        ret.max.dec = max;
+    }
+    else {
+        int64_t min = rand_range_type_int_min(type);
+        int64_t max = rand_range_type_int_max(type);
+        bool negative = false;
+
+        if (working_range) {
+            min = 0;
+            max = 0;
+
+            int i = 0;
+            if ((working_range[i] == 'm') || (working_range[i] == 'M')) {
+                min = rand_range_type_int_min(type);
+                while (working_range[i] != '.') {
+                    i++;
+                }
+            }
+            else {
+                if (working_range[i] == '-') {
+                    negative = true;
+                    i++;
+                }
+
+                while ((working_range[i] >= '0') && (working_range[i] <= '9')) {
+                    min *= 10;
+                    min += working_range[i] - '0';
+                    i++;
+                }
+            }
+
+            //working_range[i...] is either ".." or \0
+            if (working_range[i] == '.') {
+                i += 2;    //skip ".."
+            }
+
+            if (negative) {
+                min *= -1;
+                negative = false;
+            }
+
+            if (working_range[i] == 0) {
+                //single value
+                max = min;
+            }
+            else {
+                //there's also an upper value
+                if ((working_range[i] == 'm') || (working_range[i] == 'M')) {
+                    max = rand_range_type_int_max(type);
+                }
+                else {
+                    if (working_range[i] == '-') {
+                        negative = true;
+                        i++;
+                    }
+
+                    while ((working_range[i] >= '0') && (working_range[i] <= '9')) {
+                        max *= 10;
+                        max += working_range[i] - '0';
+                        i++;
+                    }
+                }
+
+                if (negative) {
+                    max *= -1;
+                    negative = false;
+                }
+
+            }
+        }
+
+        double ch = rand() / 1.0 / RAND_MAX;
+        ret.value.num = (max - min) * ch + min;
+        ret.min.num = min;
+        ret.max.num = max;
+    }
+
+    free(working_range);
+
+    return ret;
+}
+
+static char *rand_date_and_time(void) {
+    time_t t = rand_uint32() / 2;
+    struct tm lt;
+    (void)localtime_r(&t, &lt);
+
+    char *ret = (char *)malloc(21);
+    if(!ret) {
+        log_error("bad malloc");
+        return 0;
+    }
+    strftime(ret, 21, "%Y-%m-%dT%H:%M:%SZ", &lt);
+    return ret;
+}
+
+static char *rand_ipv4_address(void) {
+    char *ret = 0;
+    uint8_t ip1 = rand_uint8();
+    uint8_t ip2 = rand_uint8();
+    uint8_t ip3 = rand_uint8();
+    uint8_t ip4 = rand_uint8();
+
+    asprintf(&ret, "%d.%d.%d.%d", ip1, ip2, ip3, ip4);
+    return ret;
+}
+
+static char *rand_ipv6_address(void) {
+    char *ret = 0;
+
+    uint16_t ip1 = rand_uint16();
+    uint16_t ip2 = rand_uint16();
+    uint16_t ip3 = rand_uint16();
+    uint16_t ip4 = rand_uint16();
+    uint16_t ip5 = rand_uint16();
+    uint16_t ip6 = rand_uint16();
+    uint16_t ip7 = rand_uint16();
+    uint16_t ip8 = rand_uint16();
+
+    asprintf(&ret, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", ip1, ip2, ip3, ip4, ip5, ip6, ip7, ip8);
+    return ret;
+}
+
+static char *rand_uuid(void) {
+    char *ret = 0;
+
+    //8-4-4-4-12
+    uint32_t v1 = rand_uint32();
+    uint16_t v2 = rand_uint16();
+    uint16_t v3 = rand_uint16();
+    uint16_t v4 = rand_uint16();
+    uint16_t v5 = rand_uint16();
+    uint32_t v6 = rand_uint32();
+
+    asprintf(&ret, "%08x-%04x-%04x-%04x-%04x%08x", v1, v2, v3, v4, v5, v6);
+
+    return ret;
+}
diff --git a/ntsimulator/ntsim-ng/utils/rand_utils.h b/ntsimulator/ntsim-ng/utils/rand_utils.h
new file mode 100644 (file)
index 0000000..f684846
--- /dev/null
@@ -0,0 +1,42 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <string.h>
+#include <stdbool.h>
+#include <libyang/libyang.h>
+
+void rand_init(void);
+void rand_init_fixed(unsigned int seed);
+char *rand_get_populate_value(const struct lys_type *type);
+
+// independent functions used by rand_get_populate_value
+uint8_t rand_uint8(void);
+int8_t rand_int8(void);
+uint16_t rand_uint16(void);
+int16_t rand_int16(void);
+uint32_t rand_uint32(void);
+int32_t rand_int32(void);
+uint64_t rand_uint64(void);
+int64_t rand_int64(void);
+bool rand_bool(void);
+
+//results should be freed by user
+char *rand_regex(const char *regexp);
+char *rand_mac_address(void);
+
diff --git a/ntsimulator/ntsim-ng/utils/sys_utils.c b/ntsimulator/ntsim-ng/utils/sys_utils.c
new file mode 100644 (file)
index 0000000..fc5c942
--- /dev/null
@@ -0,0 +1,414 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "sys_utils.h"
+#include "log_utils.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <math.h>
+#include <unistd.h>
+#include <time.h>
+#include <ifaddrs.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <linux/if_link.h>
+#include <assert.h>
+
+static char b64_encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+                                    'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+                                    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+                                    'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+                                    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+                                    'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+                                    'w', 'x', 'y', 'z', '0', '1', '2', '3',
+                                    '4', '5', '6', '7', '8', '9', '+', '/'};
+
+static int b64_mod_table[] = {0, 2, 1};
+
+bool dir_exists(const char *path) {
+    assert(path);
+
+    struct stat st = {0};
+    return (stat(path, &st) != -1);
+}
+
+bool file_exists(const char *fname) {
+    assert(fname);
+
+    return (access(fname, F_OK) != -1);
+}
+
+void file_touch(const char *fname, const char *content) {
+    assert(fname);
+
+    FILE *f = fopen(fname, "w");
+    if(f == 0) {
+        log_error("fopen failed");
+        return;
+    }
+
+    if(content) {
+        fprintf(f, "%s", content);
+    }
+    fclose(f);
+}
+
+char *file_read_content(const char *fname) {
+    assert(fname);
+
+    char *buffer = 0;
+    long length;
+    FILE *f = fopen(fname, "rb");
+    if(f) {
+        fseek(f, 0, SEEK_END);
+        length = ftell(f);
+        fseek(f, 0, SEEK_SET);
+        buffer = (char*)malloc(sizeof(char) * length);
+        if(buffer) {
+            fread(buffer, 1, length, f);
+        }
+        fclose(f);
+    }
+
+    return buffer;
+}
+
+int get_int_from_string_with_default(const char *string, int default_value) {
+    int rc;
+    int value = default_value;
+
+    if(string != 0) {
+        rc = sscanf(string, "%d", &value);
+        if (rc != 1) {
+            value = default_value;
+        }
+    }
+    return value;
+}
+
+char *get_current_date_and_time(void) {
+    char *date_and_time = 0;
+
+       time_t t = time(0);
+       struct tm tm = *localtime(&t);
+       struct timeval tv;
+       int millisec;
+
+       gettimeofday(&tv, 0);
+       millisec = lrint(tv.tv_usec/1000.0); // Round to nearest millisec
+       if(millisec>=1000)      { // Allow for rounding up to nearest second
+               millisec -=1000;
+               tv.tv_sec++;
+               millisec /= 100;
+       }
+
+       asprintf(&date_and_time, "%04d-%02d-%02dT%02d:%02d:%02d.%01dZ",
+                tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+                tm.tm_hour, tm.tm_min, tm.tm_sec, millisec/100);
+
+    return date_and_time;
+}
+
+long int get_microseconds_since_epoch(void) {
+    time_t t = time(0);
+    struct timeval tv;
+    long int useconds;
+
+    gettimeofday(&tv, 0);
+    useconds = t*1000 + tv.tv_usec; //add the microseconds to the seconds
+
+    return useconds;
+}
+
+
+bool get_local_ips(const char *ifname, char **ipv4, char **ipv6) {
+    assert(ifname);
+    assert(ipv4);
+    assert(ipv6);
+
+    int s;
+    struct ifaddrs *ifaddr;
+    struct ifaddrs *ifa;
+    char host[NI_MAXHOST];
+    bool ret = true;
+
+    *ipv4 = 0;
+    *ipv6 = 0;
+
+    if (getifaddrs(&ifaddr) == -1)  {
+        ret = false;
+        goto get_local_ips_free;
+    }
+
+    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)  {
+        if (ifa->ifa_addr == NULL) {
+            continue;
+        }
+
+        s = getnameinfo(ifa->ifa_addr,sizeof(struct sockaddr_in),host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
+        if((strcmp(ifa->ifa_name, ifname) == 0) && (ifa->ifa_addr->sa_family == AF_INET)) {
+            if (s != 0) {
+                ret = false;
+                goto get_local_ips_free;
+            }
+            
+            *ipv4 = strdup(host);
+            break;
+        }
+    }
+
+
+    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)  {
+        if (ifa->ifa_addr == NULL) {
+            continue;
+        }
+
+        s = getnameinfo(ifa->ifa_addr,sizeof(struct sockaddr_in6),host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
+        if((strcmp(ifa->ifa_name, ifname) == 0) && (ifa->ifa_addr->sa_family == AF_INET6)) {
+            if (s != 0) {
+                ret = false;
+                goto get_local_ips_free;
+            }
+            
+            *ipv6 = strdup(host);
+            break;
+        }
+    }
+
+    get_local_ips_free:
+    if(ret == false) {
+        free(*ipv4);
+        free(*ipv6);
+        *ipv4 = 0;
+        *ipv6 = 0;
+    }
+
+    freeifaddrs(ifaddr);
+    return ret;
+}
+
+bool check_port_open(const char *host, uint16_t port) {
+    assert(host);
+
+    int simpleSocket = 0;
+    int returnStatus = 0; 
+    struct addrinfo simpleServer;
+    struct addrinfo *res;
+
+    memset(&simpleServer, 0, sizeof simpleServer);
+    simpleServer.ai_family = AF_UNSPEC;  // use IPv4 or IPv6, whichever
+    simpleServer.ai_socktype = SOCK_STREAM;
+    simpleServer.ai_flags = AI_ADDRCONFIG;
+
+    char sport[10];
+    sprintf(sport, "%d", port);
+
+    returnStatus = getaddrinfo(host, sport, &simpleServer, &res);
+    if(returnStatus != 0) {
+        return false;
+    }
+
+    simpleSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+    if(simpleSocket < 0) {
+        freeaddrinfo(res);
+        return false;
+    }
+
+    char s[INET6_ADDRSTRLEN];
+    switch(res->ai_addr->sa_family) {
+        case AF_INET: {
+            struct sockaddr_in *addr_in = (struct sockaddr_in *)res->ai_addr; 
+            inet_ntop(AF_INET, &(addr_in->sin_addr), s, INET_ADDRSTRLEN);
+            returnStatus = connect(simpleSocket, res->ai_addr, res->ai_addrlen);
+            break;
+        }
+
+        case AF_INET6: {
+            struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)res->ai_addr;
+            inet_ntop(AF_INET6, &(addr_in6->sin6_addr), s, INET6_ADDRSTRLEN);
+            returnStatus = connect(simpleSocket, res->ai_addr, res->ai_addrlen);
+            break;
+        }
+
+        default:
+            break;
+    }
+
+    freeaddrinfo(res);
+    if(returnStatus == 0) {
+        close(simpleSocket);
+        return true;
+    }
+    
+    return false;
+}
+
+char *b64_encode(const unsigned char *data, size_t input_length) {
+    assert(data);
+    assert(input_length);
+
+    int output_length = 4 * ((input_length + 2) / 3);
+
+    char *encoded_data = (char *)malloc(sizeof(char) * (output_length + 1));
+    if (encoded_data == 0) {
+        return 0;
+    }
+
+    for (int i = 0, j = 0; i < input_length;) {
+        uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
+        uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
+        uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
+
+        uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
+
+        encoded_data[j++] = b64_encoding_table[(triple >> 3 * 6) & 0x3F];
+        encoded_data[j++] = b64_encoding_table[(triple >> 2 * 6) & 0x3F];
+        encoded_data[j++] = b64_encoding_table[(triple >> 1 * 6) & 0x3F];
+        encoded_data[j++] = b64_encoding_table[(triple >> 0 * 6) & 0x3F];
+    }
+
+    for (int i = 0; i < b64_mod_table[input_length % 3]; i++) {
+        encoded_data[output_length - 1 - i] = '=';
+    }
+
+    encoded_data[output_length] = 0;
+
+    return encoded_data;
+}
+
+char *str_replace(const char *orig, const char *rep, const char *with) {
+    assert(orig);
+    assert(rep);
+    assert(with);
+
+    char *result; // the return string
+    const char *ins;    // the next insert point
+    char *tmp;    // varies
+    int len_rep;  // length of rep (the string to remove)
+    int len_with; // length of with (the string to replace rep with)
+    int len_front; // distance between rep and end of last rep
+    int count;    // number of replacements
+
+    // sanity checks and initialization
+    if(!orig || !rep) {
+        return 0;
+    }
+
+    len_rep = strlen(rep);
+    if(len_rep == 0) {
+        return 0; // empty rep causes infinite loop during count
+    }
+
+    if (!with) {
+        with = "";
+    }
+    len_with = strlen(with);
+
+    // count the number of replacements needed
+    ins = orig;
+    for(count = 0; (tmp = strstr(ins, rep)); ++count) {
+        ins = tmp + len_rep;
+    }
+
+    tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1);
+
+    if(!result) {
+        return 0;
+    }
+
+    // first time through the loop, all the variable are set correctly
+    // from here on,
+    //    tmp points to the end of the result string
+    //    ins points to the next occurrence of rep in orig
+    //    orig points to the remainder of orig after "end of rep"
+    while(count--) {
+        ins = strstr(orig, rep);
+        len_front = ins - orig;
+        tmp = strncpy(tmp, orig, len_front) + len_front;
+        tmp = strcpy(tmp, with) + len_with;
+        orig += len_front + len_rep; // move to next "end of rep"
+    }
+
+    strcpy(tmp, orig);
+    return result;
+}
+
+char *read_key(const char *filename) {
+    assert(filename);
+
+    FILE * fp = 0;
+    char * line = 0;
+    size_t len = 0;
+    ssize_t read;
+    char *key_string = 0;
+
+    fp = fopen(filename, "r");
+    if(fp == 0) {
+        log_error("could not open file %s", filename);
+        return 0;
+    }
+
+    while((read = getline(&line, &len, fp)) != -1) {
+        // we ignore the first and last lines forPrivate keys, Public keys and Certificates
+        if(strstr(line, "PRIVATE KEY-----") || strstr(line, "PUBLIC KEY-----") || strstr(line, "CERTIFICATE-----")) {
+            free(line);
+            line = 0;
+            len = 0;
+            continue;
+        }
+        else {
+            if(key_string) {
+                key_string = (char *)realloc(key_string, strlen(key_string) + read + 1);
+                if(key_string == 0) {
+                    log_error("bad allocation");
+                    free(line);
+                    return 0;
+                }
+
+                strcat(key_string, line);
+            }
+            else {
+                key_string = strdup(line);
+                if(key_string == 0) {
+                    log_error("bad allocation");
+                    free(line);
+                    return 0;
+                }
+            }
+            
+            free(line);
+            line = 0;
+            len = 0;
+        }
+    }
+
+    fclose(fp);
+    if(line) {
+        free(line);
+    }
+
+    return key_string;
+}
diff --git a/ntsimulator/ntsim-ng/utils/sys_utils.h b/ntsimulator/ntsim-ng/utils/sys_utils.h
new file mode 100644 (file)
index 0000000..9e7081b
--- /dev/null
@@ -0,0 +1,48 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#define STANDARD_NETCONF_PORT   830
+#define STANDARD_FTP_PORT       21
+#define STANDARD_SFTP_PORT      22
+
+#define KS_KEY_NAME                                 "melacon_server_key"
+#define SERVER_PUBLIC_SSH_KEY_PATH                  "/home/netconf/.ssh/melacon.server.key.pub"
+
+//filesystem functions
+bool dir_exists(const char *path);
+bool file_exists(const char *fname);
+void file_touch(const char *fname, const char *content);    //content can be null for just-touching
+char *file_read_content(const char *fname);
+
+int get_int_from_string_with_default(const char *string, int default_value);
+char *get_current_date_and_time(void);
+long int get_microseconds_since_epoch(void);
+
+//networking functions
+bool get_local_ips(const char *ifname, char **ipv4, char **ipv6);
+bool check_port_open(const char *host, uint16_t port);
+
+char *b64_encode(const unsigned char *data, size_t input_length);
+char *str_replace(const char *orig, const char *rep, const char *with);
+
+char *read_key(const char *filename);
diff --git a/ntsimulator/ntsim-ng/utils/type_utils.c b/ntsimulator/ntsim-ng/utils/type_utils.c
new file mode 100644 (file)
index 0000000..1221181
--- /dev/null
@@ -0,0 +1,286 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "type_utils.h"
+#include "log_utils.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+const char* typeutils_yang_type_to_str(const LY_DATA_TYPE type_base) {
+    switch(type_base) {
+        case LY_TYPE_DER:
+            return "LY_TYPE_DER";
+            break;
+
+        case LY_TYPE_BINARY:
+            return "LY_TYPE_BINARY";
+            break;
+
+        case LY_TYPE_BITS:
+            return "LY_TYPE_BITS";
+            break;
+
+        case LY_TYPE_BOOL:
+            return "LY_TYPE_BOOL";
+            break;
+
+        case LY_TYPE_DEC64:
+            return "LY_TYPE_DEC64";
+            break;
+
+        case LY_TYPE_EMPTY:
+            return "LY_TYPE_EMPTY";
+            break;
+
+        case LY_TYPE_ENUM:
+            return "LY_TYPE_ENUM";
+            break;
+
+        case LY_TYPE_IDENT:
+            return "LY_TYPE_IDENT";
+            break;
+
+        case LY_TYPE_INST:
+            return "LY_TYPE_INST";
+            break;
+
+        case LY_TYPE_LEAFREF:
+            return "LY_TYPE_LEAFREF";
+            break;
+
+        case LY_TYPE_STRING:
+            return "LY_TYPE_STRING";
+            break;
+
+        case LY_TYPE_UNION:
+            return "LY_TYPE_UNION";
+            break;
+
+        case LY_TYPE_INT8:
+            return "LY_TYPE_INT8";
+            break;
+
+        case LY_TYPE_UINT8:
+            return "LY_TYPE_UINT8";
+            break;
+
+        case LY_TYPE_INT16:
+            return "LY_TYPE_INT16";
+            break;
+
+        case LY_TYPE_UINT16:
+            return "LY_TYPE_UINT16";
+            break;
+
+        case LY_TYPE_INT32:
+            return "LY_TYPE_INT32";
+            break;
+
+        case LY_TYPE_UINT32:
+            return "LY_TYPE_UINT32";
+            break;
+
+        case LY_TYPE_INT64:
+            return "LY_TYPE_INT64";
+            break;
+
+        case LY_TYPE_UINT64:
+            return "LY_TYPE_UINT64";
+            break;
+
+        case LY_TYPE_UNKNOWN:
+            return "LY_TYPE_UNKNOWN";
+            break;
+    }
+
+    return "(unknown LY_TYPE)";
+}
+
+const char* typeutils_yang_nodetype_to_str(const LYS_NODE nodetype) {
+    switch(nodetype) {
+        case LYS_UNKNOWN:
+            return "LYS_UNKNOWN";
+            break;
+
+        case LYS_CONTAINER:
+            return "LYS_CONTAINER";
+            break;
+
+        case LYS_CHOICE:
+            return "LYS_CHOICE";
+            break;
+
+        case LYS_LEAF:
+            return "LYS_LEAF";
+            break;
+
+        case LYS_LEAFLIST:
+            return "LYS_LEAFLIST";
+            break;
+
+        case LYS_LIST:
+            return "LYS_LIST";
+            break;
+
+        case LYS_ANYXML:
+            return "LYS_ANYXML";
+            break;
+
+        case LYS_CASE:
+            return "LYS_CASE";
+            break;
+
+        case LYS_NOTIF:
+            return "LYS_NOTIF";
+            break;
+
+        case LYS_RPC:
+            return "LYS_RPC";
+            break;
+
+        case LYS_INPUT:
+            return "LYS_INPUT";
+            break;
+
+        case LYS_OUTPUT:
+            return "LYS_OUTPUT";
+            break;
+
+        case LYS_GROUPING:
+            return "LYS_GROUPING";
+            break;
+
+        case LYS_USES:
+            return "LYS_USES";
+            break;
+
+        case LYS_AUGMENT:
+            return "LYS_AUGMENT";
+            break;
+
+        case LYS_ACTION:
+            return "LYS_ACTION";
+            break;
+
+        case LYS_ANYDATA:
+            return "LYS_ANYDATA";
+            break;
+
+        case LYS_EXT:
+            return "LYS_EXT";
+            break;
+
+        default:
+            return "(unknown node type)";
+            break;
+
+    }
+}
+
+char* typeutils_type_to_str(const struct lys_type *type) {
+    assert(type);
+
+    struct lys_ident *ref = 0;
+    char *ret = 0;
+
+    switch(type->base) {
+        case LY_TYPE_ENUM:
+            if(type->info.enums.count) {
+                ret = (char*)realloc(ret, sizeof(char) * 1024 * 1024);
+                if(!ret) {
+                    log_error("bad malloc");
+                    return 0;
+                }
+
+                sprintf(ret, "enum(%d):", type->info.enums.count);
+                for(int i = 0; i < type->info.enums.count; i++) {
+                    char *add = 0;
+                    asprintf(&add, " %s(%d)", type->info.enums.enm[i].name, type->info.enums.enm[i].value);
+                    strcat(ret, add);
+                    free(add);
+                }
+
+                ret = (char*)realloc(ret, sizeof(char) * (strlen(ret) + 1));    //resize back
+            }
+            else {
+                if(type->der) {
+                    char *add = typeutils_type_to_str(&type->der->type);
+                    if(type->der->module) {
+                        asprintf(&ret, "%s:%s >>> %s", type->der->module->name, type->der->name, add);
+                    }
+                    else  {
+                        asprintf(&ret, "%s >>> %s", type->der->name, add);
+                    }
+                    free(add);
+                }
+            }
+            break;
+
+        case LY_TYPE_IDENT:         
+            if(type->info.ident.count) {
+                ref = type->info.ident.ref[0];
+                if(ref) {
+                    if(ref->module) {
+                        asprintf(&ret, "ident: %s:%s", ref->module->name, ref->name);
+                    }
+                    else  {
+                        asprintf(&ret, "ident: %s", ref->name);
+                    }
+                }
+            }
+            else if(type->der->module) {
+                return typeutils_type_to_str(&type->der->type);
+            }
+            break;
+
+        case LY_TYPE_UNION:
+            if(type->der) {
+                if(type->der->module) {
+                    asprintf(&ret, "union: %s:%s", type->der->module->name, type->der->name);
+                }
+                else  {
+                    asprintf(&ret, "union: %s", type->der->name);
+                }
+            }
+            break;
+
+        case LY_TYPE_STRING:
+            if(type->info.str.length) {
+                asprintf(&ret, "%s:%s", type->der->name, type->info.str.length->expr);
+            }
+            else {
+                asprintf(&ret, "%s", type->der->name);
+            }
+            break;
+
+        default:
+            if(type->der) {
+                if(type->der->module) {
+                    asprintf(&ret, "%s:%s", type->der->module->name, type->der->name);
+                }
+                else  {
+                    asprintf(&ret, "%s", type->der->name);
+                }
+            }
+            break;
+    }
+
+    return ret;
+}
diff --git a/ntsimulator/ntsim-ng/utils/type_utils.h b/ntsimulator/ntsim-ng/utils/type_utils.h
new file mode 100644 (file)
index 0000000..fa0cfd5
--- /dev/null
@@ -0,0 +1,27 @@
+/*************************************************************************
+*
+* Copyright 2020 highstreet technologies GmbH and others
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+***************************************************************************/
+
+#pragma once
+
+#include <string.h>
+#include <stdint.h>
+#include <libyang/libyang.h>
+
+const char* typeutils_yang_type_to_str(const LY_DATA_TYPE type_base);
+const char* typeutils_yang_nodetype_to_str(const LYS_NODE nodetype);
+
+char* typeutils_type_to_str(const struct lys_type *type);
diff --git a/ntsimulator/regxstring/CHANGES b/ntsimulator/regxstring/CHANGES
new file mode 100644 (file)
index 0000000..119f35b
--- /dev/null
@@ -0,0 +1,8 @@
+This project was cloned from https://github.com/daidodo/regxstring
+------------------------------------------------------------------
+
+Changes made were:
+- removed unnecesary files (vs solution, makefiles, etc)
+- modified regxstring_imp.cpp to accomodate "no-rand"
+- build sepparate main() in gen_regex.cpp to do my requested job
+- rest of files are untouched
diff --git a/ntsimulator/regxstring/LICENSE b/ntsimulator/regxstring/LICENSE
new file mode 100644 (file)
index 0000000..c80fb76
--- /dev/null
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright (c) 2019 Zhao DAI <daidodo@gmail.com>
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/ntsimulator/regxstring/README.md b/ntsimulator/regxstring/README.md
new file mode 100644 (file)
index 0000000..94d65b5
--- /dev/null
@@ -0,0 +1,56 @@
+# regxstring
+This is a **Random String Generator** based on **Regular Expression**.
+
+The idea is simple: Given a regular expression, generate random strings that can match it.
+
+For example, to generate 5 random IP addresses that have all *same* components, we can use this:
+```
+ $ echo "^(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.\1){3}$" | ./regxstr 5
+ 250.250.250.250
+ 213.213.213.213
+ 4.4.4.4
+ 118.118.118.118
+ 2.2.2.2
+```
+No surprising, the above regular expression matches an IP address with 4 same dot parts.
+Isn't it cool? 
+
+*regxstring* can do much more. You can try more complex regular expressions. Basically, most Perl 5 supported regular expressions are also supported by *regxstring*, as showing bellow:
+```
+Meta-character(s)   Description
+--------------------------------
+\                   Quote the next meta-character
+^                   Match the beginning of the line
+$                   Match the end of the line (or before newline at the end)
+?                   Match 1 or 0 times
++                   Match 1 or more times
+*                   Match 0 or more times
+{n}                 Match exactly n times
+{n,}                Match at least n times
+{n,m}               Match at least n but not more than m times
+.                   Match any character (except newline)
+(pattern)           Grouping
+(?:pattern)         This is for clustering, not capturing; it groups sub-expressions like "()", but doesn't make back-references as "()" does
+(?=pattern)         A zero-width positive look-ahead assertion, e.g., \w+(?=\t) matches a word followed by a tab, without including the tab
+(?!pattern)         A zero-width negative look-ahead assertion, e.g., foo(?!bar) matches any occurrence of "foo" that isn't followed by "bar"
+|                   Alternation
+[xyz]               Matches a single character that is contained within the brackets
+[^xyz]              Matches a single character that is not contained within the brackets
+[a-z]               Matches a single character that is in a given range
+[^a-z]              Matches a single character that is not in a given range
+\f                  Form feed
+\n                  Newline
+\r                  Return
+\t                  Tab
+\v                  Vertical white space
+\d                  Digits, [0-9]
+\D                  Non-digits, [^0-9]
+\s                  Space and tab, [ \t\r\n\f]
+\S                  Non-white space characters, [^ \t\r\n\f]
+\w                  Alphanumeric characters plus '_', [0-9a-zA-Z_]
+\W                  Non-word characters, [^0-9a-zA-Z_]
+\N                  Matches what the Nth marked sub-expression matched, where N is a digit from 1 to 9
+```
+One more notice, *regxstring* also includes a library that allows you to generate such strings in your C/C++ programs.
+
+Please enjoy yourself!
diff --git a/ntsimulator/regxstring/gen_regex.cpp b/ntsimulator/regxstring/gen_regex.cpp
new file mode 100644 (file)
index 0000000..e0a4953
--- /dev/null
@@ -0,0 +1,86 @@
+/*************************************************************************\r
+*\r
+* Licensed under the Apache License, Version 2.0 (the "License");\r
+* you may not use this file except in compliance with the License.\r
+* You may obtain a copy of the License at\r
+*\r
+*     http://www.apache.org/licenses/LICENSE-2.0\r
+*\r
+* Unless required by applicable law or agreed to in writing, software\r
+* distributed under the License is distributed on an "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+* See the License for the specific language governing permissions and\r
+* limitations under the License.\r
+***************************************************************************/\r
+\r
+#include <string>\r
+#include <cstdlib>\r
+#include <iostream>\r
+\r
+#include "regxstring.h"\r
+\r
+using namespace std;\r
+\r
+static string trim(std::string str){\r
+    size_t i = 0,e = str.length();\r
+    for(;i < e && std::isspace(str[i]);++i);\r
+    size_t j = e;\r
+    for(;j > i && std::isspace(str[j - 1]);--j);\r
+    return (i < j ? str.substr(i,j - i) : "");\r
+}\r
+\r
+static string pre_handle(const string & str)\r
+{\r
+    string ret = trim(str);\r
+    if(!ret.empty()) {\r
+        if(ret[0] != '^') {\r
+            ret.insert(ret.begin(),'^');\r
+        }\r
+\r
+        if(ret[ret.size() - 1] != '$') {\r
+            ret.push_back('$');\r
+        }\r
+    }\r
+    return ret;\r
+}\r
+\r
+static void rand_init(void) {\r
+    unsigned int seed;\r
+    FILE* urandom = fopen("/dev/urandom", "r");\r
+    size_t ret = fread(&seed, sizeof(int), 1, urandom);\r
+    (void)ret;\r
+    fclose(urandom);\r
+    srand(seed);\r
+    srandom(seed);\r
+}\r
+\r
+int main(int argc, const char ** argv)\r
+{\r
+    CRegxString regxstr;\r
+    string regx = "";\r
+\r
+    switch(argc) {\r
+        case 2:\r
+            rand_init();\r
+            regx = argv[1];\r
+            break;\r
+\r
+        case 3:\r
+            int pseudo_seed = 0;\r
+            int i = 0;\r
+            while(argv[1][i]) {\r
+                pseudo_seed *= 10;\r
+                pseudo_seed += argv[1][i] - '0';\r
+                i++;\r
+            }\r
+            srand(pseudo_seed);\r
+            srandom(pseudo_seed);\r
+            regx = argv[2];\r
+            break;\r
+    }\r
+\r
+    regxstr.ParseRegx(pre_handle(regx).c_str());\r
+    cout << regxstr.RandString() << endl;\r
+    \r
+    return 0;\r
+}\r
diff --git a/ntsimulator/regxstring/main.cpp b/ntsimulator/regxstring/main.cpp
new file mode 100644 (file)
index 0000000..bfc18e3
--- /dev/null
@@ -0,0 +1,149 @@
+/*************************************************************************\r
+*\r
+* Licensed under the Apache License, Version 2.0 (the "License");\r
+* you may not use this file except in compliance with the License.\r
+* You may obtain a copy of the License at\r
+*\r
+*     http://www.apache.org/licenses/LICENSE-2.0\r
+*\r
+* Unless required by applicable law or agreed to in writing, software\r
+* distributed under the License is distributed on an "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+* See the License for the specific language governing permissions and\r
+* limitations under the License.\r
+***************************************************************************/\r
+\r
+#include <iostream>\r
+#include <fstream>\r
+#include <string>\r
+#include <cstdlib>\r
+#include <cctype>\r
+\r
+#include "regxstring.h"\r
+\r
+using namespace std;\r
+\r
+bool debug;\r
+const char * filename;\r
+\r
+static std::string Trim(std::string str){\r
+    size_t i = 0,e = str.length();\r
+    for(;i < e && std::isspace(str[i]);++i);\r
+    size_t j = e;\r
+    for(;j > i && std::isspace(str[j - 1]);--j);\r
+    return (i < j ? str.substr(i,j - i) : "");\r
+}\r
+\r
+static bool ExtractArg(const char * argstr,const char * pattern,const char *& result)\r
+{\r
+    if(!argstr || !pattern)\r
+        return false;\r
+    for(;*pattern;++pattern,++argstr)\r
+        if(*pattern != *argstr)\r
+            return false;\r
+    result = *argstr ? argstr : 0;\r
+    return true;\r
+}\r
+\r
+static const char * ProgramName(const char * argstr)\r
+{\r
+    const char * ret = argstr;\r
+    for(const char * cur = argstr;cur && *cur;++cur)\r
+        if(*cur == '/')\r
+            ret = cur + 1;\r
+    return ret;\r
+}\r
+\r
+static std::string pre_handle(const std::string & str)\r
+{\r
+    std::string ret = Trim(str);\r
+    if(!ret.empty()){\r
+        if(ret[0] != '^')\r
+            ret.insert(ret.begin(),'^');\r
+        if(ret[ret.size() - 1] != '$')\r
+            ret.push_back('$');\r
+    }\r
+    return ret;\r
+}\r
+\r
+#ifdef TEST\r
+#   include "test.h"\r
+#endif\r
+\r
+static void printUsage(const char * exe)\r
+{\r
+    cout<<"Usage: "<<exe<<" [N] [-t] [-d] [-f=FILE] [-h|?|--help]\n"\r
+        <<"  N          generate N random strings, default 1\n"\r
+#ifdef TEST\r
+        <<"  -t         batch test\n"\r
+#endif\r
+        <<"  -d         output debug info\n"\r
+        <<"  -f         use FILE as input\n"\r
+        <<"  -h\n"\r
+        <<"  ?\n"\r
+        <<"  --help     print this message\n"\r
+        <<endl;\r
+}\r
+\r
+static void use(int c)\r
+{\r
+    CRegxString regxstr;\r
+    std::string regx;\r
+    std::istream * in = &cin;\r
+    if(filename){\r
+        std::ifstream * file = new std::ifstream(filename);\r
+        if(!file->is_open()){\r
+            delete file;\r
+            cerr<<"cannot open file "<<filename<<endl;\r
+            return;\r
+        }\r
+        in = file;\r
+    }\r
+    while(std::getline(*in,regx)){\r
+        regxstr.ParseRegx(pre_handle(regx).c_str());\r
+        if(debug)\r
+            regxstr.Debug(cout);\r
+        for(int i = 0;i < c;++i)\r
+            cout<<regxstr.RandString()<<endl;\r
+        cout<<endl;\r
+    }\r
+    if(filename)\r
+        delete in;\r
+}\r
+\r
+int main(int argc,const char ** argv)\r
+{\r
+    int c = 1;\r
+    bool test = false;\r
+    for(int i = 1;i < argc;++i){\r
+        const char * ret = 0;\r
+        if((ExtractArg(argv[i],"-h",ret) ||\r
+            ExtractArg(argv[i],"?",ret) ||\r
+            ExtractArg(argv[i],"--help",ret)) && !ret)\r
+        {\r
+            printUsage(ProgramName(argv[0]));\r
+            return 1;\r
+        }else if((ExtractArg(argv[i],"-t",ret) || ExtractArg(argv[i],"-test",ret)) && !ret){\r
+            test = true;\r
+        }else if((ExtractArg(argv[i],"-d",ret) || ExtractArg(argv[i],"-debug",ret)) && !ret){\r
+            debug = true;\r
+        }else if(ExtractArg(argv[i],"-f=",ret) && ret){\r
+            filename = ret;\r
+        }else\r
+            if((c = atoi(argv[i])) <= 0){\r
+                printUsage(ProgramName(argv[0]));\r
+                return 1;\r
+            }\r
+    }\r
+#ifdef TEST\r
+    if(test)\r
+        test_pcre(c);\r
+    else\r
+#endif\r
+        use(c);\r
+    //test_01();\r
+#if _MEM_LEAK\r
+    cerr<<"__NodeBase::ref = "<<__NodeBase::ref<<endl;\r
+#endif\r
+    return 0;\r
+}\r
diff --git a/ntsimulator/regxstring/regxstring.cpp b/ntsimulator/regxstring/regxstring.cpp
new file mode 100644 (file)
index 0000000..a6f1625
--- /dev/null
@@ -0,0 +1,58 @@
+/*************************************************************************\r
+*\r
+* Licensed under the Apache License, Version 2.0 (the "License");\r
+* you may not use this file except in compliance with the License.\r
+* You may obtain a copy of the License at\r
+*\r
+*     http://www.apache.org/licenses/LICENSE-2.0\r
+*\r
+* Unless required by applicable law or agreed to in writing, software\r
+* distributed under the License is distributed on an "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+* See the License for the specific language governing permissions and\r
+* limitations under the License.\r
+***************************************************************************/\r
+\r
+#include "regxstring_impl.h"\r
+#include "regxstring.h"\r
+\r
+CRegxString::CRegxString(const char * regx)\r
+    : impl_(0)\r
+{\r
+    ParseRegx(regx);\r
+}\r
+\r
+CRegxString::~CRegxString()\r
+{\r
+    if(impl_)\r
+        delete impl_;\r
+}\r
+\r
+void CRegxString::ParseRegx(const char * regx,const Config * config)\r
+{\r
+    if(!regx)\r
+        return;\r
+    if(!impl_)\r
+        impl_ = new REGXSTRING_NS::__CRegxString;\r
+    impl_->ParseRegx(regx,config);\r
+}\r
+\r
+const char * CRegxString::Regx() const\r
+{\r
+    return (impl_ ? impl_->Regx().c_str() : 0);\r
+}\r
+\r
+const char * CRegxString::RandString()\r
+{\r
+    return (impl_ ? impl_->RandString().c_str() : 0);\r
+}\r
+const char * CRegxString::LastString() const\r
+{\r
+    return (impl_ ? impl_->LastString().c_str() : 0);\r
+}\r
+\r
+void CRegxString::Debug(std::ostream & out) const\r
+{\r
+    if(impl_)\r
+        impl_->Debug(out);\r
+}\r
diff --git a/ntsimulator/regxstring/regxstring.h b/ntsimulator/regxstring/regxstring.h
new file mode 100644 (file)
index 0000000..7620e79
--- /dev/null
@@ -0,0 +1,45 @@
+/*************************************************************************\r
+*\r
+* Licensed under the Apache License, Version 2.0 (the "License");\r
+* you may not use this file except in compliance with the License.\r
+* You may obtain a copy of the License at\r
+*\r
+*     http://www.apache.org/licenses/LICENSE-2.0\r
+*\r
+* Unless required by applicable law or agreed to in writing, software\r
+* distributed under the License is distributed on an "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+* See the License for the specific language governing permissions and\r
+* limitations under the License.\r
+***************************************************************************/\r
+\r
+#ifndef DOZERG_REGXSTRING_H_20091012\r
+#define DOZERG_REGXSTRING_H_20091012\r
+\r
+namespace __DZ_Regx_String{\r
+    class __CRegxString;\r
+}\r
+\r
+struct Config\r
+{\r
+    static const int REPEAT_INFINITE = 3;\r
+    int repeatInfinite;\r
+    //functions:\r
+    Config():repeatInfinite(REPEAT_INFINITE){}\r
+};\r
+\r
+class CRegxString\r
+{\r
+    __DZ_Regx_String::__CRegxString * impl_;\r
+public:\r
+    CRegxString():impl_(0){}\r
+    explicit CRegxString(const char * regx);\r
+    ~CRegxString();\r
+    void ParseRegx(const char * regx,const Config * config = 0);\r
+    const char * Regx() const;\r
+    const char * RandString();\r
+    const char * LastString() const;\r
+    void Debug(std::ostream & out) const;\r
+};\r
+\r
+#endif\r
diff --git a/ntsimulator/regxstring/regxstring_impl.cpp b/ntsimulator/regxstring/regxstring_impl.cpp
new file mode 100644 (file)
index 0000000..9847ae6
--- /dev/null
@@ -0,0 +1,950 @@
+/*************************************************************************\r
+*\r
+* Licensed under the Apache License, Version 2.0 (the "License");\r
+* you may not use this file except in compliance with the License.\r
+* You may obtain a copy of the License at\r
+*\r
+*     http://www.apache.org/licenses/LICENSE-2.0\r
+*\r
+* Unless required by applicable law or agreed to in writing, software\r
+* distributed under the License is distributed on an "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+* See the License for the specific language governing permissions and\r
+* limitations under the License.\r
+***************************************************************************/\r
+\r
+#include <algorithm>\r
+#include <sstream>\r
+#include <ctime>\r
+#include <cassert>\r
+#include "regxstring.h"\r
+#include "regxstring_impl.h"\r
+\r
+#if _DZ_DEBUG\r
+#   include <iostream>\r
+\r
+static void printRefs(__DZ_OSTRINGSTREAM & oss,const REGXSTRING_NS::__Refs & refs)\r
+{\r
+    for(REGXSTRING_NS::__Refs::const_iterator i = refs.begin();i != refs.end();++i)\r
+        std::cout<<"\t"<<oss.str().substr(i->first,i->second);\r
+}\r
+\r
+#   define _OSS_OUT(msg) {  \\r
+        std::cout<<msg<<" : "<<gdata.oss_.str(); \\r
+        printRefs(gdata.oss_,gdata.refs_);    \\r
+        std::cout<<std::endl;}\r
+#else\r
+#   define _OSS_OUT(str)\r
+#endif\r
+\r
+NAMESAPCE_BEGIN\r
+\r
+// Replacements for new and delete\r
+template<class T>\r
+T * New(){\r
+    T * ret = __DZ_ALLOC<T>().allocate(1);\r
+    return new (ret) T;\r
+}\r
+\r
+template<class T,class A>\r
+T * New(const A & a){\r
+    T * ret = __DZ_ALLOC<T>().allocate(1);\r
+    return new (ret) T(a);\r
+}\r
+\r
+template<class T,class A,class B>\r
+T * New(const A & a,const B & b){\r
+    T * ret = __DZ_ALLOC<T>().allocate(1);\r
+    return new (ret) T(a,b);\r
+}\r
+\r
+template<class T,class A,class B,class C>\r
+T * New(const A & a,const B & b,const C & c){\r
+    T * ret = __DZ_ALLOC<T>().allocate(1);\r
+    return new (ret) T(a,b,c);\r
+}\r
+template<class T>\r
+void Delete(T * p){\r
+    typedef char __dummy[sizeof(T)];\r
+    if(p){\r
+        p->~T();\r
+        __DZ_ALLOC<T>().deallocate(p,1);\r
+    }\r
+}\r
+\r
+struct __IsNull\r
+{\r
+    bool operator ()(__NodeBase * n) const{\r
+        return !n;\r
+    }\r
+};\r
+\r
+static const char * const SEP = "  ";\r
+\r
+static __DZ_STRING sep(int lvl)\r
+{\r
+    __DZ_STRING ret;\r
+    while(lvl-- > 0)\r
+        ret += SEP;\r
+    return ret;\r
+}\r
+\r
+static void appendNode(__NodeBase *& parent,__NodeBase * node)\r
+{\r
+    if(!node)\r
+        return;\r
+    if(!parent)\r
+        parent = New<__Seq>(node);\r
+    else\r
+        parent->AppendNode(node);\r
+}\r
+\r
+namespace Tools{\r
+\r
+    inline bool IsRepeat(int ch){\r
+        return ch == '?' || ch == '+' || ch == '*';\r
+    }\r
+\r
+    inline bool IsBegin(int ch){\r
+        return ch == '^';\r
+    }\r
+\r
+    inline bool IsEnd(int ch){\r
+        return ch == '$';\r
+    }\r
+\r
+    inline bool IsSlash(int ch){\r
+        return ch == '\\';\r
+    }\r
+\r
+    inline bool IsSetBegin(int ch){\r
+        return ch == '[';\r
+    }\r
+\r
+    inline bool IsSetEnd(int ch){\r
+        return ch == ']';\r
+    }\r
+\r
+    inline bool IsGroupBegin(int ch){\r
+        return ch == '(';\r
+    }\r
+\r
+    inline bool IsGroupEnd(int ch){\r
+        return ch == ')';\r
+    }\r
+\r
+    inline bool IsSelect(int ch){\r
+        return ch == '|';\r
+    }\r
+\r
+    inline bool IsRepeatBegin(int ch){\r
+        return ch == '{';\r
+    }\r
+\r
+    inline bool IsRepeatEnd(int ch){\r
+        return ch == '}';\r
+    }\r
+\r
+    inline bool NeedEnd(int ch){\r
+        return IsGroupEnd(ch) || IsRepeatEnd(ch);\r
+    }\r
+\r
+    inline bool IsDigit(int ch){\r
+        return '0' <= ch && ch <= '9';\r
+    }\r
+\r
+    inline int TransDigit(int ch){\r
+        return ch - '0';\r
+    }\r
+\r
+    inline bool IsDash(int ch){\r
+        return ch == '-';\r
+    }\r
+\r
+    inline bool IsAny(int ch){\r
+        return ch == '.';\r
+    }\r
+\r
+    inline int IsSubexpMark(int ch){\r
+        return (ch == ':' || ch == '=' || ch == '!' || ch == '>' ? ch : 0);\r
+    }\r
+\r
+    inline int IsSubexpMark(const char * s){\r
+        return (*s == '?' ? IsSubexpMark(*(s + 1)) : 0);\r
+    }\r
+\r
+    inline char TransSlash(int ch){\r
+        switch(ch){\r
+            case 'f':return '\f';\r
+            case 'n':return '\n';\r
+            case 'r':return '\r';\r
+            case 't':return '\t';\r
+            case 'v':return '\v';\r
+        }\r
+        return ch;\r
+    }\r
+}\r
+\r
+//struct __ParseData\r
+int __ParseData::inEnds(int ch) const\r
+{\r
+    int ret = 1;\r
+    for(__Ends::const_reverse_iterator i = ends_.rbegin();i != ends_.rend();++i,++ret){\r
+        if(ch == *i)\r
+            return ret;\r
+        if(Tools::NeedEnd(*i))\r
+            break;\r
+    }\r
+    return 0;\r
+}\r
+\r
+//struct __NodeBase\r
+__NodeBase * const __NodeBase::REP_NULL = (__NodeBase *)1;\r
+\r
+#if _MEM_LEAK\r
+int __NodeBase::ref = 0;\r
+#endif\r
+\r
+__NodeBase::~__NodeBase()\r
+{\r
+#if _MEM_LEAK\r
+    --ref;\r
+#endif\r
+}\r
+\r
+int __NodeBase::Repeat(int ch)\r
+{\r
+    return 1;\r
+}\r
+\r
+void __NodeBase::AppendNode(__NodeBase * node)\r
+{\r
+    assert(0);\r
+}\r
+\r
+//struct __Edge\r
+__Edge::__Edge(int ch)\r
+    : begin_(ch == '^')\r
+{}\r
+\r
+__NodeBase * __Edge::Optimize(__ParseData & pdata)\r
+{\r
+    return REP_NULL;\r
+}\r
+\r
+void __Edge::RandString(__GenerateData & gdata) const\r
+{\r
+    _OSS_OUT("__Edge");\r
+}\r
+\r
+void __Edge::Debug(std::ostream & out,int lvl) const\r
+{\r
+    out<<sep(lvl)<<(begin_ ? "BEGIN" : "END")<<"\n";\r
+}\r
+\r
+//struct __Text\r
+__Text::__Text(int ch)\r
+    : str_(1,ch)\r
+{}\r
+\r
+__NodeBase * __Text::Optimize(__ParseData & pdata)\r
+{\r
+    return (str_.empty() ? REP_NULL : 0);\r
+}\r
+\r
+void __Text::RandString(__GenerateData & gdata) const\r
+{\r
+    gdata.oss_<<str_;\r
+    _OSS_OUT("__Text");\r
+}\r
+\r
+void __Text::Debug(std::ostream & out,int lvl) const\r
+{\r
+    out<<sep(lvl)<<"Text("<<str_<<")\n";\r
+}\r
+\r
+//class __Charset\r
+__Charset::__Charset()\r
+    : inc_(1)\r
+{}\r
+\r
+__Charset::__Charset(const __DZ_STRING & str,bool include)\r
+    : str_(str)\r
+    , inc_(include)\r
+{}\r
+\r
+__NodeBase * __Charset::Optimize(__ParseData & pdata)\r
+{\r
+    if(!inc_)\r
+        reverse();\r
+    if(str_.empty())\r
+        return REP_NULL;\r
+    inc_ = str_.size();\r
+    return 0;\r
+}\r
+\r
+void __Charset::RandString(__GenerateData & gdata) const\r
+{\r
+    assert(inc_ == str_.size());\r
+    gdata.oss_<<str_[rand() % inc_];\r
+    _OSS_OUT("__Charset");\r
+}\r
+\r
+void __Charset::Debug(std::ostream & out,int lvl) const\r
+{\r
+    out<<sep(lvl)<<"Charset(INCLUDE"\r
+        <<", "<<str_<<")\n";\r
+}\r
+\r
+void __Charset::Exclude()\r
+{\r
+    inc_ = 0;\r
+}\r
+\r
+void __Charset::AddChar(int ch)\r
+{\r
+    str_.push_back(ch);\r
+}\r
+\r
+void __Charset::AddRange(int from,int to)\r
+{\r
+    for(;from <= to;++from)\r
+        str_.push_back(from);\r
+}\r
+\r
+void __Charset::AddRange(__Charset * node)\r
+{\r
+    if(!node)\r
+        return;\r
+    unite(*node);\r
+}\r
+\r
+void __Charset::Unique()\r
+{\r
+    inc_ ? unique() : reverse();\r
+}\r
+\r
+void __Charset::unite(__Charset & node)\r
+{\r
+    if(!node.inc_)\r
+        node.reverse();\r
+    str_ += node.str_;\r
+}\r
+\r
+void __Charset::reverse()\r
+{\r
+    const int _CHAR_MIN = 32;\r
+    const int _CHAR_MAX = 126;\r
+    unique();\r
+    __DZ_STRING s;\r
+    s.swap(str_);\r
+    int c = _CHAR_MIN;\r
+    size_t i = 0,e = s.size();\r
+    for(;c <= _CHAR_MAX && i < e;++i){\r
+        int ch = s[i];\r
+        if(c < ch)\r
+            AddRange(c,ch - 1);\r
+        c = std::max(ch + 1,_CHAR_MIN);\r
+    }\r
+    if(c <= _CHAR_MAX)\r
+        AddRange(c,_CHAR_MAX);\r
+    inc_ = !inc_;\r
+}\r
+\r
+void __Charset::unique()\r
+{\r
+    if(!str_.empty()){\r
+        std::sort(str_.begin(),str_.end());\r
+        str_.erase(std::unique(str_.begin(),str_.end()),str_.end());\r
+    }\r
+}\r
+\r
+//class __Repeat\r
+__Repeat::__Repeat(__NodeBase * node,int ch)\r
+    : node_(node)\r
+    , min_(0)\r
+    , max_(0)\r
+{\r
+    switch(ch){\r
+        case '?':min_ = 0;max_ = 1;break;\r
+        case '+':min_ = 1;max_ = INFINITE;break;\r
+        case '*':min_ = 0;max_ = INFINITE;break;\r
+        default:;\r
+    }\r
+}\r
+\r
+__Repeat::__Repeat(__NodeBase * node,int min,int max)\r
+    : node_(node)\r
+    , min_(min)\r
+    , max_(max)\r
+{}\r
+\r
+__Repeat::~__Repeat(){\r
+    Delete(node_);\r
+}\r
+\r
+__NodeBase * __Repeat::Optimize(__ParseData & pdata)\r
+{\r
+    min_ &= _CLEAR_FLAGS;\r
+    max_ &= _CLEAR_FLAGS;\r
+    if(isInfinite()){\r
+        max_ = min_ + pdata.config_.repeatInfinite;\r
+        if( max_ > _REPEAT_MAX)\r
+            max_ = _REPEAT_MAX;\r
+    }\r
+    if(!node_ || (min_ > max_) || (!min_ && !max_))\r
+        return REP_NULL;\r
+    __NodeBase * r = node_->Optimize(pdata);\r
+    if(r == REP_NULL)\r
+        return REP_NULL;\r
+    else if(r){\r
+        Delete(node_);\r
+        node_ = r;\r
+    }\r
+    if(1 == max_ && 1 == min_){\r
+        r = node_;\r
+        node_ = 0;\r
+        return r;\r
+    }\r
+    max_ -= min_ - 1;\r
+    return 0;\r
+}\r
+\r
+void __Repeat::RandString(__GenerateData & gdata) const\r
+{\r
+    for(int t = min_ + rand() % max_;t > 0;t--)\r
+        node_->RandString(gdata);\r
+    _OSS_OUT("__Repeat");\r
+}\r
+\r
+void __Repeat::Debug(std::ostream & out,int lvl) const\r
+{\r
+    out<<sep(lvl)<<"Repeat["<<min_<<", "<<(min_ + max_ - 1)<<"]\n";\r
+    ++lvl;\r
+    if(node_)\r
+        node_->Debug(out,lvl);\r
+    else\r
+        out<<sep(lvl)<<"NULL\n";\r
+}\r
+\r
+int __Repeat::Repeat(int ch)\r
+{\r
+    if(canRepeat()){\r
+        switch(ch){\r
+            case '?':min_ |= _NON_GREEDY;return 2;break;\r
+            case '+':min_ |= _PROSSESSIVE;return 2;break;\r
+            default:;\r
+        }\r
+    }\r
+    return 0;\r
+}\r
+\r
+//class __Seq\r
+__Seq::__Seq(__NodeBase * node)\r
+    : seq_(1,node)\r
+{}\r
+\r
+__Seq::~__Seq(){\r
+    for(__Con::const_iterator i = seq_.begin(),e = seq_.end();i != e;++i)\r
+        Delete(*i);\r
+}\r
+\r
+__NodeBase * __Seq::Optimize(__ParseData & pdata)\r
+{\r
+    if(seq_.empty())\r
+        return REP_NULL;\r
+    for(__Con::iterator i = seq_.begin(),e = seq_.end();i != e;++i)\r
+        if(*i){\r
+            __NodeBase * r = (*i)->Optimize(pdata);\r
+            if(r){\r
+                Delete(*i);\r
+                *i = (r == REP_NULL ? 0 : r);\r
+            }\r
+        }\r
+    seq_.erase(std::remove_if(seq_.begin(),seq_.end(),__IsNull()),seq_.end());\r
+    if(seq_.empty())\r
+        return REP_NULL;\r
+    if(seq_.size() == 1){\r
+        __NodeBase * r = seq_[0];\r
+        seq_.clear();\r
+        return r;\r
+    }\r
+    return 0;\r
+}\r
+\r
+void __Seq::RandString(__GenerateData & gdata) const\r
+{\r
+    for(__Con::const_iterator i = seq_.begin(),e = seq_.end();i != e;++i)\r
+        (*i)->RandString(gdata);\r
+    _OSS_OUT("__Seq");\r
+}\r
+\r
+void __Seq::Debug(std::ostream & out,int lvl) const\r
+{\r
+    out<<sep(lvl)<<"Seq("<<seq_.size()<<")\n";\r
+    ++lvl;\r
+    for(__Con::const_iterator i = seq_.begin(),e = seq_.end();i != e;++i){\r
+        if(*i)\r
+            (*i)->Debug(out,lvl);\r
+        else\r
+            out<<sep(lvl)<<"NULL\n";\r
+    }\r
+}\r
+\r
+void __Seq::AppendNode(__NodeBase * node)\r
+{\r
+    if(!seq_.empty())\r
+        if(__Text * cur = dynamic_cast<__Text *>(node))\r
+            if(__Text * prev = dynamic_cast<__Text *>(seq_.back())){\r
+                *prev += *cur;\r
+                Delete(node);\r
+                return;\r
+            }\r
+    seq_.push_back(node);\r
+}\r
+\r
+//class __Group\r
+__Group::__Group(__NodeBase * node,int mark)\r
+    : node_(node)\r
+    , mark_(mark)\r
+{\r
+    if(!Tools::IsSubexpMark(mark_))\r
+        mark_ |= INDEX;\r
+}\r
+\r
+__Group::~__Group()\r
+{\r
+    Delete(node_);\r
+}\r
+\r
+__NodeBase * __Group::Optimize(__ParseData & pdata)\r
+{\r
+    if(!node_ || mark_ == '!')\r
+        return REP_NULL;\r
+    __NodeBase * r = node_->Optimize(pdata);\r
+    if(r == REP_NULL)\r
+        return REP_NULL;\r
+    else if(r){\r
+        Delete(node_);\r
+        node_ = r;\r
+    }\r
+    switch(mark_){\r
+        case ':':\r
+        case '=':\r
+        case '>':{\r
+            r = node_;\r
+            node_ = 0;\r
+            return r;}\r
+        default:;\r
+    }\r
+    mark_ = (mark_ & (INDEX - 1)) - 1;\r
+    return 0;\r
+}\r
+\r
+void __Group::RandString(__GenerateData & gdata) const\r
+{\r
+    assert(node_);\r
+    assert(0 <= mark_ && mark_ < MAX_GROUPS);\r
+    if(mark_ >= gdata.refs_.size())\r
+        gdata.refs_.resize(mark_ + 1);\r
+    gdata.refs_.back() = __RefValue(gdata.oss_.str().size(),__DZ_STRING::npos);\r
+    node_->RandString(gdata);\r
+    assert(mark_ < gdata.refs_.size());\r
+    gdata.refs_[mark_].second = gdata.oss_.str().size() - gdata.refs_[mark_].first;\r
+    _OSS_OUT("__Group");\r
+}\r
+\r
+void __Group::Debug(std::ostream & out,int lvl) const\r
+{\r
+    out<<sep(lvl)<<"Group(";\r
+    switch(mark_){\r
+        case ':':out<<"?:";break;\r
+        case '=':out<<"?=";break;\r
+        case '!':out<<"?!";break;\r
+        case '>':out<<"?>";break;\r
+        default:out<<(mark_ & (INDEX - 1));\r
+    }\r
+    out<<")\n";\r
+    ++lvl;\r
+    if(node_)\r
+        node_->Debug(out,lvl);\r
+    else\r
+        out<<sep(lvl)<<"NULL\n";\r
+}\r
+\r
+//class __Select\r
+__Select::__Select(__NodeBase * node)\r
+    : sel_(1,node)\r
+    , sz_(0)\r
+{}\r
+\r
+__Select::~__Select()\r
+{\r
+    for(__Con::const_iterator i = sel_.begin(),e = sel_.end();i != e;++i)\r
+        Delete(*i);\r
+}\r
+\r
+__NodeBase * __Select::Optimize(__ParseData & pdata)\r
+{\r
+    if(sel_.empty())\r
+        return REP_NULL;\r
+    for(__Con::iterator i = sel_.begin(),e = sel_.end();i != e;++i)\r
+        if(*i){\r
+            __NodeBase * r = (*i)->Optimize(pdata);\r
+            if(r){\r
+                Delete(*i);\r
+                *i = (r == REP_NULL ? 0 : r);\r
+            }\r
+        }\r
+    sel_.erase(std::remove_if(sel_.begin(),sel_.end(),__IsNull()),sel_.end());\r
+    if(sel_.empty())\r
+        return REP_NULL;\r
+    if(sel_.size() == 1){\r
+        __NodeBase * r = sel_[0];\r
+        sel_.clear();\r
+        return r;\r
+    }\r
+    sz_ = sel_.size();\r
+    return 0;\r
+}\r
+\r
+void __Select::RandString(__GenerateData & gdata) const\r
+{\r
+    if(sz_)\r
+        sel_[rand() % sz_]->RandString(gdata);\r
+    _OSS_OUT("__Select");\r
+}\r
+\r
+void __Select::Debug(std::ostream & out,int lvl) const\r
+{\r
+    out<<sep(lvl)<<"Select("<<sel_.size()<<")\n";\r
+    ++lvl;\r
+    for(__Con::const_iterator i = sel_.begin(),e = sel_.end();i != e;++i)\r
+        if(*i)\r
+            (*i)->Debug(out,lvl);\r
+        else\r
+            out<<sep(lvl)<<"NULL\n";\r
+}\r
+\r
+void __Select::AppendNode(__NodeBase * node)\r
+{\r
+    sel_.push_back(node);\r
+}\r
+\r
+//class __Ref\r
+__Ref::__Ref(int index)\r
+    : index_(index)\r
+{}\r
+\r
+__NodeBase * __Ref::Optimize(__ParseData & pdata)\r
+{\r
+    --index_;\r
+    return 0;\r
+}\r
+\r
+void __Ref::RandString(__GenerateData & gdata) const\r
+{\r
+    assert(index_ < gdata.refs_.size());\r
+    const __RefValue & ref = gdata.refs_[index_];\r
+    __DZ_STRING str = gdata.oss_.str();\r
+    if(ref.first < str.size())\r
+        gdata.oss_<<str.substr(ref.first,ref.second);\r
+    _OSS_OUT("__Ref("<<index_<<")");\r
+}\r
+\r
+void __Ref::Debug(std::ostream & out,int lvl) const\r
+{\r
+    out<<sep(lvl)<<"Ref("<<index_<<")\n";\r
+}\r
+\r
+//class __CRegxString\r
+__CRegxString::__CRegxString()\r
+    : top_(0)\r
+{}\r
+\r
+void __CRegxString::ParseRegx(const __DZ_STRING & regx,const Config * config)\r
+{\r
+    uninit();\r
+    regx_ = regx;\r
+    if(regx_.empty())\r
+        return;\r
+    Config def;\r
+    __ParseData pdata(config ? *config : def);\r
+    top_ = processSeq(pdata).first;\r
+    if(!top_)\r
+        return;\r
+    __NodeBase * r = top_->Optimize(pdata);\r
+    if(r){\r
+        Delete(top_);\r
+        top_ = (r == __NodeBase::REP_NULL ? 0 : r);\r
+    }\r
+    // if(top_)\r
+    //     srand((unsigned int)time(0));\r
+    // Changed by Adrian Lita\r
+}\r
+\r
+const __DZ_STRING & __CRegxString::RandString()\r
+{\r
+    str_.clear();\r
+    if(top_){\r
+        __DZ_OSTRINGSTREAM oss;\r
+        __GenerateData gdata(oss);\r
+        top_->RandString(gdata);\r
+        str_ = oss.str();\r
+    }\r
+    return str_;\r
+}\r
+\r
+void __CRegxString::Debug(std::ostream & out) const{\r
+    out<<"regx_ : "<<regx_<<"\nstructure :\n";\r
+    if(top_)\r
+        top_->Debug(out,0);\r
+    else\r
+        out<<"NULL\n";\r
+}\r
+\r
+void __CRegxString::uninit()\r
+{\r
+    if(top_){\r
+        Delete(top_);\r
+        top_ = 0;\r
+    }\r
+    str_.clear();\r
+}\r
+\r
+__CRegxString::__Ret __CRegxString::processSeq(__ParseData & pdata)\r
+{\r
+    __Ret ret;\r
+    __NodeBase * cur = 0;\r
+    bool begin = true;\r
+    for(const size_t e = regx_.length();pdata.i_ < e;++pdata.i_){\r
+        int ch = regx_[pdata.i_];\r
+        if(begin){\r
+            if(Tools::IsBegin(ch)){\r
+                cur = New<__Edge>(ch);\r
+                continue;\r
+            }\r
+            begin = false;\r
+        }\r
+        if(Tools::IsRepeat(ch) && cur){\r
+            int r = cur->Repeat(ch);\r
+            if(r){\r
+                if(r == 1)\r
+                    cur = New<__Repeat>(cur,ch);\r
+                continue;\r
+            }\r
+        }\r
+        if(Tools::IsRepeatBegin(ch)){\r
+            cur = processRepeat(cur,pdata);\r
+            continue;\r
+        }\r
+        appendNode(ret.first,cur);\r
+        ret.second = pdata.inEnds(ch);\r
+        if(ret.second)\r
+            return ret;\r
+        if(Tools::IsSelect(ch))\r
+            return processSelect(ret.first,pdata);\r
+        if(Tools::IsEnd(ch))\r
+            cur = New<__Edge>(ch);\r
+        else if(Tools::IsAny(ch)){\r
+             __Charset * set = New<__Charset>("\n",false);\r
+             set->Unique();\r
+             cur = set;\r
+        }else if(Tools::IsSetBegin(ch))\r
+            cur = processSet(pdata);\r
+        else if(Tools::IsGroupBegin(ch))\r
+            cur = processGroup(pdata);\r
+        else if(Tools::IsSlash(ch))\r
+            cur = processSlash(true,pdata).first;\r
+        else\r
+            cur = New<__Text>(ch);\r
+    }\r
+    appendNode(ret.first,cur);\r
+    return ret;\r
+}\r
+\r
+__CRegxString::__Ret __CRegxString::processSlash(bool bNode,__ParseData & pdata)\r
+{\r
+    ++pdata.i_;\r
+    __Ret ret((__NodeBase *)0,pdata.i_ < regx_.length() ? Tools::TransSlash(regx_[pdata.i_]) : '\\');\r
+    __Charset * set = 0;\r
+    switch(ret.second){\r
+        case 'd':set = New<__Charset>("0123456789",true);break;\r
+        case 'D':set = New<__Charset>("0123456789",false);break;\r
+        case 's':set = New<__Charset>(/*"\f\n\r\v"*/"\t ",true);break;\r
+        case 'S':set = New<__Charset>(/*"\f\n\r\v"*/"\t ",false);break;\r
+        case 'w':{   //A-Za-z0-9_\r
+            set = New<__Charset>();\r
+            set->AddRange('A','Z');\r
+            set->AddRange('a','z');\r
+            set->AddRange('0','9');\r
+            set->AddChar('_');\r
+            break;}\r
+        case 'W':{   //^A-Za-z0-9_\r
+            set =  New<__Charset>();\r
+            set->AddRange('A','Z');\r
+            set->AddRange('a','z');\r
+            set->AddRange('0','9');\r
+            set->AddChar('_');\r
+            set->Exclude();\r
+            break;}\r
+        default:;\r
+    }\r
+    if(set){\r
+        set->Unique();\r
+        ret.first = set;\r
+    }else if(bNode){\r
+        if(Tools::IsDigit(ret.second)){\r
+            int i = ret.second - '0';\r
+            if(!i)\r
+                ret.second = 0;\r
+            else if(i <= pdata.ref_)\r
+                ret.first = New<__Ref>(i);\r
+        }\r
+        if(!ret.first)\r
+            ret.first = New<__Text>(ret.second);\r
+    }\r
+    return ret;\r
+}\r
+\r
+__NodeBase * __CRegxString::processSet(__ParseData & pdata)\r
+{\r
+    size_t bak = pdata.i_++;\r
+    __Charset * ret = New<__Charset>();\r
+    bool begin = true;\r
+    int prev = 0;\r
+    for(const size_t e = regx_.length();pdata.i_ < e;++pdata.i_){\r
+        int ch = regx_[pdata.i_];\r
+        if(begin && Tools::IsBegin(ch)){\r
+            ret->Exclude();\r
+            begin = false;\r
+            continue;\r
+        }\r
+        if(Tools::IsDash(ch) && prev){\r
+            int to = 0;\r
+            if(processRange(to,pdata)){\r
+                ret->AddRange(prev,to);\r
+                prev = 0;\r
+                continue;\r
+            }\r
+        }\r
+        if(prev)\r
+            ret->AddChar(prev);\r
+        if(Tools::IsSetEnd(ch)){\r
+            ret->Unique();\r
+            return ret;\r
+        }\r
+        if(Tools::IsSlash(ch)){\r
+            __Ret s = processSlash(false,pdata);\r
+            if(s.first){    //charset\r
+                ret->AddRange(dynamic_cast<__Charset *>(s.first));\r
+                Delete(s.first);\r
+                prev = 0;\r
+                continue;\r
+            }\r
+            ch = s.second;\r
+        }\r
+        prev = ch;\r
+    }\r
+    Delete(ret);\r
+    pdata.i_ = bak;\r
+    return New<__Text>('[');\r
+}\r
+\r
+__NodeBase * __CRegxString::processGroup(__ParseData & pdata)\r
+{\r
+    int bak = pdata.i_++;\r
+    int mark = ignoreSubexpMarks(pdata);\r
+    pdata.ends_.push_back(')');\r
+    if(!mark)\r
+        mark = ++pdata.ref_;\r
+    __Ret ret = processSeq(pdata);\r
+    pdata.ends_.pop_back();\r
+    if(ret.second)\r
+        return New<__Group>(ret.first,mark);\r
+    Delete(ret.first);\r
+    pdata.i_ = bak;\r
+    return New<__Text>('(');\r
+}\r
+\r
+__CRegxString::__Ret __CRegxString::processSelect(__NodeBase * node,__ParseData & pdata)\r
+{\r
+    __Ret ret(New<__Select>(node),0);\r
+    pdata.ends_.push_back('|');\r
+    for(const size_t e = regx_.length();pdata.i_ < e;){\r
+        ++pdata.i_;\r
+        __Ret r = processSeq(pdata);\r
+        ret.first->AppendNode(r.first);\r
+        if(r.second > 1){\r
+            ret.second = r.second - 1;\r
+            break;\r
+        }\r
+    }\r
+    pdata.ends_.pop_back();\r
+    return ret;\r
+}\r
+\r
+__NodeBase * __CRegxString::processRepeat(__NodeBase * node,__ParseData & pdata)\r
+{\r
+    if(node && node->Repeat(0)){\r
+        size_t bak = pdata.i_++;\r
+        int min = 0,max = __Repeat::INFINITE;\r
+        switch(processInt(min,pdata)){\r
+            case ',':\r
+                ++pdata.i_;\r
+                if(processInt(max,pdata) == '}')\r
+                    return New<__Repeat>(node,min,(min < max ? max : min));\r
+                break;\r
+            case '}':\r
+                return New<__Repeat>(node,min,min);\r
+            default:;\r
+        }\r
+        pdata.i_ = bak;\r
+    }\r
+    return New<__Text>('{');\r
+}\r
+\r
+int __CRegxString::processInt(int & result,__ParseData & pdata)\r
+{\r
+    bool begin = true;\r
+    for(const size_t e = regx_.length();pdata.i_ < e;++pdata.i_){\r
+        int ch = regx_[pdata.i_];\r
+        if(Tools::IsDigit(ch)){\r
+            ch = Tools::TransDigit(ch);\r
+            if(begin){\r
+                result = ch;\r
+                begin = false;\r
+            }else{\r
+                result *= 10;\r
+                if(result < 0)\r
+                    return 0;\r
+                result += ch;\r
+            }\r
+        }else\r
+            return ch;\r
+    }\r
+    return 0;\r
+}\r
+\r
+bool __CRegxString::processRange(int & result,__ParseData & pdata)\r
+{\r
+    if(++pdata.i_ < regx_.size() && regx_[pdata.i_] != ']'){\r
+        result = regx_[pdata.i_];\r
+        return true;\r
+    }\r
+    --pdata.i_;\r
+    return false;\r
+}\r
+\r
+int __CRegxString::ignoreSubexpMarks(__ParseData & pdata)\r
+{\r
+    int ret = 0;\r
+    if(pdata.i_ + 1 < regx_.size()){\r
+        ret = Tools::IsSubexpMark(&regx_[pdata.i_]);\r
+        if(ret)\r
+            pdata.i_ += 2;\r
+    }\r
+    return ret;\r
+}\r
+\r
+NAMESAPCE_END\r
diff --git a/ntsimulator/regxstring/regxstring_impl.h b/ntsimulator/regxstring/regxstring_impl.h
new file mode 100644 (file)
index 0000000..c3b67b3
--- /dev/null
@@ -0,0 +1,290 @@
+/*************************************************************************\r
+*\r
+* Licensed under the Apache License, Version 2.0 (the "License");\r
+* you may not use this file except in compliance with the License.\r
+* You may obtain a copy of the License at\r
+*\r
+*     http://www.apache.org/licenses/LICENSE-2.0\r
+*\r
+* Unless required by applicable law or agreed to in writing, software\r
+* distributed under the License is distributed on an "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+* See the License for the specific language governing permissions and\r
+* limitations under the License.\r
+***************************************************************************/\r
+\r
+#ifndef DOZERG_REGXSTRING_IMPL_H_20091012\r
+#define DOZERG_REGXSTRING_IMPL_H_20091012\r
+\r
+#include <string>\r
+#include <vector>\r
+#include <iosfwd>\r
+#include <utility>\r
+#include <memory>\r
+\r
+#define _DZ_DEBUG 0\r
+\r
+#define _MEM_LEAK 0\r
+\r
+//allocator choice\r
+#ifndef __GNUC__ \r
+#   define __DZ_ALLOC       std::allocator\r
+#else\r
+#   ifndef NDEBUG\r
+#       define __DZ_ALLOC   std::allocator\r
+#   else\r
+#       include <ext/pool_allocator.h>\r
+#       define __DZ_ALLOC   __gnu_cxx::__pool_alloc\r
+#   endif\r
+#endif\r
+\r
+//stl containers redefine\r
+    //Sequence\r
+#define __DZ_BASIC_STRING(C)            std::basic_string< C,std::char_traits< C >,__DZ_ALLOC< C > >\r
+#define __DZ_BASIC_STRING1(C,T)         std::basic_string< C,T,__DZ_ALLOC< C > >\r
+#define __DZ_STRING                     __DZ_BASIC_STRING(char)\r
+#define __DZ_WSTRING                    __DZ_BASIC_STRING(wchar_t)\r
+#define __DZ_DEQUE(T)                   std::deque< T,__DZ_ALLOC< T > >\r
+#define __DZ_LIST(T)                    std::list< T,__DZ_ALLOC< T > >\r
+#define __DZ_VECTOR(T)                  std::vector< T,__DZ_ALLOC< T > >\r
+    //Associative\r
+#define __DZ_MAP(K,V)                   std::map< K,V,std::less< K >,__DZ_ALLOC<std::pair< K,V > > >\r
+#define __DZ_MAP1(K,V,C)                std::map< K,V,C,__DZ_ALLOC<std::pair< K,V > > >\r
+#define __DZ_MULTIMAP(K,V)              std::multimap< K,V,std::less< K >,__DZ_ALLOC<std::pair< K,V > > >\r
+#define __DZ_MULTIMAP1(K,V,C)           std::multimap< K,V,C,__DZ_ALLOC<std::pair< K,V > > >\r
+#define __DZ_SET(K)                     std::set< K,std::less< K >,__DZ_ALLOC< K > >\r
+#define __DZ_SET1(K,C)                  std::set< K,C,__DZ_ALLOC< K > >\r
+#define __DZ_MULTISET(K)                std::multiset< K,std::less< K >,__DZ_ALLOC< K > >\r
+#define __DZ_MULTISET1(K,C)             std::multiset< K,C,__DZ_ALLOC< K > >\r
+    //String Stream\r
+#define __DZ_BASIC_ISTRINGSTREAM(C)     std::basic_istringstream< C,std::char_traits< C >,__DZ_ALLOC< C > >\r
+#define __DZ_BASIC_ISTRINGSTREAM1(C,T)  std::basic_istringstream< C,T,__DZ_ALLOC< C > >\r
+#define __DZ_BASIC_OSTRINGSTREAM(C)     std::basic_ostringstream< C,std::char_traits< C >,__DZ_ALLOC< C > >\r
+#define __DZ_BASIC_OSTRINGSTREAM1(C,T)  std::basic_ostringstream< C,T,__DZ_ALLOC< C > >\r
+#define __DZ_BASIC_STRINGSTREAM(C)      std::basic_stringstream< C,std::char_traits< C >,__DZ_ALLOC< C > >\r
+#define __DZ_BASIC_STRINGSTREAM1(C,T)   std::basic_stringstream< C,T,__DZ_ALLOC< C > >\r
+#define __DZ_ISTRINGSTREAM              __DZ_BASIC_ISTRINGSTREAM(char)\r
+#define __DZ_OSTRINGSTREAM              __DZ_BASIC_OSTRINGSTREAM(char)\r
+#define __DZ_STRINGSTREAM               __DZ_BASIC_STRINGSTREAM(char)\r
+#define __DZ_WISTRINGSTREAM             __DZ_BASIC_ISTRINGSTREAM(wchar_t)\r
+#define __DZ_WOSTRINGSTREAM             __DZ_BASIC_OSTRINGSTREAM(wchar_t)\r
+#define __DZ_WSTRINGSTREAM              __DZ_BASIC_STRINGSTREAM(wchar_t)\r
+    //Stream Buf\r
+#define __DZ_BASIC_STRINGBUF(C)         std::basic_stringbuf< C,std::char_traits< C >,__DZ_ALLOC< C > >\r
+#define __DZ_BASIC_STRINGBUF1(C,T)      std::basic_stringbuf< C,T,__DZ_ALLOC< C > >\r
+#define __DZ_STRINGBUF                  __DZ_BASIC_STRINGBUF(char)\r
+#define __DZ_WSTRINGBUF                 __DZ_BASIC_STRINGBUF(wchar_t)\r
+    //Extension\r
+#define __DZ_ROPE(T)                    __gnu_cxx::rope< T,__DZ_ALLOC< T > >\r
+#define __DZ_SLIST(T)                   __gnu_cxx::slist< T,__DZ_ALLOC< T > >\r
+\r
+#define REGXSTRING_NS       __DZ_Regx_String\r
+\r
+#define NAMESAPCE_BEGIN     namespace __DZ_Regx_String{\r
+#define NAMESAPCE_END       }\r
+\r
+struct Config;\r
+\r
+NAMESAPCE_BEGIN\r
+\r
+typedef std::pair<size_t,size_t>    __RefValue;\r
+\r
+typedef __DZ_VECTOR(__RefValue)     __Refs;\r
+\r
+typedef __DZ_VECTOR(char)           __Ends;\r
+\r
+struct __ParseData{\r
+    __Ends ends_;\r
+    const Config & config_;\r
+    size_t i_;\r
+    int ref_;\r
+    //functions:\r
+    explicit __ParseData(const Config & config)\r
+        : config_(config)\r
+        , i_(0)\r
+        , ref_(0)\r
+    {}\r
+    int inEnds(int ch) const;\r
+};\r
+\r
+struct __GenerateData\r
+{\r
+    __Refs refs_;\r
+    __DZ_OSTRINGSTREAM & oss_;\r
+    explicit __GenerateData(__DZ_OSTRINGSTREAM & oss)\r
+        : oss_(oss)\r
+    {}\r
+};\r
+\r
+struct __NodeBase\r
+{\r
+    static __NodeBase * const REP_NULL; //replace with NULL(0)\r
+#if _MEM_LEAK\r
+    static int ref;\r
+    __NodeBase(){++ref;}\r
+#endif\r
+    virtual ~__NodeBase();\r
+    virtual __NodeBase * Optimize(__ParseData & pdata) = 0;\r
+    virtual void RandString(__GenerateData & gdata) const = 0;\r
+    virtual void Debug(std::ostream & out,int lvl) const = 0;\r
+    virtual int Repeat(int ch);\r
+    virtual void AppendNode(__NodeBase * node);\r
+};\r
+\r
+class __Edge : public __NodeBase\r
+{\r
+    bool begin_;\r
+public:\r
+    explicit __Edge(int ch);\r
+    __NodeBase * Optimize(__ParseData & pdata);\r
+    void RandString(__GenerateData & gdata) const;\r
+    void Debug(std::ostream & out,int lvl) const;\r
+};\r
+\r
+class __Text : public __NodeBase\r
+{\r
+    __DZ_STRING str_;\r
+public:\r
+    //functions\r
+    explicit __Text(int ch);\r
+    __NodeBase * Optimize(__ParseData & pdata);\r
+    void RandString(__GenerateData & gdata) const;\r
+    void Debug(std::ostream & out,int lvl) const;\r
+    __Text & operator +=(const __Text & other){str_ += other.str_;return *this;}\r
+};\r
+\r
+class __Charset : public __NodeBase\r
+{\r
+    __DZ_STRING str_;\r
+    size_t inc_;\r
+public:\r
+    //functions\r
+    __Charset();\r
+    __Charset(const __DZ_STRING & str,bool include);\r
+    __NodeBase * Optimize(__ParseData & pdata);\r
+    void RandString(__GenerateData & gdata) const;\r
+    void Debug(std::ostream & out,int lvl) const;\r
+    void Exclude();\r
+    void AddChar(int ch);\r
+    void AddRange(int from,int to);\r
+    void AddRange(__Charset * node);\r
+    void Unique();\r
+private:\r
+    void unite(__Charset & node);\r
+    void reverse();\r
+    void unique();\r
+};\r
+\r
+struct __Repeat : public __NodeBase\r
+{\r
+    static const int INFINITE = 1 << 16;\r
+private:\r
+    static const int _REPEAT_MAX = __Repeat::INFINITE - 1;\r
+    static const int _NON_GREEDY = 1 << 17;\r
+    static const int _PROSSESSIVE = 1 << 18;\r
+    static const int _CLEAR_FLAGS = _NON_GREEDY - 1;\r
+    __NodeBase * node_;\r
+    int min_,max_;\r
+public:\r
+    //functions\r
+    __Repeat(__NodeBase * node,int ch);\r
+    __Repeat(__NodeBase * node,int min,int max);\r
+    ~__Repeat();\r
+    __NodeBase * Optimize(__ParseData & pdata);\r
+    void RandString(__GenerateData & gdata) const;\r
+    void Debug(std::ostream & out,int lvl) const;\r
+    int Repeat(int ch);\r
+private:\r
+    bool isInfinite() const{return (max_ & INFINITE) != 0;}\r
+    bool isNonGreedy() const{return (min_ & _NON_GREEDY) != 0;}\r
+    bool isPossessive() const{return (min_ & _PROSSESSIVE) != 0;}\r
+    bool canRepeat() const{return !(min_ & (_NON_GREEDY | _PROSSESSIVE));}\r
+};\r
+\r
+class __Seq : public __NodeBase\r
+{\r
+    typedef __DZ_VECTOR(__NodeBase *) __Con;\r
+    __Con seq_;\r
+public:\r
+    //functions\r
+    explicit __Seq(__NodeBase * node);\r
+    ~__Seq();\r
+    __NodeBase * Optimize(__ParseData & pdata);\r
+    void RandString(__GenerateData & gdata) const;\r
+    void Debug(std::ostream & out,int lvl) const;\r
+    void AppendNode(__NodeBase * node);\r
+};\r
+\r
+class __Group : public __NodeBase\r
+{\r
+    static const int INDEX = 1 << 16;   //group index flag\r
+    static const size_t MAX_GROUPS = 9;\r
+    __NodeBase * node_;\r
+    size_t mark_;\r
+public:\r
+    //functions\r
+    __Group(__NodeBase * node,int mark);\r
+    ~__Group();\r
+    __NodeBase * Optimize(__ParseData & pdata);\r
+    void RandString(__GenerateData & gdata) const;\r
+    void Debug(std::ostream & out,int lvl) const;\r
+};\r
+\r
+class __Select : public __NodeBase\r
+{\r
+    typedef __DZ_VECTOR(__NodeBase *) __Con;\r
+    __Con sel_;\r
+    size_t sz_;\r
+public:\r
+    //functions\r
+    explicit __Select(__NodeBase * node);\r
+    ~__Select();\r
+    __NodeBase * Optimize(__ParseData & pdata);\r
+    void RandString(__GenerateData & gdata) const;\r
+    void Debug(std::ostream & out,int lvl) const;\r
+    void AppendNode(__NodeBase * node);\r
+};\r
+\r
+class __Ref : public __NodeBase\r
+{\r
+    size_t index_;\r
+public:\r
+    explicit __Ref(int index);\r
+    __NodeBase * Optimize(__ParseData & pdata);\r
+    void RandString(__GenerateData & gdata) const;\r
+    void Debug(std::ostream & out,int lvl) const;\r
+};\r
+\r
+class __CRegxString\r
+{\r
+    typedef std::pair<__NodeBase *,int> __Ret;\r
+public:\r
+    __CRegxString();\r
+    ~__CRegxString(){uninit();}\r
+    void ParseRegx(const __DZ_STRING & regx,const Config * config);\r
+    __DZ_STRING Regx() const{return regx_;}\r
+    const __DZ_STRING & RandString();\r
+    const __DZ_STRING & LastString() const{return str_;}\r
+    void Debug(std::ostream & out) const;\r
+private:\r
+    __CRegxString(const __CRegxString &);\r
+    __CRegxString & operator =(const __CRegxString &);\r
+    void uninit();\r
+    __Ret processSeq(__ParseData & pdata);\r
+    __Ret processSlash(bool bNode,__ParseData & pdata);\r
+    __NodeBase * processSet(__ParseData & pdata);\r
+    __NodeBase * processGroup(__ParseData & pdata);\r
+    __Ret processSelect(__NodeBase * node,__ParseData & pdata);\r
+    __NodeBase * processRepeat(__NodeBase * node,__ParseData & pdata);\r
+    int processInt(int & result,__ParseData & pdata);\r
+    bool processRange(int & result,__ParseData & pdata);\r
+    int ignoreSubexpMarks(__ParseData & pdata);\r
+    //fields:\r
+    __DZ_STRING regx_;\r
+    __DZ_STRING str_;\r
+    __NodeBase * top_;  //regx tree\r
+};\r
+\r
+NAMESAPCE_END\r
+\r
+#endif\r
diff --git a/ntsimulator/scripts/clean.sh b/ntsimulator/scripts/clean.sh
deleted file mode 100755 (executable)
index 5d21e4c..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/bin/bash
-################################################################################
-#
-# Copyright 2020 highstreet technologies GmbH and others
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-# 
-#     http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-################################################################################
-
-if [ "$#" -ne 1 ]; then
-    echo "ID Parameter missing."
-       echo "Usage: $0 id/all
-       
-where id is the docker container id of the NTS Manager instance that we want to clean. Use 'all' if you want to clean all containers and all managers."
-       exit 1
-fi
-
-if [ "$1" = "all" ]; then
-       echo "Cleaning up all NTS simulated devices..."
-
-       mapfile -t NTS_containers < <( docker ps -a --filter "label=NTS_Manager" --format "{{.ID}}" )
-
-       CONTAINERS=""
-
-       if [ ${#NTS_containers[@]} -gt 0 ]
-       then
-
-               for container in "${NTS_containers[@]}"
-               do
-                       CONTAINERS="$CONTAINERS $container"
-               done
-               echo "Cleaning up containers: $CONTAINERS"
-               docker kill $CONTAINERS > /dev/null 2>&1
-               docker rm $CONTAINERS > /dev/null 2>&1
-       fi
-
-       echo "Cleaning up all NTS Managers..."
-
-       mapfile -t NTS_containers < <( docker ps -a --filter "label=NTS-manager" --format "{{.ID}}" )
-
-       CONTAINERS=""
-
-       if [ ${#NTS_containers[@]} -gt 0 ]
-       then
-
-               for container in "${NTS_containers[@]}"
-               do
-                       CONTAINERS="$CONTAINERS $container"
-               done
-               echo "Cleaning up containers: $CONTAINERS"
-               docker kill $CONTAINERS > /dev/null 2>&1
-               docker rm $CONTAINERS > /dev/null 2>&1
-       fi
-
-else
-       echo "Cleaning up containers started by the NTS Manager $1..."
-
-       mapfile -t NTS_containers < <( docker ps -a --filter "label=NTS_Manager=$1" --format "{{.ID}}" )
-
-       CONTAINERS=""
-
-       if [ ${#NTS_containers[@]} -gt 0 ]
-       then
-
-               for container in "${NTS_containers[@]}"
-               do
-                       CONTAINERS="$CONTAINERS $container"
-               done
-               echo "Cleaning up containers: $CONTAINERS"
-               docker kill $CONTAINERS > /dev/null 2>&1
-               docker rm $CONTAINERS > /dev/null 2>&1
-       fi
-
-       echo "Cleaning NTS Manager $1..."
-       docker kill $1 > /dev/null 2>&1
-       docker rm $1 > /dev/null 2>&1
-fi
-
-echo "All cleaned up!"
diff --git a/ntsimulator/scripts/configuration.json b/ntsimulator/scripts/configuration.json
deleted file mode 100644 (file)
index 98d9b8d..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-       "notification-config":  {
-               "ves-heartbeat-period": 0,
-               "is-netconf-available": true,
-               "is-ves-available":     true,
-               "fault-notification-delay-period":      [0]
-       },
-       "ves-endpoint-details": {
-               "ves-endpoint-ip":      "172.17.0.1",
-               "ves-endpoint-port":    30007,
-               "ves-endpoint-auth-method":     "no-auth",
-               "ves-endpoint-username":        "",
-               "ves-endpoint-password":        "",
-               "ves-endpoint-certificate":     "",
-               "ves-registration":     false
-       }
-}
\ No newline at end of file
diff --git a/ntsimulator/scripts/docker-compose.yml b/ntsimulator/scripts/docker-compose.yml
deleted file mode 100644 (file)
index 0a4c04a..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-version: '2.4'
-services:
-  ntsimulator-o-ran-sc:
-    image: "o-ran-sc/ntsim-manager:latest"
-    #image: "10.20.6.10:30000/hightec/ntsim_manager:0.4.2-SNAPSHOT-latest"
-    container_name: NTS-Manager-o-ran-sc
-    ports:
-     - "::8300:830"
-    volumes:
-     - "/var/run/docker.sock:/var/run/docker.sock"
-     - "/var/tmp/NTS-Manager-o-ran-sc:/opt/dev/scripts"
-     - "/usr/bin/docker:/usr/bin/docker"
-    labels:
-      "NTS-manager": ""
-    environment:
-      #NTS_IP: "2001:db8:1::1"
-      NTS_IP: "10.20.11.121"
-      #EXTERNAL_NTS_IP: "8.8.8.8"
-      NETCONF_BASE: 50000
-      DOCKER_ENGINE_VERSION: "1.40"
-      #MODELS_IMAGE: "ntsim_onf_core_model_1_2"
-      MODELS_IMAGE: "o-ran-sc/ntsim-o-ran-ru-fh:latest"      
-      VesHeartbeatPeriod: 0
-      IsVesAvailable: "true"
-      IsNetconfAvailable: "true"
-      VesRegistration: "false"
-      VesEndpointPort: 8080
-      VesEndpointIp: "172.17.0.1"
-      VesEndpointAuthMethod: "basic-auth"
-      VesEndpointUsername: "sample1"
-      VesEndpointPassword: "sample1"
-      SshConnections: 1
-      TlsConnections: 0
-      K8S_DEPLOYMENT: "false"
-      CONTAINER_NAME: "nts-o-ran-sc"
-      NetconfCallHome: "false"
-      NetconfCallHomePort: 6666
-      ControllerIp: "10.20.11.121"
-      ControllerPort: 8181
-      ControllerUsername: "admin"
-      ControllerPassword: "admin"
-      IPv6Enabled: "true"
-    networks:
-      app_net:
-        ipv6_address: 2001:3200:3000::40
-  
-networks:
-  app_net:
-    enable_ipv6: true
-    driver: bridge
-    ipam:
-      driver: default
-      config:
-        - subnet: 2001:3200:3000::/64
-          gateway: 2001:3200:3000::1
\ No newline at end of file
diff --git a/ntsimulator/scripts/docker_stats.sh b/ntsimulator/scripts/docker_stats.sh
deleted file mode 100755 (executable)
index fbf15ab..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/bin/bash
-################################################################################
-#
-# Copyright 2019 highstreet technologies GmbH and others
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-# 
-#     http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-################################################################################
-
-# This script is used to complete the output of the docker stats command.
-# The docker stats command does not compute the total amount of resources (RAM or CPU)
-
-# Get the output of the docker stat command. Will be displayed at the end
-# Without modifying the special variable IFS the ouput of the docker stats command won't have
-CPU_CORES=`nproc`
-# the new lines thus resulting in a failure when using awk to process each line
-IFS=;
-mapfile -t DOCKER_PS_RESULT < <(/usr/bin/docker ps --all --format "{{.ID}}" --filter "label=NTS")
-
-CONTAINERS=""
-
-if [ ${#DOCKER_PS_RESULT[@]} -gt 0 ]
-then
-
-       for container in "${DOCKER_PS_RESULT[@]}"
-       do
-               CONTAINERS="$CONTAINERS $container"
-       done
-fi
-
-if [ -z "$CONTAINERS" ]
-then
-       CPU_SCALED=0
-       SUM_RAM=0
-else
-       DOCKER_STATS_COMMAND="/usr/bin/docker stats --no-stream --format \"table {{.CPUPerc}}\t{{.MemUsage}}\" ${CONTAINERS}"
-       DOCKER_STATS_COMMAND_RESULT=$(eval "$DOCKER_STATS_COMMAND")
-
-       SUM_CPU=`echo $DOCKER_STATS_COMMAND_RESULT | tail -n +2 | sed "s/%//g" | awk '{s+=$1} END {print s}'`
-       SUM_RAM=`echo $DOCKER_STATS_COMMAND_RESULT | tail -n +2 | sed "s/%//g" | awk '{s+=$2} END {print s}'`
-
-       CPU_SCALED=$(echo "scale=2; $SUM_CPU/$CPU_CORES" | bc)
-fi
-
-# Output the result
-echo -e "CPU=${CPU_SCALED}%;RAM=${SUM_RAM}MiB"
\ No newline at end of file
diff --git a/ntsimulator/scripts/model-install.sh.in b/ntsimulator/scripts/model-install.sh.in
deleted file mode 100755 (executable)
index 4ab9cf0..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/bin/bash
-################################################################################
-#
-# Copyright 2019 highstreet technologies GmbH and others
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-# 
-#     http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-################################################################################
-
-set -eu -o pipefail
-
-shopt -s failglob
-
-: ${SYSREPOCTL:=sysrepoctl}
-: ${SYSREPOCFG:=sysrepocfg}
-: ${SYSREPOCTL_ROOT_PERMS:=-o root:root -p 600}
-: ${YANG_DIR:=@CMAKE_CURRENT_SOURCE_DIR@/yang/manager}
-: ${STARTUP_DIR:=@CMAKE_CURRENT_SOURCE_DIR@/yang/startup}
-
-is_yang_module_installed() {
-    module=$1
-
-    $SYSREPOCTL -l | grep --count "^$module [^|]*|[^|]*| Installed .*$" > /dev/null
-}
-
-install_yang_module() {
-    module=$1
-
-    if ! is_yang_module_installed $module; then
-        echo "- Installing module $module..."
-        $SYSREPOCTL -i -g ${YANG_DIR}/$module.yang $SYSREPOCTL_ROOT_PERMS
-    else
-        echo "- Module $module already installed."
-    fi
-}
-
-uninstall_yang_module() {
-    module=$1
-
-    if is_yang_module_installed $module; then
-        echo "- Uninstalling module $module..."
-        $SYSREPOCTL -u -m $module
-    else
-        echo "- Module $module is not installed."
-    fi
-}
-
-enable_yang_module_feature() {
-    module=$1
-    feature=$2
-
-    if ! $SYSREPOCTL -l | grep --count "^$module [^|]*|[^|]*|[^|]*|[^|]*|[^|]*|[^|]*|.* $feature.*$" > /dev/null; then
-        echo "- Enabling feature $feature in $module..."
-        $SYSREPOCTL -m $module -e $feature
-    else
-        echo "- Feature $feature in $module already enabled."
-    fi
-}
-
-echo "- Installing network-topology-simulator..."
-install_yang_module network-topology-simulator
-
-echo "- Adding startup datastore in network-topology-simulator..."
-$SYSREPOCFG -d startup -i $YANG_DIR/network-topology-simulator.xml -f xml network-topology-simulator
diff --git a/ntsimulator/scripts/model-uninstall.sh b/ntsimulator/scripts/model-uninstall.sh
deleted file mode 100644 (file)
index 8ed27e7..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/bash
-################################################################################
-#
-# Copyright 2019 highstreet technologies GmbH and others
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-# 
-#     http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-################################################################################
-
-sleep 3
-
-set -eu -o pipefail
-
-shopt -s failglob
-
-: ${SYSREPOCTL:=sysrepoctl}
-
-echo "- Uninstalling microwave-model..."
-$SYSREPOCTL --uninstall --module=microwave-model
-
-echo "- Uninstalling core-model..."
-$SYSREPOCTL --uninstall --module=core-model
-
-exit 0
\ No newline at end of file
diff --git a/ntsimulator/scripts/model-uninstall.sh.in b/ntsimulator/scripts/model-uninstall.sh.in
deleted file mode 100644 (file)
index 993ddce..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/bin/bash
-################################################################################
-#
-# Copyright 2019 highstreet technologies GmbH and others
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-# 
-#     http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-################################################################################
-
-sleep 5
-
-set -eu -o pipefail
-
-shopt -s failglob
-
-: ${SYSREPOCTL:=sysrepoctl}
-: ${SYSREPOCFG:=sysrepocfg}
-: ${SYSREPOCTL_ROOT_PERMS:=-o root:root -p 600}
-: ${YANG_DIR:=@CMAKE_CURRENT_SOURCE_DIR@/yang}
-: ${STARTUP_DIR:=@CMAKE_CURRENT_SOURCE_DIR@/yang/startup}
-
-is_yang_module_installed() {
-    module=$1
-
-    $SYSREPOCTL -l | grep --count "^$module [^|]*|[^|]*| Installed .*$" > /dev/null
-}
-
-uninstall_yang_module() {
-    module=$1
-
-    if ! is_yang_module_installed $module; then
-        echo "- Module $module not installed, skipping..."
-    else
-        $SYSREPOCTL -u -m $$module
-    fi
-}
-
-echo "- Uninstalling code-model and microwave-model..."
-uninstall_yang_module microwave-model,core-model
diff --git a/ntsimulator/scripts/stock_config.xml b/ntsimulator/scripts/stock_config.xml
deleted file mode 100644 (file)
index 014c840..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-<netconf-server xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-server">
-  <listen>
-    <endpoint>
-      <name>MNG0</name>
-      <ssh>
-        <address>0.0.0.0</address>
-        <port>830</port>
-        <host-keys>
-          <host-key>
-            <name>imported SSH key</name>
-            <public-key>ssh_host_rsa_key</public-key>
-          </host-key>
-        </host-keys>
-      </ssh>
-    </endpoint>
-    <endpoint>
-      <name>MNG1</name>
-      <ssh>
-        <address>0.0.0.0</address>
-        <port>831</port>
-        <host-keys>
-          <host-key>
-            <name>imported SSH key</name>
-            <public-key>ssh_host_rsa_key</public-key>
-          </host-key>
-        </host-keys>
-      </ssh>
-    </endpoint>
-    <endpoint>
-      <name>MNG2</name>
-      <ssh>
-        <address>0.0.0.0</address>
-        <port>832</port>
-        <host-keys>
-          <host-key>
-            <name>imported SSH key</name>
-            <public-key>ssh_host_rsa_key</public-key>
-          </host-key>
-        </host-keys>
-      </ssh>
-    </endpoint>
-    <endpoint>
-      <name>MNG3</name>
-      <ssh>
-        <address>0.0.0.0</address>
-        <port>833</port>
-        <host-keys>
-          <host-key>
-            <name>imported SSH key</name>
-            <public-key>ssh_host_rsa_key</public-key>
-          </host-key>
-        </host-keys>
-      </ssh>
-    </endpoint>
-    <endpoint>
-      <name>MNG4</name>
-      <ssh>
-        <address>0.0.0.0</address>
-        <port>834</port>
-        <host-keys>
-          <host-key>
-            <name>imported SSH key</name>
-            <public-key>ssh_host_rsa_key</public-key>
-          </host-key>
-        </host-keys>
-      </ssh>
-    </endpoint>
-    <endpoint>
-      <name>MNG5</name>
-      <ssh>
-        <address>0.0.0.0</address>
-        <port>835</port>
-        <host-keys>
-          <host-key>
-            <name>imported SSH key</name>
-            <public-key>ssh_host_rsa_key</public-key>
-          </host-key>
-        </host-keys>
-      </ssh>
-    </endpoint>
-    <endpoint>
-      <name>MNG6</name>
-      <ssh>
-        <address>0.0.0.0</address>
-        <port>836</port>
-        <host-keys>
-          <host-key>
-            <name>imported SSH key</name>
-            <public-key>ssh_host_rsa_key</public-key>
-          </host-key>
-        </host-keys>
-      </ssh>
-    </endpoint>
-  </listen>
-</netconf-server>
diff --git a/ntsimulator/scripts/tls/ca.key b/ntsimulator/scripts/tls/ca.key
deleted file mode 100644 (file)
index fb005ce..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEogIBAAKCAQEArD3TDHPAMT2Z84orK4lMlarbgooIUCcRZyLe+QM+8KY8Hn+m
-GaxPEOTSL3ywszqefB/Utm2hPKLHX684iRC14ID9WDGHxPjvoPArhgFhfV+qnPfx
-KTgxZC12uOj4u1V9y+SkTCocFbRfXVBGpojrBuDHXkDMDEWNvr8/52YCv7bGaiBw
-UHolcLCUbmtKILCG0RNJyTaJpXQdAeq5Z1SJotpbfYFFtAXB32hVoLug1dzl2tjG
-9sb1wq3QaDExcbC5w6P65qOkNoyym9ne6QlQagCqVDyFn3vcqkRaTjvZmxauCeUx
-XgJoXkyWcm0lM1KMHdoTArmchw2Dz0yHHSyDAQIDAQABAoIBAFH65y3hFhQZxuHU
-3LFPG0WNWgdq3YQQ5EaboVcSRW3TIYA+r3c+vS9ESgpSJeRYvUBFAkCGM50huRWA
-177dVkPyASNuB7on5h5K0dxpYdaDpzgpBv7ggRm2TfC66lB343UdcVnTHSTzggRv
-BgGT35GZgSsKWlRo8otcifUAZ8SJWRv6UxmX0zuvqSj3Q49ucevb57/CmYdgGxCP
-5flP/fqAdKen8/A03KPaltMERdo5xXbs5f7iBjcCZM1427Ta5cjiBW1zDWU4zbzn
-9+unwWPEuuPaGGtS6500qBJy6mIgM/9nYP9LKz9sJMEVJJZLZc1/2pjbJSNEiNJV
-SlJrvbECgYEA2u+xyfMsc2iE+dC8913NvIJnK7v7ixh5eu86SjJoYvflBvnEpPoX
-XxWlWUkO5jR1Hk2v1Z4U4hD/OR1kUwAqbN3MdCDd00hkhgVns8AgZtH0aXmdz+xq
-M0CKGXU7L/XS5mpiI8g24im1+1/rQjLxxUQjv0nfMxixa/ENmmtuisUCgYEAyWZ2
-CzAROlhxjaCbe+WopjG0AevCcrAPAeRgqIOm9sJ51q0cg2B6E/Zn27CvzKxsFzgM
-+Vu3MoC0vVMK+Dc3o7idaQ0ew7kY5KO6LY8wDu5s3EGiS0KGJum2iIStE3lee/dd
-TDcX6yE/3WYvvNf7w7uN7nme3s3EuSDDKpPFCw0CgYAaSnpxI/CMk1qUnUpz8iHI
-p2g4SkS0uWWtK5k2W8NJTzeDlO7WWOoBkxneFPXjEx2VXALnhio/04aylyL7DKQL
-mr74mxHIU4MuzOtdHI9HiaLuH5qh42QFb5Sl5fwLkFuZK+FJJrvggN3HqAcaVf/O
-jpY0XGyfODHmInZdutT1eQKBgBAVoMPP+PBB8/+tnf1NICT1vzyQCZ2DNg+en6GV
-shXu/jAI70gGwnkpqq2+9KtR8egAz/hyPLVJ1iVwpmWgc08eBWRIafaTp8tK0Cmn
-T91BaWxFyaJdE72z2KIahoARp1wbK1ZU6BIdO66A5LsePLsrFXDAQdHleRqX5T5X
-QttZAoGASjKxjcbfZN9Q4jfvof2tacpdKbof9K03tbcRRkcBBF/mtiK4ER+c7dPU
-YcGJwOCT9YofASM0Qnq3F118Ic7DJAB332R1/UMY1krkCLAGfjAndL5XguFLpDQx
-c3dqfZ38rGw4GIr/rGJsPInYzkLxTfoYit/9dZjLLoxxvwlLTLs=
------END RSA PRIVATE KEY-----
diff --git a/ntsimulator/scripts/tls/ca.pem b/ntsimulator/scripts/tls/ca.pem
deleted file mode 100644 (file)
index 62593ab..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
------BEGIN CERTIFICATE-----
-MIID7TCCAtWgAwIBAgIJAMtE1NGAR5KoMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYD
-VQQGEwJDWjEWMBQGA1UECAwNU291dGggTW9yYXZpYTENMAsGA1UEBwwEQnJubzEP
-MA0GA1UECgwGQ0VTTkVUMQwwCgYDVQQLDANUTUMxEzARBgNVBAMMCmV4YW1wbGUg
-Q0ExIjAgBgkqhkiG9w0BCQEWE2V4YW1wbGVjYUBsb2NhbGhvc3QwHhcNMTQwNzI0
-MTQxOTAyWhcNMjQwNzIxMTQxOTAyWjCBjDELMAkGA1UEBhMCQ1oxFjAUBgNVBAgM
-DVNvdXRoIE1vcmF2aWExDTALBgNVBAcMBEJybm8xDzANBgNVBAoMBkNFU05FVDEM
-MAoGA1UECwwDVE1DMRMwEQYDVQQDDApleGFtcGxlIENBMSIwIAYJKoZIhvcNAQkB
-FhNleGFtcGxlY2FAbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEArD3TDHPAMT2Z84orK4lMlarbgooIUCcRZyLe+QM+8KY8Hn+mGaxPEOTS
-L3ywszqefB/Utm2hPKLHX684iRC14ID9WDGHxPjvoPArhgFhfV+qnPfxKTgxZC12
-uOj4u1V9y+SkTCocFbRfXVBGpojrBuDHXkDMDEWNvr8/52YCv7bGaiBwUHolcLCU
-bmtKILCG0RNJyTaJpXQdAeq5Z1SJotpbfYFFtAXB32hVoLug1dzl2tjG9sb1wq3Q
-aDExcbC5w6P65qOkNoyym9ne6QlQagCqVDyFn3vcqkRaTjvZmxauCeUxXgJoXkyW
-cm0lM1KMHdoTArmchw2Dz0yHHSyDAQIDAQABo1AwTjAdBgNVHQ4EFgQUc1YQIqjZ
-sHVwlea0AB4N+ilNI2gwHwYDVR0jBBgwFoAUc1YQIqjZsHVwlea0AB4N+ilNI2gw
-DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAI/1KH60qnw9Xs2RGfi0/
-IKf5EynXt4bQX8EIyVKwSkYKe04zZxYfLIl/Q2HOPYoFmm3daj5ddr0ZS1i4p4fT
-UhstjsYWvXs3W/HhVmFUslakkn3PrswhP77fCk6eEJLxdfyJ1C7Uudq2m1isZbKi
-h+XF0mG1LxJaDMocSz4eAya7M5brwjy8DoOmA1TnLQFCVcpn+sCr7VC4wE/JqxyV
-hBCk/MuGqqM3B1j90bGFZ112ZOecyE0EDSr6IbiRBtmeNbEwOFjKXhNLYdxpBZ9D
-8A/368OckZkCrVLGuJNxK9UwCVTe8IhotHUqU9EqFDmxdV8oIdU/OzUwwNPA/Bd/
-9g==
------END CERTIFICATE-----
diff --git a/ntsimulator/scripts/tls/ca.srl b/ntsimulator/scripts/tls/ca.srl
deleted file mode 100644 (file)
index c10d829..0000000
+++ /dev/null
@@ -1 +0,0 @@
-91390D611074ACC8
diff --git a/ntsimulator/scripts/tls/client.crt b/ntsimulator/scripts/tls/client.crt
deleted file mode 100644 (file)
index 8e52dac..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIECTCCAvGgAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBjDELMAkGA1UEBhMCQ1ox
-FjAUBgNVBAgMDVNvdXRoIE1vcmF2aWExDTALBgNVBAcMBEJybm8xDzANBgNVBAoM
-BkNFU05FVDEMMAoGA1UECwwDVE1DMRMwEQYDVQQDDApleGFtcGxlIENBMSIwIAYJ
-KoZIhvcNAQkBFhNleGFtcGxlY2FAbG9jYWxob3N0MB4XDTE1MDczMDA3MjcxOFoX
-DTM1MDcyNTA3MjcxOFowgYUxCzAJBgNVBAYTAkNaMRYwFAYDVQQIDA1Tb3V0aCBN
-b3JhdmlhMQ8wDQYDVQQKDAZDRVNORVQxDDAKBgNVBAsMA1RNQzEXMBUGA1UEAwwO
-ZXhhbXBsZSBjbGllbnQxJjAkBgkqhkiG9w0BCQEWF2V4YW1wbGVjbGllbnRAbG9j
-YWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAueCQaNQWoNmF
-K6LKu1p8U8ZWdWg/PvDdLsJyzfzl/Qw4UA68SfFNaY06zZl8QB9W02nr5kWeeMY0
-VA3adrPgOlvfx3oWlFbkETnMaN4OT3WTQ0Wt6jAWZDzVfopwpJPAzRPxACDftIqF
-GagYcF32hZlVNqqnVdbXh0S0EViweqp/dbG4VDUHSNVbglc+u4UbEzNIFXMdEFsJ
-ZpkynOmSiTsIATqIhb+2srkVgLwhfkC2qkuHQwAHdubuB07ObM2z01UhyEdDvEYG
-HwtYAGDBL2TAcsI0oGeVkRyuOkV0QY0UN7UEFI1yTYw+xZ42HgFx3uGwApCImxhb
-j69GBYWFqwIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVu
-U1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUXGpLeLnh2cSDARAV
-A7KrBxGYpo8wHwYDVR0jBBgwFoAUc1YQIqjZsHVwlea0AB4N+ilNI2gwDQYJKoZI
-hvcNAQELBQADggEBAJPV3RTXFRtNyOU4rjPpYeBAIAFp2aqGc4t2J1c7oPp/1n+l
-ZvjnwtlJpZHxMM783e2ryDQ6dkvXDf8kpwKlg3U3mkJ3xKkDdWrM4QwghXdCN519
-aa9qmu0zdFL+jUAaWlQ5tsceOrvbusCcbMqiFGk/QfpHqPv52SVWbYyUx7IX7DE+
-UjgsLHycfV/tlcx4ZE6soTzl9VdgSL/zmzG3rjsr58J80rXckLgBhvijgBlIAJvW
-fC7D0vaouvBInSFXymdPVoUDZ30cdGLf+hI/i/TfsEMOinLrXVdkSGNo6FXAHKSv
-XeB9oFKSzhQ7OPyRyqvEPycUSw/qD6FVr80oDDc=
------END CERTIFICATE-----
diff --git a/ntsimulator/scripts/tls/client.key b/ntsimulator/scripts/tls/client.key
deleted file mode 100644 (file)
index 7ccdab1..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEAueCQaNQWoNmFK6LKu1p8U8ZWdWg/PvDdLsJyzfzl/Qw4UA68
-SfFNaY06zZl8QB9W02nr5kWeeMY0VA3adrPgOlvfx3oWlFbkETnMaN4OT3WTQ0Wt
-6jAWZDzVfopwpJPAzRPxACDftIqFGagYcF32hZlVNqqnVdbXh0S0EViweqp/dbG4
-VDUHSNVbglc+u4UbEzNIFXMdEFsJZpkynOmSiTsIATqIhb+2srkVgLwhfkC2qkuH
-QwAHdubuB07ObM2z01UhyEdDvEYGHwtYAGDBL2TAcsI0oGeVkRyuOkV0QY0UN7UE
-FI1yTYw+xZ42HgFx3uGwApCImxhbj69GBYWFqwIDAQABAoIBAQCZN9kR8DGu6V7y
-t0Ax68asL8O5B/OKaHWKQ9LqpVrXmikZJOxkbzoGldow/CIFoU+q+Zbwu9aDa65a
-0wiP7Hoa4Py3q5XNNUrOQDyU/OYC7cI0I83WS0lJ2zOJGYj8wKae5Z81IeQFKGHK
-4lsy1OGPAvPRGh7RjUUgRavA2MCwe07rWRuDb/OJFe4Oh56UMEjwMiNBtMNtncog
-j1vr/qgRJdf9tf0zlJmLvUJ9+HSFFV9I/97LJyFhb95gAfHkjdVroLVgT3Cho+4P
-WtZaKCIGD0OwfOG2nLV4leXvRUk62/LMlB8NI9+JF7Xm+HCKbaWHNWC7mvWSLV58
-Zl4AbUWRAoGBANyJ6SFHFRHSPDY026SsdMzXR0eUxBAK7G70oSBKKhY+O1j0ocLE
-jI2krHJBhHbLlnvJVyMUaCUOTS5m0uDw9hgSsAqeSL3hL38kxVZw+KNG9Ouno1Fl
-KnE/xXHlPQyeGs/P8nAMzHZxQtEsQdQayJEhK2XXHTsy7Q3MxDisfVJ1AoGBANfD
-34gB+OMx6pwj7zk3qWbYXSX8xjCZMR0ciko+h4xeMP2N8B0oyoqC+v1ABMAtJ3wG
-sGZd0hV9gwM7OUM3SEwkn6oeg1GemWLcn4rlSmTnZc4aeVwrEWlnSNFX3s4g9l4u
-k8Ugu4MVJYqH8HuDQ5Ggl6/QAwPzMSEdCW0O+jOfAoGAIBRbegC5+t6m7Yegz4Ja
-dxV1g98K6f58x+MDsQu4tYWV4mmrQgaPH2dtwizvlMwmdpkh+LNWNtWuumowkJHc
-akIFo3XExQIFg6wYnGtQb4e5xrGa2xMpKlIJaXjb+YLiCYqJDG2ALFZrTrvuU2kV
-9a5qfqTc1qigvNolTM0iaaUCgYApmrZWhnLUdEKV2wP813PNxfioI4afxlpHD8LG
-sCn48gymR6E+Lihn7vuwq5B+8fYEH1ISWxLwW+RQUjIneNhy/jjfV8TgjyFqg7or
-0Sy4KjpiNI6kLBXOakELRNNMkeSPopGR2E7v5rr3bGD9oAD+aqX1G7oJH/KgPPYd
-Vl7+ZwKBgQDcHyWYrimjyUgKaQD2GmoO9wdcJYQ59ke9K+OuGlp4ti5arsi7N1tP
-B4f09aeELM2ASIuk8Q/Mx0jQFnm8lzRFXdewgvdPoZW/7VufM9O7dGPOc41cm2Dh
-yrTcXx/VmUBb+/fnXVEgCv7gylp/wtdTGHQBQJHR81jFBz0lnLj+gg==
------END RSA PRIVATE KEY-----
diff --git a/ntsimulator/scripts/tls/enable_ssh_key.sh b/ntsimulator/scripts/tls/enable_ssh_key.sh
deleted file mode 100755 (executable)
index 9bfbbd6..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#! /bin/bash
-################################################################################
-#
-# Copyright 2019 highstreet technologies GmbH and others
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-# 
-#     http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-################################################################################
-# Script to enable SSH publicKey authentication in the localhost NETCONF server
-
-sleep 5
-
-SSH_PUB_KEY="$(cat /home/netconf/.ssh/id_dsa.pub| awk '{print $2}')"
-
-echo '<system xmlns="urn:ietf:params:xml:ns:yang:ietf-system"><authentication><user><name>netconf</name><authorized-key><name>ssh_key</name><algorithm>ssh-dss</algorithm>' >> load_auth_pubkey.xml
-echo '<key-data>'"$SSH_PUB_KEY"'</key-data></authorized-key></user></authentication></system>' >> load_auth_pubkey.xml
-
-sysrepocfg --merge=load_auth_pubkey.xml --format=xml ietf-system
-rm load_auth_pubkey.xml
-
-ssh-keyscan -p 830 127.0.0.1 >> ~/.ssh/known_hosts
-
-echo 'Done'
-exit 0
\ No newline at end of file
diff --git a/ntsimulator/scripts/tls/enable_tls.sh b/ntsimulator/scripts/tls/enable_tls.sh
deleted file mode 100755 (executable)
index 3d21471..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-#! /bin/bash
-################################################################################
-#
-# Copyright 2019 highstreet technologies GmbH and others
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-# 
-#     http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-################################################################################
-
-sleep 10
-
-openssl genrsa -out melacon.server.key 2048
-
-openssl req -new -sha256 -key melacon.server.key -subj "/C=US/ST=CA/O=MeLaCon, Inc./CN=melacon.com" -out melacon.server.csr
-openssl x509 -req -in melacon.server.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out melacon.server.crt -days 500 -sha256
-rm melacon.server.csr
-
-MELACON_SERVER_KEY="$(sed '1d;$d' melacon.server.key)"
-
-echo '<action xmlns="urn:ietf:params:xml:ns:yang:1"><keystore xmlns="urn:ietf:params:xml:ns:yang:ietf-keystore"><private-keys><load-private-key><name>melacon_server_key</name>' >> load_private_key.xml
-echo '<private-key>'"$MELACON_SERVER_KEY"'</private-key></load-private-key></private-keys></keystore></action>' >> load_private_key.xml
-
-netopeer2-cli <<END
-auth pref publickey 1000
-auth keys add /home/netconf/.ssh/id_dsa.pub /home/netconf/.ssh/id_dsa
-connect --host 127.0.0.1 --login netconf
-user-rpc --content=load_private_key.xml
-disconnect
-END
-
-rm load_private_key.xml
-
-MELACON_CERT="$(sed '1d;$d' melacon.server.crt)"
-CA_CERT="$(sed '1d;$d' ca.pem)"
-
-echo '<keystore xmlns="urn:ietf:params:xml:ns:yang:ietf-keystore"><private-keys><private-key><name>melacon_server_key</name><certificate-chains><certificate-chain><name>melacon_server_cert</name>' >> load_server_certs.xml
-echo '<certificate>'"$MELACON_CERT"'</certificate></certificate-chain></certificate-chains></private-key></private-keys><trusted-certificates><name>trusted_ca_list</name><trusted-certificate><name>ca</name>' >> load_server_certs.xml
-echo '<certificate>'"$CA_CERT"'</certificate></trusted-certificate></trusted-certificates></keystore>' >> load_server_certs.xml
-
-sysrepocfg --merge=load_server_certs.xml --format=xml ietf-keystore
-rm load_server_certs.xml
-
-echo '<netconf-server xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-server"><listen>' >> tls_endpoints.xml
-echo '<endpoint><name>MNG_TLS_1</name><tls><address>0.0.0.0</address><port>837</port><certificates><certificate><name>melacon_server_cert</name></certificate></certificates><client-auth><trusted-ca-certs>trusted_ca_list</trusted-ca-certs><cert-maps><cert-to-name><id>1</id><fingerprint>02:E9:38:1F:F6:8B:62:DE:0A:0B:C5:03:81:A8:03:49:A0:00:7F:8B:F3</fingerprint><map-type xmlns:x509c2n="urn:ietf:params:xml:ns:yang:ietf-x509-cert-to-name">x509c2n:specified</map-type><name>netconf</name></cert-to-name></cert-maps></client-auth></tls></endpoint>' >> tls_endpoints.xml
-echo '<endpoint><name>MNG_TLS_2</name><tls><address>0.0.0.0</address><port>838</port><certificates><certificate><name>melacon_server_cert</name></certificate></certificates><client-auth><trusted-ca-certs>trusted_ca_list</trusted-ca-certs><cert-maps><cert-to-name><id>1</id><fingerprint>02:E9:38:1F:F6:8B:62:DE:0A:0B:C5:03:81:A8:03:49:A0:00:7F:8B:F3</fingerprint><map-type xmlns:x509c2n="urn:ietf:params:xml:ns:yang:ietf-x509-cert-to-name">x509c2n:specified</map-type><name>netconf</name></cert-to-name></cert-maps></client-auth></tls></endpoint>' >> tls_endpoints.xml
-echo '<endpoint><name>MNG_TLS_3</name><tls><address>0.0.0.0</address><port>839</port><certificates><certificate><name>melacon_server_cert</name></certificate></certificates><client-auth><trusted-ca-certs>trusted_ca_list</trusted-ca-certs><cert-maps><cert-to-name><id>1</id><fingerprint>02:E9:38:1F:F6:8B:62:DE:0A:0B:C5:03:81:A8:03:49:A0:00:7F:8B:F3</fingerprint><map-type xmlns:x509c2n="urn:ietf:params:xml:ns:yang:ietf-x509-cert-to-name">x509c2n:specified</map-type><name>netconf</name></cert-to-name></cert-maps></client-auth></tls></endpoint>' >> tls_endpoints.xml
-echo '</listen></netconf-server>' >> tls_endpoints.xml
-
-sysrepocfg --merge=tls_endpoints.xml --format=xml ietf-netconf-server
-rm tls_endpoints.xml
-
-echo 'Done'
-exit 0
\ No newline at end of file
diff --git a/ntsimulator/scripts/tls/netconf_browser.crt b/ntsimulator/scripts/tls/netconf_browser.crt
deleted file mode 100644 (file)
index 687579d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDGDCCAgACCQCROQ1hEHSsyDANBgkqhkiG9w0BAQsFADCBjDELMAkGA1UEBhMC
-Q1oxFjAUBgNVBAgMDVNvdXRoIE1vcmF2aWExDTALBgNVBAcMBEJybm8xDzANBgNV
-BAoMBkNFU05FVDEMMAoGA1UECwwDVE1DMRMwEQYDVQQDDApleGFtcGxlIENBMSIw
-IAYJKoZIhvcNAQkBFhNleGFtcGxlY2FAbG9jYWxob3N0MB4XDTE5MDYxNzEyNDMy
-N1oXDTIwMTAyOTEyNDMyN1owDzENMAsGA1UEAwwEdGVzdDCCASIwDQYJKoZIhvcN
-AQEBBQADggEPADCCAQoCggEBAIKxdFmW7Cr4x7txXrHgaIZYpfsI9QwkwX+3q4h9
-kbY1QVaram/AlGWgXe/42q1z0UVRGGSsnwZvIv+daT4XE47Q/7JfUcYyo1EdGORc
-ym++D+gmIy37cUzB1oe9zZrxJ3zSZnwcQV13kZMwyOAs5DT1MpqPSypclv8t3c0Z
-H0mdzpcF4sJXBg14MoQqZSwSeZZrg9tAe36hhyrKhIVXReY+Lse0X72XS/qwCnA9
-26hjm//8d7j9nskzou9xOLeBh/umZUXHkUVmY1iGQ4jt7HAvg0yZ+2zg02YyZNfY
-Xb21jGB21qy1Jf2roFCn2+7bAjqpI8+Y4C8nm+fl/sScugUCAwEAATANBgkqhkiG
-9w0BAQsFAAOCAQEAX1Gf0xZDTrUVHITSc/sRC03e+Ju658p4fx9BlP2KqqnoZHdh
-zJhmps05FAnvHx/7c4tIABBt3puLl6CofznaE2+QAUxeCiTv2vm/4O3nLU4As5jP
-udfKU+XgVI5PTEorDgVsHnv3/JBmZUxuR4VM63hBJtBvSl4QvNXRtpXjjkljwPvJ
-r+Ea9z712F2dw48c/tzRLUIp7n/py0zhSLiBLBmwsT8fkr5hKmhenqqgY5Vkfa36
-UmfEeOVhhdy5tfs2jwxy9gNFNIryijbn4HMBJEy0zEfva8VEmrYqDJQ5AYX/xcwf
-8D0Sgg3582eQgbQR7eYl0DMlv2JUn5I4AjUutg==
------END CERTIFICATE-----
diff --git a/ntsimulator/scripts/tls/netconf_browser.csr b/ntsimulator/scripts/tls/netconf_browser.csr
deleted file mode 100644 (file)
index 61d8a4c..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
------BEGIN CERTIFICATE REQUEST-----
-MIICVDCCATwCAQAwDzENMAsGA1UEAwwEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQAD
-ggEPADCCAQoCggEBAIKxdFmW7Cr4x7txXrHgaIZYpfsI9QwkwX+3q4h9kbY1QVar
-am/AlGWgXe/42q1z0UVRGGSsnwZvIv+daT4XE47Q/7JfUcYyo1EdGORcym++D+gm
-Iy37cUzB1oe9zZrxJ3zSZnwcQV13kZMwyOAs5DT1MpqPSypclv8t3c0ZH0mdzpcF
-4sJXBg14MoQqZSwSeZZrg9tAe36hhyrKhIVXReY+Lse0X72XS/qwCnA926hjm//8
-d7j9nskzou9xOLeBh/umZUXHkUVmY1iGQ4jt7HAvg0yZ+2zg02YyZNfYXb21jGB2
-1qy1Jf2roFCn2+7bAjqpI8+Y4C8nm+fl/sScugUCAwEAAaAAMA0GCSqGSIb3DQEB
-CwUAA4IBAQB4mtqz9WtRqU4IBn+FNFQGBuX6uDSfDhC2Qo6mQB1kdErEnbdL6TYn
-gkgZradYwMAaBPKDwAx74YpWs6C4HgkORP1KPweDIjZNcpEAY0HwtXdUQHzMWFOh
-gdCjVYd7WdWg7CFl01lAx1HHzakIvW6ZxjjKoPm4SaFSGvyKzj0CyH01BoSM7pgt
-ZBbQcFkV6ZYItXPZR6Bi5hJnUkNu/K8rPEQ2Fr/wXUUz3PZhO+ZGG+WZbMFuo64V
-QUMEBwWNNf1I6r9EsLiar6Y1q22P6tLmjcY9Nbca/pD+3pplZ+/j6wpnufLM8ati
-dvWZorvVAKwQim5RFnCZ7VSmqKIaywIO
------END CERTIFICATE REQUEST-----
diff --git a/ntsimulator/src/CMakeLists.txt b/ntsimulator/src/CMakeLists.txt
deleted file mode 100644 (file)
index 7623ab5..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-set(UTILS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/utils")
-
-include_directories(
-    "${PROJECT_SOURCE_DIR}/inc/utils" 
-    "/usr/include"
-)
-
-add_subdirectory(ntsimulator-manager)
-add_subdirectory(o-ran-notifications)
-add_subdirectory(ves-messages)
-
-# sources
-set (UTILS_SOURCES
-    ${UTILS_DIR}/utils.c
-)
-
-add_library(utils STATIC ${UTILS_SOURCES})
-set_property(TARGET utils PROPERTY COMPILE_FLAGS "-fPIC")
-target_link_libraries(utils m)
-target_link_libraries(utils cjson)
\ No newline at end of file
diff --git a/ntsimulator/src/generic-notifications/CMakeLists.txt b/ntsimulator/src/generic-notifications/CMakeLists.txt
deleted file mode 100644 (file)
index c87e843..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-set (NOTIFICATIONS_SOURCES
-    generic-notifications.c
-)
-
-include_directories(
-    "/usr/include/x86_64-linux-gnu"
-    "/usr/local/include/cjson"
-    "/usr/local/include/libyang"
-)
-
-add_executable(generic-notifications ${NOTIFICATIONS_SOURCES})
-target_link_libraries(generic-notifications utils)
-target_link_libraries(generic-notifications sysrepo)
-target_link_libraries(generic-notifications m)
-target_link_libraries(generic-notifications curl)
-target_link_libraries(generic-notifications cjson)
-target_link_libraries(generic-notifications yang)
-
-install(TARGETS generic-notifications DESTINATION ${CMAKE_INSTALL_BINDIR})
\ No newline at end of file
diff --git a/ntsimulator/src/generic-notifications/generic-notifications.c b/ntsimulator/src/generic-notifications/generic-notifications.c
deleted file mode 100644 (file)
index 174b0a2..0000000
+++ /dev/null
@@ -1,379 +0,0 @@
-/*************************************************************************
-*
-* Copyright 2019 highstreet technologies GmbH and others
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*     http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-***************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
-#include <inttypes.h>
-#include <time.h>
-#include <math.h>
-#include <sys/time.h>
-#include <cjson/cJSON.h>
-#include <string.h>
-#include <assert.h>
-
-#include "sysrepo.h"
-#include "sysrepo/values.h"
-#include "libyang/libyang.h"
-
-#include "utils.h"
-
-#define EMEM printf("Memory allocation failed (%s:%d)", __FILE__, __LINE__);
-
-static int op_set_srval(struct lyd_node *node, char *path, int dup, sr_val_t *val, char **val_buf)
-{
-    uint32_t i;
-    struct lyd_node_leaf_list *leaf;
-    const char *str;
-
-    if (!dup) {
-        assert(val_buf);
-        (*val_buf) = NULL;
-    }
-
-    if (!dup) {
-        val->xpath = path;
-    } else {
-        sr_val_set_xpath(val, path);
-    }
-    val->dflt = 0;
-    val->data.int64_val = 0;
-
-    switch (node->schema->nodetype) {
-    case LYS_CONTAINER:
-        val->type = ((struct lys_node_container *)node->schema)->presence ? SR_CONTAINER_PRESENCE_T : SR_CONTAINER_T;
-        break;
-    case LYS_LIST:
-        val->type = SR_LIST_T;
-        break;
-    case LYS_LEAF:
-    case LYS_LEAFLIST:
-        leaf = (struct lyd_node_leaf_list *)node;
-settype:
-        switch (leaf->value_type) {
-        case LY_TYPE_BINARY:
-            val->type = SR_BINARY_T;
-            str = leaf->value.binary;
-            if (dup) {
-                sr_val_set_str_data(val, val->type, str);
-            } else {
-                val->data.string_val = (char *)str;
-            }
-            if (NULL == val->data.binary_val) {
-                EMEM;
-                return -1;
-            }
-            break;
-        case LY_TYPE_BITS:
-            val->type = SR_BITS_T;
-            str = leaf->value_str;
-            if (dup) {
-                sr_val_set_str_data(val, val->type, str);
-            } else {
-                val->data.string_val = (char *)str;
-            }
-            break;
-        case LY_TYPE_BOOL:
-            val->type = SR_BOOL_T;
-            val->data.bool_val = leaf->value.bln;
-            break;
-        case LY_TYPE_DEC64:
-            val->type = SR_DECIMAL64_T;
-            val->data.decimal64_val = (double)leaf->value.dec64;
-            for (i = 0; i < ((struct lys_node_leaf *)leaf->schema)->type.info.dec64.dig; i++) {
-                /* shift decimal point */
-                val->data.decimal64_val *= 0.1;
-            }
-            break;
-        case LY_TYPE_EMPTY:
-            val->type = SR_LEAF_EMPTY_T;
-            break;
-        case LY_TYPE_ENUM:
-            val->type = SR_ENUM_T;
-            str = leaf->value.enm->name;
-            if (dup) {
-                sr_val_set_str_data(val, val->type, str);
-            } else {
-                val->data.string_val = (char *)str;
-            }
-            if (NULL == val->data.enum_val) {
-                EMEM;
-                return -1;
-            }
-            break;
-        case LY_TYPE_IDENT:
-            val->type = SR_IDENTITYREF_T;
-
-            str = malloc(strlen(lys_main_module(leaf->value.ident->module)->name) + 1 + strlen(leaf->value.ident->name) + 1);
-            if (NULL == str) {
-                EMEM;
-                return -1;
-            }
-            sprintf((char *)str, "%s:%s", lys_main_module(leaf->value.ident->module)->name, leaf->value.ident->name);
-            val->data.identityref_val = (char *)str;
-            if (!dup) {
-                (*val_buf) = (char *)str;
-            }
-            break;
-        case LY_TYPE_INST:
-            val->type = SR_INSTANCEID_T;
-            if (dup) {
-                sr_val_set_str_data(val, val->type, leaf->value_str);
-            } else {
-                val->data.string_val = (char *)leaf->value_str;
-            }
-            break;
-        case LY_TYPE_STRING:
-            val->type = SR_STRING_T;
-            str = leaf->value.string;
-            if (dup) {
-                sr_val_set_str_data(val, val->type, str);
-            } else {
-                val->data.string_val = (char *)str;
-            }
-            if (NULL == val->data.string_val) {
-                EMEM;
-                return -1;
-            }
-            break;
-        case LY_TYPE_INT8:
-            val->type = SR_INT8_T;
-            val->data.int8_val = leaf->value.int8;
-            break;
-        case LY_TYPE_UINT8:
-            val->type = SR_UINT8_T;
-            val->data.uint8_val = leaf->value.uint8;
-            break;
-        case LY_TYPE_INT16:
-            val->type = SR_INT16_T;
-            val->data.int16_val = leaf->value.int16;
-            break;
-        case LY_TYPE_UINT16:
-            val->type = SR_UINT16_T;
-            val->data.uint16_val = leaf->value.uint16;
-            break;
-        case LY_TYPE_INT32:
-            val->type = SR_INT32_T;
-            val->data.int32_val = leaf->value.int32;
-            break;
-        case LY_TYPE_UINT32:
-            val->type = SR_UINT32_T;
-            val->data.uint32_val = leaf->value.uint32;
-            break;
-        case LY_TYPE_INT64:
-            val->type = SR_INT64_T;
-            val->data.int64_val = leaf->value.int64;
-            break;
-        case LY_TYPE_UINT64:
-            val->type = SR_UINT64_T;
-            val->data.uint64_val = leaf->value.uint64;
-            break;
-        case LY_TYPE_LEAFREF:
-            leaf = (struct lyd_node_leaf_list *)leaf->value.leafref;
-            goto settype;
-        default:
-            //LY_DERIVED, LY_UNION
-            val->type = SR_UNKNOWN_T;
-            break;
-        }
-        break;
-    default:
-        val->type = SR_UNKNOWN_T;
-        break;
-    }
-
-    return 0;
-}
-
-static int op_add_srval(sr_val_t **values, size_t *values_cnt, struct lyd_node *node)
-{
-    char *path, *buf = NULL;
-    int ret;
-
-    if (sr_realloc_values(*values_cnt, *values_cnt + 1, values) != SR_ERR_OK) {
-        return -1;
-    }
-    ++(*values_cnt);
-
-    path = lyd_path(node);
-    ret = op_set_srval(node, path, 1, &(*values)[*values_cnt - 1], &buf);
-    free(path);
-    free(buf);
-
-    return ret;
-}
-
-static void add_attrtibutes(sr_val_t **values_list, size_t *values_cnt, struct lyd_node *node)
-{
-    struct lyd_node *iter = NULL;
-
-    LY_TREE_FOR(node->child, iter) {
-        if (op_add_srval(values_list, values_cnt, iter)) {
-            printf("Could not transform libyang into sysrepo values...\n");
-            return;
-        }
-        if (iter->schema->nodetype == LYS_CONTAINER || iter->schema->nodetype == LYS_LIST)
-        {
-            add_attrtibutes(values_list, values_cnt, iter);
-        }
-    }
-}
-
-
-static int send_dummy_notif(sr_session_ctx_t *sess, const char *module_name, const char *notif_object)
-{
-       int rc = SR_ERR_OK;
-
-    struct ly_ctx *ctx = NULL;
-    struct lyd_node *data = NULL, *iter = NULL;
-    sr_schema_t *schemas = NULL;
-    size_t schema_cnt = 0;
-    sr_val_t *vnotif = NULL;
-       size_t num_values= 0;
-
-    ctx = ly_ctx_new("/etc/sysrepo/yang", LY_CTX_ALLIMPLEMENTED);
-    if (!ctx) 
-    {
-       printf("Creating context failed...\n");
-       return SR_ERR_OPERATION_FAILED;
-    }
-
-    rc = sr_list_schemas(sess, &schemas, &schema_cnt);
-    if (rc != SR_ERR_OK)
-    {
-        printf("Could not list the schemas from the sysrepo session...\n");
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    const char *schema_path = NULL;
-
-    for (size_t i = 0; i < schema_cnt; i++) 
-    {
-        schema_path = schemas[i].revision.file_path_yang;
-
-        if (NULL != schema_path && 0 == strcmp(module_name, schemas[i].module_name)) {
-            printf("Trying to install schema: %s\n", schema_path);
-            if (NULL == lys_parse_path(ctx, schema_path, LYS_IN_YANG)) 
-            {
-                fprintf(stderr, "Failed to parse schema file '%s': %s (%s)",
-                        schema_path, ly_errmsg(ctx), ly_errpath(ctx));
-                return SR_ERR_OPERATION_FAILED;
-                // continue;
-            }
-            break;
-        }
-    }
-
-    printf("Successfully loaded schemas, trying now to parse the JSON...\n");
-
-    data = lyd_parse_mem(ctx, notif_object, LYD_JSON, LYD_OPT_NOTIF, NULL);
-    if (data == NULL)
-    {
-        printf("Could not create JSON object, not valid!\n");
-        return SR_ERR_VALIDATION_FAILED;
-    }
-
-    printf("Successfully parsed the JSON notification object...\n");
-
-    add_attrtibutes(&vnotif, &num_values, data);
-
-    if (num_values == 0)
-    {
-        printf("Could not generate objects for sending inside the notif...\n");
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    rc = sr_event_notif_send(sess, lyd_path(data), vnotif, num_values, SR_EV_NOTIF_DEFAULT);
-    if (rc != SR_ERR_OK)
-    {
-        printf("Error: could not send notification...\n");
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    lyd_free(data);
-    ly_ctx_destroy(ctx, NULL);
-
-    sr_free_values(vnotif, num_values);
-
-    printf("Successfully sent notification from module=%s with %d number of atttributes\n", module_name, num_values);
-
-       return rc;
-}
-
-int
-main(int argc, char **argv)
-{
-    sr_conn_ctx_t *connection = NULL;
-    sr_session_ctx_t *session = NULL;
-    sr_subscription_ctx_t *subscription = NULL;
-    int rc = SR_ERR_OK;
-
-    setbuf(stdout, NULL);
-    setbuf(stderr, NULL);
-
-    const char *notif_object = NULL;
-    const char *module_name = NULL;
-
-    if (argc != 3) {
-        printf("%s <module_name> <notification-object>\n", argv[0]);
-        return EXIT_FAILURE;
-    }
-    module_name = argv[1];
-    notif_object = argv[2];
-
-    /* connect to sysrepo */
-    rc = sr_connect("generic_notifications", SR_CONN_DEFAULT, &connection);
-    if (SR_ERR_OK != rc) {
-        fprintf(stderr, "Error by sr_connect: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    /* start session */
-    rc = sr_session_start(connection, SR_DS_RUNNING, SR_SESS_DEFAULT, &session);
-    if (SR_ERR_OK != rc) {
-        fprintf(stderr, "Error by sr_session_start: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    rc = send_dummy_notif(session, module_name, notif_object);
-    if (SR_ERR_OK != rc) {
-        fprintf(stderr, "Error by send_dummy_notif: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-    printf("Application exit reached, exiting.\n");
-
-    return 0;
-
-cleanup:
-    if (NULL != subscription) {
-        sr_unsubscribe(session, subscription);
-    }
-    if (NULL != session) {
-        sr_session_stop(session);
-    }
-    if (NULL != connection) {
-        sr_disconnect(connection);
-    }
-    printf("Error encountered. Exiting...");
-    return rc;
-}
-
-
-
-
diff --git a/ntsimulator/src/ntsimulator-manager/CMakeLists.txt b/ntsimulator/src/ntsimulator-manager/CMakeLists.txt
deleted file mode 100644 (file)
index aacbcff..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-set (NTSIMULATOR_SOURCES
-    ntsimulator-manager.c
-    simulator-operations.c
-)
-
-include_directories(
-    "/usr/include/x86_64-linux-gnu"
-    "/usr/local/include/cjson"
-)
-
-add_executable(ntsimulator-manager ${NTSIMULATOR_SOURCES})
-target_link_libraries(ntsimulator-manager utils)
-target_link_libraries(ntsimulator-manager curl)
-target_link_libraries(ntsimulator-manager cjson)
-target_link_libraries(ntsimulator-manager sysrepo)
-
-install(TARGETS ntsimulator-manager DESTINATION ${CMAKE_INSTALL_BINDIR})
\ No newline at end of file
diff --git a/ntsimulator/src/ntsimulator-manager/ntsimulator-manager.c b/ntsimulator/src/ntsimulator-manager/ntsimulator-manager.c
deleted file mode 100644 (file)
index 3571ab4..0000000
+++ /dev/null
@@ -1,1374 +0,0 @@
-/*************************************************************************
-*
-* Copyright 2019 highstreet technologies GmbH and others
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*     http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-***************************************************************************/
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <string.h>
-
-#include "sysrepo.h"
-#include "sysrepo/values.h"
-
-#include "utils.h"
-#include "simulator-operations.h"
-
-volatile int exit_application = 0;
-
-volatile unsigned int simulated_devices_config = 0;
-volatile unsigned int mounted_devices_config = 0;
-
-
-static device_stack_t *device_list = NULL;
-
-controller_t controller_details;
-
-#define XPATH_MAX_LEN 500
-#define CONTROLLER_LIST_MAX_LEN 1
-
-static void
-print_current_config(sr_session_ctx_t *session, const char *module_name)
-{
-    sr_val_t *values = NULL;
-    size_t count = 0;
-    int rc = SR_ERR_OK;
-    char xpath[XPATH_MAX_LEN] = {0};
-    snprintf(xpath, XPATH_MAX_LEN, "/%s:*//.", module_name);
-
-    sr_val_t *odl_ip = NULL;
-    sr_val_t *odl_port = NULL;
-    sr_val_t *odl_username = NULL;
-    sr_val_t *odl_password = NULL;
-
-    rc = sr_get_items(session, xpath, &values, &count);
-    if (SR_ERR_OK != rc) {
-        printf("Error by sr_get_items: %s\n", sr_strerror(rc));
-        return;
-    }
-    for (size_t i = 0; i < count; i++){
-
-        sr_print_val(&values[i]);
-
-        if (sr_xpath_node_name_eq(values[i].xpath, "controller-ip"))
-        {
-               rc = sr_dup_val(&values[i], &odl_ip);
-        }
-        else if (sr_xpath_node_name_eq(values[i].xpath, "controller-port"))
-        {
-               rc = sr_dup_val(&values[i], &odl_port);
-        }
-        else if (sr_xpath_node_name_eq(values[i].xpath, "controller-username"))
-        {
-               rc = sr_dup_val(&values[i], &odl_username);
-        }
-        else if (sr_xpath_node_name_eq(values[i].xpath, "controller-password"))
-        {
-               rc = sr_dup_val(&values[i], &odl_password);
-        }
-    }
-
-    char *ipv6 = strchr(odl_ip->data.string_val, ':');
-    char odl_ip_string[URL_AND_CREDENTIALS_MAX_LEN];
-    if (ipv6 != NULL)
-    {
-        sprintf(odl_ip_string, "[%s]", odl_ip->data.string_val);
-    }
-    else
-    {
-        sprintf(odl_ip_string, "%s", odl_ip->data.string_val);
-    }
-
-
-    //URL used for mounting/unmounting a device; the device name needs to be appended
-   char url[URL_AND_CREDENTIALS_MAX_LEN];
-   sprintf(url, "http://%s:%d/restconf/config/network-topology:network-topology/topology/"
-                "topology-netconf/node/",
-                odl_ip_string, odl_port->data.uint32_val);
-
-   char credentials[URL_AND_CREDENTIALS_MAX_LEN];
-   sprintf(credentials, "%s:%s", odl_username->data.string_val, odl_password->data.string_val);
-
-   //URLs used for adding key pair to ODL, for TLS connections
-   char url_for_keystore_add[URL_AND_CREDENTIALS_MAX_LEN];
-   sprintf(url_for_keystore_add, "http://%s:%d/restconf/operations/netconf-keystore:add-keystore-entry",
-                        odl_ip_string, odl_port->data.uint32_val);
-
-   char url_for_private_key_add[URL_AND_CREDENTIALS_MAX_LEN];
-   sprintf(url_for_private_key_add, "http://%s:%d/restconf/operations/netconf-keystore:add-private-key",
-                        odl_ip_string, odl_port->data.uint32_val);
-
-   char url_for_trusted_ca_add[URL_AND_CREDENTIALS_MAX_LEN];
-   sprintf(url_for_trusted_ca_add, "http://%s:%d/restconf/operations/netconf-keystore:add-trusted-certificate",
-                        odl_ip_string, odl_port->data.uint32_val);
-
-   strcpy(controller_details.url, url);
-   strcpy(controller_details.credentials, credentials);
-   strcpy(controller_details.url_for_keystore_add, url_for_keystore_add);
-   strcpy(controller_details.url_for_private_key_add, url_for_private_key_add);
-   strcpy(controller_details.url_for_trusted_ca_add, url_for_trusted_ca_add);
-
-   sr_free_val(odl_ip);
-   sr_free_val(odl_port);
-   sr_free_val(odl_username);
-   sr_free_val(odl_password);
-
-   sr_free_values(values, count);
-}
-
-static void clean_current_docker_configuration(void);
-
-static int simulated_devices_changed(int new_value)
-{
-       int rc = SR_ERR_OK;
-
-    if (strcmp(getenv("K8S_DEPLOYMENT"), "true") == 0)
-    {
-        if (new_value != simulated_devices_config)
-        {
-            simulated_devices_config = new_value;
-            rc = send_k8s_scale(new_value);
-            if (rc != SR_ERR_OK)
-            {
-                printf("Could not send new_scale=%d to k8s cluster.\n", new_value);
-            }
-        }
-        return SR_ERR_OK;
-    }
-
-    if (simulated_devices_config > new_value)
-    {
-       //we are configuring less elements that currently
-       for (int i = 0; i < simulated_devices_config - new_value; ++i)
-       {
-               rc = stop_device(device_list);
-       }
-    }
-    else if (simulated_devices_config < new_value)
-    {
-       //we are configuring more elements that currently
-       for (int i = 0; i < new_value - simulated_devices_config; ++i)
-       {
-               rc = start_device(device_list);
-            if (rc != SR_ERR_OK)
-            {
-                printf("ERROR: Could not start simulated device. Ignoring, trying with the next simulated device, if any...\n");
-            }
-       }
-    }
-
-    simulated_devices_config = new_value;
-
-    return rc;
-}
-
-int mounted_devices_changed(sr_session_ctx_t *session, int new_value)
-{
-       int rc = SR_ERR_OK;
-
-       if (mounted_devices_config > new_value)
-       {
-         //we need have less mounted elements
-         for (int i = 0; i < mounted_devices_config - new_value; ++i)
-         {
-                 printf("Sending unmount device...\n");
-                 rc = unmount_device(device_list, controller_details);
-         }
-       }
-       else if (mounted_devices_config < new_value)
-       {
-         //we are configuring more elements that currently
-         for (int i = 0; i < new_value - mounted_devices_config; ++i)
-         {
-                 printf("Sending mount device...\n");
-                 rc = mount_device(device_list, controller_details);
-         }
-       }
-
-       mounted_devices_config = new_value;
-
-    return rc;
-}
-
-static int
-simulator_config_change_cb(sr_session_ctx_t *session, const char *module_name, sr_notif_event_t event, void *private_ctx)
-{
-       int rc;
-
-    printf("\n\n ========== CONFIG HAS CHANGED, CURRENT RUNNING CONFIG %s: ==========\n\n", module_name);
-    print_current_config(session, module_name);
-
-    sr_val_t *val = NULL;
-
-    /* get the value from sysrepo, we do not care if the value did not change in our case */
-    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/simulated-devices", &val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    rc = simulated_devices_changed(val->data.uint32_val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    sr_free_val(val);
-       val = NULL;
-
-    /* get the value from sysrepo, we do not care if the value did not change in our case */
-    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/mounted-devices", &val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    if (mounted_devices_config != val->data.uint32_val)
-    {
-       if (val->data.uint32_val > simulated_devices_config)
-       {
-               printf("Cannot set mount value greater than number of simulated devices.\n");
-               sr_free_val(val);
-                       val = NULL;
-               return SR_ERR_OK;
-       }
-
-               rc = mounted_devices_changed(session, val->data.uint32_val);
-               if (rc != SR_ERR_OK) {
-                       goto sr_error;
-               }
-    }
-
-    sr_free_val(val);
-       val = NULL;
-
-    size_t count = 0;
-
-    /* get the value from sysrepo, we do not care if the value did not change in our case */
-    rc = sr_get_items(session, "/network-topology-simulator:simulator-config/notification-config/fault-notification-delay-period", &val, &count);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    rc = notification_delay_period_changed(val, count);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-    sr_free_values(val, count);
-       val = NULL;
-
-    /* get the value from sysrepo, we do not care if the value did not change in our case */
-       rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/ves-heartbeat-period", &val);
-       if (rc != SR_ERR_OK) {
-               goto sr_error;
-       }
-
-       rc = ves_heartbeat_period_changed(val->data.uint32_val);
-       if (rc != SR_ERR_OK) {
-               goto sr_error;
-       }
-
-       sr_free_val(val);
-       val = NULL;
-
-    /* get the value from sysrepo, we do not care if the value did not change in our case */
-    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-ip", &val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    rc = ves_ip_changed(val->data.string_val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    sr_free_val(val);
-    val = NULL;
-
-    /* get the value from sysrepo, we do not care if the value did not change in our case */
-    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-auth-method", &val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    rc = ves_auth_method_changed(val->data.enum_val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    if (strcmp(val->data.enum_val, "basic-auth") == 0)
-    {
-        sr_free_val(val);
-        val = NULL;
-
-        /* get the value from sysrepo, we do not care if the value did not change in our case */
-        rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-username", &val);
-        if (rc != SR_ERR_OK) {
-            goto sr_error;
-        }
-
-        rc = ves_username_changed(val->data.string_val);
-        if (rc != SR_ERR_OK) {
-            goto sr_error;
-        }
-
-        sr_free_val(val);
-        val = NULL;
-
-        /* get the value from sysrepo, we do not care if the value did not change in our case */
-        rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-password", &val);
-        if (rc != SR_ERR_OK) {
-            goto sr_error;
-        }
-
-        rc = ves_password_changed(val->data.string_val);
-        if (rc != SR_ERR_OK) {
-            goto sr_error;
-        }
-
-        sr_free_val(val);
-        val = NULL;
-    }
-    else 
-    {
-        sr_free_val(val);
-        val = NULL;
-    }
-
-       /* get the value from sysrepo, we do not care if the value did not change in our case */
-       rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-port", &val);
-       if (rc != SR_ERR_OK) {
-               goto sr_error;
-       }
-
-       rc = ves_port_changed(val->data.uint16_val);
-       if (rc != SR_ERR_OK) {
-               goto sr_error;
-       }
-
-       sr_free_val(val);
-       val = NULL;
-
-       /* get the value from sysrepo, we do not care if the value did not change in our case */
-       rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-registration", &val);
-       if (rc != SR_ERR_OK) {
-               goto sr_error;
-       }
-
-       rc = ves_registration_changed(val->data.bool_val);
-       if (rc != SR_ERR_OK) {
-               goto sr_error;
-       }
-
-       sr_free_val(val);
-       val = NULL;
-
-       /* get the value from sysrepo, we do not care if the value did not change in our case */
-       rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/is-netconf-available", &val);
-       if (rc != SR_ERR_OK) {
-               goto sr_error;
-       }
-
-       rc = is_netconf_available_changed(val->data.bool_val);
-       if (rc != SR_ERR_OK) {
-               goto sr_error;
-       }
-
-       sr_free_val(val);
-       val = NULL;
-
-    /* get the value from sysrepo, we do not care if the value did not change in our case */
-    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/is-ves-available", &val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    rc = is_ves_available_changed(val->data.bool_val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    sr_free_val(val);
-    val = NULL;
-
-    /* get the value from sysrepo, we do not care if the value did not change in our case */
-    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/netconf-call-home", &val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    rc = netconf_call_home_changed(val->data.bool_val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    sr_free_val(val);
-    val = NULL;
-
-    /* get the value from sysrepo, we do not care if the value did not change in our case */
-    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-ip", &val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    rc = controller_ip_changed(val->data.string_val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    sr_free_val(val);
-    val = NULL;
-
-    /* get the value from sysrepo, we do not care if the value did not change in our case */
-    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-port", &val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    rc = controller_port_changed(val->data.uint16_val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    sr_free_val(val);
-    val = NULL;
-
-    /* get the value from sysrepo, we do not care if the value did not change in our case */
-    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/netconf-call-home-port", &val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    rc = controller_netconf_call_home_port_changed(val->data.uint16_val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    sr_free_val(val);
-    val = NULL;
-
-    /* get the value from sysrepo, we do not care if the value did not change in our case */
-    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-username", &val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    rc = controller_username_changed(val->data.string_val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    sr_free_val(val);
-    val = NULL;
-
-    /* get the value from sysrepo, we do not care if the value did not change in our case */
-    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-password", &val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    rc = controller_password_changed(val->data.string_val);
-    if (rc != SR_ERR_OK) {
-        goto sr_error;
-    }
-
-    sr_free_val(val);
-    val = NULL;
-
-    return SR_ERR_OK;
-
-sr_error:
-       printf("NTSimulator config change callback failed: %s.", sr_strerror(rc));
-       if (val != NULL)
-       {
-               sr_free_val(val);
-               val = NULL;
-       }
-       return rc;
-}
-
-static int
-simulator_status_cb(const char *xpath, sr_val_t **values, size_t *values_cnt,
-        uint64_t request_id, const char *original_xpath, void *private_ctx)
-{
-       int rc;
-
-       // printf("\n\n ========== Called simulator_status_cb for xpath: %s ==========\n\n", xpath);
-
-    counterAlarms ves_counter, netconf_counter;
-    rc = compute_notifications_count(&ves_counter, &netconf_counter);
-    if (rc != SR_ERR_OK)
-    {
-        printf("Could not compute the total number of notification count.\n");
-    }
-
-       if (sr_xpath_node_name_eq(xpath, "simulated-devices-list")) 
-    {
-               sr_val_t *v;
-               size_t current_num_of_values= 0;
-
-               if (simulated_devices_config == 0) //nothing to return if no devices are running
-               {
-                       *values = NULL;
-                       *values_cnt = 0;
-
-                       return SR_ERR_OK;
-               }
-
-        rc = get_docker_containers_operational_state_curl(device_list);
-        if (rc != SR_ERR_OK)
-        {
-            printf("Could not get the operational state for the devices simulated.\n");
-            return SR_ERR_OPERATION_FAILED;
-        }
-
-               device_t *current_device = device_list->head;
-
-               while (current_device != NULL)
-               {
-            counterAlarms vesCount, netconfCount;
-            rc = getDeviceCounters(current_device->device_id, &vesCount, &netconfCount);
-            if (rc != SR_ERR_OK)
-            {
-                printf("Could not get Notification Counters for device with uuid=\"%s\"", current_device->device_id);
-            }
-
-            char device_name[200];
-            sprintf(device_name, "%s-%d", getenv("CONTAINER_NAME"), current_device->device_number);            
-
-                       CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-                       sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, device_name, "device-ip");
-                       v[current_num_of_values - 1].type = SR_STRING_T;
-                       v[current_num_of_values - 1].data.string_val = getenv("NTS_IP");
-
-                       for (int i = 0; i < NETCONF_CONNECTIONS_PER_DEVICE; ++i)
-                       {
-                               CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-                               sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, device_name, "device-port");
-                               v[current_num_of_values - 1].type = SR_UINT32_T;
-                               v[current_num_of_values - 1].data.uint32_val = current_device->netconf_port + i;
-                       }
-
-                       CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-                       sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, device_name, "is-mounted");
-                       v[current_num_of_values - 1].type = SR_BOOL_T;
-                       v[current_num_of_values - 1].data.bool_val = current_device->is_mounted;
-
-                       char *operational_state = get_docker_container_operational_state(device_list, current_device->device_id);
-
-                       CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-                       sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, device_name, "operational-state");
-                       sr_val_build_str_data(&v[current_num_of_values - 1], SR_ENUM_T, "%s", operational_state);
-
-            CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "normal");
-            v[current_num_of_values - 1].type = SR_UINT32_T;
-            v[current_num_of_values - 1].data.uint32_val = vesCount.normal;
-
-            CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "warning");
-            v[current_num_of_values - 1].type = SR_UINT32_T;
-            v[current_num_of_values - 1].data.uint32_val = vesCount.warning;
-
-            CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "minor");
-            v[current_num_of_values - 1].type = SR_UINT32_T;
-            v[current_num_of_values - 1].data.uint32_val = vesCount.minor;
-
-            CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "major");
-            v[current_num_of_values - 1].type = SR_UINT32_T;
-            v[current_num_of_values - 1].data.uint32_val = vesCount.major;
-
-            CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "critical");
-            v[current_num_of_values - 1].type = SR_UINT32_T;
-            v[current_num_of_values - 1].data.uint32_val = vesCount.critical;
-
-            CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "normal");
-            v[current_num_of_values - 1].type = SR_UINT32_T;
-            v[current_num_of_values - 1].data.uint32_val = netconfCount.normal;
-
-            CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "warning");
-            v[current_num_of_values - 1].type = SR_UINT32_T;
-            v[current_num_of_values - 1].data.uint32_val = netconfCount.warning;
-
-            CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "minor");
-            v[current_num_of_values - 1].type = SR_UINT32_T;
-            v[current_num_of_values - 1].data.uint32_val = netconfCount.minor;
-
-            CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "major");
-            v[current_num_of_values - 1].type = SR_UINT32_T;
-            v[current_num_of_values - 1].data.uint32_val = netconfCount.major;
-
-            CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "critical");
-            v[current_num_of_values - 1].type = SR_UINT32_T;
-            v[current_num_of_values - 1].data.uint32_val = netconfCount.critical;
-
-                       current_device = current_device->next;
-               }
-
-               //return the values that we have just created
-               *values = v;
-               *values_cnt = current_num_of_values;
-        }
-        else if (sr_xpath_node_name_eq(xpath, "simulation-usage-details"))
-        {
-               float cpu_usage = 0.0, mem_usage = 0.0;
-
-               char *resource_usage_from_script = get_docker_container_resource_stats();
-
-               if (resource_usage_from_script != NULL)
-               {
-                       printf("Received line: %s\n", resource_usage_from_script);
-                       sscanf(resource_usage_from_script, "CPU=%f%%;RAM=%fMiB", &cpu_usage, &mem_usage);
-                       printf("Read cpu=\"%f\" and mem=\"%f\"\n", cpu_usage, mem_usage);
-                       free(resource_usage_from_script);
-               }
-
-               sr_val_t *v;
-               /* convenient functions such as this can be found in sysrepo/values.h */
-               size_t current_num_of_values= 0;
-
-               CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-               sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "running-simulated-devices");
-               v[current_num_of_values - 1].type = SR_UINT32_T;
-               v[current_num_of_values - 1].data.uint32_val = get_current_number_of_devices(device_list);
-
-               CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-               sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "running-mounted-devices");
-               v[current_num_of_values - 1].type = SR_UINT32_T;
-               v[current_num_of_values - 1].data.uint32_val = get_current_number_of_mounted_devices(device_list);
-
-               CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-               sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "base-netconf-port");
-               v[current_num_of_values - 1].type = SR_UINT32_T;
-               v[current_num_of_values - 1].data.uint32_val = get_netconf_port_base();
-
-               CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-               sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "cpu-usage");
-               v[current_num_of_values - 1].type = SR_DECIMAL64_T;
-               v[current_num_of_values - 1].data.decimal64_val = cpu_usage;
-
-               CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-               sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "mem-usage");
-               v[current_num_of_values - 1].type = SR_UINT32_T;
-               v[current_num_of_values - 1].data.uint32_val = (int)mem_usage;
-
-        CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "ssh-connections");
-        v[current_num_of_values - 1].type = SR_UINT32_T;
-        v[current_num_of_values - 1].data.uint32_val = getSshConnectionsFromConfigJson();
-
-        CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "tls-connections");
-        v[current_num_of_values - 1].type = SR_UINT32_T;
-        v[current_num_of_values - 1].data.uint32_val = getTlsConnectionsFromConfigJson();
-
-               //return the values that we have just created
-               *values = v;
-               *values_cnt = current_num_of_values;
-        }
-     else if (sr_xpath_node_name_eq(xpath, "total-ves-notifications"))
-     {
-        sr_val_t *v;
-        /* convenient functions such as this can be found in sysrepo/values.h */
-        size_t current_num_of_values= 0;
-
-        CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "normal");
-        v[current_num_of_values - 1].type = SR_UINT32_T;
-        v[current_num_of_values - 1].data.uint32_val = ves_counter.normal;
-
-        CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "warning");
-        v[current_num_of_values - 1].type = SR_UINT32_T;
-        v[current_num_of_values - 1].data.uint32_val = ves_counter.warning;
-
-        CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "minor");
-        v[current_num_of_values - 1].type = SR_UINT32_T;
-        v[current_num_of_values - 1].data.uint32_val = ves_counter.minor;
-
-        CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "major");
-        v[current_num_of_values - 1].type = SR_UINT32_T;
-        v[current_num_of_values - 1].data.uint32_val = ves_counter.major;
-
-        CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "critical");
-        v[current_num_of_values - 1].type = SR_UINT32_T;
-        v[current_num_of_values - 1].data.uint32_val = ves_counter.critical;
-
-        //return the values that we have just created
-        *values = v;
-        *values_cnt = current_num_of_values;
-     }
-     else if (sr_xpath_node_name_eq(xpath, "total-netconf-notifications"))
-     {
-        sr_val_t *v;
-        /* convenient functions such as this can be found in sysrepo/values.h */
-        size_t current_num_of_values= 0;
-
-        CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "normal");
-        v[current_num_of_values - 1].type = SR_UINT32_T;
-        v[current_num_of_values - 1].data.uint32_val = netconf_counter.normal;
-
-        CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "warning");
-        v[current_num_of_values - 1].type = SR_UINT32_T;
-        v[current_num_of_values - 1].data.uint32_val = netconf_counter.warning;
-
-        CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "minor");
-        v[current_num_of_values - 1].type = SR_UINT32_T;
-        v[current_num_of_values - 1].data.uint32_val = netconf_counter.minor;
-
-        CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "major");
-        v[current_num_of_values - 1].type = SR_UINT32_T;
-        v[current_num_of_values - 1].data.uint32_val = netconf_counter.major;
-
-        CREATE_NEW_VALUE(rc, v, current_num_of_values);
-
-        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "critical");
-        v[current_num_of_values - 1].type = SR_UINT32_T;
-        v[current_num_of_values - 1].data.uint32_val = netconf_counter.critical;
-
-        //return the values that we have just created
-        *values = v;
-        *values_cnt = current_num_of_values;
-     }
-
-    return SR_ERR_OK;
-}
-
-static int odl_add_key_pair_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
-      sr_val_t **output, size_t *output_cnt, void *private_ctx)
-{
-    int rc = SR_ERR_OK;
-    controller_t controller_list[CONTROLLER_LIST_MAX_LEN];
-    int controller_list_size = 0;
-
-    controller_list[0] = controller_details;
-    controller_list_size++;
-
-    for (int i = 0; i < controller_list_size; ++i)
-    {
-        printf("%d iteration: Got back url=%s and credentials=%s\n", i, controller_list[i].url, controller_list[i].credentials);
-    }
-
-    rc = add_key_pair_to_odl(controller_list, controller_list_size);
-    if (rc != SR_ERR_OK)
-    {
-        printf("Failed to add key pair to ODL.\n");
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    return rc;
-}
-
-static int invoke_notification_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
-      sr_val_t **output, size_t *output_cnt, void *private_ctx)
-{
-    int rc = SR_ERR_OK;
-
-    char *device_name = NULL, *module_name = NULL, *notification_object = NULL;
-    
-    /* print input values */
-    printf("\n\n ========== RECEIVED RPC REQUEST ==========\n\n");
-    printf(">>> RPC Input:\n\n");
-    
-    device_name = strdup(input[0].data.string_val);
-    module_name = strdup(input[1].data.string_val);
-    notification_object = strdup(input[2].data.string_val);
-
-    rc = sr_new_values(1, output);
-    if (SR_ERR_OK != rc) {
-        return rc;
-    }
-
-    /* set 'output/step-count' leaf */
-    rc = sr_val_set_xpath(&(*output)[0], "/network-topology-simulator:invoke-notification/status");
-    if (SR_ERR_OK != rc) {
-        return rc;
-    }
-
-    rc = invoke_device_notification(device_name, module_name, notification_object);
-    
-    if (rc != SR_ERR_OK)
-    {
-        sr_val_build_str_data(&(*output)[0], SR_ENUM_T, "%s", "ERROR");
-    }
-    else
-    {
-        sr_val_build_str_data(&(*output)[0], SR_ENUM_T, "%s", "SUCCESS");
-    }
-    *output_cnt = 1;
-
-    return SR_ERR_OK;
-}
-
-
-static void
-sigint_handler(int signum)
-{
-    exit_application = 1;
-}
-
-int
-main(int argc, char **argv)
-{
-    sr_conn_ctx_t *connection = NULL;
-    sr_session_ctx_t *session = NULL;
-    sr_subscription_ctx_t *subscription = NULL;
-    int rc = SR_ERR_OK;
-
-    setbuf(stdout, NULL);
-
-    rc = _init_curl_k8s();
-    if (rc != SR_ERR_OK)
-    {
-        fprintf(stderr, "Could not initialize cURL for K8S connection: %s\n", sr_strerror(rc));
-    }
-
-    device_list = new_device_stack();
-    rc = _init_curl();
-    if (rc != SR_ERR_OK)
-    {
-        fprintf(stderr, "Could not initialize cURL: %s\n", sr_strerror(rc));
-    }
-
-    rc = writeSkeletonConfigFile();
-    if (rc != SR_ERR_OK)
-    {
-        fprintf(stderr, "Could not initialize configuration JSON file: %s\n", sr_strerror(rc));
-    }
-
-    /* connect to sysrepo */
-    rc = sr_connect("network-topology-simulator", SR_CONN_DEFAULT, &connection);
-    if (SR_ERR_OK != rc) {
-        fprintf(stderr, "Error by sr_connect: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    /* start session */
-    rc = sr_session_start(connection, SR_DS_STARTUP, SR_SESS_DEFAULT, &session);
-    if (SR_ERR_OK != rc) {
-        fprintf(stderr, "Error by sr_session_start: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    // setting the values that come in an ENV variable as defaults - ves-heartbeat-period
-    int vesHeartbeatPeriod = getIntFromString(getenv("VesHeartbeatPeriod"), 0);
-
-    sr_val_t value = { 0 };
-    value.type = SR_UINT32_T;
-    value.data.uint32_val = vesHeartbeatPeriod;
-    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/notification-config/ves-heartbeat-period", 
-            &value, SR_EDIT_DEFAULT);
-    if (SR_ERR_OK != rc) {
-        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    rc = ves_heartbeat_period_changed(vesHeartbeatPeriod);
-    if (SR_ERR_OK != rc) {
-        printf("Error by ves_heartbeat_period_changed: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    // setting the values that come in an ENV variable as defaults - is-netconf-available
-
-    int isNetconfAvailable = 1;
-
-    char *isNetconfAvailablString = getenv("IsNetconfAvailable");
-    if (isNetconfAvailablString != NULL)
-    {
-        if (strcmp(isNetconfAvailablString, "false") == 0)
-        {
-            isNetconfAvailable = 0;
-        }
-    }
-
-    value = (const sr_val_t) { 0 };
-    value.type = SR_BOOL_T;
-    value.data.bool_val = isNetconfAvailable;
-    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/notification-config/is-netconf-available", 
-            &value, SR_EDIT_DEFAULT);
-    if (SR_ERR_OK != rc) {
-        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    rc = is_netconf_available_changed(isNetconfAvailable);
-    if (SR_ERR_OK != rc) {
-        printf("Error by is_netconf_available_changed: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    // setting the values that come in an ENV variable as defaults - is-ves-available
-
-    int isVesAvailable = 1;
-
-    char *isVesAvailablString = getenv("IsVesAvailable");
-    if (isVesAvailablString != NULL)
-    {
-        if (strcmp(isVesAvailablString, "false") == 0)
-        {
-            isVesAvailable = 0;
-        }
-    }
-
-    value = (const sr_val_t) { 0 };
-    value.type = SR_BOOL_T;
-    value.data.bool_val = isVesAvailable;
-    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/notification-config/is-ves-available", 
-            &value, SR_EDIT_DEFAULT);
-    if (SR_ERR_OK != rc) {
-        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    rc = is_ves_available_changed(isVesAvailable);
-    if (SR_ERR_OK != rc) {
-        printf("Error by is_ves_available_changed: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    // setting the values that come in an ENV variable as defaults - ves-endpoint-port
-
-    int vesEndpointPort = getIntFromString(getenv("VesEndpointPort"), 8080);
-
-    value = (const sr_val_t) { 0 };
-    value.type = SR_UINT16_T;
-    value.data.uint16_val = vesEndpointPort;
-    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-port", 
-            &value, SR_EDIT_DEFAULT);
-    if (SR_ERR_OK != rc) {
-        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    rc = ves_port_changed(vesEndpointPort);
-    if (SR_ERR_OK != rc) {
-        printf("Error by ves_port_changed: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    // setting the values that come in an ENV variable as defaults - ves-endpoint-ip
-
-    value = (const sr_val_t) { 0 };
-    value.type = SR_STRING_T;
-    value.data.string_val = getenv("VesEndpointIp");
-    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-ip", 
-            &value, SR_EDIT_DEFAULT);
-    if (SR_ERR_OK != rc) {
-        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    rc = ves_ip_changed(getenv("VesEndpointIp"));
-    if (SR_ERR_OK != rc) {
-        printf("Error by ves_ip_changed: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    // setting the values that come in an ENV variable as defaults - ves-endpoint-auth-method
-
-    value = (const sr_val_t) { 0 };
-    value.type = SR_ENUM_T;
-    value.data.enum_val = getenv("VesEndpointAuthMethod");
-    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-auth-method", 
-            &value, SR_EDIT_DEFAULT);
-    if (SR_ERR_OK != rc) {
-        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    rc = ves_auth_method_changed(getenv("VesEndpointAuthMethod"));
-    if (SR_ERR_OK != rc) {
-        printf("Error by ves_auth_method_changed: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    //TODO only basic-auth implemented vor VES
-    if (strcmp(getenv("VesEndpointAuthMethod"), "basic-auth")  == 0)
-    {
-        // setting the values that come in an ENV variable as defaults - ves-endpoint-usename
-
-        value = (const sr_val_t) { 0 };
-        value.type = SR_STRING_T;
-        value.data.string_val = getenv("VesEndpointUsername");
-        rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-username",
-                &value, SR_EDIT_DEFAULT);
-        if (SR_ERR_OK != rc) {
-            printf("Error by sr_set_item: %s\n", sr_strerror(rc));
-            goto cleanup;
-        }
-
-        rc = ves_username_changed(getenv("VesEndpointUsername"));
-        if (SR_ERR_OK != rc) {
-            printf("Error by ves_username_changed: %s\n", sr_strerror(rc));
-            goto cleanup;
-        }
-
-        // setting the values that come in an ENV variable as defaults - ves-endpoint-password
-
-        value = (const sr_val_t) { 0 };
-        value.type = SR_STRING_T;
-        value.data.string_val = getenv("VesEndpointPassword");
-        rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-password",
-                &value, SR_EDIT_DEFAULT);
-        if (SR_ERR_OK != rc) {
-            printf("Error by sr_set_item: %s\n", sr_strerror(rc));
-            goto cleanup;
-        }
-
-        rc = ves_password_changed(getenv("VesEndpointPassword"));
-        if (SR_ERR_OK != rc) {
-            printf("Error by ves_password_changed: %s\n", sr_strerror(rc));
-            goto cleanup;
-        }
-    }
-
-    // setting the values that come in an ENV variable as defaults - ves-registration
-
-    int vesRegistration = 1;
-
-    char *vesRegistrationString = getenv("VesRegistration");
-    if (vesRegistrationString != NULL)
-    {
-        if (strcmp(vesRegistrationString, "false") == 0)
-        {
-            vesRegistration = 0;
-        }
-    }
-
-    value = (const sr_val_t) { 0 };
-    value.type = SR_BOOL_T;
-    value.data.bool_val = vesRegistration;
-    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-registration",
-            &value, SR_EDIT_DEFAULT);
-    if (SR_ERR_OK != rc) {
-        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    rc = ves_registration_changed(vesRegistration);
-    if (SR_ERR_OK != rc) {
-        printf("Error by ves_registration_changed: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    // setting the values that come in an ENV variable as defaults - ssh-connections
-
-    int sshConnections = getIntFromString(getenv("SshConnections"), 1);
-
-    rc = ssh_connections_changed(sshConnections);
-    if (SR_ERR_OK != rc) {
-        printf("Error by ssh_connections_changed: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    // setting the values that come in an ENV variable as defaults - tls-connections
-
-    int tlsConnections = getIntFromString(getenv("TlsConnections"), 0);
-
-    rc = tls_connections_changed(tlsConnections);
-    if (SR_ERR_OK != rc) {
-        printf("Error by tls_connections_changed: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    if (strcmp(getenv("K8S_DEPLOYMENT"), "true") == 0)
-    {
-        rc = send_k8s_extend_port();
-        if (rc != SR_ERR_OK)
-        {
-            printf("Could not send the number of ports to k8s cluster\n");
-        }
-    }
-
-    // setting the values that come in an ENV variable as defaults - controller-ip
-
-    value = (const sr_val_t) { 0 };
-    value.type = SR_STRING_T;
-    value.data.string_val = getenv("ControllerIp");
-    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-ip", 
-            &value, SR_EDIT_DEFAULT);
-    if (SR_ERR_OK != rc) {
-        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    rc = controller_ip_changed(getenv("ControllerIp"));
-    if (SR_ERR_OK != rc) {
-        printf("Error by controller_ip_changed: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    // setting the values that come in an ENV variable as defaults - controller-port
-
-    int controllerPort = getIntFromString(getenv("ControllerPort"), 8181);
-
-    value = (const sr_val_t) { 0 };
-    value.type = SR_UINT16_T;
-    value.data.uint16_val = controllerPort;
-    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-port", 
-            &value, SR_EDIT_DEFAULT);
-    if (SR_ERR_OK != rc) {
-        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    rc = controller_port_changed(controllerPort);
-    if (SR_ERR_OK != rc) {
-        printf("Error by controller_port_changed: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    // setting the values that come in an ENV variable as defaults - netconf-call-home-port
-
-    int netconfCallHomePort = getIntFromString(getenv("NetconfCallHomePort"), 6666);
-
-    value = (const sr_val_t) { 0 };
-    value.type = SR_UINT16_T;
-    value.data.uint16_val = netconfCallHomePort;
-    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/netconf-call-home-port", 
-            &value, SR_EDIT_DEFAULT);
-    if (SR_ERR_OK != rc) {
-        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    rc = controller_netconf_call_home_port_changed(netconfCallHomePort);
-    if (SR_ERR_OK != rc) {
-        printf("Error by controller_netconf_call_home_port_changed: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    // setting the values that come in an ENV variable as defaults - controller-username
-
-    value = (const sr_val_t) { 0 };
-    value.type = SR_STRING_T;
-    value.data.string_val = getenv("ControllerUsername");
-    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-username", 
-            &value, SR_EDIT_DEFAULT);
-    if (SR_ERR_OK != rc) {
-        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    rc = controller_username_changed(getenv("ControllerUsername"));
-    if (SR_ERR_OK != rc) {
-        printf("Error by controller_username_changed: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    // setting the values that come in an ENV variable as defaults - controller-password
-
-    value = (const sr_val_t) { 0 };
-    value.type = SR_STRING_T;
-    value.data.string_val = getenv("ControllerPassword");
-    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-password", 
-            &value, SR_EDIT_DEFAULT);
-    if (SR_ERR_OK != rc) {
-        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    rc = controller_password_changed(getenv("ControllerPassword"));
-    if (SR_ERR_OK != rc) {
-        printf("Error by controller_password_changed: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    // setting the values that come in an ENV variable as defaults - netconf-call-home
-
-    int netconfCallHome = 1;
-
-    char *netconfCallHomeString = getenv("NetconfCallHome");
-    if (netconfCallHomeString != NULL)
-    {
-        if (strcmp(netconfCallHomeString, "false") == 0)
-        {
-            netconfCallHome = 0;
-        }
-    }
-
-    value = (const sr_val_t) { 0 };
-    value.type = SR_BOOL_T;
-    value.data.bool_val = netconfCallHome;
-    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/netconf-call-home", 
-            &value, SR_EDIT_DEFAULT);
-    if (SR_ERR_OK != rc) {
-        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    rc = netconf_call_home_changed(netconfCallHome);
-    if (SR_ERR_OK != rc) {
-        printf("Error by netconf_call_home_changed: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    //commit the changes that we have done until now
-    rc = sr_commit(session);
-    if (SR_ERR_OK != rc) {
-        printf("Error by sr_commit: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-       /* read startup config */
-       printf("\n\n ========== READING STARTUP CONFIG network-topology-simulator: ==========\n\n");
-       print_current_config(session, "network-topology-simulator");
-
-       /* subscribe for changes in running config */
-       rc = sr_module_change_subscribe(session, "network-topology-simulator", simulator_config_change_cb, NULL,
-                       0, SR_SUBSCR_DEFAULT | SR_SUBSCR_APPLY_ONLY, &subscription);
-       if (SR_ERR_OK != rc) {
-               fprintf(stderr, "Error by sr_module_change_subscribe: %s\n", sr_strerror(rc));
-               goto cleanup;
-       }
-
-    /* subscribe as state data provider for the ntsimulator state data */
-    rc = sr_dp_get_items_subscribe(session, "/network-topology-simulator:simulator-status", simulator_status_cb, NULL,
-               SR_SUBSCR_CTX_REUSE, &subscription);
-    if (rc != SR_ERR_OK) {
-        goto cleanup;
-    }
-
-    rc = notification_delay_period_changed(NULL, 0);
-    if (rc != SR_ERR_OK) {
-       printf("Could not write the delay period to file!\n");
-        goto cleanup;
-    }
-
-    rc = _init_curl_odl();
-    if (rc != SR_ERR_OK)
-    {
-        fprintf(stderr, "Could not initialize cURL for ODL connection: %s\n", sr_strerror(rc));
-    }
-
-    rc = sr_rpc_subscribe(session, "/network-topology-simulator:add-key-pair-to-odl", odl_add_key_pair_cb, (void *)session,
-               SR_SUBSCR_CTX_REUSE, &subscription);
-
-       printf("\n\n ========== STARTUP CONFIG network-topology-simulator APPLIED AS RUNNING ==========\n\n");
-
-    rc = writeSkeletonStatusFile();
-    if (rc != SR_ERR_OK)
-    {
-        fprintf(stderr, "Could not initialize status JSON file: %s\n", sr_strerror(rc));
-    }
-
-    rc = sr_rpc_subscribe(session, "/network-topology-simulator:invoke-notification", invoke_notification_cb,
-            (void *)session, SR_SUBSCR_DEFAULT, &subscription);
-    if (SR_ERR_OK != rc) {
-        fprintf(stderr, "Error by sr_rpc_subscribe: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    rc = pull_docker_image_of_simulated_device();
-
-    /* loop until ctrl-c is pressed / SIGINT is received */
-    signal(SIGINT, sigint_handler);
-    signal(SIGTERM, sigint_handler);
-    signal(SIGPIPE, SIG_IGN);
-
-    while (!exit_application) {
-
-               sleep(1);  /* or do some more useful work... */
-    }
-
-    printf("Application exit requested, exiting.\n");
-
-cleanup:
-    if (NULL != subscription) {
-        sr_unsubscribe(session, subscription);
-    }
-    if (NULL != session) {
-        sr_session_stop(session);
-    }
-    if (NULL != connection) {
-        sr_disconnect(connection);
-    }
-
-    clean_current_docker_configuration();
-    rc = cleanup_curl();
-    rc = cleanup_curl_odl();
-    rc = cleanup_curl_k8s();
-
-    return rc;
-}
-
-static void clean_current_docker_configuration(void)
-{
-    if (strcmp(getenv("K8S_DEPLOYMENT"), "true"))
-    {
-        return;
-    }
-
-       printf("Cleaning docker containers...\n");
-
-       if (device_list == NULL)
-       {
-               return;
-       }
-
-       for (int i = 0; i < simulated_devices_config; ++i)
-       {
-               stop_device(device_list);
-       }
-
-       printf("Cleaning completed!\n");
-}
diff --git a/ntsimulator/src/ntsimulator-manager/simulator-operations.c b/ntsimulator/src/ntsimulator-manager/simulator-operations.c
deleted file mode 100644 (file)
index 87b1d68..0000000
+++ /dev/null
@@ -1,3009 +0,0 @@
-/*************************************************************************
-*
-* Copyright 2019 highstreet technologies GmbH and others
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*     http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-***************************************************************************/
-
-#include "simulator-operations.h"
-#include "sysrepo.h"
-#include "sysrepo/values.h"
-#include <string.h>
-#include <math.h>
-#include <linux/limits.h>
-#include <unistd.h>
-
-#include "utils.h"
-
-#define LINE_BUFSIZE 128
-
-static         CURL *curl; //share the same curl connection for communicating with the Docker Engine API
-static         CURL *curl_odl; //share the same curl connection for mounting servers in ODL
-static         CURL *curl_k8s; //share the same curl connection for communicating with the K8S cluster
-
-/*
-curl -X POST -H 'Content-Type: application/json' -i http://localhost:5000/scale --data '{"simulatedDevices":2}'
-*/
-
-static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
-{
-  size_t realsize = size * nmemb;
-  struct MemoryStruct *mem = (struct MemoryStruct *)userp;
-
-  char *ptr = realloc(mem->memory, mem->size + realsize + 1);
-  if(ptr == NULL) {
-    /* out of memory! */
-    printf("not enough memory (realloc returned NULL)\n");
-    return 0;
-  }
-
-  mem->memory = ptr;
-  memcpy(&(mem->memory[mem->size]), contents, realsize);
-  mem->size += realsize;
-  mem->memory[mem->size] = 0;
-
-  return realsize;
-}
-
-static void set_curl_common_info()
-{
-    struct curl_slist *chunk = NULL;
-    chunk = curl_slist_append(chunk, "Content-Type: application/json");
-    chunk = curl_slist_append(chunk, "Accept: application/json");
-
-    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
-
-    curl_easy_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, "/var/run/docker.sock");
-
-    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
-    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 2L); // seconds timeout for a connection
-    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); //seconds timeout for an operation
-
-    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
-}
-
-static void set_curl_common_info_odl()
-{
-    struct curl_slist *chunk = NULL;
-    chunk = curl_slist_append(chunk, "Content-Type: application/xml");
-    chunk = curl_slist_append(chunk, "Accept: application/xml");
-
-    curl_easy_setopt(curl_odl, CURLOPT_HTTPHEADER, chunk);
-
-    curl_easy_setopt(curl_odl, CURLOPT_CONNECTTIMEOUT, 2L); // seconds timeout for a connection
-    curl_easy_setopt(curl_odl, CURLOPT_TIMEOUT, 10L); //seconds timeout for an operation
-
-    curl_easy_setopt(curl_odl, CURLOPT_VERBOSE, 1L);
-}
-
-static void set_curl_common_info_k8s()
-{
-    struct curl_slist *chunk = NULL;
-    chunk = curl_slist_append(chunk, "Content-Type: application/json");
-    chunk = curl_slist_append(chunk, "Accept: application/json");
-
-    curl_easy_setopt(curl_k8s, CURLOPT_HTTPHEADER, chunk);
-
-    curl_easy_setopt(curl_k8s, CURLOPT_CONNECTTIMEOUT, 2L); // seconds timeout for a connection
-    curl_easy_setopt(curl_k8s, CURLOPT_TIMEOUT, 10L); //seconds timeout for an operation
-
-    curl_easy_setopt(curl_k8s, CURLOPT_VERBOSE, 1L);
-}
-
-static cJSON* get_docker_container_bindings(void)
-{
-       struct MemoryStruct curl_response_mem;
-
-       curl_response_mem.memory = malloc(1);  /* will be grown as needed by the realloc above */
-       curl_response_mem.size = 0;    /* no data at this point */
-
-       CURLcode res;
-
-       curl_easy_reset(curl);
-       set_curl_common_info();
-
-       char url[200];
-       sprintf(url, "http:/v%s/containers/%s/json", getenv("DOCKER_ENGINE_VERSION"), getenv("HOSTNAME"));
-
-       curl_easy_setopt(curl, CURLOPT_URL, url);
-
-    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
-    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
-
-       curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
-
-       res = curl_easy_perform(curl);
-
-       if (res != CURLE_OK)
-       {
-               return NULL;
-       }
-       else
-       {
-               cJSON *json_response = cJSON_Parse(curl_response_mem.memory);
-
-               printf("%lu bytes retrieved\n", (unsigned long)curl_response_mem.size);
-
-               if (json_response == NULL)
-               {
-                       printf("Could not parse JSON response for url=\"%s\"\n", url);
-                       return NULL;
-               }
-
-               cJSON *hostConfig = cJSON_GetObjectItemCaseSensitive(json_response, "HostConfig");
-
-               if (hostConfig == NULL)
-               {
-                       printf("Could not get HostConfig object\n");
-                       return NULL;
-               }
-
-               cJSON *binds = cJSON_GetObjectItemCaseSensitive(hostConfig, "Binds");
-
-               if (binds == NULL)
-               {
-                       printf("Could not get Binds object\n");
-                       return NULL;
-               }
-
-               cJSON *bindsCopy = cJSON_Duplicate(binds, 1);
-
-           cJSON_Delete(json_response);
-
-               return bindsCopy;
-       }
-
-       return NULL;
-}
-
-static cJSON* get_docker_container_network_node(void)
-{
-    struct MemoryStruct curl_response_mem;
-
-    curl_response_mem.memory = malloc(1);  /* will be grown as needed by the realloc above */
-    curl_response_mem.size = 0;    /* no data at this point */
-
-    CURLcode res;
-
-    curl_easy_reset(curl);
-    set_curl_common_info();
-
-    char url[200];
-    sprintf(url, "http:/v%s/containers/%s/json", getenv("DOCKER_ENGINE_VERSION"), getenv("HOSTNAME"));
-
-    curl_easy_setopt(curl, CURLOPT_URL, url);
-
-    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
-    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
-
-    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
-
-    res = curl_easy_perform(curl);
-
-    if (res != CURLE_OK)
-    {
-        return NULL;
-    }
-    else
-    {
-        cJSON *json_response = cJSON_Parse(curl_response_mem.memory);
-
-        printf("%lu bytes retrieved\n", (unsigned long)curl_response_mem.size);
-
-        if (json_response == NULL)
-        {
-            printf("Could not parse JSON response for url=\"%s\"\n", url);
-            return NULL;
-        }
-
-        cJSON *hostConfig = cJSON_GetObjectItemCaseSensitive(json_response, "HostConfig");
-
-        if (hostConfig == NULL)
-        {
-            printf("Could not get HostConfig object\n");
-            return NULL;
-        }
-
-        cJSON *networkMode = cJSON_GetObjectItemCaseSensitive(hostConfig, "NetworkMode");
-
-        if (networkMode == NULL)
-        {
-            printf("Could not get NetworkMode object\n");
-            return NULL;
-        }
-
-        cJSON *networkCopy = cJSON_Duplicate(networkMode, 1);
-
-        cJSON_Delete(json_response);
-
-        return networkCopy;
-    }
-
-    return NULL;
-}
-
-static char* create_docker_container_curl(int base_netconf_port, cJSON* managerBinds, cJSON* networkMode, int device_number)
-{
-    if (managerBinds == NULL)
-    {
-        printf("Could not retrieve JSON object: Binds\n");
-        return NULL;
-    }
-    cJSON *binds = cJSON_Duplicate(managerBinds, 1);
-
-    if (networkMode == NULL)
-       {
-               printf("Could not retrieve JSON object: NetworkMode\n");
-               return NULL;
-       }
-       cJSON *netMode = cJSON_Duplicate(networkMode, 1);
-
-       struct MemoryStruct curl_response_mem;
-
-       curl_response_mem.memory = malloc(1);  /* will be grown as needed by the realloc above */
-       curl_response_mem.size = 0;    /* no data at this point */
-
-       CURLcode res;
-
-       curl_easy_reset(curl);
-       set_curl_common_info();
-
-       char url[100];
-       sprintf(url, "http:/v%s/containers/create", getenv("DOCKER_ENGINE_VERSION"));
-
-       // the docker image name to be used is defined in the Dockerfile of the NTS Manager,
-       // under the MODELS_IMAGE env variable
-       char models_var[50];
-       sprintf(models_var, "%s", getenv("MODELS_IMAGE"));
-
-       curl_easy_setopt(curl, CURLOPT_URL, url);
-
-    cJSON *postDataJson = cJSON_CreateObject();
-
-    if (cJSON_AddStringToObject(postDataJson, "Image", models_var) == NULL)
-    {
-        printf("Could not create JSON object: Image\n");
-        return NULL;
-    }
-
-    char device_name[100];
-    sprintf(device_name, "%s-%d", getenv("CONTAINER_NAME"), device_number);
-
-    if (cJSON_AddStringToObject(postDataJson, "Hostname", device_name) == NULL)
-    {
-        printf("Could not create JSON object: Hostname\n");
-        return NULL;
-    }    
-
-    cJSON *hostConfig = cJSON_CreateObject();
-    if (hostConfig == NULL)
-    {
-        printf("Could not create JSON object: HostConfig\n");
-        return NULL;
-    }
-
-    cJSON_AddItemToObject(postDataJson, "HostConfig", hostConfig);
-
-    cJSON *portBindings = cJSON_CreateObject();
-    if (portBindings == NULL)
-    {
-        printf("Could not create JSON object: PortBindings\n");
-        return NULL;
-    }
-
-    cJSON_AddItemToObject(hostConfig, "PortBindings", portBindings);
-
-    for (int i = 0; i < NETCONF_CONNECTIONS_PER_DEVICE; ++i)
-    {
-       cJSON *port = cJSON_CreateArray();
-               if (port == NULL)
-               {
-               printf("Could not create JSON object: port\n");
-                       return NULL;
-               }
-
-               char dockerContainerPort[20];
-               sprintf(dockerContainerPort, "%d/tcp", 830 + i);
-
-           cJSON_AddItemToObject(portBindings, dockerContainerPort, port);
-
-           cJSON *hostPort = cJSON_CreateObject();
-           if (hostPort == NULL)
-               {
-               printf("Could not create JSON object: HostPort\n");
-                       return NULL;
-               }
-
-           char dockerHostPort[10];
-           sprintf(dockerHostPort, "%d", base_netconf_port + i);
-           if (cJSON_AddStringToObject(hostPort, "HostPort", dockerHostPort) == NULL)
-           {
-               printf("Could not create JSON object: HostPortString\n");
-               return NULL;
-           }
-           if (cJSON_AddStringToObject(hostPort, "HostIp", getenv("NTS_IP")) == NULL)
-           {
-               printf("Could not create JSON object: HostIpString\n");
-               return NULL;
-           }
-
-           cJSON_AddItemToArray(port, hostPort);
-    }
-
-    cJSON *labels = cJSON_CreateObject();
-    if (labels == NULL)
-       {
-       printf("Could not create JSON object: Labels\n");
-               return NULL;
-       }
-
-    cJSON_AddItemToObject(postDataJson, "Labels", labels);
-
-    if (cJSON_AddStringToObject(labels, "NTS", "") == NULL)
-    {
-       printf("Could not create JSON object: NTS\n");
-       return NULL;
-    }
-
-       if (cJSON_AddStringToObject(labels, "NTS_Manager", getenv("HOSTNAME")) == NULL)
-    {
-       printf("Could not create JSON object: NTS Manager\n");
-       return NULL;
-    }
-
-    cJSON *env_variables_array = cJSON_CreateArray();
-    if (env_variables_array == NULL)
-       {
-       printf("Could not create JSON object: Env array\n");
-               return NULL;
-       }
-
-    cJSON_AddItemToObject(postDataJson, "Env", env_variables_array);
-
-    char environment_var[100];
-    sprintf(environment_var, "NTS_IP=%s", getenv("NTS_IP"));
-
-    cJSON *env_var_obj = cJSON_CreateString(environment_var);
-    if (env_var_obj == NULL)
-       {
-       printf("Could not create JSON object: Env array object NTS_IP\n");
-               return NULL;
-       }
-    cJSON_AddItemToArray(env_variables_array, env_var_obj);
-
-    char *external_nts_ip = getenv("EXTERNAL_NTS_IP");
-    if (external_nts_ip == NULL)
-    {
-        sprintf(environment_var, "EXTERNAL_NTS_IP=%s", getenv("NTS_IP"));
-    }
-    else
-    {
-        sprintf(environment_var, "EXTERNAL_NTS_IP=%s", external_nts_ip);
-    }
-
-    cJSON *env_var_obj_0 = cJSON_CreateString(environment_var);
-    if (env_var_obj_0 == NULL)
-       {
-        printf("Could not create JSON object: Env array object EXTERNAL_NTS_IP\n");
-               return NULL;
-       }
-    cJSON_AddItemToArray(env_variables_array, env_var_obj_0);
-
-    sprintf(environment_var, "NETCONF_BASE=%d", base_netconf_port);
-    cJSON *env_var_obj_2 = cJSON_CreateString(environment_var);
-    if (env_var_obj_2 == NULL)
-       {
-       printf("Could not create JSON object: Env array object NETCONF_BASE\n");
-               return NULL;
-       }
-    cJSON_AddItemToArray(env_variables_array, env_var_obj_2);
-
-    char scripts_dir[200];
-    sprintf(scripts_dir, "SCRIPTS_DIR=%s", getenv("SCRIPTS_DIR"));
-    cJSON *env_var_obj_3 = cJSON_CreateString(scripts_dir);
-    if (env_var_obj_3 == NULL)
-    {
-        printf("Could not create JSON object: Env array object SCRIPTS_DIR\n");
-        return NULL;
-    }
-    cJSON_AddItemToArray(env_variables_array, env_var_obj_3);
-
-    char k8s_deployment[50];
-    sprintf(k8s_deployment, "K8S_DEPLOYMENT=%s", getenv("K8S_DEPLOYMENT"));
-    cJSON *env_var_obj_4 = cJSON_CreateString(k8s_deployment);
-    if (env_var_obj_4 == NULL)
-    {
-        printf("Could not create JSON object: Env array object K8S_DEPLOYMENT\n");
-        return NULL;
-    }
-    cJSON_AddItemToArray(env_variables_array, env_var_obj_4);
-
-    char ipv6_enabled[50];
-    sprintf(ipv6_enabled, "IPv6Enabled=%s", getenv("IPv6Enabled"));
-    cJSON *env_var_obj_5 = cJSON_CreateString(ipv6_enabled);
-    if (env_var_obj_5 == NULL)
-    {
-        printf("Could not create JSON object: Env array object IPv6Enabled\n");
-        return NULL;
-    }
-    cJSON_AddItemToArray(env_variables_array, env_var_obj_5);
-
-    cJSON_AddItemToObject(hostConfig, "Binds", binds);
-
-    cJSON_AddItemToObject(hostConfig, "NetworkMode", netMode);
-
-    char *post_data_string = NULL;
-
-    post_data_string = cJSON_PrintUnformatted(postDataJson);
-
-    printf("Post data JSON:\n%s\n", post_data_string);
-
-    if (postDataJson != NULL)
-    {
-       cJSON_Delete(postDataJson);
-    }
-
-    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data_string);
-
-       curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
-
-       res = curl_easy_perform(curl);
-
-    if (post_data_string != NULL)
-    {
-        free(post_data_string);
-    }
-
-       if (res != CURLE_OK)
-       {
-               return NULL;
-       }
-       else
-       {
-               cJSON *json_response = cJSON_Parse(curl_response_mem.memory);
-               const cJSON *container_id = NULL;
-
-               printf("%lu bytes retrieved\n", (unsigned long)curl_response_mem.size);
-
-               container_id = cJSON_GetObjectItemCaseSensitive(json_response, "Id");
-
-               if (cJSON_IsString(container_id) && (container_id->valuestring != NULL))
-               {
-                       printf("Container id: \"%s\"\n", container_id->valuestring);
-
-                       char container_id_short[13];
-
-                       memset(container_id_short, '\0', sizeof(container_id_short));
-                       strncpy(container_id_short, container_id->valuestring, 12);
-
-                       printf("Container id short: \"%s\"\n", container_id_short);
-
-                   cJSON_Delete(json_response);
-                       return strdup(container_id_short);
-               }
-
-           cJSON_Delete(json_response);
-       }
-
-       return NULL;
-}
-
-static int start_docker_container_curl(char *container_id)
-{
-    struct MemoryStruct curl_response_mem;
-
-    curl_response_mem.memory = malloc(1);  /* will be grown as needed by the realloc above */
-    curl_response_mem.size = 0;    /* no data at this point */
-
-    CURLcode res;
-
-    curl_easy_reset(curl);
-    set_curl_common_info();
-
-    char url[100];
-    sprintf(url, "http:/v%s/containers/%s/start", getenv("DOCKER_ENGINE_VERSION"), container_id);
-
-    curl_easy_setopt(curl, CURLOPT_URL, url);
-
-    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
-
-    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
-
-    res = curl_easy_perform(curl);
-
-    if (res != CURLE_OK)
-    {
-        return SR_ERR_OPERATION_FAILED;
-    }
-    else
-    {
-        printf("Container %s started successfully!\n", container_id);
-    }
-
-    return SR_ERR_OK;
-}
-
-static int rename_docker_container_curl(char *container_id, int device_number)
-{
-    struct MemoryStruct curl_response_mem;
-
-    curl_response_mem.memory = malloc(1);  /* will be grown as needed by the realloc above */
-    curl_response_mem.size = 0;    /* no data at this point */
-
-    CURLcode res;
-
-    curl_easy_reset(curl);
-    set_curl_common_info();
-
-    char device_name[100];
-    sprintf(device_name, "%s-%d", getenv("CONTAINER_NAME"), device_number);
-
-    char url[100];
-    sprintf(url, "http:/v%s/containers/%s/rename?name=%s", getenv("DOCKER_ENGINE_VERSION"), container_id,
-                device_name);
-
-    curl_easy_setopt(curl, CURLOPT_URL, url);
-
-    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
-
-    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
-
-    res = curl_easy_perform(curl);
-
-    if (res != CURLE_OK)
-    {
-        return SR_ERR_OPERATION_FAILED;
-    }
-    else
-    {
-        printf("Container %s renamed successfully to %s!\n", container_id, device_name);
-    }
-
-    return SR_ERR_OK;
-}
-
-static int kill_and_remove_docker_container_curl(char *container_id)
-{
-       struct MemoryStruct curl_response_mem;
-
-       curl_response_mem.memory = malloc(1);  /* will be grown as needed by the realloc above */
-       curl_response_mem.size = 0;    /* no data at this point */
-
-       CURLcode res;
-
-       curl_easy_reset(curl);
-       set_curl_common_info();
-
-       char url[100];
-       sprintf(url, "http:/v%s/containers/%s?force=true", getenv("DOCKER_ENGINE_VERSION"), container_id);
-
-       curl_easy_setopt(curl, CURLOPT_URL, url);
-
-    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
-    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
-
-       curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
-
-       res = curl_easy_perform(curl);
-
-       if (res != CURLE_OK)
-       {
-               return SR_ERR_OPERATION_FAILED;
-       }
-       else
-       {
-               printf("Container %s removed successfully!\n", container_id);
-       }
-
-       return SR_ERR_OK;
-}
-
-static int send_mount_device_instance_ssh(char *url, char *credentials, char *device_name, int device_port)
-{
-       CURLcode res;
-
-       curl_easy_reset(curl_odl);
-       set_curl_common_info_odl();
-
-       char url_for_curl[200];
-       sprintf(url_for_curl, "%s%s_%d", url, device_name, device_port);
-
-       curl_easy_setopt(curl_odl, CURLOPT_URL, url_for_curl);
-
-       char post_data_xml[1500];
-
-       sprintf(post_data_xml,
-            "<node xmlns=\"urn:TBD:params:xml:ns:yang:network-topology\">"
-            "<node-id>%s_%d</node-id>"
-            "<host xmlns=\"urn:opendaylight:netconf-node-topology\">%s</host>"
-            "<port xmlns=\"urn:opendaylight:netconf-node-topology\">%d</port>"
-            "<username xmlns=\"urn:opendaylight:netconf-node-topology\">%s</username>"
-            "<password xmlns=\"urn:opendaylight:netconf-node-topology\">%s</password>"
-            "<tcp-only xmlns=\"urn:opendaylight:netconf-node-topology\">false</tcp-only>"
-            "<keepalive-delay xmlns=\"urn:opendaylight:netconf-node-topology\">120</keepalive-delay>"
-            "<reconnect-on-changed-schema xmlns=\"urn:opendaylight:netconf-node-topology\">false</reconnect-on-changed-schema>"
-            "<sleep-factor xmlns=\"urn:opendaylight:netconf-node-topology\">1.5</sleep-factor>"
-            "<connection-timeout-millis xmlns=\"urn:opendaylight:netconf-node-topology\">20000</connection-timeout-millis>"
-            "<max-connection-attempts xmlns=\"urn:opendaylight:netconf-node-topology\">100</max-connection-attempts>"
-            "<between-attempts-timeout-millis xmlns=\"urn:opendaylight:netconf-node-topology\">2000</between-attempts-timeout-millis>"
-            "</node>",
-                       device_name, device_port, (getenv("EXTERNAL_NTS_IP") == NULL) ? getenv("NTS_IP") : getenv("EXTERNAL_NTS_IP"),
-            device_port, "netconf", "netconf");
-
-       printf("Post data:\n%s\n", post_data_xml);
-
-       curl_easy_setopt(curl_odl, CURLOPT_POSTFIELDS, post_data_xml);
-    curl_easy_setopt(curl_odl, CURLOPT_CUSTOMREQUEST, "PUT");
-    curl_easy_setopt(curl_odl, CURLOPT_USERPWD, credentials);
-
-       res = curl_easy_perform(curl_odl);
-       if (res != CURLE_OK)
-       {
-               printf("cURL failed to url=%s\n", url_for_curl);
-       }
-
-       long http_response_code = 0;
-       curl_easy_getinfo (curl_odl, CURLINFO_RESPONSE_CODE, &http_response_code);
-       if (http_response_code >= 200 && http_response_code <= 226 && http_response_code != CURLE_ABORTED_BY_CALLBACK)
-       {
-               printf("cURL succeeded to url=%s\n", url_for_curl);
-       }
-       else
-       {
-           printf("cURL to url=%s failed with code=%ld\n", url_for_curl, http_response_code);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       return SR_ERR_OK;
-}
-
-static int send_mount_device_instance_tls(char *url, char *credentials, char *device_name, int device_port)
-{
-       CURLcode res;
-
-       curl_easy_reset(curl_odl);
-       set_curl_common_info_odl();
-
-       char url_for_curl[200];
-       sprintf(url_for_curl, "%s%s_%d", url, device_name, device_port);
-
-       curl_easy_setopt(curl_odl, CURLOPT_URL, url_for_curl);
-
-       char post_data_xml[1500];
-
-       sprintf(post_data_xml,
-                       "<node xmlns=\"urn:TBD:params:xml:ns:yang:network-topology\">"
-                       "<protocol xmlns=\"urn:opendaylight:netconf-node-topology\">"
-                       "<name>TLS</name>"
-                       "</protocol>"
-                       "<node-id>%s_%d</node-id>"
-                       "<host xmlns=\"urn:opendaylight:netconf-node-topology\">%s</host>"
-                       "<key-based xmlns=\"urn:opendaylight:netconf-node-topology\">"
-                       "<username>%s</username>"
-                       "<key-id>device-key</key-id>"
-                       "</key-based>"
-                       "<port xmlns=\"urn:opendaylight:netconf-node-topology\">%d</port>"
-                       "<tcp-only xmlns=\"urn:opendaylight:netconf-node-topology\">false</tcp-only>"
-                       "<keepalive-delay xmlns=\"urn:opendaylight:netconf-node-topology\">120</keepalive-delay>"
-                       "<reconnect-on-changed-schema xmlns=\"urn:opendaylight:netconf-node-topology\">false</reconnect-on-changed-schema>"
-                       "<sleep-factor xmlns=\"urn:opendaylight:netconf-node-topology\">1.5</sleep-factor>"
-                       "<connection-timeout-millis xmlns=\"urn:opendaylight:netconf-node-topology\">20000</connection-timeout-millis>"
-                       "<max-connection-attempts xmlns=\"urn:opendaylight:netconf-node-topology\">100</max-connection-attempts>"
-                       "<between-attempts-timeout-millis xmlns=\"urn:opendaylight:netconf-node-topology\">2000</between-attempts-timeout-millis>"
-                       "</node>",
-                       device_name, device_port, (getenv("EXTERNAL_NTS_IP") == NULL) ? getenv("NTS_IP") : getenv("EXTERNAL_NTS_IP"), "netconf", device_port);
-
-       printf("Post data:\n%s\n", post_data_xml);
-
-       curl_easy_setopt(curl_odl, CURLOPT_POSTFIELDS, post_data_xml);
-    curl_easy_setopt(curl_odl, CURLOPT_CUSTOMREQUEST, "PUT");
-    curl_easy_setopt(curl_odl, CURLOPT_USERPWD, credentials);
-
-       res = curl_easy_perform(curl_odl);
-       if (res != CURLE_OK)
-       {
-               printf("cURL failed to url=%s\n", url_for_curl);
-       }
-
-       long http_response_code = 0;
-       curl_easy_getinfo (curl_odl, CURLINFO_RESPONSE_CODE, &http_response_code);
-       if (http_response_code >= 200 && http_response_code <= 226 && http_response_code != CURLE_ABORTED_BY_CALLBACK)
-       {
-               printf("cURL succeeded to url=%s\n", url_for_curl);
-       }
-       else
-       {
-           printf("cURL to url=%s failed with code=%ld\n", url_for_curl, http_response_code);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       return SR_ERR_OK;
-}
-
-static int send_unmount_device_instance(char *url, char *credentials, char *device_name, int device_port)
-{
-       CURLcode res;
-
-       curl_easy_reset(curl_odl);
-       set_curl_common_info_odl();
-
-       char url_for_curl[200];
-       sprintf(url_for_curl, "%s%s_%d", url, device_name, device_port);
-
-       curl_easy_setopt(curl_odl, CURLOPT_URL, url_for_curl);
-
-       curl_easy_setopt(curl_odl, CURLOPT_POSTFIELDS, "");
-       curl_easy_setopt(curl_odl, CURLOPT_CUSTOMREQUEST, "DELETE");
-       curl_easy_setopt(curl_odl, CURLOPT_USERPWD, credentials);
-
-       res = curl_easy_perform(curl_odl);
-       if (res != CURLE_OK)
-       {
-               printf("cURL failed to url=%s\n", url_for_curl);
-       }
-
-       long http_response_code = 0;
-       curl_easy_getinfo (curl_odl, CURLINFO_RESPONSE_CODE, &http_response_code);
-       if (http_response_code == 200 && http_response_code != CURLE_ABORTED_BY_CALLBACK)
-       {
-               printf("cURL succeeded to url=%s\n", url_for_curl);
-       }
-       else
-       {
-               printf("cURL to url=%s failed with code=%ld\n", url_for_curl, http_response_code);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       return SR_ERR_OK;
-}
-
-
-static int send_mount_device(device_t *current_device, controller_t controller_details)
-{
-       int rc = SR_ERR_OK;
-       bool is_mounted = true;
-    int port = 0;
-
-    char device_name[200];
-    sprintf(device_name, "%s-%d", getenv("CONTAINER_NAME"), current_device->device_number);
-
-       //This is where we hardcoded: 7 devices will have SSH connections and 3 devices will have TLS connections
-       for (int i = 0; i < SSH_CONNECTIONS_PER_DEVICE; ++port, ++i)
-       {
-        
-
-               rc = send_mount_device_instance_ssh(controller_details.url, controller_details.credentials,
-                               device_name, current_device->netconf_port + port);
-               if (rc != SR_ERR_OK)
-               {
-                       is_mounted = false;
-               }
-       }
-       for (int i = 0; i < TLS_CONNECTIONS_PER_DEVICE; ++port, ++i)
-       {
-               rc = send_mount_device_instance_tls(controller_details.url, controller_details.credentials,
-                               device_name, current_device->netconf_port + port);
-               if (rc != SR_ERR_OK)
-               {
-                       is_mounted = false;
-               }
-       }
-
-       current_device->is_mounted = is_mounted;
-
-       return SR_ERR_OK;
-}
-
-static int send_unmount_device(device_t *current_device, controller_t controller_details)
-{
-       int rc = SR_ERR_OK;
-    char device_name[100];
-    sprintf(device_name, "%s-%d", getenv("CONTAINER_NAME"), current_device->device_number);
-
-       for (int port = 0; port < NETCONF_CONNECTIONS_PER_DEVICE; ++port)
-       {
-               rc = send_unmount_device_instance(controller_details.url, controller_details.credentials,
-                               device_name, current_device->netconf_port + port);
-               if (rc != SR_ERR_OK)
-               {
-                       printf("Could not send unmount for ODL with url=\"%s\", for device=\"%s\" and port=%d\n",
-                                       controller_details.url, device_name, current_device->netconf_port);
-               }
-       }
-       current_device->is_mounted = false;
-
-       return SR_ERR_OK;
-}
-
-device_stack_t *new_device_stack(void)
-{
-       device_stack_t *stack = malloc(sizeof(*stack));
-
-       if (stack) {
-               stack->head = NULL;
-               stack->stack_size = 0;
-       }
-       return stack;
-}
-
-void push_device(device_stack_t *theStack, char *dev_id, int port, int dev_num)
-{
-       device_t *new_dev = malloc(sizeof(*new_dev));
-
-       if (new_dev) {
-               new_dev->device_id = strdup(dev_id);
-               new_dev->netconf_port = port;
-        new_dev->device_number = dev_num;
-               new_dev->is_mounted = false;
-               new_dev->operational_state = strdup("not-specified");
-
-               new_dev->next = theStack->head;
-
-               theStack->head = new_dev;
-               theStack->stack_size++;
-       }
-}
-
-void pop_device(device_stack_t *theStack)
-{
-       if (theStack && theStack->head) {
-               device_t *temp = theStack->head;
-               theStack->head = theStack->head->next;
-
-               free(temp->device_id);
-               free(temp->operational_state);
-               free(temp);
-               theStack->stack_size--;
-       }
-}
-
-int get_netconf_port_next(device_stack_t *theStack)
-{
-    if (theStack && theStack->stack_size > 0) {
-        return theStack->head->netconf_port + NETCONF_CONNECTIONS_PER_DEVICE;
-    }
-
-    return get_netconf_port_base();
-}
-
-int get_netconf_port_base()
-{
-    int netconf_port_base;
-
-    netconf_port_base = getIntFromString(getenv("NETCONF_BASE"), 50000);
-
-    return netconf_port_base;
-}
-
-// we start numbering the containers from 0
-int get_device_number_next(device_stack_t *theStack)
-{
-    if (theStack && theStack->stack_size > 0) {
-        return theStack->head->device_number + 1;
-    }
-
-    return 0;
-}
-
-char *get_id_last_device(device_stack_t *theStack)
-{
-    if (theStack && theStack->head) {
-        return theStack->head->device_id;
-    }
-    return NULL;
-}
-
-int get_current_number_of_mounted_devices(device_stack_t *theStack)
-{
-       int mounted_devices = 0;
-
-       if (theStack && theStack->head)
-       {
-               device_t *current_device = theStack->head;
-
-               while (current_device != NULL)
-               {
-                       if (current_device->is_mounted)
-                       {
-                               mounted_devices++;
-                       }
-                       current_device = current_device->next;
-               }
-       }
-
-       return mounted_devices;
-}
-
-int get_current_number_of_devices(device_stack_t *theStack)
-{
-    //TODO implement function for k8s deployment
-    if (strcmp(getenv("K8S_DEPLOYMENT"), "true") == 0)
-    {
-        return 0;
-    }
-
-       struct MemoryStruct curl_response_mem;
-
-       curl_response_mem.memory = malloc(1);  /* will be grown as needed by the realloc above */
-       curl_response_mem.size = 0;    /* no data at this point */
-
-       CURLcode res;
-
-       curl_easy_reset(curl);
-       set_curl_common_info();
-
-       char url[100];
-       sprintf(url, "http:/v%s/containers/json?all=true&filters={\"label\":[\"NTS_Manager=%s\"],\"status\":[\"running\"]}",
-                       getenv("DOCKER_ENGINE_VERSION"), getenv("HOSTNAME"));
-
-       curl_easy_setopt(curl, CURLOPT_URL, url);
-
-       curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
-       curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
-
-       curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
-
-       res = curl_easy_perform(curl);
-
-       if (res != CURLE_OK)
-       {
-               return SR_ERR_OPERATION_FAILED;
-       }
-       else
-       {
-               cJSON *json_response = cJSON_Parse(curl_response_mem.memory);
-
-               printf("%lu bytes retrieved\n", (unsigned long)curl_response_mem.size);
-
-               if (json_response == NULL || !cJSON_IsArray(json_response))
-               {
-                       printf("Could not parse JSON response for url=\"%s\"\n", url);
-                       return SR_ERR_OPERATION_FAILED;
-               }
-
-               int num_of_devices = cJSON_GetArraySize(json_response);
-               cJSON_Delete(json_response);
-
-               return num_of_devices;
-       }
-
-       return 0;
-}
-
-static int set_operational_state_of_device(device_stack_t *theStack, char *device_id, char *operational_state)
-{
-       if (theStack && theStack->head)
-       {
-               device_t *current_device = theStack->head;
-
-               while (current_device != NULL)
-               {
-                       if (strcmp(current_device->device_id, device_id) == 0)
-                       {
-                               free(current_device->operational_state);
-                               current_device->operational_state = strdup(operational_state);
-
-                               return SR_ERR_OK;
-                       }
-
-                       current_device = current_device->next;
-               }
-       }
-
-       printf("Could not find device with uuid=\"%s\"\n", device_id);
-       return SR_ERR_OPERATION_FAILED;
-}
-
-char* get_docker_container_operational_state(device_stack_t *theStack, char *container_id)
-{
-       if (theStack && theStack->head)
-       {
-               device_t *current_device = theStack->head;
-
-               while (current_device != NULL)
-               {
-                       if (strcmp(current_device->device_id, container_id) == 0)
-                       {
-                               return current_device->operational_state;
-                       }
-
-                       current_device = current_device->next;
-               }
-       }
-
-       return NULL;
-}
-
-int start_device(device_stack_t *theStack)
-{
-       int rc = SR_ERR_OK;
-       static cJSON *managerBindings = NULL, *networkMode = NULL;
-
-    if (managerBindings == NULL)
-    {
-        managerBindings = get_docker_container_bindings();
-    }
-
-    if (networkMode == NULL)
-       {
-               networkMode = get_docker_container_network_node();
-       }
-
-       int netconf_base = get_netconf_port_next(theStack);
-    int device_number = get_device_number_next(theStack);
-
-       char *dev_id = create_docker_container_curl(netconf_base, managerBindings, networkMode, device_number);
-    if (dev_id == NULL)
-    {
-        printf("ERROR: Could not create docker container!\n");
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-       push_device(theStack, dev_id, netconf_base, device_number);
-
-       rc = start_docker_container_curl(dev_id);
-       if (rc != SR_ERR_OK)
-       {
-               printf("Could not start device with device_id=\"%s\"\n", dev_id);
-       }
-
-    rc = rename_docker_container_curl(dev_id, device_number);
-       if (rc != SR_ERR_OK)
-       {
-               printf("Could not rename device with device_id=\"%s\"\n", dev_id);
-       }
-
-       if (dev_id) {
-               free(dev_id);
-       }
-
-       return SR_ERR_OK;
-}
-
-int _init_curl()
-{
-       curl = curl_easy_init();
-
-       if (curl == NULL) {
-               printf("cURL initialization error! Aborting call!\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       return SR_ERR_OK;
-}
-
-int cleanup_curl()
-{
-       if (curl != NULL)
-       {
-               curl_easy_cleanup(curl);
-       }
-
-       return SR_ERR_OK;
-}
-
-int _init_curl_odl()
-{
-       curl_odl = curl_easy_init();
-
-       if (curl_odl == NULL) {
-               printf("cURL initialization error! Aborting call!\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       return SR_ERR_OK;
-}
-
-int cleanup_curl_odl()
-{
-       if (curl_odl != NULL)
-       {
-               curl_easy_cleanup(curl_odl);
-       }
-
-       return SR_ERR_OK;
-}
-
-int _init_curl_k8s()
-{
-    curl_k8s = curl_easy_init();
-
-    if (curl_k8s == NULL) {
-        printf("cURL initialization error! Aborting call!\n");
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    return SR_ERR_OK;
-}
-
-int cleanup_curl_k8s()
-{
-    if (curl_k8s != NULL)
-    {
-        curl_easy_cleanup(curl_k8s);
-    }
-
-    return SR_ERR_OK;
-}
-
-int stop_device(device_stack_t *theStack)
-{
-       int rc = SR_ERR_OK;
-       char *last_id = get_id_last_device(theStack);
-
-       rc = kill_and_remove_docker_container_curl(last_id);
-       if (rc != SR_ERR_OK)
-       {
-               printf("Could not kill and remove docker container with uuid=\"%s\"\n", last_id);
-       }
-
-    rc = removeDeviceEntryFromStatusFile(last_id);
-    if (rc != SR_ERR_OK)
-    {
-        printf("Could not remove entry from status file for uuid=\"%s\"\n", last_id);
-    }
-
-       pop_device(theStack);
-
-       return SR_ERR_OK;
-}
-
-int mount_device(device_stack_t *theStack, controller_t controller_details)
-{
-       int rc;
-
-       if (theStack && theStack->head)
-       {
-               device_t *current_device = theStack->head;
-               while (current_device != NULL && current_device->is_mounted == true)
-               {
-                       printf("Device \"%s\" is already mounted, skipping...\n", current_device->device_id);
-                       current_device = current_device->next;
-               }
-
-               if (current_device != NULL)
-               {
-                       printf("Sending mount device for device \"%s\"...\n", current_device->device_id);
-                       rc = send_mount_device(current_device, controller_details);
-                       if (rc != SR_ERR_OK)
-                       {
-                               return SR_ERR_OPERATION_FAILED;
-                       }
-               }
-       }
-
-       return SR_ERR_OK;
-}
-
-int unmount_device(device_stack_t *theStack, controller_t controller_list)
-{
-       int rc;
-
-       if (theStack && theStack->head)
-       {
-               device_t *current_device = theStack->head;
-               while (current_device != NULL && current_device->is_mounted == false)
-               {
-                       printf("Device \"%s\" is already unmounted, skipping...\n", current_device->device_id);
-                       current_device = current_device->next;
-               }
-
-               if (current_device != NULL)
-               {
-                       printf("Sending unmount device for device \"%s\"...\n", current_device->device_id);
-                       rc = send_unmount_device(current_device, controller_list);
-                       if (rc != SR_ERR_OK)
-                       {
-                               return SR_ERR_OPERATION_FAILED;
-                       }
-               }
-       }
-
-       return SR_ERR_OK;
-}
-
-int get_docker_containers_operational_state_curl(device_stack_t *theStack)
-{
-
-    //TODO implement function for k8s deployment
-    if (strcmp(getenv("K8S_DEPLOYMENT"), "true") == 0)
-    {
-        return SR_ERR_OK;
-    }
-
-       int rc = SR_ERR_OK;
-       struct MemoryStruct curl_response_mem;
-
-       curl_response_mem.memory = malloc(1);  /* will be grown as needed by the realloc above */
-       curl_response_mem.size = 0;    /* no data at this point */
-
-       CURLcode res;
-
-       curl_easy_reset(curl);
-       set_curl_common_info();
-
-       char url[100];
-       sprintf(url, "http:/v%s/containers/json?all=true&filters={\"label\":[\"NTS_Manager=%s\"]}", 
-    getenv("DOCKER_ENGINE_VERSION"), getenv("HOSTNAME"));
-
-       curl_easy_setopt(curl, CURLOPT_URL, url);
-
-    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
-    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
-
-       curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
-
-       res = curl_easy_perform(curl);
-
-       if (res != CURLE_OK)
-       {
-               return SR_ERR_OPERATION_FAILED;
-       }
-       else
-       {
-               cJSON *json_response = cJSON_Parse(curl_response_mem.memory);
-               const cJSON *container = NULL;
-
-               printf("%lu bytes retrieved\n", (unsigned long)curl_response_mem.size);
-
-               if (json_response == NULL || !cJSON_IsArray(json_response))
-               {
-                       printf("Could not parse JSON response for url=\"%s\"\n", url);
-                       return SR_ERR_OPERATION_FAILED;
-               }
-
-           cJSON_ArrayForEach(container, json_response)
-           {
-               cJSON *container_id_long = cJSON_GetObjectItemCaseSensitive(container, "Id");
-               cJSON *state = cJSON_GetObjectItemCaseSensitive(container, "State");
-
-                       if (cJSON_IsString(container_id_long) && (container_id_long->valuestring != NULL))
-                       {
-                               char container_id_short[13];
-
-                               memset(container_id_short, '\0', sizeof(container_id_short));
-                               strncpy(container_id_short, container_id_long->valuestring, 12);
-
-                               if (cJSON_IsString(state) && (state->valuestring != NULL))
-                               {
-                                       rc = set_operational_state_of_device(theStack, container_id_short, state->valuestring);
-                                       if (rc != SR_ERR_OK)
-                                       {
-                                               printf("Could not set the operational state for the device with uuid=\"%s\"\n", container_id_short);
-                                               return SR_ERR_OPERATION_FAILED;
-                                       }
-                               }
-                       }
-           }
-
-           cJSON_Delete(json_response);
-       }
-
-       return SR_ERR_OK;
-}
-
-char* get_docker_container_resource_stats(device_stack_t *theStack)
-{
-    //TOD need to implement this for k8s deployment
-    if (strcmp(getenv("K8S_DEPLOYMENT"), "true"))
-    {
-        return strdup("CPU=0%;RAM=0MiB");
-    }
-
-       char line[LINE_BUFSIZE];
-       int linenr;
-       FILE *pipe;
-
-       /* Get a pipe where the output from the scripts comes in */
-       char script[200];
-       sprintf(script, "/opt/dev/docker_stats.sh %s", getenv("HOSTNAME"));
-
-       pipe = popen(script, "r");
-       if (pipe == NULL) {  /* check for errors */
-               printf("Could not open script.\n");
-               return NULL;        /* return with exit code indicating error */
-       }
-
-       /* Read script output from the pipe line by line */
-       linenr = 1;
-       while (fgets(line, LINE_BUFSIZE, pipe) != NULL) {
-               printf("Script output line %d: %s", linenr, line);
-               ++linenr;
-
-               pclose(pipe); /* Close the pipe */
-               return strdup(line);
-       }
-
-       /* Once here, out of the loop, the script has ended. */
-       pclose(pipe); /* Close the pipe */
-       return NULL;     /* return with exit code indicating success. */
-}
-
-int notification_delay_period_changed(sr_val_t *val, size_t count)
-{
-       char *stringConfiguration = readConfigFileInString();
-
-       if (stringConfiguration == NULL)
-       {
-               printf("Could not read configuration file!\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
-       if (jsonConfig == NULL)
-       {
-               free(stringConfiguration);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-               }
-               return SR_ERR_OPERATION_FAILED;
-       }
-       //we don't need the string anymore
-       free(stringConfiguration);
-       stringConfiguration = NULL;
-
-       cJSON *notifConfig = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
-       if (!cJSON_IsObject(notifConfig))
-       {
-               printf("Configuration JSON is not as expected: notification-config is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *faultNotifDelay = cJSON_GetObjectItemCaseSensitive(notifConfig, "fault-notification-delay-period");
-       if (!cJSON_IsArray(faultNotifDelay))
-       {
-               printf("Configuration JSON is not as expected: fault-notification-delay-period is not an array.");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-    cJSON_DeleteItemFromObject(notifConfig, "fault-notification-delay-period");
-
-    faultNotifDelay = NULL;
-
-    faultNotifDelay = cJSON_CreateArray();
-    if (faultNotifDelay == NULL) 
-    {
-        cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-    }
-    cJSON_AddItemToObject(notifConfig, "fault-notification-delay-period", faultNotifDelay);
-
-    if (val != NULL && count > 0)
-    {
-        cJSON *arrayEntry = NULL;
-        for (size_t i=0; i<count; ++i)
-        {
-            arrayEntry = cJSON_CreateNumber(val[i].data.uint32_val);
-            if (arrayEntry == NULL) 
-            {
-                cJSON_Delete(jsonConfig);
-                return SR_ERR_OPERATION_FAILED;
-            }
-            cJSON_AddItemToArray(faultNotifDelay, arrayEntry);
-        }
-    }
-    else
-    {
-        cJSON *arrayEntry =  cJSON_CreateNumber(0);
-        if (arrayEntry == NULL) 
-        {
-            cJSON_Delete(jsonConfig);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        cJSON_AddItemToArray(faultNotifDelay, arrayEntry);
-    }
-
-       //writing the new JSON to the configuration file
-       stringConfiguration = cJSON_Print(jsonConfig);
-       writeConfigFile(stringConfiguration);
-
-    if (stringConfiguration != NULL)
-    {
-        free(stringConfiguration);
-        stringConfiguration = NULL;
-    }
-
-       cJSON_Delete(jsonConfig);
-
-       return SR_ERR_OK;
-}
-
-int ves_heartbeat_period_changed(int period)
-{
-       char *stringConfiguration = readConfigFileInString();
-
-       if (stringConfiguration == NULL)
-       {
-               printf("Could not read configuration file!\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
-       if (jsonConfig == NULL)
-       {
-               free(stringConfiguration);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-               }
-               return SR_ERR_OPERATION_FAILED;
-       }
-       //we don't need the string anymore
-       free(stringConfiguration);
-       stringConfiguration = NULL;
-
-       cJSON *notifConfig = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
-       if (!cJSON_IsObject(notifConfig))
-       {
-               printf("Configuration JSON is not as expected: notification-config is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *vesHeartbeatPeriod = cJSON_GetObjectItemCaseSensitive(notifConfig, "ves-heartbeat-period");
-       if (!cJSON_IsNumber(vesHeartbeatPeriod))
-       {
-               printf("Configuration JSON is not as expected: ves-heartbeat-period is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       //we set the value of the fault-notification-delay-period object
-       cJSON_SetNumberValue(vesHeartbeatPeriod, period);
-
-       //writing the new JSON to the configuration file
-       stringConfiguration = cJSON_Print(jsonConfig);
-       writeConfigFile(stringConfiguration);
-
-    if (stringConfiguration != NULL)
-    {
-        free(stringConfiguration);
-        stringConfiguration = NULL;
-    }
-
-       cJSON_Delete(jsonConfig);
-
-       return SR_ERR_OK;
-}
-
-static int add_keystore_entry_odl(char *url, char *credentials)
-{
-       CURLcode res;
-
-       curl_easy_reset(curl_odl);
-       set_curl_common_info_odl();
-
-       char url_for_curl[200];
-       sprintf(url_for_curl, "%s", url);
-
-       curl_easy_setopt(curl_odl, CURLOPT_URL, url_for_curl);
-
-       char post_data_xml[2000];
-
-       sprintf(post_data_xml,
-                       "<input xmlns=\"urn:opendaylight:netconf:keystore\">"
-                       "<key-credential>"
-                       "<key-id>device-key</key-id>"
-                       "<private-key>MIIEpAIBAAKCAQEAueCQaNQWoNmFK6LKu1p8U8ZWdWg/PvDdLsJyzfzl/Qw4UA68"
-                       "SfFNaY06zZl8QB9W02nr5kWeeMY0VA3adrPgOlvfx3oWlFbkETnMaN4OT3WTQ0Wt"
-                       "6jAWZDzVfopwpJPAzRPxACDftIqFGagYcF32hZlVNqqnVdbXh0S0EViweqp/dbG4"
-                       "VDUHSNVbglc+u4UbEzNIFXMdEFsJZpkynOmSiTsIATqIhb+2srkVgLwhfkC2qkuH"
-                       "QwAHdubuB07ObM2z01UhyEdDvEYGHwtYAGDBL2TAcsI0oGeVkRyuOkV0QY0UN7UE"
-                       "FI1yTYw+xZ42HgFx3uGwApCImxhbj69GBYWFqwIDAQABAoIBAQCZN9kR8DGu6V7y"
-                       "t0Ax68asL8O5B/OKaHWKQ9LqpVrXmikZJOxkbzoGldow/CIFoU+q+Zbwu9aDa65a"
-                       "0wiP7Hoa4Py3q5XNNUrOQDyU/OYC7cI0I83WS0lJ2zOJGYj8wKae5Z81IeQFKGHK"
-                       "4lsy1OGPAvPRGh7RjUUgRavA2MCwe07rWRuDb/OJFe4Oh56UMEjwMiNBtMNtncog"
-                       "j1vr/qgRJdf9tf0zlJmLvUJ9+HSFFV9I/97LJyFhb95gAfHkjdVroLVgT3Cho+4P"
-                       "WtZaKCIGD0OwfOG2nLV4leXvRUk62/LMlB8NI9+JF7Xm+HCKbaWHNWC7mvWSLV58"
-                       "Zl4AbUWRAoGBANyJ6SFHFRHSPDY026SsdMzXR0eUxBAK7G70oSBKKhY+O1j0ocLE"
-                       "jI2krHJBhHbLlnvJVyMUaCUOTS5m0uDw9hgSsAqeSL3hL38kxVZw+KNG9Ouno1Fl"
-                       "KnE/xXHlPQyeGs/P8nAMzHZxQtEsQdQayJEhK2XXHTsy7Q3MxDisfVJ1AoGBANfD"
-                       "34gB+OMx6pwj7zk3qWbYXSX8xjCZMR0ciko+h4xeMP2N8B0oyoqC+v1ABMAtJ3wG"
-                       "sGZd0hV9gwM7OUM3SEwkn6oeg1GemWLcn4rlSmTnZc4aeVwrEWlnSNFX3s4g9l4u"
-                       "k8Ugu4MVJYqH8HuDQ5Ggl6/QAwPzMSEdCW0O+jOfAoGAIBRbegC5+t6m7Yegz4Ja"
-                       "dxV1g98K6f58x+MDsQu4tYWV4mmrQgaPH2dtwizvlMwmdpkh+LNWNtWuumowkJHc"
-                       "akIFo3XExQIFg6wYnGtQb4e5xrGa2xMpKlIJaXjb+YLiCYqJDG2ALFZrTrvuU2kV"
-                       "9a5qfqTc1qigvNolTM0iaaUCgYApmrZWhnLUdEKV2wP813PNxfioI4afxlpHD8LG"
-                       "sCn48gymR6E+Lihn7vuwq5B+8fYEH1ISWxLwW+RQUjIneNhy/jjfV8TgjyFqg7or"
-                       "0Sy4KjpiNI6kLBXOakELRNNMkeSPopGR2E7v5rr3bGD9oAD+aqX1G7oJH/KgPPYd"
-                       "Vl7+ZwKBgQDcHyWYrimjyUgKaQD2GmoO9wdcJYQ59ke9K+OuGlp4ti5arsi7N1tP"
-                       "B4f09aeELM2ASIuk8Q/Mx0jQFnm8lzRFXdewgvdPoZW/7VufM9O7dGPOc41cm2Dh"
-                       "yrTcXx/VmUBb+/fnXVEgCv7gylp/wtdTGHQBQJHR81jFBz0lnLj+gg==</private-key>"
-                       "<passphrase></passphrase>"
-                       "</key-credential>"
-                       "</input>");
-
-       printf("Post data:\n%s\n", post_data_xml);
-
-       curl_easy_setopt(curl_odl, CURLOPT_POSTFIELDS, post_data_xml);
-       curl_easy_setopt(curl_odl, CURLOPT_CUSTOMREQUEST, "POST");
-       curl_easy_setopt(curl_odl, CURLOPT_USERPWD, credentials);
-
-       res = curl_easy_perform(curl_odl);
-       if (res != CURLE_OK)
-       {
-               printf("cURL failed to url=%s\n", url_for_curl);
-       }
-
-       long http_response_code = 0;
-       curl_easy_getinfo (curl_odl, CURLINFO_RESPONSE_CODE, &http_response_code);
-       if (http_response_code >= 200 && http_response_code <= 226 && http_response_code != CURLE_ABORTED_BY_CALLBACK)
-       {
-               printf("cURL succeeded to url=%s\n", url_for_curl);
-       }
-       else
-       {
-               printf("cURL to url=%s failed with code=%ld\n", url_for_curl, http_response_code);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       return SR_ERR_OK;
-}
-
-static int add_private_key_odl(char *url, char *credentials)
-{
-       CURLcode res;
-
-       curl_easy_reset(curl_odl);
-       set_curl_common_info_odl();
-
-       char url_for_curl[200];
-       sprintf(url_for_curl, "%s", url);
-
-       curl_easy_setopt(curl_odl, CURLOPT_URL, url_for_curl);
-
-       char post_data_xml[4000];
-
-       sprintf(post_data_xml,
-                       "<input xmlns=\"urn:opendaylight:netconf:keystore\">"
-                       "<private-key>"
-                       "<name>device-key</name>"
-                       "<data>MIIEpAIBAAKCAQEAueCQaNQWoNmFK6LKu1p8U8ZWdWg/PvDdLsJyzfzl/Qw4UA68SfFNaY06zZl8QB9W02nr5kWeeMY0VA3adrPgOlvfx3oWlFbkETnMaN4OT3WTQ0Wt6jAWZDzVfopwpJPAzRPxACDftIqFGagYcF32hZlVNqqnVdbXh0S0EViweqp/dbG4VDUHSNVbglc+u4UbEzNIFXMdEFsJZpkynOmSiTsIATqIhb+2srkVgLwhfkC2qkuHQwAHdubuB07ObM2z01UhyEdDvEYGHwtYAGDBL2TAcsI0oGeVkRyuOkV0QY0UN7UEFI1yTYw+xZ42HgFx3uGwApCImxhbj69GBYWFqwIDAQABAoIBAQCZN9kR8DGu6V7yt0Ax68asL8O5B/OKaHWKQ9LqpVrXmikZJOxkbzoGldow/CIFoU+q+Zbwu9aDa65a0wiP7Hoa4Py3q5XNNUrOQDyU/OYC7cI0I83WS0lJ2zOJGYj8wKae5Z81IeQFKGHK4lsy1OGPAvPRGh7RjUUgRavA2MCwe07rWRuDb/OJFe4Oh56UMEjwMiNBtMNtncogj1vr/qgRJdf9tf0zlJmLvUJ9+HSFFV9I/97LJyFhb95gAfHkjdVroLVgT3Cho+4PWtZaKCIGD0OwfOG2nLV4leXvRUk62/LMlB8NI9+JF7Xm+HCKbaWHNWC7mvWSLV58Zl4AbUWRAoGBANyJ6SFHFRHSPDY026SsdMzXR0eUxBAK7G70oSBKKhY+O1j0ocLEjI2krHJBhHbLlnvJVyMUaCUOTS5m0uDw9hgSsAqeSL3hL38kxVZw+KNG9Ouno1FlKnE/xXHlPQyeGs/P8nAMzHZxQtEsQdQayJEhK2XXHTsy7Q3MxDisfVJ1AoGBANfD34gB+OMx6pwj7zk3qWbYXSX8xjCZMR0ciko+h4xeMP2N8B0oyoqC+v1ABMAtJ3wGsGZd0hV9gwM7OUM3SEwkn6oeg1GemWLcn4rlSmTnZc4aeVwrEWlnSNFX3s4g9l4uk8Ugu4MVJYqH8HuDQ5Ggl6/QAwPzMSEdCW0O+jOfAoGAIBRbegC5+t6m7Yegz4JadxV1g98K6f58x+MDsQu4tYWV4mmrQgaPH2dtwizvlMwmdpkh+LNWNtWuumowkJHcakIFo3XExQIFg6wYnGtQb4e5xrGa2xMpKlIJaXjb+YLiCYqJDG2ALFZrTrvuU2kV9a5qfqTc1qigvNolTM0iaaUCgYApmrZWhnLUdEKV2wP813PNxfioI4afxlpHD8LGsCn48gymR6E+Lihn7vuwq5B+8fYEH1ISWxLwW+RQUjIneNhy/jjfV8TgjyFqg7or0Sy4KjpiNI6kLBXOakELRNNMkeSPopGR2E7v5rr3bGD9oAD+aqX1G7oJH/KgPPYdVl7+ZwKBgQDcHyWYrimjyUgKaQD2GmoO9wdcJYQ59ke9K+OuGlp4ti5arsi7N1tPB4f09aeELM2ASIuk8Q/Mx0jQFnm8lzRFXdewgvdPoZW/7VufM9O7dGPOc41cm2DhyrTcXx/VmUBb+/fnXVEgCv7gylp/wtdTGHQBQJHR81jFBz0lnLj+gg==</data>"
-                       "<certificate-chain>MIIECTCCAvGgAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBjDELMAkGA1UEBhMCQ1oxFjAUBgNVBAgMDVNvdXRoIE1vcmF2aWExDTALBgNVBAcMBEJybm8xDzANBgNVBAoMBkNFU05FVDEMMAoGA1UECwwDVE1DMRMwEQYDVQQDDApleGFtcGxlIENBMSIwIAYJKoZIhvcNAQkBFhNleGFtcGxlY2FAbG9jYWxob3N0MB4XDTE1MDczMDA3MjcxOFoXDTM1MDcyNTA3MjcxOFowgYUxCzAJBgNVBAYTAkNaMRYwFAYDVQQIDA1Tb3V0aCBNb3JhdmlhMQ8wDQYDVQQKDAZDRVNORVQxDDAKBgNVBAsMA1RNQzEXMBUGA1UEAwwOZXhhbXBsZSBjbGllbnQxJjAkBgkqhkiG9w0BCQEWF2V4YW1wbGVjbGllbnRAbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAueCQaNQWoNmFK6LKu1p8U8ZWdWg/PvDdLsJyzfzl/Qw4UA68SfFNaY06zZl8QB9W02nr5kWeeMY0VA3adrPgOlvfx3oWlFbkETnMaN4OT3WTQ0Wt6jAWZDzVfopwpJPAzRPxACDftIqFGagYcF32hZlVNqqnVdbXh0S0EViweqp/dbG4VDUHSNVbglc+u4UbEzNIFXMdEFsJZpkynOmSiTsIATqIhb+2srkVgLwhfkC2qkuHQwAHdubuB07ObM2z01UhyEdDvEYGHwtYAGDBL2TAcsI0oGeVkRyuOkV0QY0UN7UEFI1yTYw+xZ42HgFx3uGwApCImxhbj69GBYWFqwIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUXGpLeLnh2cSDARAVA7KrBxGYpo8wHwYDVR0jBBgwFoAUc1YQIqjZsHVwlea0AB4N+ilNI2gwDQYJKoZIhvcNAQELBQADggEBAJPV3RTXFRtNyOU4rjPpYeBAIAFp2aqGc4t2J1c7oPp/1n+lZvjnwtlJpZHxMM783e2ryDQ6dkvXDf8kpwKlg3U3mkJ3xKkDdWrM4QwghXdCN519aa9qmu0zdFL+jUAaWlQ5tsceOrvbusCcbMqiFGk/QfpHqPv52SVWbYyUx7IX7DE+UjgsLHycfV/tlcx4ZE6soTzl9VdgSL/zmzG3rjsr58J80rXckLgBhvijgBlIAJvWfC7D0vaouvBInSFXymdPVoUDZ30cdGLf+hI/i/TfsEMOinLrXVdkSGNo6FXAHKSvXeB9oFKSzhQ7OPyRyqvEPycUSw/qD6FVr80oDDc=</certificate-chain>"
-                       "</private-key>"
-                       "</input>");
-
-       printf("Post data:\n%s\n", post_data_xml);
-
-       curl_easy_setopt(curl_odl, CURLOPT_POSTFIELDS, post_data_xml);
-       curl_easy_setopt(curl_odl, CURLOPT_CUSTOMREQUEST, "POST");
-       curl_easy_setopt(curl_odl, CURLOPT_USERPWD, credentials);
-
-       res = curl_easy_perform(curl_odl);
-       if (res != CURLE_OK)
-       {
-               printf("cURL failed to url=%s\n", url_for_curl);
-       }
-
-       long http_response_code = 0;
-       curl_easy_getinfo (curl_odl, CURLINFO_RESPONSE_CODE, &http_response_code);
-       if (http_response_code >= 200 && http_response_code <= 226 && http_response_code != CURLE_ABORTED_BY_CALLBACK)
-       {
-               printf("cURL succeeded to url=%s\n", url_for_curl);
-       }
-       else
-       {
-               printf("cURL to url=%s failed with code=%ld\n", url_for_curl, http_response_code);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       return SR_ERR_OK;
-}
-
-static int add_trusted_ca_odl(char *url, char *credentials)
-{
-       CURLcode res;
-
-       curl_easy_reset(curl_odl);
-       set_curl_common_info_odl();
-
-       char url_for_curl[200];
-       sprintf(url_for_curl, "%s", url);
-
-       curl_easy_setopt(curl_odl, CURLOPT_URL, url_for_curl);
-
-       char post_data_xml[2000];
-
-       sprintf(post_data_xml,
-                       "<input xmlns=\"urn:opendaylight:netconf:keystore\">"
-                       "<trusted-certificate>"
-                       "<name>test_trusted_cert</name>"
-                       "<certificate>MIID7TCCAtWgAwIBAgIJAMtE1NGAR5KoMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJDWjEWMBQGA1UECAwNU291dGggTW9yYXZpYTENMAsGA1UEBwwEQnJubzEPMA0GA1UECgwGQ0VTTkVUMQwwCgYDVQQLDANUTUMxEzARBgNVBAMMCmV4YW1wbGUgQ0ExIjAgBgkqhkiG9w0BCQEWE2V4YW1wbGVjYUBsb2NhbGhvc3QwHhcNMTQwNzI0MTQxOTAyWhcNMjQwNzIxMTQxOTAyWjCBjDELMAkGA1UEBhMCQ1oxFjAUBgNVBAgMDVNvdXRoIE1vcmF2aWExDTALBgNVBAcMBEJybm8xDzANBgNVBAoMBkNFU05FVDEMMAoGA1UECwwDVE1DMRMwEQYDVQQDDApleGFtcGxlIENBMSIwIAYJKoZIhvcNAQkBFhNleGFtcGxlY2FAbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArD3TDHPAMT2Z84orK4lMlarbgooIUCcRZyLe+QM+8KY8Hn+mGaxPEOTSL3ywszqefB/Utm2hPKLHX684iRC14ID9WDGHxPjvoPArhgFhfV+qnPfxKTgxZC12uOj4u1V9y+SkTCocFbRfXVBGpojrBuDHXkDMDEWNvr8/52YCv7bGaiBwUHolcLCUbmtKILCG0RNJyTaJpXQdAeq5Z1SJotpbfYFFtAXB32hVoLug1dzl2tjG9sb1wq3QaDExcbC5w6P65qOkNoyym9ne6QlQagCqVDyFn3vcqkRaTjvZmxauCeUxXgJoXkyWcm0lM1KMHdoTArmchw2Dz0yHHSyDAQIDAQABo1AwTjAdBgNVHQ4EFgQUc1YQIqjZsHVwlea0AB4N+ilNI2gwHwYDVR0jBBgwFoAUc1YQIqjZsHVwlea0AB4N+ilNI2gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAI/1KH60qnw9Xs2RGfi0/IKf5EynXt4bQX8EIyVKwSkYKe04zZxYfLIl/Q2HOPYoFmm3daj5ddr0ZS1i4p4fTUhstjsYWvXs3W/HhVmFUslakkn3PrswhP77fCk6eEJLxdfyJ1C7Uudq2m1isZbKih+XF0mG1LxJaDMocSz4eAya7M5brwjy8DoOmA1TnLQFCVcpn+sCr7VC4wE/JqxyVhBCk/MuGqqM3B1j90bGFZ112ZOecyE0EDSr6IbiRBtmeNbEwOFjKXhNLYdxpBZ9D8A/368OckZkCrVLGuJNxK9UwCVTe8IhotHUqU9EqFDmxdV8oIdU/OzUwwNPA/Bd/9g==</certificate>"
-                       "</trusted-certificate>"
-                       "</input>");
-
-       printf("Post data:\n%s\n", post_data_xml);
-
-       curl_easy_setopt(curl_odl, CURLOPT_POSTFIELDS, post_data_xml);
-       curl_easy_setopt(curl_odl, CURLOPT_CUSTOMREQUEST, "POST");
-       curl_easy_setopt(curl_odl, CURLOPT_USERPWD, credentials);
-
-       res = curl_easy_perform(curl_odl);
-       if (res != CURLE_OK)
-       {
-               printf("cURL failed to url=%s\n", url_for_curl);
-       }
-
-       long http_response_code = 0;
-       curl_easy_getinfo (curl_odl, CURLINFO_RESPONSE_CODE, &http_response_code);
-       if (http_response_code >= 200 && http_response_code <= 226 && http_response_code != CURLE_ABORTED_BY_CALLBACK)
-       {
-               printf("cURL succeeded to url=%s\n", url_for_curl);
-       }
-       else
-       {
-               printf("cURL to url=%s failed with code=%ld\n", url_for_curl, http_response_code);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       return SR_ERR_OK;
-}
-
-int add_key_pair_to_odl(controller_t *controller_list, int controller_list_size)
-{
-       int rc = SR_ERR_OK;
-
-       rc = add_keystore_entry_odl(controller_list[0].url_for_keystore_add, controller_list[0].credentials);
-       if (rc != SR_ERR_OK)
-       {
-               printf("Failed to add keystore entry to ODL.\n");
-       }
-
-       rc = add_private_key_odl(controller_list[0].url_for_private_key_add, controller_list[0].credentials);
-       if (rc != SR_ERR_OK)
-       {
-               printf("Failed to add private key entry to ODL.\n");
-       }
-
-       rc = add_trusted_ca_odl(controller_list[0].url_for_trusted_ca_add, controller_list[0].credentials);
-       if (rc != SR_ERR_OK)
-       {
-               printf("Failed to add trusted CA entry to ODL.\n");
-       }
-
-       return SR_ERR_OK;
-}
-
-int ves_ip_changed(char *new_ip)
-{
-    char *stringConfiguration = readConfigFileInString();
-
-    if (stringConfiguration == NULL)
-    {
-        printf("Could not read configuration file!\n");
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
-    if (jsonConfig == NULL)
-    {
-        free(stringConfiguration);
-        const char *error_ptr = cJSON_GetErrorPtr();
-        if (error_ptr != NULL)
-        {
-            fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-        }
-        return SR_ERR_OPERATION_FAILED;
-    }
-    //we don't need the string anymore
-    free(stringConfiguration);
-    stringConfiguration = NULL;
-
-    cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
-    if (!cJSON_IsObject(vesDetails))
-    {
-        printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
-        cJSON_Delete(jsonConfig);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    cJSON *vesIp = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-ip");
-    if (!cJSON_IsString(vesIp))
-    {
-        printf("Configuration JSON is not as expected: ves-endpoint-ip is not a string");
-        cJSON_Delete(jsonConfig);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    //we set the value of the fault-notification-delay-period object
-    cJSON_ReplaceItemInObject(vesDetails, "ves-endpoint-ip", cJSON_CreateString(new_ip));
-
-    //writing the new JSON to the configuration file
-    stringConfiguration = cJSON_Print(jsonConfig);
-    writeConfigFile(stringConfiguration);
-
-    if (stringConfiguration != NULL)
-    {
-        free(stringConfiguration);
-        stringConfiguration = NULL;
-    }
-
-    cJSON_Delete(jsonConfig);
-
-    return SR_ERR_OK;
-}
-
-int ves_port_changed(int new_port)
-{
-       char *stringConfiguration = readConfigFileInString();
-
-       if (stringConfiguration == NULL)
-       {
-               printf("Could not read configuration file!\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
-       if (jsonConfig == NULL)
-       {
-               free(stringConfiguration);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-               }
-               return SR_ERR_OPERATION_FAILED;
-       }
-       //we don't need the string anymore
-       free(stringConfiguration);
-       stringConfiguration = NULL;
-
-       cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
-       if (!cJSON_IsObject(vesDetails))
-       {
-               printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *vesPort = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-port");
-       if (!cJSON_IsNumber(vesPort))
-       {
-               printf("Configuration JSON is not as expected: ves-endpoint-port is not a number.");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       //we set the value of the fault-notification-delay-period object
-       cJSON_SetNumberValue(vesPort, new_port);
-
-       //writing the new JSON to the configuration file
-       stringConfiguration = cJSON_Print(jsonConfig);
-       writeConfigFile(stringConfiguration);
-
-    if (stringConfiguration != NULL)
-    {
-        free(stringConfiguration);
-        stringConfiguration = NULL;
-    }
-
-       cJSON_Delete(jsonConfig);
-
-       return SR_ERR_OK;
-}
-
-int ves_username_changed(char *new_username)
-{
-    char *stringConfiguration = readConfigFileInString();
-
-    if (stringConfiguration == NULL)
-    {
-        printf("Could not read configuration file!\n");
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
-    if (jsonConfig == NULL)
-    {
-        free(stringConfiguration);
-        const char *error_ptr = cJSON_GetErrorPtr();
-        if (error_ptr != NULL)
-        {
-            fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-        }
-        return SR_ERR_OPERATION_FAILED;
-    }
-    //we don't need the string anymore
-    free(stringConfiguration);
-    stringConfiguration = NULL;
-
-    cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
-    if (!cJSON_IsObject(vesDetails))
-    {
-        printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
-        cJSON_Delete(jsonConfig);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    cJSON *vesUsername = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-username");
-    if (!cJSON_IsString(vesUsername))
-    {
-        printf("Configuration JSON is not as expected: ves-endpoint-username is not a string");
-        cJSON_Delete(jsonConfig);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    //we set the value of the fault-notification-delay-period object
-    cJSON_ReplaceItemInObject(vesDetails, "ves-endpoint-username", cJSON_CreateString(new_username));
-
-    //writing the new JSON to the configuration file
-    stringConfiguration = cJSON_Print(jsonConfig);
-    writeConfigFile(stringConfiguration);
-
-    if (stringConfiguration != NULL)
-    {
-        free(stringConfiguration);
-        stringConfiguration = NULL;
-    }
-
-    cJSON_Delete(jsonConfig);
-
-    return SR_ERR_OK;
-}
-
-int ves_password_changed(char *new_password)
-{
-    char *stringConfiguration = readConfigFileInString();
-
-    if (stringConfiguration == NULL)
-    {
-        printf("Could not read configuration file!\n");
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
-    if (jsonConfig == NULL)
-    {
-        free(stringConfiguration);
-        const char *error_ptr = cJSON_GetErrorPtr();
-        if (error_ptr != NULL)
-        {
-            fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-        }
-        return SR_ERR_OPERATION_FAILED;
-    }
-    //we don't need the string anymore
-    free(stringConfiguration);
-    stringConfiguration = NULL;
-
-    cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
-    if (!cJSON_IsObject(vesDetails))
-    {
-        printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
-        cJSON_Delete(jsonConfig);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    cJSON *vesPassword = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-password");
-    if (!cJSON_IsString(vesPassword))
-    {
-        printf("Configuration JSON is not as expected: ves-endpoint-password is not a string");
-        cJSON_Delete(jsonConfig);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    //we set the value of the fault-notification-delay-period object
-    cJSON_ReplaceItemInObject(vesDetails, "ves-endpoint-password", cJSON_CreateString(new_password));
-
-    //writing the new JSON to the configuration file
-    stringConfiguration = cJSON_Print(jsonConfig);
-    writeConfigFile(stringConfiguration);
-
-    if (stringConfiguration != NULL)
-    {
-        free(stringConfiguration);
-        stringConfiguration = NULL;
-    }
-
-    cJSON_Delete(jsonConfig);
-
-    return SR_ERR_OK;
-}
-
-int ves_auth_method_changed(char *new_auth_method)
-{
-    char *stringConfiguration = readConfigFileInString();
-
-    if (stringConfiguration == NULL)
-    {
-        printf("Could not read configuration file!\n");
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
-    if (jsonConfig == NULL)
-    {
-        free(stringConfiguration);
-        const char *error_ptr = cJSON_GetErrorPtr();
-        if (error_ptr != NULL)
-        {
-            fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-        }
-        return SR_ERR_OPERATION_FAILED;
-    }
-    //we don't need the string anymore
-    free(stringConfiguration);
-    stringConfiguration = NULL;
-
-    cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
-    if (!cJSON_IsObject(vesDetails))
-    {
-        printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
-        cJSON_Delete(jsonConfig);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    cJSON *vesAuthMethod = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-auth-method");
-    if (!cJSON_IsString(vesAuthMethod))
-    {
-        printf("Configuration JSON is not as expected: ves-endpoint-auth-method is not a string");
-        cJSON_Delete(jsonConfig);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    //we set the value of the fault-notification-delay-period object
-    cJSON_ReplaceItemInObject(vesDetails, "ves-endpoint-auth-method", cJSON_CreateString(new_auth_method));
-
-    //writing the new JSON to the configuration file
-    stringConfiguration = cJSON_Print(jsonConfig);
-    writeConfigFile(stringConfiguration);
-
-    if (stringConfiguration != NULL)
-    {
-        free(stringConfiguration);
-        stringConfiguration = NULL;
-    }
-
-    cJSON_Delete(jsonConfig);
-
-    return SR_ERR_OK;
-}
-
-int ves_registration_changed(cJSON_bool new_bool)
-{
-       char *stringConfiguration = readConfigFileInString();
-
-       if (stringConfiguration == NULL)
-       {
-               printf("Could not read configuration file!\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
-       if (jsonConfig == NULL)
-       {
-               free(stringConfiguration);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-               }
-               return SR_ERR_OPERATION_FAILED;
-       }
-       //we don't need the string anymore
-       free(stringConfiguration);
-       stringConfiguration = NULL;
-
-       cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
-       if (!cJSON_IsObject(vesDetails))
-       {
-               printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *vesRegistration = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-registration");
-       if (!cJSON_IsBool(vesRegistration))
-       {
-               printf("Configuration JSON is not as expected: ves-registration is not a bool.");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       //we set the value of the ves-registration object
-       cJSON_ReplaceItemInObject(vesDetails, "ves-registration", cJSON_CreateBool(new_bool));
-
-       //writing the new JSON to the configuration file
-       stringConfiguration = cJSON_Print(jsonConfig);
-       writeConfigFile(stringConfiguration);
-
-    if (stringConfiguration != NULL)
-    {
-        free(stringConfiguration);
-        stringConfiguration = NULL;
-    }
-
-       cJSON_Delete(jsonConfig);
-
-       return SR_ERR_OK;
-}
-
-int is_netconf_available_changed(cJSON_bool new_bool)
-{
-       char *stringConfiguration = readConfigFileInString();
-
-       if (stringConfiguration == NULL)
-       {
-               printf("Could not read configuration file!\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
-       if (jsonConfig == NULL)
-       {
-               free(stringConfiguration);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-               }
-               return SR_ERR_OPERATION_FAILED;
-       }
-       //we don't need the string anymore
-       free(stringConfiguration);
-       stringConfiguration = NULL;
-
-       cJSON *notifConfig = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
-       if (!cJSON_IsObject(notifConfig))
-       {
-               printf("Configuration JSON is not as expected: notification-config is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *isNetconfAvailable = cJSON_GetObjectItemCaseSensitive(notifConfig, "is-netconf-available");
-       if (!cJSON_IsBool(isNetconfAvailable))
-       {
-               printf("Configuration JSON is not as expected: is-netconf-available is not a bool.");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       //we set the value of the ves-registration object
-       cJSON_ReplaceItemInObject(notifConfig, "is-netconf-available", cJSON_CreateBool(new_bool));
-
-       //writing the new JSON to the configuration file
-       stringConfiguration = cJSON_Print(jsonConfig);
-       writeConfigFile(stringConfiguration);
-
-    if (stringConfiguration != NULL)
-    {
-        free(stringConfiguration);
-        stringConfiguration = NULL;
-    }
-
-       cJSON_Delete(jsonConfig);
-
-       return SR_ERR_OK;
-}
-
-int is_ves_available_changed(cJSON_bool new_bool)
-{
-       char *stringConfiguration = readConfigFileInString();
-
-       if (stringConfiguration == NULL)
-       {
-               printf("Could not read configuration file!\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
-       if (jsonConfig == NULL)
-       {
-               free(stringConfiguration);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-               }
-               return SR_ERR_OPERATION_FAILED;
-       }
-       //we don't need the string anymore
-       free(stringConfiguration);
-       stringConfiguration = NULL;
-
-       cJSON *notifConfig = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
-       if (!cJSON_IsObject(notifConfig))
-       {
-               printf("Configuration JSON is not as expected: notification-config is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *isVesAvailable = cJSON_GetObjectItemCaseSensitive(notifConfig, "is-ves-available");
-       if (!cJSON_IsBool(isVesAvailable))
-       {
-               printf("Configuration JSON is not as expected: is-ves-available is not a bool.");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       //we set the value of the ves-registration object
-       cJSON_ReplaceItemInObject(notifConfig, "is-ves-available", cJSON_CreateBool(new_bool));
-
-       //writing the new JSON to the configuration file
-       stringConfiguration = cJSON_Print(jsonConfig);
-       writeConfigFile(stringConfiguration);
-
-    if (stringConfiguration != NULL)
-    {
-        free(stringConfiguration);
-        stringConfiguration = NULL;
-    }
-
-       cJSON_Delete(jsonConfig);
-
-       return SR_ERR_OK;
-}
-
-    int ssh_connections_changed(int number)
-    {
-    char *stringConfiguration = readConfigFileInString();
-
-    if (stringConfiguration == NULL)
-    {
-        printf("Could not read configuration file!\n");
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
-    if (jsonConfig == NULL)
-    {
-        free(stringConfiguration);
-        const char *error_ptr = cJSON_GetErrorPtr();
-        if (error_ptr != NULL)
-        {
-            fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-        }
-        return SR_ERR_OPERATION_FAILED;
-    }
-    //we don't need the string anymore
-    free(stringConfiguration);
-    stringConfiguration = NULL;
-
-    cJSON *sshConnections = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ssh-connections");
-    if (!cJSON_IsNumber(sshConnections))
-    {
-        printf("Configuration JSON is not as expected: ssh-connections is not an object");
-        cJSON_Delete(jsonConfig);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    //we set the value of the ssh-connections object
-    cJSON_SetNumberValue(sshConnections, number);
-
-    //writing the new JSON to the configuration file
-    stringConfiguration = cJSON_Print(jsonConfig);
-    writeConfigFile(stringConfiguration);
-
-    if (stringConfiguration != NULL)
-    {
-        free(stringConfiguration);
-        stringConfiguration = NULL;
-    }
-
-    cJSON_Delete(jsonConfig);
-
-    return SR_ERR_OK;
-}
-
-int tls_connections_changed(int number)
-    {
-    char *stringConfiguration = readConfigFileInString();
-
-    if (stringConfiguration == NULL)
-    {
-        printf("Could not read configuration file!\n");
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
-    if (jsonConfig == NULL)
-    {
-        free(stringConfiguration);
-        const char *error_ptr = cJSON_GetErrorPtr();
-        if (error_ptr != NULL)
-        {
-            fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-        }
-        return SR_ERR_OPERATION_FAILED;
-    }
-    //we don't need the string anymore
-    free(stringConfiguration);
-    stringConfiguration = NULL;
-
-    cJSON *tlsConnections = cJSON_GetObjectItemCaseSensitive(jsonConfig, "tls-connections");
-    if (!cJSON_IsNumber(tlsConnections))
-    {
-        printf("Configuration JSON is not as expected: tls-connections is not an object");
-        cJSON_Delete(jsonConfig);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    //we set the value of the tls-connections object
-    cJSON_SetNumberValue(tlsConnections, number);
-
-    //writing the new JSON to the configuration file
-    stringConfiguration = cJSON_Print(jsonConfig);
-    writeConfigFile(stringConfiguration);
-
-    if (stringConfiguration != NULL)
-    {
-        free(stringConfiguration);
-        stringConfiguration = NULL;
-    }
-
-    cJSON_Delete(jsonConfig);
-
-    return SR_ERR_OK;
-}
-
-/*
-curl -X POST -H 'Content-Type: application/json' -i http://localhost:5000/extend-ports --data '{"number-of-ports":12}'
-*/
-int send_k8s_extend_port(void)
-{
-    int num_of_ports = getSshConnectionsFromConfigJson() + getTlsConnectionsFromConfigJson();
-
-    CURLcode res;
-
-    curl_easy_reset(curl_k8s);
-    set_curl_common_info_k8s();
-
-    char url_for_curl[100];
-    sprintf(url_for_curl, "http://localhost:5000/extend-ports");
-
-    curl_easy_setopt(curl_k8s, CURLOPT_URL, url_for_curl);
-
-    char post_data_json[1500];
-
-    sprintf(post_data_json,
-            "{\"number-of-ports\":%d}",
-            num_of_ports);
-
-    printf("Post data:\n%s\n", post_data_json);
-
-    curl_easy_setopt(curl_k8s, CURLOPT_POSTFIELDS, post_data_json);
-    curl_easy_setopt(curl_k8s, CURLOPT_CUSTOMREQUEST, "POST");
-
-    res = curl_easy_perform(curl_k8s);
-    if (res != CURLE_OK)
-    {
-        printf("cURL failed to url=%s\n", url_for_curl);
-    }
-
-    long http_response_code = 0;
-    curl_easy_getinfo (curl_k8s, CURLINFO_RESPONSE_CODE, &http_response_code);
-    if (http_response_code >= 200 && http_response_code <= 226 && http_response_code != CURLE_ABORTED_BY_CALLBACK)
-    {
-        printf("cURL succeeded to url=%s\n", url_for_curl);
-    }
-    else
-    {
-        printf("cURL to url=%s failed with code=%ld\n", url_for_curl, http_response_code);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    return SR_ERR_OK;
-}
-
-/*
-curl -X POST -H 'Content-Type: application/json' -i http://localhost:5000/scale --data '{"simulatedDevices":2}'
-*/
-int send_k8s_scale(int number_of_devices)
-{
-    CURLcode res;
-
-    curl_easy_reset(curl_k8s);
-    set_curl_common_info_k8s();
-
-    char url_for_curl[100];
-    sprintf(url_for_curl, "http://localhost:5000/scale");
-
-    curl_easy_setopt(curl_k8s, CURLOPT_URL, url_for_curl);
-
-    char post_data_json[1500];
-
-    sprintf(post_data_json,
-            "{\"simulatedDevices\":%d}",
-            number_of_devices);
-
-    printf("Post data:\n%s\n", post_data_json);
-
-    curl_easy_setopt(curl_k8s, CURLOPT_POSTFIELDS, post_data_json);
-    curl_easy_setopt(curl_k8s, CURLOPT_CUSTOMREQUEST, "POST");
-
-    res = curl_easy_perform(curl_k8s);
-    if (res != CURLE_OK)
-    {
-        printf("cURL failed to url=%s\n", url_for_curl);
-    }
-
-    long http_response_code = 0;
-    curl_easy_getinfo (curl_k8s, CURLINFO_RESPONSE_CODE, &http_response_code);
-    if (http_response_code >= 200 && http_response_code <= 226 && http_response_code != CURLE_ABORTED_BY_CALLBACK)
-    {
-        printf("cURL succeeded to url=%s\n", url_for_curl);
-    }
-    else
-    {
-        printf("cURL to url=%s failed with code=%ld\n", url_for_curl, http_response_code);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    return SR_ERR_OK;
-}
-
-int controller_ip_changed(char *new_ip)
-{
-       char *stringConfiguration = readConfigFileInString();
-
-       if (stringConfiguration == NULL)
-       {
-               printf("Could not read configuration file!\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
-       if (jsonConfig == NULL)
-       {
-               free(stringConfiguration);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-               }
-               return SR_ERR_OPERATION_FAILED;
-       }
-       //we don't need the string anymore
-       free(stringConfiguration);
-       stringConfiguration = NULL;
-
-       cJSON *controllerDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "controller-details");
-       if (!cJSON_IsObject(controllerDetails))
-       {
-               printf("Configuration JSON is not as expected: controller-details is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *controllerIp = cJSON_GetObjectItemCaseSensitive(controllerDetails, "controller-ip");
-       if (!cJSON_IsString(controllerIp))
-       {
-               printf("Configuration JSON is not as expected: controller-ip is not a string");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       //we set the value of the fault-notification-delay-period object
-       cJSON_ReplaceItemInObject(controllerDetails, "controller-ip", cJSON_CreateString(new_ip));
-
-       //writing the new JSON to the configuration file
-       stringConfiguration = cJSON_Print(jsonConfig);
-       writeConfigFile(stringConfiguration);
-
-    if (stringConfiguration != NULL)
-    {
-        free(stringConfiguration);
-        stringConfiguration = NULL;
-    }
-
-       cJSON_Delete(jsonConfig);
-
-       return SR_ERR_OK;
-}
-
-int controller_port_changed(int new_port)
-{
-       char *stringConfiguration = readConfigFileInString();
-
-       if (stringConfiguration == NULL)
-       {
-               printf("Could not read configuration file!\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
-       if (jsonConfig == NULL)
-       {
-               free(stringConfiguration);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-               }
-               return SR_ERR_OPERATION_FAILED;
-       }
-       //we don't need the string anymore
-       free(stringConfiguration);
-       stringConfiguration = NULL;
-
-       cJSON *controllerDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "controller-details");
-       if (!cJSON_IsObject(controllerDetails))
-       {
-               printf("Configuration JSON is not as expected: controller-details is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *controllerPort = cJSON_GetObjectItemCaseSensitive(controllerDetails, "controller-port");
-       if (!cJSON_IsNumber(controllerPort))
-       {
-               printf("Configuration JSON is not as expected: controller-port is not a number.");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       //we set the value of the fault-notification-delay-period object
-       cJSON_SetNumberValue(controllerPort, new_port);
-
-       //writing the new JSON to the configuration file
-       stringConfiguration = cJSON_Print(jsonConfig);
-       writeConfigFile(stringConfiguration);
-
-    if (stringConfiguration != NULL)
-    {
-        free(stringConfiguration);
-        stringConfiguration = NULL;
-    }
-
-       cJSON_Delete(jsonConfig);
-
-       return SR_ERR_OK;
-}
-
-int controller_netconf_call_home_port_changed(int new_port)
-{
-       char *stringConfiguration = readConfigFileInString();
-
-       if (stringConfiguration == NULL)
-       {
-               printf("Could not read configuration file!\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
-       if (jsonConfig == NULL)
-       {
-               free(stringConfiguration);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-               }
-               return SR_ERR_OPERATION_FAILED;
-       }
-       //we don't need the string anymore
-       free(stringConfiguration);
-       stringConfiguration = NULL;
-
-       cJSON *controllerDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "controller-details");
-       if (!cJSON_IsObject(controllerDetails))
-       {
-               printf("Configuration JSON is not as expected: controller-details is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *netconfCallHomePort = cJSON_GetObjectItemCaseSensitive(controllerDetails, "netconf-call-home-port");
-       if (!cJSON_IsNumber(netconfCallHomePort))
-       {
-               printf("Configuration JSON is not as expected: netconf-call-home-port is not a number.");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       //we set the value of the fault-notification-delay-period object
-       cJSON_SetNumberValue(netconfCallHomePort, new_port);
-
-       //writing the new JSON to the configuration file
-       stringConfiguration = cJSON_Print(jsonConfig);
-       writeConfigFile(stringConfiguration);
-
-    if (stringConfiguration != NULL)
-    {
-        free(stringConfiguration);
-        stringConfiguration = NULL;
-    }
-
-       cJSON_Delete(jsonConfig);
-
-       return SR_ERR_OK;
-}
-
-int controller_username_changed(char *new_username)
-{
-       char *stringConfiguration = readConfigFileInString();
-
-       if (stringConfiguration == NULL)
-       {
-               printf("Could not read configuration file!\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
-       if (jsonConfig == NULL)
-       {
-               free(stringConfiguration);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-               }
-               return SR_ERR_OPERATION_FAILED;
-       }
-       //we don't need the string anymore
-       free(stringConfiguration);
-       stringConfiguration = NULL;
-
-       cJSON *controllerDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "controller-details");
-       if (!cJSON_IsObject(controllerDetails))
-       {
-               printf("Configuration JSON is not as expected: controller-details is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *controllerUsername = cJSON_GetObjectItemCaseSensitive(controllerDetails, "controller-username");
-       if (!cJSON_IsString(controllerUsername))
-       {
-               printf("Configuration JSON is not as expected: controller-username is not a string");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       //we set the value of the fault-notification-delay-period object
-       cJSON_ReplaceItemInObject(controllerDetails, "controller-username", cJSON_CreateString(new_username));
-
-       //writing the new JSON to the configuration file
-       stringConfiguration = cJSON_Print(jsonConfig);
-       writeConfigFile(stringConfiguration);
-
-    if (stringConfiguration != NULL)
-    {
-        free(stringConfiguration);
-        stringConfiguration = NULL;
-    }
-
-       cJSON_Delete(jsonConfig);
-
-       return SR_ERR_OK;
-}
-
-int controller_password_changed(char *new_password)
-{
-       char *stringConfiguration = readConfigFileInString();
-
-       if (stringConfiguration == NULL)
-       {
-               printf("Could not read configuration file!\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
-       if (jsonConfig == NULL)
-       {
-               free(stringConfiguration);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-               }
-               return SR_ERR_OPERATION_FAILED;
-       }
-       //we don't need the string anymore
-       free(stringConfiguration);
-       stringConfiguration = NULL;
-
-       cJSON *controllerDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "controller-details");
-       if (!cJSON_IsObject(controllerDetails))
-       {
-               printf("Configuration JSON is not as expected: controller-details is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *controllerPassword = cJSON_GetObjectItemCaseSensitive(controllerDetails, "controller-password");
-       if (!cJSON_IsString(controllerPassword))
-       {
-               printf("Configuration JSON is not as expected: controller-password is not a string");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       //we set the value of the fault-notification-delay-period object
-       cJSON_ReplaceItemInObject(controllerDetails, "controller-password", cJSON_CreateString(new_password));
-
-       //writing the new JSON to the configuration file
-       stringConfiguration = cJSON_Print(jsonConfig);
-       writeConfigFile(stringConfiguration);
-
-    if (stringConfiguration != NULL)
-    {
-        free(stringConfiguration);
-        stringConfiguration = NULL;
-    }
-
-       cJSON_Delete(jsonConfig);
-
-       return SR_ERR_OK;
-}
-
-int netconf_call_home_changed(cJSON_bool new_bool)
-{
-       char *stringConfiguration = readConfigFileInString();
-
-       if (stringConfiguration == NULL)
-       {
-               printf("Could not read configuration file!\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *jsonConfig = cJSON_Parse(stringConfiguration);
-       if (jsonConfig == NULL)
-       {
-               free(stringConfiguration);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-               }
-               return SR_ERR_OPERATION_FAILED;
-       }
-       //we don't need the string anymore
-       free(stringConfiguration);
-       stringConfiguration = NULL;
-
-       cJSON *netconfCallHome = cJSON_GetObjectItemCaseSensitive(jsonConfig, "netconf-call-home");
-       if (!cJSON_IsBool(netconfCallHome))
-       {
-               printf("Configuration JSON is not as expected: netconf-call-home is not a bool.");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       //we set the value of the ves-registration object
-       cJSON_ReplaceItemInObject(jsonConfig, "netconf-call-home", cJSON_CreateBool(new_bool));
-
-       //writing the new JSON to the configuration file
-       stringConfiguration = cJSON_Print(jsonConfig);
-       writeConfigFile(stringConfiguration);
-
-    if (stringConfiguration != NULL)
-    {
-        free(stringConfiguration);
-        stringConfiguration = NULL;
-    }
-
-       cJSON_Delete(jsonConfig);
-
-       return SR_ERR_OK;
-}
-
-static int start_device_notification(char *exec_id)
-{
-    struct MemoryStruct curl_response_mem;
-
-    curl_response_mem.memory = malloc(1);  /* will be grown as needed by the realloc above */
-    curl_response_mem.size = 0;    /* no data at this point */
-
-    CURLcode res;
-
-    curl_easy_reset(curl);
-    set_curl_common_info();
-
-    char url[500];
-    sprintf(url, "http:/v%s/exec/%s/start", getenv("DOCKER_ENGINE_VERSION"), exec_id);
-
-    curl_easy_setopt(curl, CURLOPT_URL, url);
-
-    cJSON *postDataJson = cJSON_CreateObject();
-
-    if (cJSON_AddFalseToObject(postDataJson, "Detach") == NULL)
-    {
-        printf("Could not create JSON object: Detach\n");
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    if (cJSON_AddFalseToObject(postDataJson, "Tty") == NULL)
-    {
-        printf("Could not create JSON object: Tty\n");
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    char *post_data_string = NULL;
-
-    post_data_string = cJSON_PrintUnformatted(postDataJson);
-
-    printf("Post data JSON:\n%s\n", post_data_string);
-
-    if (postDataJson != NULL)
-    {
-        cJSON_Delete(postDataJson);
-    }
-
-    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data_string);
-
-    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
-
-    res = curl_easy_perform(curl);
-
-    if (post_data_string != NULL)
-    {
-        free(post_data_string);
-    }
-
-    if (res != CURLE_OK)
-    {
-        return SR_ERR_OPERATION_FAILED;
-    }
-    else
-    {
-        cJSON *json_response = cJSON_Parse(curl_response_mem.memory);
-        const cJSON *message = NULL;
-
-        printf("%lu bytes retrieved\n", (unsigned long)curl_response_mem.size);
-
-        message = cJSON_GetObjectItemCaseSensitive(json_response, "message");
-
-        if (cJSON_IsString(message) && (message->valuestring != NULL))
-        {
-            printf("Message: \"%s\"\n", message->valuestring);
-        }
-
-        cJSON_Delete(json_response);
-    }
-
-    return SR_ERR_OK;
-}
-
-static int inspect_device_notification_execution(char *exec_id)
-{
-    int rc = SR_ERR_OK;
-
-    struct MemoryStruct curl_response_mem;
-
-    curl_response_mem.memory = malloc(1);  /* will be grown as needed by the realloc above */
-    curl_response_mem.size = 0;    /* no data at this point */
-
-    CURLcode res;
-
-    curl_easy_reset(curl);
-    set_curl_common_info();
-
-    char url[500];
-    sprintf(url, "http:/v%s/exec/%s/json", getenv("DOCKER_ENGINE_VERSION"), exec_id);
-
-    curl_easy_setopt(curl, CURLOPT_URL, url);
-
-    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
-    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
-
-    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
-
-    res = curl_easy_perform(curl);
-
-    if (res != CURLE_OK)
-    {
-        rc = SR_ERR_OPERATION_FAILED;
-    }
-    else
-    {
-        cJSON *json_response = cJSON_Parse(curl_response_mem.memory);
-        const cJSON *exit_code = NULL;
-
-        exit_code = cJSON_GetObjectItemCaseSensitive(json_response, "ExitCode");
-
-        if (cJSON_IsNumber(exit_code))
-        {
-            rc = exit_code->valueint;
-        }
-        else
-        {
-            printf("Exit code is not a number!\n");
-            rc = SR_ERR_OPERATION_FAILED;
-        }
-        
-        cJSON_Delete(json_response);
-    }
-
-    return rc;
-}
-
-int invoke_device_notification(char *device_id, char *module_name, char *notification_string)
-{
-    int rc = SR_ERR_OK;
-
-    printf("Device-name = %s\nModule-name = %s\nNotification-object = %s\n", device_id, module_name, notification_string);
-
-    struct MemoryStruct curl_response_mem;
-
-    curl_response_mem.memory = malloc(1);  /* will be grown as needed by the realloc above */
-    curl_response_mem.size = 0;    /* no data at this point */
-
-    CURLcode res;
-
-    curl_easy_reset(curl);
-    set_curl_common_info();
-
-    char url[300];
-    sprintf(url, "http:/v%s/containers/%s/exec", getenv("DOCKER_ENGINE_VERSION"), device_id);
-
-    curl_easy_setopt(curl, CURLOPT_URL, url);
-
-    cJSON *postDataJson = cJSON_CreateObject();
-
-    if (cJSON_AddFalseToObject(postDataJson, "AtttachStdin") == NULL)
-    {
-        printf("Could not create JSON object: AtttachStdin\n");
-        rc = SR_ERR_OPERATION_FAILED;
-        goto cleanup;
-    }
-
-    if (cJSON_AddTrueToObject(postDataJson, "AtttachStdout") == NULL)
-    {
-        printf("Could not create JSON object: AtttachStdout\n");
-        rc = SR_ERR_OPERATION_FAILED;
-        goto cleanup;
-    }
-
-    if (cJSON_AddTrueToObject(postDataJson, "AtttachStderr") == NULL)
-    {
-        printf("Could not create JSON object: AtttachStderr\n");
-        rc = SR_ERR_OPERATION_FAILED;
-        goto cleanup;
-    }
-
-    if (cJSON_AddTrueToObject(postDataJson, "Privileged") == NULL)
-    {
-        printf("Could not create JSON object: Privileged\n");
-        rc = SR_ERR_OPERATION_FAILED;
-        goto cleanup;
-    }
-
-    if (cJSON_AddStringToObject(postDataJson, "User", "root") == NULL)
-    {
-        printf("Could not create JSON object: User\n");
-        rc = SR_ERR_OPERATION_FAILED;
-        goto cleanup;
-    }
-
-    cJSON *cmd_array = cJSON_CreateArray();
-    if (cmd_array == NULL)
-    {
-        printf("Could not create JSON object: Cmd array\n");
-        rc = SR_ERR_OPERATION_FAILED;
-        goto cleanup;
-    }
-
-    cJSON_AddItemToObject(postDataJson, "Cmd", cmd_array);
-
-    cJSON *cmd_string_1 = cJSON_CreateString("sh");
-    cJSON_AddItemToArray(cmd_array, cmd_string_1);
-
-    cJSON *cmd_string_2 = cJSON_CreateString("-c");
-    cJSON_AddItemToArray(cmd_array, cmd_string_2);
-
-    //some notifications require a really long notification object
-    char string_command[1000000];
-    sprintf(string_command, "/usr/local/bin/generic-notifications %s '%s'", module_name, notification_string);
-
-    cJSON *cmd_string_3 = cJSON_CreateString(string_command);
-    cJSON_AddItemToArray(cmd_array, cmd_string_3);
-
-    char *post_data_string = NULL;
-
-    post_data_string = cJSON_PrintUnformatted(postDataJson);
-
-    printf("Post data JSON:\n%s\n", post_data_string);
-
-    if (postDataJson != NULL)
-    {
-        cJSON_Delete(postDataJson);
-    }
-
-    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data_string);
-
-    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
-
-    res = curl_easy_perform(curl);
-
-    if (post_data_string != NULL)
-    {
-        free(post_data_string);
-    }
-
-    if (res != CURLE_OK)
-    {
-        rc = SR_ERR_OPERATION_FAILED;
-        goto cleanup;
-    }
-    else
-    {
-        cJSON *json_response = cJSON_Parse(curl_response_mem.memory);
-        const cJSON *exec_id = NULL;
-
-        exec_id = cJSON_GetObjectItemCaseSensitive(json_response, "Id");
-
-        if (cJSON_IsString(exec_id) && (exec_id->valuestring != NULL))
-        {
-            printf("Exec id: \"%s\"\n", exec_id->valuestring);
-
-            rc = start_device_notification(exec_id->valuestring);
-            if (rc != SR_ERR_OK)
-            {
-                printf("Could not start the execution of the notification...\n");
-            }
-
-            sleep(1);
-
-            rc = inspect_device_notification_execution(exec_id->valuestring);
-        }
-
-        cJSON_Delete(json_response);
-    }
-
-cleanup:
-    if (device_id != NULL)
-    {
-        free(device_id);
-    }
-    if (module_name != NULL)
-    {
-        free(module_name);
-    }
-    if (notification_string != NULL)
-    {
-        free(notification_string);
-    }
-
-    return rc;
-}
-
-int pull_docker_image_of_simulated_device()
-{
-    struct MemoryStruct curl_response_mem;
-
-    curl_response_mem.memory = malloc(1);  /* will be grown as needed by the realloc above */
-    curl_response_mem.size = 0;    /* no data at this point */
-
-    CURLcode res;
-
-    curl_easy_reset(curl);
-    set_curl_common_info();
-
-    char url[300];
-    sprintf(url, "http:/v%s/images/create?fromImage=%s", getenv("DOCKER_ENGINE_VERSION"), getenv("MODELS_IMAGE"));
-
-    curl_easy_setopt(curl, CURLOPT_URL, url);
-
-    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
-
-    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&curl_response_mem);
-
-    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 300L);
-
-    res = curl_easy_perform(curl);
-
-    if (res != CURLE_OK)
-    {
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    return SR_ERR_OK;
-}
\ No newline at end of file
diff --git a/ntsimulator/src/ntsimulator-manager/simulator-operations.h b/ntsimulator/src/ntsimulator-manager/simulator-operations.h
deleted file mode 100644 (file)
index 8958b1d..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*************************************************************************
-*
-* Copyright 2019 highstreet technologies GmbH and others
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*     http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-***************************************************************************/
-
-#ifndef SRC_NTSIMULATOR_MANAGER_SIMULATOR_OPERATIONS_H_
-#define SRC_NTSIMULATOR_MANAGER_SIMULATOR_OPERATIONS_H_
-
-#include <curl/curl.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stdio.h>
-
-#include "sysrepo.h"
-#include "sysrepo/values.h"
-
-#include <cjson/cJSON.h>
-
-#define CURL_MEM_SIZE 2048
-
-
-/**
- * Storing the device information
-*/
-
-typedef struct device {
-       char *device_id;
-       int netconf_port;
-    int device_number;
-       bool is_mounted;
-       char *operational_state;
-       struct device *next;
-} device_t;
-
-typedef struct device_stack {
-       device_t *head;
-       size_t stack_size;
-} device_stack_t;
-
-#define URL_AND_CREDENTIALS_MAX_LEN 400
-
-typedef struct controller
-{
-       char url[URL_AND_CREDENTIALS_MAX_LEN];
-       char credentials[URL_AND_CREDENTIALS_MAX_LEN];
-       char url_for_keystore_add[URL_AND_CREDENTIALS_MAX_LEN];
-       char url_for_private_key_add[URL_AND_CREDENTIALS_MAX_LEN];
-       char url_for_trusted_ca_add[URL_AND_CREDENTIALS_MAX_LEN];
-} controller_t;
-
-
-device_stack_t *new_device_stack(void);
-void push_device(device_stack_t *theStack, char *dev_id, int port, int dev_num);
-void pop_device(device_stack_t *theStack);
-int get_netconf_port_next(device_stack_t *theStack);
-int get_netconf_port_base(void);
-int get_device_number_next(device_stack_t *theStack);
-char *get_id_last_device(device_stack_t *theStack);
-int get_current_number_of_devices(device_stack_t *theStack);
-int get_current_number_of_mounted_devices(device_stack_t *theStack);
-
-
-/**
- * cURL utilities
-*/
-
-struct MemoryStruct {
-  char *memory;
-  size_t size;
-};
-
-int _init_curl(void);
-int cleanup_curl(void);
-
-int _init_curl_odl(void);
-int cleanup_curl_odl(void);
-
-int _init_curl_k8s(void);
-int cleanup_curl_k8s(void);
-
-int start_device(device_stack_t *theStack);
-int stop_device(device_stack_t *theStack);
-
-int mount_device(device_stack_t *theStack, controller_t controller_details);
-int unmount_device(device_stack_t *theStack, controller_t controller_details);
-
-char* get_docker_container_operational_state(device_stack_t *theStack, char *container_id);
-int get_docker_containers_operational_state_curl(device_stack_t *theStack);
-
-char* get_docker_container_resource_stats();
-
-int notification_delay_period_changed(sr_val_t *val, size_t count);
-int ves_heartbeat_period_changed(int period);
-int ves_ip_changed(char *new_ip);
-int ves_port_changed(int new_port);
-int ves_username_changed(char *new_username);
-int ves_password_changed(char *new_password);
-int ves_auth_method_changed(char *new_auth_method);
-int ves_registration_changed(cJSON_bool new_bool);
-int is_netconf_available_changed(cJSON_bool new_bool);
-int is_ves_available_changed(cJSON_bool new_bool);
-int ssh_connections_changed(int number);
-int tls_connections_changed(int number);
-
-int controller_ip_changed(char *new_ip);
-int controller_port_changed(int new_port);
-int controller_netconf_call_home_port_changed(int new_port);
-int controller_username_changed(char *new_username);
-int controller_password_changed(char *new_password);
-int netconf_call_home_changed(cJSON_bool new_bool);
-
-
-int add_key_pair_to_odl(controller_t *controller_list, int controller_list_size);
-
-int send_k8s_scale(int number_of_devices);
-int send_k8s_extend_port(void);
-
-int invoke_device_notification(char *device_id, char *module_name, char *notification_string);
-
-int pull_docker_image_of_simulated_device(void);
-
-#endif /* SRC_NTSIMULATOR_MANAGER_SIMULATOR_OPERATIONS_H_ */
diff --git a/ntsimulator/src/o-ran-notifications/CMakeLists.txt b/ntsimulator/src/o-ran-notifications/CMakeLists.txt
deleted file mode 100644 (file)
index d915ca2..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-set (NOTIFICATIONS_SOURCES
-    o-ran-notifications.c
-)
-
-include_directories(
-    "/usr/include/x86_64-linux-gnu"
-    "/usr/local/include/cjson"
-)
-
-add_executable(o-ran-notifications ${NOTIFICATIONS_SOURCES})
-target_link_libraries(o-ran-notifications utils)
-target_link_libraries(o-ran-notifications sysrepo)
-target_link_libraries(o-ran-notifications m)
-target_link_libraries(o-ran-notifications curl)
-target_link_libraries(o-ran-notifications cjson)
-
-install(TARGETS o-ran-notifications DESTINATION ${CMAKE_INSTALL_BINDIR})
\ No newline at end of file
diff --git a/ntsimulator/src/o-ran-notifications/o-ran-notifications.c b/ntsimulator/src/o-ran-notifications/o-ran-notifications.c
deleted file mode 100644 (file)
index 3699e28..0000000
+++ /dev/null
@@ -1,443 +0,0 @@
-/*************************************************************************
-*
-* Copyright 2019 highstreet technologies GmbH and others
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*     http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-***************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
-#include <inttypes.h>
-#include <time.h>
-#include <math.h>
-#include <sys/time.h>
-#include <cjson/cJSON.h>
-#include <string.h>
-
-#include "sysrepo.h"
-#include "sysrepo/values.h"
-
-#include "utils.h"
-
-#define LINE_BUFSIZE 128
-#define ORAN_FAULT_ALARMS_NUMBER 10
-#define AFFECTED_OBJECTS_MAX_NUMBER 100
-
-volatile int exit_application = 0;
-
-static counterAlarms netconf_alarm_counter = {
-    .normal = 0,
-    .warning = 0,
-    .minor = 0,
-    .major = 0,
-    .critical = 0
-};
-static counterAlarms ves_alarm_counter= {
-    .normal = 0,
-    .warning = 0,
-    .minor = 0,
-    .major = 0,
-    .critical = 0
-};
-
-struct faultAlarms
-{
-       int             faultId;
-       char*           faultSource;
-       int             cleared[10];
-       char*           faultSeverity;
-       char*           faultText;
-       char*           affectedObjects[AFFECTED_OBJECTS_MAX_NUMBER];
-};
-struct faultAlarms oran_fault_alarms[ORAN_FAULT_ALARMS_NUMBER] = {
-               {.faultId = 1, .faultSource = "jknsdfnui", .affectedObjects = {"akddconoj", "asodmnjvf", "roiemfkmods"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "MAJOR", .faultText = "sdnjosopnojnsd"},
-               {.faultId = 2, .faultSource = "onascokjnasc", .affectedObjects = {"sdouvncsjdfv13", "asjdn13ejlncd4"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "WARNING", .faultText = "4pionfcsofn42on"},
-               {.faultId = 3, .faultSource = "asonxpkn", .affectedObjects = {"0j4fiwef320fd", "sdlvkmsdv-9023"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "CRITICAL", .faultText = "sdjnonj32onjsa23"},
-               {.faultId = 4, .faultSource = "asnjcpkd", .affectedObjects = {"0j4fiwef320fd", "sdlvkmsdv-9023", "laksmdklmdas21"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "MINOR", .faultText = "asdjln12osa453"},
-               {.faultId = 5, .faultSource = "dskmfl", .affectedObjects = {"sdkm31wdlk"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "MAJOR", .faultText = "dknovrf34ekl"},
-               {.faultId = 6, .faultSource = "dsllkje232kl", .affectedObjects = {"sFKOM24KLMerw"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "MAJOR", .faultText = "frpkm24k lsd     kmewfpm"},
-               {.faultId = 7, .faultSource = "fvkdlsfjnwej23kloe", .affectedObjects = {"fvkm24km", "sdfk23d", "kmdfkmo32", "wekl2332"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "WARNING", .faultText = "dsm 2d 32j sdfmr32"},
-               {.faultId = 8, .faultSource = "dkom32", .affectedObjects = {"kmsdfkpm23ds", "sdmkp32"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "CRITICAL", .faultText = "dsonj32 don32 mdson32pk654"},
-               {.faultId = 9, .faultSource = "weflm3", .affectedObjects = {"klklm32kl3", "dsfln234poewj23-", "spmd32k"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "MINOR", .faultText = "dsflknjwej32"},
-               {.faultId = 10, .faultSource = "fweiunvfrem32", .affectedObjects = {"sfkm23klsdf2343"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "MAJOR", .faultText = "dfskjnl4j dsfknl2 fodn54 65k"}
-};
-
-static         CURL *curl;
-
-static int _init_curl()
-{
-       curl = curl_easy_init();
-
-       if (curl == NULL) {
-               printf("cURL initialization error! Aborting call!\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       return SR_ERR_OK;
-}
-
-static int cleanup_curl()
-{
-       if (curl != NULL)
-       {
-               curl_easy_cleanup(curl);
-       }
-
-       return SR_ERR_OK;
-}
-
-static int send_fault_ves_message(char *alarm_condition, char *alarm_object, char *severity, char *date_time, char *specific_problem, int port)
-{
-       CURLcode res;
-       static int sequence_id = 0;
-       int netconf_port_base = 0;
-
-       prepare_ves_message_curl(curl);
-
-       cJSON *postDataJson = cJSON_CreateObject();
-
-       cJSON *event = cJSON_CreateObject();
-       if (event == NULL)
-       {
-               printf("Could not create JSON object: event\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-       cJSON_AddItemToObject(postDataJson, "event", event);
-
-       char *hostname = getenv("HOSTNAME");
-
-    netconf_port_base = getIntFromString(getenv("NETCONF_BASE"), 1);
-    netconf_port_base += port;
-
-       char source_name[100];
-       sprintf(source_name, "%s_%d", hostname, netconf_port_base);
-
-       cJSON *commonEventHeader = vesCreateCommonEventHeader("fault", "O_RAN_COMPONENT_Alarms", source_name, sequence_id++);
-       if (commonEventHeader == NULL)
-       {
-               printf("Could not create JSON object: commonEventHeader\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-       cJSON_AddItemToObject(event, "commonEventHeader", commonEventHeader);
-
-       cJSON *faultFields = vesCreateFaultFields(alarm_condition, alarm_object, severity, date_time, specific_problem);
-       if (faultFields == NULL)
-       {
-               printf("Could not create JSON object: faultFields\n");
-               if (postDataJson != NULL)
-               {
-                       cJSON_Delete(postDataJson);
-               }
-               return SR_ERR_OPERATION_FAILED;
-       }
-       cJSON_AddItemToObject(event, "faultFields", faultFields);
-
-    char *post_data_string = NULL;
-
-       post_data_string = cJSON_PrintUnformatted(postDataJson);
-
-       printf("Post data JSON:\n%s\n", post_data_string);
-
-       if (postDataJson != NULL)
-       {
-               cJSON_Delete(postDataJson);
-       }
-
-       curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data_string);
-
-       res = curl_easy_perform(curl);
-
-       if (res != CURLE_OK)
-       {
-               printf("Failed to send cURL...\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       return SR_ERR_OK;
-}
-
-static int send_dummy_notif(sr_session_ctx_t *sess)
-{
-       int rc;
-
-    char dateAndTime[256];
-    time_t t = time(NULL);
-    struct tm tm = *localtime(&t);
-    struct timeval tv;
-    int millisec;
-
-    gettimeofday(&tv, NULL);
-    millisec = lrint(tv.tv_usec/1000.0); // Round to nearest millisec
-    if (millisec>=1000)
-    { // Allow for rounding up to nearest second
-        millisec -=1000;
-        tv.tv_sec++;
-        millisec /= 100;
-    }
-    sprintf(dateAndTime, "%04d-%02d-%02dT%02d:%02d:%02d.%01dZ",
-    tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-    tm.tm_hour, tm.tm_min, tm.tm_sec, millisec/100);
-
-    int ran = (int) random_at_most(ORAN_FAULT_ALARMS_NUMBER - 1);
-
-    //TODO we hardcode here the number of ports for each device, 10
-    int random_port = (int) random_at_most(9);
-
-    if (oran_fault_alarms[ran].cleared[random_port] == 1)
-    {
-       oran_fault_alarms[ran].cleared[random_port] = 0;
-    }
-    else
-    {
-       oran_fault_alarms[ran].cleared[random_port] = 1;
-    }
-
-       sr_val_t *vnotif;
-       size_t current_num_of_values= 0;
-
-       CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
-
-       sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-fm:alarm-notif/fault-id");
-       vnotif[current_num_of_values - 1].type = SR_UINT16_T;
-       vnotif[current_num_of_values - 1].data.uint16_val = oran_fault_alarms[ran].faultId;
-
-       CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
-
-       sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-fm:alarm-notif/fault-source");
-       sr_val_set_str_data(&vnotif[current_num_of_values - 1], SR_STRING_T, oran_fault_alarms[ran].faultSource);
-
-       CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
-
-       sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-fm:alarm-notif/fault-severity");
-       sr_val_set_str_data(&vnotif[current_num_of_values - 1], SR_ENUM_T, oran_fault_alarms[ran].faultSeverity);
-
-       CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
-
-       sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-fm:alarm-notif/is-cleared");
-       vnotif[current_num_of_values - 1].type = SR_BOOL_T;
-       vnotif[current_num_of_values - 1].data.bool_val = oran_fault_alarms[ran].cleared[random_port];
-
-       CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
-
-       sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-fm:alarm-notif/fault-text");
-       sr_val_set_str_data(&vnotif[current_num_of_values - 1], SR_STRING_T, oran_fault_alarms[ran].faultText);
-
-       CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
-
-       sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-fm:alarm-notif/event-time");
-       sr_val_build_str_data(&vnotif[current_num_of_values - 1], SR_STRING_T, "%s", dateAndTime);
-
-       for (int  i = 0; i < AFFECTED_OBJECTS_MAX_NUMBER; ++i)
-       {
-               char path[400];
-               if (oran_fault_alarms[ran].affectedObjects[i] == NULL)
-               {
-                       break;
-               }
-
-               sprintf(path, "/o-ran-fm:alarm-notif/affected-objects[name='%s']", oran_fault_alarms[ran].affectedObjects[i]);
-
-               CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
-
-               sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", path);
-               vnotif[current_num_of_values - 1].type = SR_LIST_T;
-       }
-
-       int isNetconfAvailable = getNetconfAvailableFromConfigJson();
-       int isVesAvailable = getVesAvailableFromConfigJson();
-
-       if (isNetconfAvailable)
-       {
-               rc = sr_event_notif_send(sess, "/o-ran-fm:alarm-notif", vnotif, current_num_of_values, SR_EV_NOTIF_DEFAULT);
-               if (rc != SR_ERR_OK)
-               {
-                       printf("Failed to send notification send_dummy_notif\n");
-                       return SR_ERR_OPERATION_FAILED;
-               }
-               if (oran_fault_alarms[ran].cleared[random_port])
-               {
-                       netconf_alarm_counter.normal++;
-               }
-               else
-               {
-            if (strcmp(oran_fault_alarms[ran].faultSeverity, "WARNING") == 0)
-            {
-                netconf_alarm_counter.warning++;
-            }
-            else if (strcmp(oran_fault_alarms[ran].faultSeverity, "MINOR") == 0)
-            {
-                netconf_alarm_counter.minor++;
-            }
-            else if (strcmp(oran_fault_alarms[ran].faultSeverity, "MAJOR") == 0)
-            {
-                netconf_alarm_counter.major++;
-            }
-            else if (strcmp(oran_fault_alarms[ran].faultSeverity, "CRITICAL") == 0)
-            {
-                netconf_alarm_counter.critical++;
-            }
-               }
-               
-               printf("Successfully sent notification with timestamp=\"%s\"\n", dateAndTime);
-       }
-       if (isVesAvailable)
-       {
-               char faultId[10];
-               sprintf(faultId, "%d", oran_fault_alarms[ran].faultId);
-               rc = send_fault_ves_message(faultId, oran_fault_alarms[ran].faultSource,
-                               (oran_fault_alarms[ran].cleared[random_port]) ? "NORMAL" : oran_fault_alarms[ran].faultSeverity, dateAndTime, oran_fault_alarms[ran].faultText, random_port);
-               if (rc != SR_ERR_OK)
-               {
-                       printf("Could not send Fault VES message\n");
-               }
-        if (oran_fault_alarms[ran].cleared[random_port])
-               {
-                       ves_alarm_counter.normal++;
-               }
-               else
-               {
-            if (strcmp(oran_fault_alarms[ran].faultSeverity, "WARNING") == 0)
-            {
-                ves_alarm_counter.warning++;
-            }
-            else if (strcmp(oran_fault_alarms[ran].faultSeverity, "MINOR") == 0)
-            {
-                ves_alarm_counter.minor++;
-            }
-            else if (strcmp(oran_fault_alarms[ran].faultSeverity, "MAJOR") == 0)
-            {
-                ves_alarm_counter.major++;
-            }
-            else if (strcmp(oran_fault_alarms[ran].faultSeverity, "CRITICAL") == 0)
-            {
-                ves_alarm_counter.critical++;
-            }
-               }
-       }
-    printf("Writing counters to file...\n");
-    rc = writeStatusNotificationCounters(ves_alarm_counter, netconf_alarm_counter);
-    if (rc != SR_ERR_OK)
-    {
-        printf("Could not write status to file...\n");
-    }
-
-       sr_free_values(vnotif, current_num_of_values);
-
-       return SR_ERR_OK;
-}
-
-static void
-sigint_handler(int signum)
-{
-    exit_application = 1;
-}
-
-int
-main(int argc, char **argv)
-{
-    sr_conn_ctx_t *connection = NULL;
-    sr_session_ctx_t *session = NULL;
-    sr_subscription_ctx_t *subscription = NULL;
-    int rc = SR_ERR_OK;
-
-    setbuf(stdout, NULL);
-
-    /* connect to sysrepo */
-    rc = sr_connect("oran_notifications", SR_CONN_DEFAULT, &connection);
-    if (SR_ERR_OK != rc) {
-        fprintf(stderr, "Error by sr_connect: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    /* start session */
-    rc = sr_session_start(connection, SR_DS_RUNNING, SR_SESS_DEFAULT, &session);
-    if (SR_ERR_OK != rc) {
-        fprintf(stderr, "Error by sr_session_start: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    rc = _init_curl();
-    if (rc != SR_ERR_OK)
-    {
-        fprintf(stderr, "Could not initialize cURL: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    /* loop until ctrl-c is pressed / SIGINT is received */
-    signal(SIGINT, sigint_handler);
-    signal(SIGPIPE, SIG_IGN);
-
-    while (!exit_application) {
-        int notif_delay[100], count = 0;
-
-        rc = getFaultNotificationDelayPeriodFromConfigJson(notif_delay, &count);
-        if (rc != SR_ERR_OK)
-        {
-            printf("Could not get fault notification delay period.");
-            sleep(1);
-            continue;
-        }
-
-        if (count > 1)
-        {
-            for (int i = 0; i < count; ++i)
-            {
-                sleep(notif_delay[i]);
-                send_dummy_notif(session);                
-            }
-        }
-        else if (count == 1)
-        {
-            if (notif_delay[0] > 0)
-            {
-                sleep(notif_delay[0]);
-                send_dummy_notif(session);
-            }
-            else 
-            {
-                sleep(1);
-                // reset the counters when the notifciation delay period is switched back to 0
-                netconf_alarm_counter.normal = netconf_alarm_counter.warning = \
-                netconf_alarm_counter.minor = netconf_alarm_counter.major = \
-                netconf_alarm_counter.critical = 0;
-                
-                ves_alarm_counter.normal = ves_alarm_counter.warning = \
-                ves_alarm_counter.minor = ves_alarm_counter.major = \
-                ves_alarm_counter.critical = 0;
-            }
-        }
-
-    }
-
-    printf("Application exit requested, exiting.\n");
-
-cleanup:
-    if (NULL != subscription) {
-        sr_unsubscribe(session, subscription);
-    }
-    if (NULL != session) {
-        sr_session_stop(session);
-    }
-    if (NULL != connection) {
-        sr_disconnect(connection);
-    }
-    cleanup_curl();
-    printf("Error encountered. Exiting...");
-    return rc;
-}
-
-
-
-
diff --git a/ntsimulator/src/software-management-oran/CMakeLists.txt b/ntsimulator/src/software-management-oran/CMakeLists.txt
deleted file mode 100644 (file)
index f49ce32..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-set (SW_MANAGEMENT_SOURCES
-    sw-management-rpc.c
-)
-
-include_directories(
-    "/usr/include/x86_64-linux-gnu"
-    "/usr/local/include/cjson"
-    "${PROJECT_SOURCE_DIR}/inc/utils"
-)
-
-add_executable(software-management ${SW_MANAGEMENT_SOURCES})
-target_link_libraries(software-management utils)
-target_link_libraries(software-management sysrepo)
-target_link_libraries(software-management pthread)
-
-install(TARGETS software-management DESTINATION ${CMAKE_INSTALL_BINDIR})
\ No newline at end of file
diff --git a/ntsimulator/src/software-management-oran/sw-management-rpc.c b/ntsimulator/src/software-management-oran/sw-management-rpc.c
deleted file mode 100644 (file)
index 1540596..0000000
+++ /dev/null
@@ -1,519 +0,0 @@
-/**
- * @file sw-management-rpc.c
- * @author Rastislav Szabo <raszabo@cisco.com>, Lukas Macko <lmacko@cisco.com>,
- *         Milan Lenco <milan.lenco@pantheon.tech>
- * @brief Example usage of RPC API.
- *
- * @copyright
- * Copyright 2016 Cisco Systems, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
-#include <string.h>
-
-#include <pthread.h>
-
-#include "sysrepo.h"
-#include "sysrepo/values.h"
-
-#include "utils.h"
-
-#define LINE_BUFSIZE 128
-
-volatile int exit_application = 0;
-
-pthread_mutex_t lock;
-
-static int sw_download_error_count, sw_install_error_count, sw_activate_error_count;
-
-void call_software_management_script(char *script_name)
-{
-    char line[LINE_BUFSIZE];
-       int linenr;
-       FILE *pipe;
-
-       /* Get a pipe where the output from the scripts comes in */
-       char script[200];
-       sprintf(script, "/opt/dev/%s", script_name);
-
-       pipe = popen(script, "r");
-       if (pipe == NULL) {  /* check for errors */
-               printf("Could not open script.\n");
-               return;        /* return with exit code indicating error */
-       }
-
-       /* Read script output from the pipe line by line */
-       linenr = 1;
-       while (fgets(line, LINE_BUFSIZE, pipe) != NULL) {
-               printf("Script output line %d: %s", linenr, line);
-               ++linenr;
-       }
-
-       /* Once here, out of the loop, the script has ended. */
-       pclose(pipe); /* Close the pipe */
-       return;     /* return with exit code indicating success. */
-}
-
-struct sw_download_struct
-{
-    sr_session_ctx_t *sess;
-    char *filename;
-};
-
-void* sw_download_notification_send(void *arguments)
-{
-    // create the values to be sent in the notification
-    struct sw_download_struct *args = (struct sw_download_struct *)arguments;
-    int rc = SR_ERR_OK;
-
-    sw_download_error_count++;
-
-    sr_val_t *notif = NULL;
-    size_t current_num_of_values_notif = 0;
-
-    CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif);
-
-    char *trunc_filename;
-    trunc_filename = strrchr(args->filename, '/');
-
-    sr_val_build_xpath(&notif[current_num_of_values_notif - 1], "%s", "/o-ran-software-management:download-event/file-name");
-    if (trunc_filename != NULL)
-    {
-        sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_STRING_T, trunc_filename + 1);
-
-        if (strcmp(trunc_filename+1, "reset") == 0)
-        {
-            call_software_management_script("edit-config-demo-start.sh");
-        }
-        else
-        {
-            call_software_management_script("edit-config-after-download.sh");
-        }
-    }
-    else
-    {
-        sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_STRING_T, args->filename);
-        if (strcmp(args->filename, "reset") == 0)
-        {
-            call_software_management_script("edit-config-demo-start.sh");
-        }
-        else
-        {
-            call_software_management_script("edit-config-after-download.sh");
-        }
-    }
-
-    if (args->filename != NULL)
-    {
-        free(args->filename);
-    }
-
-    CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif);
-
-       sr_val_build_xpath(&notif[current_num_of_values_notif - 1], "%s", "/o-ran-software-management:download-event/status");
-    //every 5 RPCs we send an error
-    if (sw_download_error_count % 5 == 0)
-    {
-           sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_ENUM_T, "AUTHENTICATION_ERROR");
-    }
-    else
-    {
-        sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_ENUM_T, "COMPLETED");
-    }
-    
-
-    // wait 5 seconds before sending the notification
-    sleep(5);
-
-    /* send notification for event_notif_sub(_tree)_example */
-    printf(">>> Sending event notification for '/o-ran-software-management:download-event'...\n");
-    rc = sr_event_notif_send(args->sess, "/o-ran-software-management:download-event", notif, current_num_of_values_notif, SR_EV_NOTIF_DEFAULT);
-    if (SR_ERR_NOT_FOUND == rc) {
-        printf("No application subscribed for '/o-ran-software-management:download-event', skipping.\n");
-        rc = SR_ERR_OK;
-    }
-    sr_free_values(notif, current_num_of_values_notif);
-
-    return NULL;
-}
-
-struct sw_install_struct
-{
-    sr_session_ctx_t *sess;
-    char *slot_name;
-};
-
-void* sw_install_notification_send(void *arguments)
-{
-    // create the values to be sent in the notification
-    struct sw_install_struct *args = (struct sw_install_struct *)arguments;
-    int rc = SR_ERR_OK;
-    sw_install_error_count++;
-
-    sr_val_t *notif = NULL;
-    size_t current_num_of_values_notif = 0;
-
-    CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif);
-
-    sr_val_build_xpath(&notif[current_num_of_values_notif - 1], "%s", "/o-ran-software-management:install-event/slot-name");
-    sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_STRING_T, args->slot_name);
-
-    if (args->slot_name != NULL)
-    {
-        free(args->slot_name);
-    }
-
-    CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif);
-
-       sr_val_build_xpath(&notif[current_num_of_values_notif - 1], "%s", "/o-ran-software-management:install-event/status");
-
-       //every 5 RPCs we send an error
-    if (sw_install_error_count % 5 == 0)
-    {
-           sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_ENUM_T, "INTEGRITY_ERROR");
-    }
-    else
-    {
-        sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_ENUM_T, "COMPLETED");
-    }
-
-    // wait 5 seconds before sending the notification
-    sleep(5);
-
-    /* send notification for event_notif_sub(_tree)_example */
-    printf(">>> Sending event notification for '/o-ran-software-management:install-event'...\n");
-    rc = sr_event_notif_send(args->sess, "/o-ran-software-management:install-event", notif, current_num_of_values_notif, SR_EV_NOTIF_DEFAULT);
-    if (SR_ERR_NOT_FOUND == rc) {
-        printf("No application subscribed for '/o-ran-software-management:install-event', skipping.\n");
-        rc = SR_ERR_OK;
-    }
-    sr_free_values(notif, current_num_of_values_notif);
-
-    return NULL;
-}
-
-struct sw_activate_struct
-{
-    sr_session_ctx_t *sess;
-    char *slot_name;
-};
-
-void* sw_activate_notification_send(void *arguments)
-{
-    // create the values to be sent in the notification
-    struct sw_activate_struct *args = (struct sw_activate_struct *)arguments;
-    int rc = SR_ERR_OK;
-    sw_activate_error_count++;
-
-    sr_val_t *notif = NULL;
-    size_t current_num_of_values_notif = 0;
-
-    CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif);
-
-    sr_val_build_xpath(&notif[current_num_of_values_notif - 1], "%s", "/o-ran-software-management:activation-event/slot-name");
-    sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_STRING_T, args->slot_name);
-
-    if (args->slot_name != NULL)
-    {
-        free(args->slot_name);
-    }
-
-    CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif);
-
-       sr_val_build_xpath(&notif[current_num_of_values_notif - 1], "%s", "/o-ran-software-management:activation-event/status");
-       //every 5 RPCs we send an error
-    if (sw_activate_error_count % 5 == 0)
-    {
-           sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_ENUM_T, "APPLICATION_ERROR");
-    }
-    else
-    {
-        sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_ENUM_T, "COMPLETED");
-
-        call_software_management_script("edit-config-after-activate.sh");
-    }
-
-    CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif);
-
-       sr_val_build_xpath(&notif[current_num_of_values_notif - 1], "%s", "/o-ran-software-management:activation-event/return-code");
-    notif[current_num_of_values_notif - 1].type = SR_UINT8_T;
-    notif[current_num_of_values_notif - 1].data.uint8_val = 200;
-
-    // wait 5 seconds before sending the notification
-    sleep(5);
-
-    /* send notification for event_notif_sub(_tree)_example */
-    printf(">>> Sending event notification for '/o-ran-software-management:activation-event'...\n");
-    rc = sr_event_notif_send(args->sess, "/o-ran-software-management:activation-event", notif, current_num_of_values_notif, SR_EV_NOTIF_DEFAULT);
-    if (SR_ERR_NOT_FOUND == rc) {
-        printf("No application subscribed for '/o-ran-software-management:activation-event', skipping.\n");
-        rc = SR_ERR_OK;
-    }
-    sr_free_values(notif, current_num_of_values_notif);
-
-    return NULL;
-}
-
-static int
-sw_download_rpc_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
-       sr_val_t **output, size_t *output_cnt, void *private_ctx)
-{
-    int rc = SR_ERR_OK;
-    sr_session_ctx_t *session = (sr_session_ctx_t *)private_ctx;
-
-    /**
-     * Here you would actually run the operation against the provided input values
-     * and obtained the output values.
-     */
-
-    /* allocate output values */
-    rc = sr_new_values(2, output);
-    if (SR_ERR_OK != rc) {
-        return rc;
-    }
-
-    rc = sr_val_set_xpath(&(*output)[0], "/o-ran-software-management:software-download/status");
-    if (SR_ERR_OK != rc) {
-        return rc;
-    }
-    (*output)[0].type = SR_ENUM_T;
-    (*output)[0].data.enum_val = "STARTED";
-
-    rc = sr_val_set_xpath(&(*output)[1], "/o-ran-software-management:software-download/notification-timeout");
-    if (SR_ERR_OK != rc) {
-        return rc;
-    }
-    (*output)[1].type = SR_INT32_T;
-    (*output)[1].data.int32_val = 10;
-
-    /* inform sysrepo about the number of output values */
-    *output_cnt = 2;
-
-    struct sw_download_struct *args = (struct sw_download_struct *)malloc(sizeof(struct sw_download_struct));
-    args->sess = session;
-    args->filename = strdup(input[0].data.string_val);
-
-    pthread_t sw_download_thread;
-       if(pthread_create(&sw_download_thread, NULL, &sw_download_notification_send, (void *)args))
-       {
-               fprintf(stderr, "Could not create thread for SW Download thread\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-    /**
-     * Do not deallocate input values!
-     * They will get freed automatically by sysrepo.
-     */
-    return rc;
-}
-
-static int
-sw_install_rpc_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
-       sr_val_t **output, size_t *output_cnt, void *private_ctx)
-{
-    int rc = SR_ERR_OK;
-    sr_session_ctx_t *session = (sr_session_ctx_t *)private_ctx;
-
-    /**
-     * Here you would actually run the operation against the provided input values
-     * and obtained the output values.
-     */
-
-    /* allocate output values */
-    rc = sr_new_values(1, output);
-    if (SR_ERR_OK != rc) {
-        return rc;
-    }
-
-    rc = sr_val_set_xpath(&(*output)[0], "/o-ran-software-management:software-install/status");
-    if (SR_ERR_OK != rc) {
-        return rc;
-    }
-    (*output)[0].type = SR_ENUM_T;
-    (*output)[0].data.enum_val = "STARTED";
-
-    /* inform sysrepo about the number of output values */
-    *output_cnt = 1;
-
-    struct sw_install_struct *args = (struct sw_install_struct *)malloc(sizeof(struct sw_install_struct));
-    args->sess = session;
-    args->slot_name = strdup(input[0].data.string_val);
-
-    pthread_t sw_install_thread;
-       if(pthread_create(&sw_install_thread, NULL, &sw_install_notification_send, (void *)args))
-       {
-               fprintf(stderr, "Could not create thread for SW Install thread\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-    /**
-     * Do not deallocate input values!
-     * They will get freed automatically by sysrepo.
-     */
-    return rc;
-}
-
-static int
-sw_activate_rpc_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
-       sr_val_t **output, size_t *output_cnt, void *private_ctx)
-{
-    int rc = SR_ERR_OK;
-    sr_session_ctx_t *session = (sr_session_ctx_t *)private_ctx;
-
-    /**
-     * Here you would actually run the operation against the provided input values
-     * and obtained the output values.
-     */
-
-    /* allocate output values */
-    rc = sr_new_values(2, output);
-    if (SR_ERR_OK != rc) {
-        return rc;
-    }
-
-    rc = sr_val_set_xpath(&(*output)[0], "/o-ran-software-management:software-activate/status");
-    if (SR_ERR_OK != rc) {
-        return rc;
-    }
-    (*output)[0].type = SR_ENUM_T;
-    (*output)[0].data.enum_val = "STARTED";
-
-    rc = sr_val_set_xpath(&(*output)[1], "/o-ran-software-management:software-activate/notification-timeout");
-    if (SR_ERR_OK != rc) {
-        return rc;
-    }
-    (*output)[1].type = SR_INT32_T;
-    (*output)[1].data.int32_val = 10;
-
-    /* inform sysrepo about the number of output values */
-    *output_cnt = 2;
-
-    struct sw_activate_struct *args = (struct sw_activate_struct *)malloc(sizeof(struct sw_activate_struct));
-    args->sess = session;
-    args->slot_name = strdup(input[0].data.string_val);
-
-    pthread_t sw_activate_thread;
-       if(pthread_create(&sw_activate_thread, NULL, &sw_activate_notification_send, (void *)args))
-       {
-               fprintf(stderr, "Could not create thread for SW Activate thread\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-    /**
-     * Do not deallocate input values!
-     * They will get freed automatically by sysrepo.
-     */
-    return rc;
-}
-
-static void
-sigint_handler(int signum)
-{
-    exit_application = 1;
-}
-
-static int
-rpc_handler(sr_session_ctx_t *session)
-{
-    sr_subscription_ctx_t *subscription = NULL;
-    int rc = SR_ERR_OK;
-
-    /* subscribe for handling software-download RPC */
-    rc = sr_rpc_subscribe(session, "/o-ran-software-management:software-download", sw_download_rpc_cb,
-            (void *)session, SR_SUBSCR_DEFAULT, &subscription);
-    if (SR_ERR_OK != rc) {
-        fprintf(stderr, "Error by sr_rpc_subscribe: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    /* subscribe for handling software-install RPC */
-    rc = sr_rpc_subscribe(session, "/o-ran-software-management:software-install", sw_install_rpc_cb,
-            (void *)session, SR_SUBSCR_DEFAULT, &subscription);
-    if (SR_ERR_OK != rc) {
-        fprintf(stderr, "Error by sr_rpc_subscribe: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-        /* subscribe for handling software-activate RPC */
-    rc = sr_rpc_subscribe(session, "/o-ran-software-management:software-activate", sw_activate_rpc_cb,
-            (void *)session, SR_SUBSCR_DEFAULT, &subscription);
-    if (SR_ERR_OK != rc) {
-        fprintf(stderr, "Error by sr_rpc_subscribe: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    printf("\n\n ========== SUBSCRIBED FOR HANDLING RPC ==========\n\n");
-
-    /* loop until ctrl-c is pressed / SIGINT is received */
-    signal(SIGINT, sigint_handler);
-    signal(SIGPIPE, SIG_IGN);
-    while (!exit_application) {
-        sleep(1000);  /* or do some more useful work... */
-    }
-
-    printf("Application exit requested, exiting.\n");
-
-cleanup:
-    if (NULL != subscription) {
-        sr_unsubscribe(session, subscription);
-    }
-    return rc;
-}
-
-int
-main(int argc, char **argv)
-{
-    sr_conn_ctx_t *connection = NULL;
-    sr_session_ctx_t *session = NULL;
-    int rc = SR_ERR_OK;
-
-    setbuf(stdout, NULL);
-
-    if (pthread_mutex_init(&lock, NULL) != 0)
-       {
-               printf("Mutex init failed...\n");
-               goto cleanup;
-       }
-
-    /* connect to sysrepo */
-    rc = sr_connect("sw_management_rpc_app", SR_CONN_DEFAULT, &connection);
-    if (SR_ERR_OK != rc) {
-        fprintf(stderr, "Error by sr_connect: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    /* start session */
-    rc = sr_session_start(connection, SR_DS_RUNNING, SR_SESS_DEFAULT, &session);
-    if (SR_ERR_OK != rc) {
-        fprintf(stderr, "Error by sr_session_start: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    /* run as a RPC handler */
-    printf("This application will be an RPC handler for 'software-download' operation of 'o-ran-software-management'.\n");
-    rc = rpc_handler(session);
-
-cleanup:
-    if (NULL != session) {
-        sr_session_stop(session);
-    }
-    if (NULL != connection) {
-        sr_disconnect(connection);
-    }
-    return rc;
-}
diff --git a/ntsimulator/src/software-management-xran/CMakeLists.txt b/ntsimulator/src/software-management-xran/CMakeLists.txt
deleted file mode 100644 (file)
index f49ce32..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-set (SW_MANAGEMENT_SOURCES
-    sw-management-rpc.c
-)
-
-include_directories(
-    "/usr/include/x86_64-linux-gnu"
-    "/usr/local/include/cjson"
-    "${PROJECT_SOURCE_DIR}/inc/utils"
-)
-
-add_executable(software-management ${SW_MANAGEMENT_SOURCES})
-target_link_libraries(software-management utils)
-target_link_libraries(software-management sysrepo)
-target_link_libraries(software-management pthread)
-
-install(TARGETS software-management DESTINATION ${CMAKE_INSTALL_BINDIR})
\ No newline at end of file
diff --git a/ntsimulator/src/software-management-xran/sw-management-rpc.c b/ntsimulator/src/software-management-xran/sw-management-rpc.c
deleted file mode 100644 (file)
index b2b5025..0000000
+++ /dev/null
@@ -1,519 +0,0 @@
-/**
- * @file sw-management-rpc.c
- * @author Rastislav Szabo <raszabo@cisco.com>, Lukas Macko <lmacko@cisco.com>,
- *         Milan Lenco <milan.lenco@pantheon.tech>
- * @brief Example usage of RPC API.
- *
- * @copyright
- * Copyright 2016 Cisco Systems, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
-#include <string.h>
-
-#include <pthread.h>
-
-#include "sysrepo.h"
-#include "sysrepo/values.h"
-
-#include "utils.h"
-
-#define LINE_BUFSIZE 128
-
-volatile int exit_application = 0;
-
-pthread_mutex_t lock;
-
-static int sw_download_error_count, sw_install_error_count, sw_activate_error_count;
-
-void call_software_management_script(char *script_name)
-{
-    char line[LINE_BUFSIZE];
-       int linenr;
-       FILE *pipe;
-
-       /* Get a pipe where the output from the scripts comes in */
-       char script[200];
-       sprintf(script, "/opt/dev/%s", script_name);
-
-       pipe = popen(script, "r");
-       if (pipe == NULL) {  /* check for errors */
-               printf("Could not open script.\n");
-               return;        /* return with exit code indicating error */
-       }
-
-       /* Read script output from the pipe line by line */
-       linenr = 1;
-       while (fgets(line, LINE_BUFSIZE, pipe) != NULL) {
-               printf("Script output line %d: %s", linenr, line);
-               ++linenr;
-       }
-
-       /* Once here, out of the loop, the script has ended. */
-       pclose(pipe); /* Close the pipe */
-       return;     /* return with exit code indicating success. */
-}
-
-struct sw_download_struct
-{
-    sr_session_ctx_t *sess;
-    char *filename;
-};
-
-void* sw_download_notification_send(void *arguments)
-{
-    // create the values to be sent in the notification
-    struct sw_download_struct *args = (struct sw_download_struct *)arguments;
-    int rc = SR_ERR_OK;
-
-    sw_download_error_count++;
-
-    sr_val_t *notif = NULL;
-    size_t current_num_of_values_notif = 0;
-
-    CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif);
-
-    char *trunc_filename;
-    trunc_filename = strrchr(args->filename, '/');
-
-    sr_val_build_xpath(&notif[current_num_of_values_notif - 1], "%s", "/xran-software-management:download-event/file-name");
-    if (trunc_filename != NULL)
-    {
-        sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_STRING_T, trunc_filename + 1);
-
-        if (strcmp(trunc_filename+1, "reset") == 0)
-        {
-            call_software_management_script("edit-config-demo-start.sh");
-        }
-        else
-        {
-            call_software_management_script("edit-config-after-download.sh");
-        }
-    }
-    else
-    {
-        sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_STRING_T, args->filename);
-        if (strcmp(args->filename, "reset") == 0)
-        {
-            call_software_management_script("edit-config-demo-start.sh");
-        }
-        else
-        {
-            call_software_management_script("edit-config-after-download.sh");
-        }
-    }
-
-    if (args->filename != NULL)
-    {
-        free(args->filename);
-    }
-
-    CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif);
-
-       sr_val_build_xpath(&notif[current_num_of_values_notif - 1], "%s", "/xran-software-management:download-event/status");
-    //every 5 RPCs we send an error
-    if (sw_download_error_count % 5 == 0)
-    {
-           sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_ENUM_T, "AUTHENTICATION_ERROR");
-    }
-    else
-    {
-        sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_ENUM_T, "COMPLETED");
-    }
-    
-
-    // wait 5 seconds before sending the notification
-    sleep(5);
-
-    /* send notification for event_notif_sub(_tree)_example */
-    printf(">>> Sending event notification for '/xran-software-management:download-event'...\n");
-    rc = sr_event_notif_send(args->sess, "/xran-software-management:download-event", notif, current_num_of_values_notif, SR_EV_NOTIF_DEFAULT);
-    if (SR_ERR_NOT_FOUND == rc) {
-        printf("No application subscribed for '/xran-software-management:download-event', skipping.\n");
-        rc = SR_ERR_OK;
-    }
-    sr_free_values(notif, current_num_of_values_notif);
-
-    return NULL;
-}
-
-struct sw_install_struct
-{
-    sr_session_ctx_t *sess;
-    char *slot_name;
-};
-
-void* sw_install_notification_send(void *arguments)
-{
-    // create the values to be sent in the notification
-    struct sw_install_struct *args = (struct sw_install_struct *)arguments;
-    int rc = SR_ERR_OK;
-    sw_install_error_count++;
-
-    sr_val_t *notif = NULL;
-    size_t current_num_of_values_notif = 0;
-
-    CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif);
-
-    sr_val_build_xpath(&notif[current_num_of_values_notif - 1], "%s", "/xran-software-management:install-event/slot-name");
-    sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_STRING_T, args->slot_name);
-
-    if (args->slot_name != NULL)
-    {
-        free(args->slot_name);
-    }
-
-    CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif);
-
-       sr_val_build_xpath(&notif[current_num_of_values_notif - 1], "%s", "/xran-software-management:install-event/status");
-
-       //every 5 RPCs we send an error
-    if (sw_install_error_count % 5 == 0)
-    {
-           sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_ENUM_T, "INTEGRITY_ERROR");
-    }
-    else
-    {
-        sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_ENUM_T, "COMPLETED");
-    }
-
-    // wait 5 seconds before sending the notification
-    sleep(5);
-
-    /* send notification for event_notif_sub(_tree)_example */
-    printf(">>> Sending event notification for '/xran-software-management:install-event'...\n");
-    rc = sr_event_notif_send(args->sess, "/xran-software-management:install-event", notif, current_num_of_values_notif, SR_EV_NOTIF_DEFAULT);
-    if (SR_ERR_NOT_FOUND == rc) {
-        printf("No application subscribed for '/xran-software-management:install-event', skipping.\n");
-        rc = SR_ERR_OK;
-    }
-    sr_free_values(notif, current_num_of_values_notif);
-
-    return NULL;
-}
-
-struct sw_activate_struct
-{
-    sr_session_ctx_t *sess;
-    char *slot_name;
-};
-
-void* sw_activate_notification_send(void *arguments)
-{
-    // create the values to be sent in the notification
-    struct sw_activate_struct *args = (struct sw_activate_struct *)arguments;
-    int rc = SR_ERR_OK;
-    sw_activate_error_count++;
-
-    sr_val_t *notif = NULL;
-    size_t current_num_of_values_notif = 0;
-
-    CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif);
-
-    sr_val_build_xpath(&notif[current_num_of_values_notif - 1], "%s", "/xran-software-management:activation-event/slot-name");
-    sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_STRING_T, args->slot_name);
-
-    if (args->slot_name != NULL)
-    {
-        free(args->slot_name);
-    }
-
-    CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif);
-
-       sr_val_build_xpath(&notif[current_num_of_values_notif - 1], "%s", "/xran-software-management:activation-event/status");
-       //every 5 RPCs we send an error
-    if (sw_activate_error_count % 5 == 0)
-    {
-           sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_ENUM_T, "APPLICATION_ERROR");
-    }
-    else
-    {
-        sr_val_set_str_data(&notif[current_num_of_values_notif - 1], SR_ENUM_T, "COMPLETED");
-
-        call_software_management_script("edit-config-after-activate.sh");
-    }
-
-    CREATE_NEW_VALUE(rc, notif, current_num_of_values_notif);
-
-       sr_val_build_xpath(&notif[current_num_of_values_notif - 1], "%s", "/xran-software-management:activation-event/return-code");
-    notif[current_num_of_values_notif - 1].type = SR_UINT8_T;
-    notif[current_num_of_values_notif - 1].data.uint8_val = 200;
-
-    // wait 5 seconds before sending the notification
-    sleep(5);
-
-    /* send notification for event_notif_sub(_tree)_example */
-    printf(">>> Sending event notification for '/xran-software-management:activation-event'...\n");
-    rc = sr_event_notif_send(args->sess, "/xran-software-management:activation-event", notif, current_num_of_values_notif, SR_EV_NOTIF_DEFAULT);
-    if (SR_ERR_NOT_FOUND == rc) {
-        printf("No application subscribed for '/xran-software-management:activation-event', skipping.\n");
-        rc = SR_ERR_OK;
-    }
-    sr_free_values(notif, current_num_of_values_notif);
-
-    return NULL;
-}
-
-static int
-sw_download_rpc_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
-       sr_val_t **output, size_t *output_cnt, void *private_ctx)
-{
-    int rc = SR_ERR_OK;
-    sr_session_ctx_t *session = (sr_session_ctx_t *)private_ctx;
-
-    /**
-     * Here you would actually run the operation against the provided input values
-     * and obtained the output values.
-     */
-
-    /* allocate output values */
-    rc = sr_new_values(2, output);
-    if (SR_ERR_OK != rc) {
-        return rc;
-    }
-
-    rc = sr_val_set_xpath(&(*output)[0], "/xran-software-management:software-download/status");
-    if (SR_ERR_OK != rc) {
-        return rc;
-    }
-    (*output)[0].type = SR_ENUM_T;
-    (*output)[0].data.enum_val = "STARTED";
-
-    rc = sr_val_set_xpath(&(*output)[1], "/xran-software-management:software-download/notification-timeout");
-    if (SR_ERR_OK != rc) {
-        return rc;
-    }
-    (*output)[1].type = SR_INT32_T;
-    (*output)[1].data.int32_val = 10;
-
-    /* inform sysrepo about the number of output values */
-    *output_cnt = 2;
-
-    struct sw_download_struct *args = (struct sw_download_struct *)malloc(sizeof(struct sw_download_struct));
-    args->sess = session;
-    args->filename = strdup(input[0].data.string_val);
-
-    pthread_t sw_download_thread;
-       if(pthread_create(&sw_download_thread, NULL, &sw_download_notification_send, (void *)args))
-       {
-               fprintf(stderr, "Could not create thread for SW Download thread\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-    /**
-     * Do not deallocate input values!
-     * They will get freed automatically by sysrepo.
-     */
-    return rc;
-}
-
-static int
-sw_install_rpc_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
-       sr_val_t **output, size_t *output_cnt, void *private_ctx)
-{
-    int rc = SR_ERR_OK;
-    sr_session_ctx_t *session = (sr_session_ctx_t *)private_ctx;
-
-    /**
-     * Here you would actually run the operation against the provided input values
-     * and obtained the output values.
-     */
-
-    /* allocate output values */
-    rc = sr_new_values(1, output);
-    if (SR_ERR_OK != rc) {
-        return rc;
-    }
-
-    rc = sr_val_set_xpath(&(*output)[0], "/xran-software-management:software-install/status");
-    if (SR_ERR_OK != rc) {
-        return rc;
-    }
-    (*output)[0].type = SR_ENUM_T;
-    (*output)[0].data.enum_val = "STARTED";
-
-    /* inform sysrepo about the number of output values */
-    *output_cnt = 1;
-
-    struct sw_install_struct *args = (struct sw_install_struct *)malloc(sizeof(struct sw_install_struct));
-    args->sess = session;
-    args->slot_name = strdup(input[0].data.string_val);
-
-    pthread_t sw_install_thread;
-       if(pthread_create(&sw_install_thread, NULL, &sw_install_notification_send, (void *)args))
-       {
-               fprintf(stderr, "Could not create thread for SW Install thread\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-    /**
-     * Do not deallocate input values!
-     * They will get freed automatically by sysrepo.
-     */
-    return rc;
-}
-
-static int
-sw_activate_rpc_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
-       sr_val_t **output, size_t *output_cnt, void *private_ctx)
-{
-    int rc = SR_ERR_OK;
-    sr_session_ctx_t *session = (sr_session_ctx_t *)private_ctx;
-
-    /**
-     * Here you would actually run the operation against the provided input values
-     * and obtained the output values.
-     */
-
-    /* allocate output values */
-    rc = sr_new_values(2, output);
-    if (SR_ERR_OK != rc) {
-        return rc;
-    }
-
-    rc = sr_val_set_xpath(&(*output)[0], "/xran-software-management:software-activate/status");
-    if (SR_ERR_OK != rc) {
-        return rc;
-    }
-    (*output)[0].type = SR_ENUM_T;
-    (*output)[0].data.enum_val = "STARTED";
-
-    rc = sr_val_set_xpath(&(*output)[1], "/xran-software-management:software-activate/notification-timeout");
-    if (SR_ERR_OK != rc) {
-        return rc;
-    }
-    (*output)[1].type = SR_INT32_T;
-    (*output)[1].data.int32_val = 10;
-
-    /* inform sysrepo about the number of output values */
-    *output_cnt = 2;
-
-    struct sw_activate_struct *args = (struct sw_activate_struct *)malloc(sizeof(struct sw_activate_struct));
-    args->sess = session;
-    args->slot_name = strdup(input[0].data.string_val);
-
-    pthread_t sw_activate_thread;
-       if(pthread_create(&sw_activate_thread, NULL, &sw_activate_notification_send, (void *)args))
-       {
-               fprintf(stderr, "Could not create thread for SW Activate thread\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-    /**
-     * Do not deallocate input values!
-     * They will get freed automatically by sysrepo.
-     */
-    return rc;
-}
-
-static void
-sigint_handler(int signum)
-{
-    exit_application = 1;
-}
-
-static int
-rpc_handler(sr_session_ctx_t *session)
-{
-    sr_subscription_ctx_t *subscription = NULL;
-    int rc = SR_ERR_OK;
-
-    /* subscribe for handling software-download RPC */
-    rc = sr_rpc_subscribe(session, "/xran-software-management:software-download", sw_download_rpc_cb,
-            (void *)session, SR_SUBSCR_DEFAULT, &subscription);
-    if (SR_ERR_OK != rc) {
-        fprintf(stderr, "Error by sr_rpc_subscribe: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    /* subscribe for handling software-install RPC */
-    rc = sr_rpc_subscribe(session, "/xran-software-management:software-install", sw_install_rpc_cb,
-            (void *)session, SR_SUBSCR_DEFAULT, &subscription);
-    if (SR_ERR_OK != rc) {
-        fprintf(stderr, "Error by sr_rpc_subscribe: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-        /* subscribe for handling software-activate RPC */
-    rc = sr_rpc_subscribe(session, "/xran-software-management:software-activate", sw_activate_rpc_cb,
-            (void *)session, SR_SUBSCR_DEFAULT, &subscription);
-    if (SR_ERR_OK != rc) {
-        fprintf(stderr, "Error by sr_rpc_subscribe: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    printf("\n\n ========== SUBSCRIBED FOR HANDLING RPC ==========\n\n");
-
-    /* loop until ctrl-c is pressed / SIGINT is received */
-    signal(SIGINT, sigint_handler);
-    signal(SIGPIPE, SIG_IGN);
-    while (!exit_application) {
-        sleep(1000);  /* or do some more useful work... */
-    }
-
-    printf("Application exit requested, exiting.\n");
-
-cleanup:
-    if (NULL != subscription) {
-        sr_unsubscribe(session, subscription);
-    }
-    return rc;
-}
-
-int
-main(int argc, char **argv)
-{
-    sr_conn_ctx_t *connection = NULL;
-    sr_session_ctx_t *session = NULL;
-    int rc = SR_ERR_OK;
-
-    setbuf(stdout, NULL);
-
-    if (pthread_mutex_init(&lock, NULL) != 0)
-       {
-               printf("Mutex init failed...\n");
-               goto cleanup;
-       }
-
-    /* connect to sysrepo */
-    rc = sr_connect("sw_management_rpc_app", SR_CONN_DEFAULT, &connection);
-    if (SR_ERR_OK != rc) {
-        fprintf(stderr, "Error by sr_connect: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    /* start session */
-    rc = sr_session_start(connection, SR_DS_RUNNING, SR_SESS_DEFAULT, &session);
-    if (SR_ERR_OK != rc) {
-        fprintf(stderr, "Error by sr_session_start: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    /* run as a RPC handler */
-    printf("This application will be an RPC handler for 'software-download' operation of 'xran-software-management'.\n");
-    rc = rpc_handler(session);
-
-cleanup:
-    if (NULL != session) {
-        sr_session_stop(session);
-    }
-    if (NULL != connection) {
-        sr_disconnect(connection);
-    }
-    return rc;
-}
diff --git a/ntsimulator/src/utils/utils.c b/ntsimulator/src/utils/utils.c
deleted file mode 100644 (file)
index 49b1816..0000000
+++ /dev/null
@@ -1,2396 +0,0 @@
-/*************************************************************************
-*
-* Copyright 2019 highstreet technologies GmbH and others
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*     http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-***************************************************************************/
-
-#include "utils.h"
-
-#include <math.h>
-#include <time.h>
-#include <sys/time.h>
-#include <stdio.h>
-#include <string.h>
-
-void set_curl_common_info_ves(CURL *curl)
-{
-       struct curl_slist *chunk = NULL;
-       chunk = curl_slist_append(chunk, "Content-Type: application/json");
-       chunk = curl_slist_append(chunk, "Accept: application/json");
-
-    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
-
-    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 2L); // seconds timeout for a connection
-    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L); //seconds timeout for an operation
-
-    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
-}
-
-void getCurrentDateAndTime(char *date_and_time)
-{
-       time_t t = time(NULL);
-       struct tm tm = *localtime(&t);
-       struct timeval tv;
-       int millisec;
-
-       gettimeofday(&tv, NULL);
-       millisec = lrint(tv.tv_usec/1000.0); // Round to nearest millisec
-       if (millisec>=1000)
-       { // Allow for rounding up to nearest second
-               millisec -=1000;
-               tv.tv_sec++;
-               millisec /= 100;
-       }
-       sprintf(date_and_time, "%04d-%02d-%02dT%02d:%02d:%02d.%01dZ",
-       tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-       tm.tm_hour, tm.tm_min, tm.tm_sec, millisec/100);
-
-       return;
-}
-
-void   generateRandomMacAddress(char *mac_address)
-{
-       long rand1, rand2, rand3, rand4, rand5, rand6;
-       rand1 = random_at_most(255);
-       rand2 = random_at_most(255);
-       rand3 = random_at_most(255);
-       rand4 = random_at_most(255);
-       rand5 = random_at_most(255);
-       rand6 = random_at_most(255);
-
-       sprintf(mac_address, "%02X:%02X:%02X:%02X:%02X:%02X", rand1, rand2, rand3, rand4, rand5, rand6);
-
-       return;
-}
-
-long random_at_most(long max) 
-{
-    unsigned long
-        // max <= RAND_MAX < ULONG_MAX, so this is okay.
-        num_bins = (unsigned long) max + 1,
-        num_rand = (unsigned long) RAND_MAX + 1,
-        bin_size = num_rand / num_bins,
-        defect   = num_rand % num_bins;
-
-    unsigned int seed;
-    FILE* urandom = fopen("/dev/urandom", "r");
-    fread(&seed, sizeof(int), 1, urandom);
-    fclose(urandom);
-    srandom(seed);
-
-    long x;
-    do 
-    {
-        x = random();
-    }
-    // This is carefully written not to overflow
-    while (num_rand - defect <= (unsigned long)x);
-
-    // Truncated division is intentional
-    return x/bin_size;
-}
-
-int getSecondsFromLastQuarterInterval(void)
-{
-       time_t t = time(NULL);
-       time_t t_past = time(NULL);
-       struct tm tm = *localtime(&t);
-       struct tm tm_15_min_ago = tm;
-
-       //round to the last quarter hour
-       tm_15_min_ago.tm_min -= (tm_15_min_ago.tm_min % 15);
-       tm_15_min_ago.tm_sec = 0;
-
-       t=mktime(&tm_15_min_ago);
-       t_past=mktime(&tm);
-
-       double seconds = difftime(t_past, t);
-
-       return (int)seconds;
-}
-
-int getSecondsFromLastDayInterval(void)
-{
-       time_t t = time(NULL);
-       time_t t_past = time(NULL);
-       struct tm tm = *localtime(&t);
-       struct tm tm_day_ago = tm;
-
-       //round to the last quarter hour
-       tm_day_ago.tm_hour = 0;
-       tm_day_ago.tm_min = 0;
-       tm_day_ago.tm_sec = 0;
-
-       t=mktime(&tm_day_ago);
-       t_past=mktime(&tm);
-
-       double seconds = difftime(t_past, t);
-
-       return (int)seconds;
-}
-
-void getPreviousQuarterInterval(int number_of_intervals, char *date_and_time)
-{
-       time_t t = time(NULL);
-       t -= 15 * 60 * number_of_intervals;
-       struct tm tm = *localtime(&t);
-
-       tm.tm_min -= (tm.tm_min % 15);
-       tm.tm_sec = 0;
-
-       sprintf(date_and_time, "%04d-%02d-%02dT%02d:%02d:%02d.0Z",
-       tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-       tm.tm_hour, tm.tm_min, tm.tm_sec);
-
-       return;
-}
-
-void getPreviousDayPmTimestamp(int number_of_intervals, char *date_and_time)
-{
-       time_t t = time(NULL);
-       t -= 24 * 60 * 60 * number_of_intervals;
-       struct tm tm = *localtime(&t);
-
-       tm.tm_hour = 0;
-       tm.tm_min = 0;
-       tm.tm_sec = 0;
-
-       sprintf(date_and_time, "%04d-%02d-%02dT%02d:%02d:%02d.0Z",
-       tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-       tm.tm_hour, tm.tm_min, tm.tm_sec);
-
-       return;
-}
-
-long int getMicrosecondsSinceEpoch(void)
-{
-       time_t t = time(NULL);
-       struct timeval tv;
-       long int useconds;
-
-       gettimeofday(&tv, NULL);
-       useconds = t*1000 + tv.tv_usec; //add the microseconds to the seconds
-
-       return useconds;
-}
-
-//TODO need to implement other authentication methods as well, not only no-auth
-void prepare_ves_message_curl(CURL *curl)
-{
-       curl_easy_reset(curl);
-       set_curl_common_info_ves(curl);
-
-       char *ves_ip = getVesIpFromConfigJson();
-       int ves_port = getVesPortFromConfigJson();
-    char *ves_auth_method = getVesAuthMethodFromConfigJson();
-    if (strcmp(ves_auth_method, "basic-auth") == 0)
-    {
-        char *ves_username = getVesUsernameFromConfigJson();
-        char *ves_password = getVesPasswordFromConfigJson();
-
-        char credentials[200];
-        sprintf(credentials, "%s:%s", ves_username, ves_password);
-
-        free(ves_username);
-        free(ves_password);
-
-        curl_easy_setopt(curl, CURLOPT_USERPWD, credentials);
-    }
-    free(ves_auth_method);
-
-       char url[300];
-       char ves_protocol[15] = "https";
-       if( !strcmp(getenv("VES_HTTPS"), "false")  )
-       {
-           strcpy(ves_protocol ,"http" );
-           printf("VES connection protocol %s enabled\n", ves_protocol);
-       }
-
-       sprintf(url, "%s://%s:%d/eventListener/v7", ves_protocol, ves_ip, ves_port);
-       curl_easy_setopt(curl, CURLOPT_URL, url);
-
-    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
-    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
-    curl_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 0L);
-    curl_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 0L);
-
-       free(ves_ip);
-
-       return;
-}
-
-/*
- * Dynamically allocated memory;
- * Caller needs to free the memory after it uses the value.
- *
-*/
-cJSON* vesCreateCommonEventHeader(char *domain, char *event_type, char *source_name, int seq_id)
-{
-       char dateAndTime[50];
-       getCurrentDateAndTime(dateAndTime);
-
-       long useconds = getMicrosecondsSinceEpoch();
-
-       cJSON *commonEventHeader = cJSON_CreateObject();
-       if (commonEventHeader == NULL)
-       {
-               printf("Could not create JSON object: commonEventHeader\n");
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(commonEventHeader, "domain", domain) == NULL)
-       {
-               printf("Could not create JSON object: domain\n");
-               cJSON_Delete(commonEventHeader);
-               return NULL;
-       }
-
-       char eventId[200];
-       sprintf(eventId, "%s_%s", source_name, dateAndTime);
-
-       if (cJSON_AddStringToObject(commonEventHeader, "eventId", eventId) == NULL)
-       {
-               printf("Could not create JSON object: eventId\n");
-               cJSON_Delete(commonEventHeader);
-               return NULL;
-       }
-
-       char event_name[200];
-       sprintf(event_name, "%s_%s", domain, event_type);
-
-       if (cJSON_AddStringToObject(commonEventHeader, "eventName", event_name) == NULL)
-       {
-               printf("Could not create JSON object: eventName\n");
-               cJSON_Delete(commonEventHeader);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(commonEventHeader, "eventType", event_type) == NULL)
-       {
-               printf("Could not create JSON object: eventType\n");
-               cJSON_Delete(commonEventHeader);
-               return NULL;
-       }
-
-       if (cJSON_AddNumberToObject(commonEventHeader, "sequence", (double)(seq_id)) == NULL)
-       {
-               printf("Could not create JSON object: sequence\n");
-               cJSON_Delete(commonEventHeader);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(commonEventHeader, "priority", "Low") == NULL)
-       {
-               printf("Could not create JSON object: priority\n");
-               cJSON_Delete(commonEventHeader);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(commonEventHeader, "reportingEntityId", "") == NULL)
-       {
-               printf("Could not create JSON object: reportingEntityId\n");
-               cJSON_Delete(commonEventHeader);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(commonEventHeader, "reportingEntityName", source_name) == NULL)
-       {
-               printf("Could not create JSON object: reportingEntityName\n");
-               cJSON_Delete(commonEventHeader);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(commonEventHeader, "sourceId", "") == NULL)
-       {
-               printf("Could not create JSON object: sourceId\n");
-               cJSON_Delete(commonEventHeader);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(commonEventHeader, "sourceName", source_name) == NULL)
-       {
-               printf("Could not create JSON object: sourceName\n");
-               cJSON_Delete(commonEventHeader);
-               return NULL;
-       }
-
-       if (cJSON_AddNumberToObject(commonEventHeader, "startEpochMicrosec", (double)(useconds)) == NULL)
-       {
-               printf("Could not create JSON object: startEpochMicrosec\n");
-               cJSON_Delete(commonEventHeader);
-               return NULL;
-       }
-
-       if (cJSON_AddNumberToObject(commonEventHeader, "lastEpochMicrosec", (double)(useconds)) == NULL)
-       {
-               printf("Could not create JSON object: lastEpochMicrosec\n");
-               cJSON_Delete(commonEventHeader);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(commonEventHeader, "nfNamingCode", "sdn controller") == NULL)
-       {
-               printf("Could not create JSON object: nfNamingCode\n");
-               cJSON_Delete(commonEventHeader);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(commonEventHeader, "nfVendorName", "sdn") == NULL)
-       {
-               printf("Could not create JSON object: nfVendorName\n");
-               cJSON_Delete(commonEventHeader);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(commonEventHeader, "timeZoneOffset", "+00:00") == NULL)
-       {
-               printf("Could not create JSON object: timeZoneOffset\n");
-               cJSON_Delete(commonEventHeader);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(commonEventHeader, "version", "4.0.1") == NULL)
-       {
-               printf("Could not create JSON object: version\n");
-               cJSON_Delete(commonEventHeader);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(commonEventHeader, "vesEventListenerVersion", "7.0.1") == NULL)
-       {
-               printf("Could not create JSON object: vesEventListenerVersion\n");
-               cJSON_Delete(commonEventHeader);
-               return NULL;
-       }
-
-       return commonEventHeader;
-}
-
-/*
- * Dynamically allocated memory;
- * Caller needs to free the memory after it uses the value.
- *
-*/
-cJSON* vesCreateHeartbeatFields(int heartbeat_interval)
-{
-       char dateAndTime[50];
-       getCurrentDateAndTime(dateAndTime);
-
-       cJSON *heartbeatFields = cJSON_CreateObject();
-       if (heartbeatFields == NULL)
-       {
-               printf("Could not create JSON object: heartbeatFields\n");
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(heartbeatFields, "heartbeatFieldsVersion", "3.0") == NULL)
-       {
-               printf("Could not create JSON object: heartbeatFieldsVersion\n");
-               cJSON_Delete(heartbeatFields);
-               return NULL;
-       }
-
-       if (cJSON_AddNumberToObject(heartbeatFields, "heartbeatInterval", (double)(heartbeat_interval)) == NULL)
-       {
-               printf("Could not create JSON object: heartbeatInterval\n");
-               cJSON_Delete(heartbeatFields);
-               return NULL;
-       }
-
-       cJSON *additionalFields = cJSON_CreateObject();
-       if (additionalFields == NULL)
-       {
-               printf("Could not create JSON object: additionalFields\n");
-               cJSON_Delete(heartbeatFields);
-               return NULL;
-       }
-       cJSON_AddItemToObject(heartbeatFields, "additionalFields", additionalFields);
-
-       if (cJSON_AddStringToObject(additionalFields, "eventTime", dateAndTime) == NULL)
-       {
-               printf("Could not create JSON object: eventTime\n");
-               cJSON_Delete(heartbeatFields);
-               return NULL;
-       }
-
-       return heartbeatFields;
-}
-
-/*
- * Dynamically allocated memory;
- * Caller needs to free the memory after it uses the value.
- *
-*/
-char*  readConfigFileInString(void)
-{
-       char * buffer = 0;
-       long length;
-       char config_file[200];
-
-       //sprintf(config_file, "%s/configuration.json", getenv("SCRIPTS_DIR"));
-
-       // --> recommended fix, Karl Koch, Deutsche Telekom AG, 22. 5. 2020.
-       //     Path to config_file contains NULL when env variable is unset.
-       char *scripts_dir = getenv("SCRIPTS_DIR");
-       char *scripts_dir_default = "/opt/dev/ntsimulator/scripts";
-
-       if(NULL != scripts_dir)
-       {
-        sprintf(config_file, "%s/configuration.json", scripts_dir);
-       }
-       else
-       {
-        sprintf(config_file, "%s/configuration.json", scripts_dir_default);
-           printf("warning: opening config file in default path: <%s>\n",
-                  config_file);
-       }
-       // end of fix <--
-
-       FILE * f = fopen (config_file, "rb");
-
-       if (f)
-       {
-         fseek (f, 0, SEEK_END);
-         length = ftell (f);
-         fseek (f, 0, SEEK_SET);
-         buffer = malloc (length + 1);
-         if (buffer)
-         {
-           fread (buffer, 1, length, f);
-         }
-         fclose (f);
-         buffer[length] = '\0';
-       }
-
-       if (buffer)
-       {
-         return buffer;
-       }
-
-       return NULL;
-}
-
-void   writeConfigFile(char *config)
-{
-       char config_file[200];
-
-       //sprintf(config_file, "%s/configuration.json", getenv("SCRIPTS_DIR"));
-
-       // --> recommended fix, Karl Koch, Deutsche Telekom AG, 22. 5. 2020.
-       //     Path to config_file contains NULL when env variable is unset.
-       char *scripts_dir = getenv("SCRIPTS_DIR");
-       char *scripts_dir_default = "/opt/dev/ntsimulator/scripts";
-
-       if(NULL != scripts_dir)
-       {
-        sprintf(config_file, "%s/configuration.json", scripts_dir);
-       }
-       else
-       {
-        sprintf(config_file, "%s/configuration.json", scripts_dir_default);
-        printf("warning: opening config file in default path: <%s>\n",
-                  config_file);
-       }
-       // end of fix <--
-
-       FILE * f = fopen (config_file, "w");
-
-       if (f)
-       {
-               fputs(config, f);
-               fclose(f);
-       }
-       else
-       {
-               printf("Could not write configuration file");
-       }
-}
-
-int getFaultNotificationDelayPeriodFromConfigJson(int *period_array, int *count)
-{
-       char *stringConfig = readConfigFileInString();
-
-       if (stringConfig == NULL)
-       {
-               printf("Could not read JSON configuration file in string.");
-               return 0;
-       }
-
-       cJSON *jsonConfig = cJSON_Parse(stringConfig);
-       if (jsonConfig == NULL)
-       {
-               free(stringConfig);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-               }
-               return SR_ERR_OPERATION_FAILED;
-       }
-       //we don't need the string anymore
-       free(stringConfig);
-       stringConfig = NULL;
-
-       cJSON *notifConfig = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
-       if (!cJSON_IsObject(notifConfig))
-       {
-               printf("Configuration JSON is not as expected: notification-config is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *faultNotifDelay = cJSON_GetObjectItemCaseSensitive(notifConfig, "fault-notification-delay-period");
-       if (!cJSON_IsArray(faultNotifDelay))
-       {
-               printf("Configuration JSON is not as expected: fault-notification-delay-period is not an array.");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-    cJSON *iterator = NULL;
-    *count = 0;
-    int i = 0;
-
-    cJSON_ArrayForEach(iterator, faultNotifDelay) 
-    {
-        if (cJSON_IsNumber(iterator)) 
-        {
-            period_array[i++] = iterator->valueint;
-        } 
-        else 
-        {
-            printf("Invalid number in array!");
-        }
-    }
-
-    *count = i;
-
-       cJSON_Delete(jsonConfig);
-
-       return SR_ERR_OK;
-}
-
-int    getVesHeartbeatPeriodFromConfigJson(void)
-{
-       char *stringConfig = readConfigFileInString();
-       int vesHeartbeat = 0;
-
-       if (stringConfig == NULL)
-       {
-               printf("Could not read JSON configuration file in string.");
-               return 0;
-       }
-
-       cJSON *jsonConfig = cJSON_Parse(stringConfig);
-       if (jsonConfig == NULL)
-       {
-               free(stringConfig);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-               }
-               return SR_ERR_OPERATION_FAILED;
-       }
-       //we don't need the string anymore
-       free(stringConfig);
-       stringConfig = NULL;
-
-       cJSON *notifConfig = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
-       if (!cJSON_IsObject(notifConfig))
-       {
-               printf("Configuration JSON is not as expected: notification-config is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *vesHeartbeatPeriod = cJSON_GetObjectItemCaseSensitive(notifConfig, "ves-heartbeat-period");
-       if (!cJSON_IsNumber(vesHeartbeatPeriod))
-       {
-               printf("Configuration JSON is not as expected: ves-heartbeat-period is not a number");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       vesHeartbeat = (int)(vesHeartbeatPeriod->valuedouble);
-
-       cJSON_Delete(jsonConfig);
-
-       return vesHeartbeat;
-}
-
-
-/*
- * Dynamically allocated memory;
- * Caller needs to free the memory after it uses the value.
- *
-*/
-char*  getVesAuthMethodFromConfigJson(void)
-{
-       char *stringConfig = readConfigFileInString();
-
-       if (stringConfig == NULL)
-       {
-               printf("Could not read JSON configuration file in string.");
-               return 0;
-       }
-
-       cJSON *jsonConfig = cJSON_Parse(stringConfig);
-       if (jsonConfig == NULL)
-       {
-               free(stringConfig);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-               }
-               return NULL;
-       }
-       //we don't need the string anymore
-       free(stringConfig);
-       stringConfig = NULL;
-
-       cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
-       if (!cJSON_IsObject(vesDetails))
-       {
-               printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
-               cJSON_Delete(jsonConfig);
-               return NULL;
-       }
-
-       cJSON *vesAuthMethod = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-auth-method");
-       if (!cJSON_IsString(vesAuthMethod))
-       {
-               printf("Configuration JSON is not as expected: ves-endpoint-auth-method is not an object");
-               cJSON_Delete(jsonConfig);
-               return NULL;
-       }
-
-       char *auth_method_string = strdup(cJSON_GetStringValue(vesAuthMethod));
-
-       cJSON_Delete(jsonConfig);
-
-       return auth_method_string;
-}
-
-/*
- * Dynamically allocated memory;
- * Caller needs to free the memory after it uses the value.
- *
-*/
-char*  getVesIpFromConfigJson(void)
-{
-    char *stringConfig = readConfigFileInString();
-
-    if (stringConfig == NULL)
-    {
-        printf("Could not read JSON configuration file in string.");
-        return 0;
-    }
-
-    cJSON *jsonConfig = cJSON_Parse(stringConfig);
-    if (jsonConfig == NULL)
-    {
-        free(stringConfig);
-        const char *error_ptr = cJSON_GetErrorPtr();
-        if (error_ptr != NULL)
-        {
-            fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-        }
-        return NULL;
-    }
-    //we don't need the string anymore
-    free(stringConfig);
-    stringConfig = NULL;
-
-    cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
-    if (!cJSON_IsObject(vesDetails))
-    {
-        printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
-        cJSON_Delete(jsonConfig);
-        return NULL;
-    }
-
-    cJSON *vesIp = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-ip");
-    if (!cJSON_IsString(vesIp))
-    {
-        printf("Configuration JSON is not as expected: ves-endpoint-ip is not an object");
-        cJSON_Delete(jsonConfig);
-        return NULL;
-    }
-
-    char *ves_ip = strdup(cJSON_GetStringValue(vesIp));
-
-    cJSON_Delete(jsonConfig);
-
-    return ves_ip;
-}
-
-/*
- * Dynamically allocated memory;
- * Caller needs to free the memory after it uses the value.
- *
-*/
-char*  getVesUsernameFromConfigJson(void)
-{
-    char *stringConfig = readConfigFileInString();
-
-    if (stringConfig == NULL)
-    {
-        printf("Could not read JSON configuration file in string.");
-        return 0;
-    }
-
-    cJSON *jsonConfig = cJSON_Parse(stringConfig);
-    if (jsonConfig == NULL)
-    {
-        free(stringConfig);
-        const char *error_ptr = cJSON_GetErrorPtr();
-        if (error_ptr != NULL)
-        {
-            fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-        }
-        return NULL;
-    }
-    //we don't need the string anymore
-    free(stringConfig);
-    stringConfig = NULL;
-
-    cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
-    if (!cJSON_IsObject(vesDetails))
-    {
-        printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
-        cJSON_Delete(jsonConfig);
-        return NULL;
-    }
-
-    cJSON *vesUsername = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-username");
-    if (!cJSON_IsString(vesUsername))
-    {
-        printf("Configuration JSON is not as expected: ves-endpoint-username is not an object");
-        cJSON_Delete(jsonConfig);
-        return NULL;
-    }
-
-    char *ves_username = strdup(cJSON_GetStringValue(vesUsername));
-
-    cJSON_Delete(jsonConfig);
-
-    return ves_username;
-}
-
-/*
- * Dynamically allocated memory;
- * Caller needs to free the memory after it uses the value.
- *
-*/
-char*  getVesPasswordFromConfigJson(void)
-{
-    char *stringConfig = readConfigFileInString();
-
-    if (stringConfig == NULL)
-    {
-        printf("Could not read JSON configuration file in string.");
-        return 0;
-    }
-
-    cJSON *jsonConfig = cJSON_Parse(stringConfig);
-    if (jsonConfig == NULL)
-    {
-        free(stringConfig);
-        const char *error_ptr = cJSON_GetErrorPtr();
-        if (error_ptr != NULL)
-        {
-            fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-        }
-        return NULL;
-    }
-    //we don't need the string anymore
-    free(stringConfig);
-    stringConfig = NULL;
-
-    cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
-    if (!cJSON_IsObject(vesDetails))
-    {
-        printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
-        cJSON_Delete(jsonConfig);
-        return NULL;
-    }
-
-    cJSON *vesPassword = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-password");
-    if (!cJSON_IsString(vesPassword))
-    {
-        printf("Configuration JSON is not as expected: ves-endpoint-password is not an object");
-        cJSON_Delete(jsonConfig);
-        return NULL;
-    }
-
-    char *ves_password = strdup(cJSON_GetStringValue(vesPassword));
-
-    cJSON_Delete(jsonConfig);
-
-    return ves_password;
-}
-
-int    getVesPortFromConfigJson(void)
-{
-       char *stringConfig = readConfigFileInString();
-
-       if (stringConfig == NULL)
-       {
-               printf("Could not read JSON configuration file in string.");
-               return 0;
-       }
-
-       cJSON *jsonConfig = cJSON_Parse(stringConfig);
-       if (jsonConfig == NULL)
-       {
-               free(stringConfig);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-               }
-               return SR_ERR_OPERATION_FAILED;
-       }
-       //we don't need the string anymore
-       free(stringConfig);
-       stringConfig = NULL;
-
-       cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
-       if (!cJSON_IsObject(vesDetails))
-       {
-               printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *vesPort = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-port");
-       if (!cJSON_IsNumber(vesPort))
-       {
-               printf("Configuration JSON is not as expected: ves-endpoint-port is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       int port = (int)(vesPort->valuedouble);
-
-       cJSON_Delete(jsonConfig);
-
-       return port;
-}
-
-int    getVesRegistrationFromConfigJson(void)
-{
-       char *stringConfig = readConfigFileInString();
-
-       if (stringConfig == NULL)
-       {
-               printf("Could not read JSON configuration file in string.");
-               return 0;
-       }
-
-       cJSON *jsonConfig = cJSON_Parse(stringConfig);
-       if (jsonConfig == NULL)
-       {
-               free(stringConfig);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-               }
-               return SR_ERR_OPERATION_FAILED;
-       }
-       //we don't need the string anymore
-       free(stringConfig);
-       stringConfig = NULL;
-
-       cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
-       if (!cJSON_IsObject(vesDetails))
-       {
-               printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *vesReg = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-registration");
-       if (!cJSON_IsBool(vesReg))
-       {
-               printf("Configuration JSON is not as expected: ves-registration is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       int is_ves_reg = (cJSON_IsTrue(vesReg)) ? TRUE : FALSE;
-
-       cJSON_Delete(jsonConfig);
-
-       return is_ves_reg;
-}
-
-/*
- * Dynamically allocated memory;
- * Caller needs to free the memory after it uses the value.
- *
-*/
-cJSON* vesCreatePnfRegistrationFields(int port, bool is_tls)
-{
-       cJSON *pnfRegistrationFields = cJSON_CreateObject();
-       if (pnfRegistrationFields == NULL)
-       {
-               printf("Could not create JSON object: pnfRegistrationFields\n");
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(pnfRegistrationFields, "pnfRegistrationFieldsVersion", "2.0") == NULL)
-       {
-               printf("Could not create JSON object: pnfRegistrationFieldsVersion\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(pnfRegistrationFields, "lastServiceDate", "2019-08-16") == NULL)
-       {
-               printf("Could not create JSON object: lastServiceDate\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       char mac_addr[40];
-       generateRandomMacAddress(mac_addr);
-
-       if (cJSON_AddStringToObject(pnfRegistrationFields, "macAddress", mac_addr) == NULL)
-       {
-               printf("Could not create JSON object: macAddress\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(pnfRegistrationFields, "manufactureDate", "2019-08-16") == NULL)
-       {
-               printf("Could not create JSON object: manufactureDate\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(pnfRegistrationFields, "modelNumber", "Simulated Device Melacon") == NULL)
-       {
-               printf("Could not create JSON object: manufactureDate\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(pnfRegistrationFields, "oamV4IpAddress", getenv("EXTERNAL_NTS_IP")) == NULL)
-       {
-               printf("Could not create JSON object: oamV4IpAddress\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(pnfRegistrationFields, "oamV6IpAddress", "0:0:0:0:0:ffff:a0a:011") == NULL)
-       {
-               printf("Could not create JSON object: oamV6IpAddress\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       char serial_number[100];
-       sprintf(serial_number, "%s-%s-%d-Simulated Device Melacon", getenv("HOSTNAME"), getenv("EXTERNAL_NTS_IP"), port);
-
-       if (cJSON_AddStringToObject(pnfRegistrationFields, "serialNumber", serial_number) == NULL)
-       {
-               printf("Could not create JSON object: serialNumber\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(pnfRegistrationFields, "softwareVersion", "2.3.5") == NULL)
-       {
-               printf("Could not create JSON object: softwareVersion\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(pnfRegistrationFields, "unitFamily", "Simulated Device") == NULL)
-       {
-               printf("Could not create JSON object: unitFamily\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(pnfRegistrationFields, "unitType", "O-RAN-sim") == NULL)
-       {
-               printf("Could not create JSON object: unitType\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(pnfRegistrationFields, "vendorName", "Melacon") == NULL)
-       {
-               printf("Could not create JSON object: vendorName\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       cJSON *additionalFields = cJSON_CreateObject();
-       if (additionalFields == NULL)
-       {
-               printf("Could not create JSON object: additionalFields\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-       cJSON_AddItemToObject(pnfRegistrationFields, "additionalFields", additionalFields);
-
-       char portString[10];
-       sprintf(portString, "%d", port);
-
-       if (cJSON_AddStringToObject(additionalFields, "oamPort", portString) == NULL)
-       {
-               printf("Could not create JSON object: oamPort\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       if (is_tls)
-       {
-               //TLS specific configuration
-               if (cJSON_AddStringToObject(additionalFields, "protocol", "TLS") == NULL)
-               {
-                       printf("Could not create JSON object: protocol\n");
-                       cJSON_Delete(pnfRegistrationFields);
-                       return NULL;
-               }
-
-               //TODO here we have the username from the docker container hardcoded: netconf
-               if (cJSON_AddStringToObject(additionalFields, "username", "netconf") == NULL)
-               {
-                       printf("Could not create JSON object: username\n");
-                       cJSON_Delete(pnfRegistrationFields);
-                       return NULL;
-               }
-
-               if (cJSON_AddStringToObject(additionalFields, "keyId", "device-key") == NULL)
-               {
-                       printf("Could not create JSON object: keyId\n");
-                       cJSON_Delete(pnfRegistrationFields);
-                       return NULL;
-               }
-       }
-       else
-       {
-               //SSH specific configuration
-               if (cJSON_AddStringToObject(additionalFields, "protocol", "SSH") == NULL)
-               {
-                       printf("Could not create JSON object: protocol\n");
-                       cJSON_Delete(pnfRegistrationFields);
-                       return NULL;
-               }
-
-               //TODO here we have the username from the docker container hardcoded: netconf
-               if (cJSON_AddStringToObject(additionalFields, "username", "netconf") == NULL)
-               {
-                       printf("Could not create JSON object: username\n");
-                       cJSON_Delete(pnfRegistrationFields);
-                       return NULL;
-               }
-
-               //TODO here we have the password from the docker container hardcoded: netconf
-               if (cJSON_AddStringToObject(additionalFields, "password", "netconf") == NULL)
-               {
-                       printf("Could not create JSON object: password\n");
-                       cJSON_Delete(pnfRegistrationFields);
-                       return NULL;
-               }
-       }
-
-       if (cJSON_AddStringToObject(additionalFields, "reconnectOnChangedSchema", "false") == NULL)
-       {
-               printf("Could not create JSON object: reconnectOnChangedSchema\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(additionalFields, "sleep-factor", "1.5") == NULL)
-       {
-               printf("Could not create JSON object: sleep-factor\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(additionalFields, "tcpOnly", "false") == NULL)
-       {
-               printf("Could not create JSON object: tcpOnly\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(additionalFields, "connectionTimeout", "20000") == NULL)
-       {
-               printf("Could not create JSON object: connectionTimeout\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(additionalFields, "maxConnectionAttempts", "100") == NULL)
-       {
-               printf("Could not create JSON object: maxConnectionAttempts\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(additionalFields, "betweenAttemptsTimeout", "2000") == NULL)
-       {
-               printf("Could not create JSON object: betweenAttemptsTimeout\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(additionalFields, "keepaliveDelay", "120") == NULL)
-       {
-               printf("Could not create JSON object: keepaliveDelay\n");
-               cJSON_Delete(pnfRegistrationFields);
-               return NULL;
-       }
-
-       return pnfRegistrationFields;
-}
-
-int    getNetconfAvailableFromConfigJson(void)
-{
-       char *stringConfig = readConfigFileInString();
-
-       if (stringConfig == NULL)
-       {
-               printf("Could not read JSON configuration file in string.");
-               return 0;
-       }
-
-       cJSON *jsonConfig = cJSON_Parse(stringConfig);
-       if (jsonConfig == NULL)
-       {
-               free(stringConfig);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-               }
-               return SR_ERR_OPERATION_FAILED;
-       }
-       //we don't need the string anymore
-       free(stringConfig);
-       stringConfig = NULL;
-
-       cJSON *notifDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
-       if (!cJSON_IsObject(notifDetails))
-       {
-               printf("Configuration JSON is not as expected: notification-config is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *isNetconfAvailable = cJSON_GetObjectItemCaseSensitive(notifDetails, "is-netconf-available");
-       if (!cJSON_IsBool(isNetconfAvailable))
-       {
-               printf("Configuration JSON is not as expected: is-netconf-available is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       int is_netconf_available = (cJSON_IsTrue(isNetconfAvailable)) ? TRUE : FALSE;
-
-       cJSON_Delete(jsonConfig);
-
-       return is_netconf_available;
-}
-
-int    getVesAvailableFromConfigJson(void)
-{
-       char *stringConfig = readConfigFileInString();
-
-       if (stringConfig == NULL)
-       {
-               printf("Could not read JSON configuration file in string.");
-               return 0;
-       }
-
-       cJSON *jsonConfig = cJSON_Parse(stringConfig);
-       if (jsonConfig == NULL)
-       {
-               free(stringConfig);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-               }
-               return SR_ERR_OPERATION_FAILED;
-       }
-       //we don't need the string anymore
-       free(stringConfig);
-       stringConfig = NULL;
-
-       cJSON *notifDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
-       if (!cJSON_IsObject(notifDetails))
-       {
-               printf("Configuration JSON is not as expected: notification-config is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       cJSON *isVesAvailable = cJSON_GetObjectItemCaseSensitive(notifDetails, "is-ves-available");
-       if (!cJSON_IsBool(isVesAvailable))
-       {
-               printf("Configuration JSON is not as expected: is-ves-available is not an object");
-               cJSON_Delete(jsonConfig);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       int is_netconf_available = (cJSON_IsTrue(isVesAvailable)) ? TRUE : FALSE;
-
-       cJSON_Delete(jsonConfig);
-
-       return is_netconf_available;
-}
-
-/*
- * Dynamically allocated memory;
- * Caller needs to free the memory after it uses the value.
- *
-*/
-cJSON* vesCreateFaultFields(char *alarm_condition, char *alarm_object, char *severity, char *date_time, char *specific_problem)
-{
-       cJSON *faultFields = cJSON_CreateObject();
-       if (faultFields == NULL)
-       {
-               printf("Could not create JSON object: faultFields\n");
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(faultFields, "faultFieldsVersion", "4.0") == NULL)
-       {
-               printf("Could not create JSON object: faultFieldsVersion\n");
-               cJSON_Delete(faultFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(faultFields, "alarmCondition", alarm_condition) == NULL)
-       {
-               printf("Could not create JSON object: alarmCondition\n");
-               cJSON_Delete(faultFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(faultFields, "alarmInterfaceA", alarm_object) == NULL)
-       {
-               printf("Could not create JSON object: alarmInterfaceA\n");
-               cJSON_Delete(faultFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(faultFields, "eventSourceType", "O_RAN_COMPONENT") == NULL)
-       {
-               printf("Could not create JSON object: eventSourceType\n");
-               cJSON_Delete(faultFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(faultFields, "specificProblem", specific_problem) == NULL)
-       {
-               printf("Could not create JSON object: specificProblem\n");
-               cJSON_Delete(faultFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(faultFields, "eventSeverity", severity) == NULL)
-       {
-               printf("Could not create JSON object: eventSeverity\n");
-               cJSON_Delete(faultFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(faultFields, "vfStatus", "Active") == NULL)
-       {
-               printf("Could not create JSON object: vfStatus\n");
-               cJSON_Delete(faultFields);
-               return NULL;
-       }
-
-       cJSON *alarmAdditionalInformation = cJSON_CreateObject();
-       if (alarmAdditionalInformation == NULL)
-       {
-               printf("Could not create JSON object: alarmAdditionalInformation\n");
-               cJSON_Delete(faultFields);
-               return NULL;
-       }
-       cJSON_AddItemToObject(faultFields, "alarmAdditionalInformation", alarmAdditionalInformation);
-
-       if (cJSON_AddStringToObject(alarmAdditionalInformation, "eventTime", date_time) == NULL)
-       {
-               printf("Could not create JSON object: eventTime\n");
-               cJSON_Delete(faultFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(alarmAdditionalInformation, "equipType", "O-RAN-sim") == NULL)
-       {
-               printf("Could not create JSON object: equipType\n");
-               cJSON_Delete(faultFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(alarmAdditionalInformation, "vendor", "Melacon") == NULL)
-       {
-               printf("Could not create JSON object: vendor\n");
-               cJSON_Delete(faultFields);
-               return NULL;
-       }
-
-       if (cJSON_AddStringToObject(alarmAdditionalInformation, "model", "Simulated Device") == NULL)
-       {
-               printf("Could not create JSON object: model\n");
-               cJSON_Delete(faultFields);
-               return NULL;
-       }
-
-       return faultFields;
-}
-
-static cJSON* createSeverityCounters(counterAlarms count)
-{
-    cJSON *severityCounters = cJSON_CreateObject();
-    if (severityCounters == NULL)
-    {
-        printf("Could not create JSON object: severityCounters\n");
-        return NULL;
-    }
-
-    if (cJSON_AddNumberToObject(severityCounters, "severity-normal", count.normal) == NULL)
-    {
-        printf("Could not create JSON object: severity-normal\n");
-        return NULL;
-    }
-
-    if (cJSON_AddNumberToObject(severityCounters, "severity-warning", count.warning) == NULL)
-    {
-        printf("Could not create JSON object: severity-warning\n");
-        return NULL;
-    }
-
-    if (cJSON_AddNumberToObject(severityCounters, "severity-minor", count.minor) == NULL)
-    {
-        printf("Could not create JSON object: severity-minor\n");
-        return NULL;
-    }
-
-    if (cJSON_AddNumberToObject(severityCounters, "severity-major", count.major) == NULL)
-    {
-        printf("Could not create JSON object: severity-major\n");
-        return NULL;
-    }
-
-    if (cJSON_AddNumberToObject(severityCounters, "severity-critical", count.critical) == NULL)
-    {
-        printf("Could not create JSON object: severity-critical\n");
-        return NULL;
-    }
-
-    return severityCounters;
-}
-
-void writeStatusFile(char *status)
-{
-       char status_file[200];
-       sprintf(status_file, "%s/status.json", getenv("SCRIPTS_DIR"));
-       FILE * f = fopen (status_file, "w");
-
-       if (f)
-       {
-               fputs(status, f);
-               fclose(f);
-       }
-       else
-       {
-               printf("Could not write status file!\n");
-       }
-}
-
-int    writeSkeletonStatusFile()
-{
-    cJSON *statusObject = cJSON_CreateObject();
-    if (statusObject == NULL)
-    {
-        printf("Could not create JSON object: statusObject\n");
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    // counterAlarms counter = {
-    //     .normal = 0,
-    //     .warning = 0,
-    //     .minor = 0,
-    //     .major = 0,
-    //     .critical = 0
-    // };
-
-    // cJSON *totalVesNotifications = createSeverityCounters(counter);
-    // if (totalVesNotifications == NULL)
-    // {
-    //     printf("Could not create JSON object: totalVesNotifications\n");
-    //     cJSON_Delete(statusObject);
-    //     return SR_ERR_OPERATION_FAILED;
-    // }
-    // cJSON_AddItemToObject(statusObject, "total-ves-notifications-sent", totalVesNotifications);
-
-    // cJSON *totalNetconfNotifications = createSeverityCounters(counter);
-    // if (totalNetconfNotifications == NULL)
-    // {
-    //     printf("Could not create JSON object: totalNetconfNotifications\n");
-    //     cJSON_Delete(statusObject);
-    //     return SR_ERR_OPERATION_FAILED;
-    // }
-    // cJSON_AddItemToObject(statusObject, "total-netconf-notifications-sent", totalNetconfNotifications);
-
-    cJSON *deviceList = cJSON_CreateArray();
-    if (deviceList == NULL)
-    {
-        printf("Could not create JSON object: deviceList\n");
-        cJSON_Delete(statusObject);
-        return SR_ERR_OPERATION_FAILED;
-       }
-    cJSON_AddItemToObject(statusObject, "device-list", deviceList);
-
-    char *status_string = NULL;
-
-    status_string = cJSON_PrintUnformatted(statusObject);
-
-    writeStatusFile(status_string);
-
-    if (status_string != NULL)
-    {
-        free(status_string);
-        status_string = NULL;
-    }
-
-    if (statusObject != NULL)
-    {
-           cJSON_Delete(statusObject);
-    }
-
-    return SR_ERR_OK;
-}
-
-/*
- * Dynamically allocated memory;
- * Caller needs to free the memory after it uses the value.
- *
-*/
-char*  readStatusFileInString(void)
-{
-       char * buffer = 0;
-       long length;
-       char config_file[200];
-       sprintf(config_file, "%s/status.json", getenv("SCRIPTS_DIR"));
-       FILE * f = fopen (config_file, "rb");
-
-       if (f)
-       {
-         fseek (f, 0, SEEK_END);
-         length = ftell (f);
-         fseek (f, 0, SEEK_SET);
-         buffer = malloc (length + 1);
-         if (buffer)
-         {
-           fread (buffer, 1, length, f);
-         }
-         fclose (f);
-         buffer[length] = '\0';
-       }
-
-       if (buffer)
-       {
-         return buffer;
-       }
-
-       return NULL;
-}
-
-/*
- * Dynamically allocated memory;
- * Caller needs to free the memory after it uses the value.
- *
-*/
-cJSON*  getDeviceListFromStatusFile(void)
-{
-    char *stringStatus = readStatusFileInString();
-
-       if (stringStatus == NULL)
-       {
-               printf("Could not read status file!\n");
-               return NULL;
-       }
-
-       cJSON *jsonStatus = cJSON_Parse(stringStatus);
-       if (jsonStatus == NULL)
-       {
-               free(stringStatus);
-               const char *error_ptr = cJSON_GetErrorPtr();
-               if (error_ptr != NULL)
-               {
-                       fprintf(stderr, "Could not parse JSON status! Error before: %s\n", error_ptr);
-               }
-               return NULL;
-       }
-       //we don't need the string anymore
-       free(stringStatus);
-       stringStatus = NULL;
-
-    return jsonStatus;
-}
-
-cJSON* createDeviceListEntry(counterAlarms ves_counter, counterAlarms netconf_counter)
-{
-    cJSON *deviceListEntry = cJSON_CreateObject();
-    if (deviceListEntry == NULL)
-    {
-        printf("Could not create JSON object: deviceListEntry\n");
-        return NULL;
-    }
-
-    char hostname[100];
-    sprintf(hostname, "%s", getenv("HOSTNAME"));
-
-    if (cJSON_AddStringToObject(deviceListEntry, "device-name", hostname) == NULL)
-    {
-        printf("Could not create JSON object: device-name\n");
-        cJSON_Delete(deviceListEntry);
-        return NULL;
-    }
-
-    cJSON *vesNotificationsSent = createSeverityCounters(ves_counter);
-    if (vesNotificationsSent == NULL)
-    {
-        printf("Could not create JSON object: vesNotificationsSent\n");
-        cJSON_Delete(deviceListEntry);
-        return NULL;
-    }
-    cJSON_AddItemToObject(deviceListEntry, "ves-notifications-sent", vesNotificationsSent);
-
-    cJSON *netconfNotificationsSent = createSeverityCounters(netconf_counter);
-    if (netconfNotificationsSent == NULL)
-    {
-        printf("Could not create JSON object: netconfNotificationsSent\n");
-        cJSON_Delete(deviceListEntry);
-        return NULL;
-    }
-    cJSON_AddItemToObject(deviceListEntry, "netconf-notifications-sent", netconfNotificationsSent);
-
-    return deviceListEntry;
-}
-
-static void modifySeverityCounters(cJSON **severityCounters, counterAlarms count)
-{
-    cJSON *severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-normal");
-    if (!cJSON_IsNumber(severity))
-    {
-        printf("Status JSON is not as expected: severity-normal is not an number");
-        return;
-    }
-    //we set the value of the severity-normal object
-    cJSON_SetNumberValue(severity, count.normal);
-
-    severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-warning");
-    if (!cJSON_IsNumber(severity))
-    {
-        printf("Status JSON is not as expected: severity-warning is not an number");
-        return;
-    }
-    //we set the value of the severity-warning object
-    cJSON_SetNumberValue(severity, count.warning);
-
-    severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-minor");
-    if (!cJSON_IsNumber(severity))
-    {
-        printf("Status JSON is not as expected: severity-minor is not an number");
-        return;
-    }
-    //we set the value of the severity-minor object
-    cJSON_SetNumberValue(severity, count.minor);
-
-    severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-major");
-    if (!cJSON_IsNumber(severity))
-    {
-        printf("Status JSON is not as expected: severity-major is not an number");
-        return;
-    }
-    //we set the value of the severity-major object
-       cJSON_SetNumberValue(severity, count.major);
-
-    severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-critical");
-    if (!cJSON_IsNumber(severity))
-    {
-        printf("Status JSON is not as expected: severity-critical is not an number");
-        return;
-    }
-    //we set the value of the severity-critical object
-       cJSON_SetNumberValue(severity, count.critical);
-
-    return;
-}
-
-static void modifyDeviceListEntry(cJSON **deviceListEntry, counterAlarms ves_counter, counterAlarms netconf_counter)
-{
-    cJSON *vesNotificationsSent= cJSON_GetObjectItemCaseSensitive(*deviceListEntry, "ves-notifications-sent");
-    if (!cJSON_IsObject(vesNotificationsSent))
-    {
-        printf("Status JSON is not as expected: ves-notifications-sent is not a object");
-        return;
-    }
-
-    modifySeverityCounters(&vesNotificationsSent, ves_counter);
-
-    cJSON *netconfNotificationsSent= cJSON_GetObjectItemCaseSensitive(*deviceListEntry, "netconf-notifications-sent");
-    if (!cJSON_IsObject(netconfNotificationsSent))
-    {
-        printf("Status JSON is not as expected: netconf-notifications-sent is not a object");
-        return;
-    }
-
-    modifySeverityCounters(&netconfNotificationsSent, netconf_counter);
-}
-
-int writeStatusNotificationCounters(counterAlarms ves_counter, counterAlarms netconf_counter)
-{
-       cJSON *jsonStatus = getDeviceListFromStatusFile();
-
-       cJSON *deviceList = cJSON_GetObjectItemCaseSensitive(jsonStatus, "device-list");
-       if (!cJSON_IsArray(deviceList))
-       {
-               printf("Status JSON is not as expected: device-list is not an object");
-               cJSON_Delete(jsonStatus);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-    int array_size = cJSON_GetArraySize(deviceList);
-
-    int found = 0;
-    for (int i=0; i<array_size; ++i)
-    {
-        cJSON *deviceListEntry = cJSON_GetArrayItem(deviceList, i);
-        char hostname[100];
-        sprintf(hostname, "%s", getenv("HOSTNAME"));
-
-        cJSON *deviceName = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "device-name");
-        if (!cJSON_IsString(deviceName))
-        {
-            printf("Status JSON is not as expected: device-name is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        char *deviceNameString = cJSON_GetStringValue(deviceName);
-
-        if (strcmp(hostname, deviceNameString) == 0)
-        {
-            modifyDeviceListEntry(&deviceListEntry, ves_counter, netconf_counter);
-            found = 1;
-            break;
-        }
-    }
-    if (found == 0)
-    {
-        cJSON* deviceListEntry = createDeviceListEntry(ves_counter, netconf_counter);
-    
-        cJSON_AddItemToArray(deviceList, deviceListEntry);  
-    }
-
-       //writing the new JSON to the configuration file
-       char *stringStatus = cJSON_PrintUnformatted(jsonStatus);
-       writeStatusFile(stringStatus);
-
-    if (stringStatus != NULL)
-    {
-        free(stringStatus);
-        stringStatus = NULL;
-    }
-
-    if (jsonStatus != NULL)
-    {
-           cJSON_Delete(jsonStatus);
-    }
-
-       return SR_ERR_OK;
-}
-
-
-int removeDeviceEntryFromStatusFile(char *containerId)
-{
-    cJSON *jsonStatus = getDeviceListFromStatusFile();
-
-       cJSON *deviceList = cJSON_GetObjectItemCaseSensitive(jsonStatus, "device-list");
-       if (!cJSON_IsArray(deviceList))
-       {
-               printf("Status JSON is not as expected: device-list is not an object");
-               cJSON_Delete(jsonStatus);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-    int array_size = cJSON_GetArraySize(deviceList);
-    int found = array_size;
-
-    for (int i=0; i<array_size; ++i)
-    {
-        cJSON *deviceListEntry = cJSON_GetArrayItem(deviceList, i);
-        char hostname[100];
-        sprintf(hostname, "%s", getenv("HOSTNAME"));
-
-        cJSON *deviceName = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "device-name");
-        if (!cJSON_IsString(deviceName))
-        {
-            printf("Status JSON is not as expected: device-name is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        char *deviceNameString = cJSON_GetStringValue(deviceName);
-
-        if (strcmp(containerId, deviceNameString) == 0)
-        {
-            found = i;
-            break;
-        }
-    }
-
-    if (found < array_size)
-    {
-        cJSON_DeleteItemFromArray(deviceList, found);
-    }
-    else
-    {
-        printf("Could not find status file entry for device with id=\"%s\"", containerId);
-    }
-
-       //writing the new JSON to the configuration file
-       char *stringStatus = cJSON_PrintUnformatted(jsonStatus);
-       writeStatusFile(stringStatus);
-
-    if (stringStatus != NULL)
-    {
-        free(stringStatus);
-        stringStatus = NULL;
-    }
-
-    if (jsonStatus != NULL)
-    {
-        cJSON_Delete(jsonStatus);
-    }
-
-       return SR_ERR_OK;
-}
-
-int compute_notifications_count(counterAlarms *ves_counter, counterAlarms *netconf_counter)
-{
-    ves_counter->normal = ves_counter->warning = \
-            ves_counter->minor = ves_counter->major = \
-            ves_counter->critical = 0;
-    netconf_counter->normal = netconf_counter->warning = \
-            netconf_counter->minor = netconf_counter->major = \
-            netconf_counter->critical = 0;
-
-    cJSON *jsonStatus = getDeviceListFromStatusFile();
-
-    cJSON *deviceList = cJSON_GetObjectItemCaseSensitive(jsonStatus, "device-list");
-       if (!cJSON_IsArray(deviceList))
-       {
-               printf("Status JSON is not as expected: device-list is not an object");
-               cJSON_Delete(jsonStatus);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-    int array_size = cJSON_GetArraySize(deviceList);
-
-    for (int i=0; i<array_size; ++i)
-    {
-        cJSON *deviceListEntry = cJSON_GetArrayItem(deviceList, i);
-
-        cJSON *vesNotifications = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "ves-notifications-sent");
-        if (!cJSON_IsObject(vesNotifications))
-        {
-            printf("Status JSON is not as expected: ves-notifications-sent is not an object.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-
-        cJSON *severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-normal");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-normal is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        int counter = (int)(severity->valuedouble);
-        ves_counter->normal += counter;
-
-        severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-warning");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-warning is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        counter = (int)(severity->valuedouble);
-        ves_counter->warning += counter;
-
-        severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-minor");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-minor is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        counter = (int)(severity->valuedouble);
-        ves_counter->minor += counter;
-
-        severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-major");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-major is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        counter = (int)(severity->valuedouble);
-        ves_counter->major += counter;
-
-        severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-critical");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-critical is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        counter = (int)(severity->valuedouble);
-        ves_counter->critical += counter;
-
-        cJSON *netconfNotifications = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "netconf-notifications-sent");
-        if (!cJSON_IsObject(netconfNotifications))
-        {
-            printf("Status JSON is not as expected: netconf-notifications-sent is not an object.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-
-        severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-normal");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-normal is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        
-        counter = (int)(severity->valuedouble);
-        netconf_counter->normal += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
-
-        severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-warning");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-warning is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        counter = (int)(severity->valuedouble);
-        netconf_counter->warning += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
-
-        severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-minor");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-minor is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        counter = (int)(severity->valuedouble);
-        netconf_counter->minor += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
-
-        severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-major");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-major is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        counter = (int)(severity->valuedouble);
-        netconf_counter->major += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
-
-        severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-critical");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-critical is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        counter = (int)(severity->valuedouble);
-        netconf_counter->critical += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
-    }
-
-    cJSON_Delete(jsonStatus);
-
-    return SR_ERR_OK;
-}
-
-int getDeviceCounters(char *containerId, counterAlarms *ves_counter, counterAlarms *netconf_counter)
-{
-    cJSON *jsonStatus = getDeviceListFromStatusFile();
-
-    cJSON *deviceList = cJSON_GetObjectItemCaseSensitive(jsonStatus, "device-list");
-       if (!cJSON_IsArray(deviceList))
-       {
-               printf("Status JSON is not as expected: device-list is not an object");
-               cJSON_Delete(jsonStatus);
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-    int array_size = cJSON_GetArraySize(deviceList);
-
-    ves_counter->critical = ves_counter->major = ves_counter->minor = ves_counter->warning = ves_counter->normal = 0;
-    netconf_counter->critical = netconf_counter->major = netconf_counter->minor = netconf_counter->warning = netconf_counter->normal = 0;
-
-    for (int i=0; i<array_size; ++i)
-    {
-        cJSON *deviceListEntry = cJSON_GetArrayItem(deviceList, i);
-
-        cJSON *deviceName = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "device-name");
-        if (!cJSON_IsString(deviceName))
-        {
-            printf("Status JSON is not as expected: device-name is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        char *deviceNameString = cJSON_GetStringValue(deviceName);
-
-        if (strcmp(deviceNameString, containerId) != 0)
-        {
-            continue;
-        }
-
-        cJSON *vesNotifications = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "ves-notifications-sent");
-        if (!cJSON_IsObject(vesNotifications))
-        {
-            printf("Status JSON is not as expected: ves-notifications-sent is not an object.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-
-        cJSON *severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-normal");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-normal is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        int counter = (int)(severity->valuedouble);
-        ves_counter->normal = counter;
-
-        severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-warning");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-warning is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        counter = (int)(severity->valuedouble);
-        ves_counter->warning = counter;
-
-        severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-minor");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-minor is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        counter = (int)(severity->valuedouble);
-        ves_counter->minor = counter;
-
-        severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-major");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-major is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        counter = (int)(severity->valuedouble);
-        ves_counter->major = counter;
-
-        severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-critical");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-critical is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        counter = (int)(severity->valuedouble);
-        ves_counter->critical = counter;
-
-        cJSON *netconfNotifications = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "netconf-notifications-sent");
-        if (!cJSON_IsObject(netconfNotifications))
-        {
-            printf("Status JSON is not as expected: netconf-notifications-sent is not an object.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-
-        severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-normal");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-normal is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        
-        counter = (int)(severity->valuedouble);
-        netconf_counter->normal = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
-
-        severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-warning");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-warning is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        counter = (int)(severity->valuedouble);
-        netconf_counter->warning = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
-
-        severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-minor");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-minor is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        counter = (int)(severity->valuedouble);
-        netconf_counter->minor = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
-
-        severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-major");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-major is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        counter = (int)(severity->valuedouble);
-        netconf_counter->major = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
-
-        severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-critical");
-        if (!cJSON_IsNumber(severity))
-        {
-            printf("Status JSON is not as expected: severity-critical is not a string.");
-            cJSON_Delete(jsonStatus);
-            return SR_ERR_OPERATION_FAILED;
-        }
-        counter = (int)(severity->valuedouble);
-        netconf_counter->critical = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
-    }
-
-    cJSON_Delete(jsonStatus);
-
-    return SR_ERR_OK;
-}
-
-int writeSkeletonConfigFile()
-{
-    cJSON *configObject = cJSON_CreateObject();
-    if (configObject == NULL)
-    {
-        printf("Could not create JSON object: configObject\n");
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    cJSON *notificationConfig = cJSON_CreateObject();
-    if (notificationConfig == NULL)
-    {
-        printf("Could not create JSON object: notificationConfig\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-    cJSON_AddItemToObject(configObject, "notification-config", notificationConfig);
-
-    if (cJSON_AddNumberToObject(notificationConfig, "ves-heartbeat-period", 0) == NULL)
-    {
-        printf("Could not create JSON object: ves-heartbeat-period\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    if (cJSON_AddTrueToObject(notificationConfig, "is-netconf-available") == NULL)
-    {
-        printf("Could not create JSON object: is-netconf-available\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    if (cJSON_AddTrueToObject(notificationConfig, "is-ves-available") == NULL)
-    {
-        printf("Could not create JSON object: is-ves-available\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    cJSON *faultNotificationDelayPeriod = cJSON_CreateArray();
-    if (faultNotificationDelayPeriod == NULL)
-    {
-        printf("Could not create JSON object: faultNotificationDelayPeriod\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-       }
-    cJSON_AddItemToObject(notificationConfig, "fault-notification-delay-period", faultNotificationDelayPeriod);
-
-    cJSON *arrayItem = cJSON_CreateNumber(0);
-    if (arrayItem == NULL)
-    {
-        printf("Could not create JSON object: arrayItem\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-       }
-    cJSON_AddItemToArray(faultNotificationDelayPeriod, arrayItem);
-
-    cJSON *vesEndPointDetails = cJSON_CreateObject();
-    if (vesEndPointDetails == NULL)
-    {
-        printf("Could not create JSON object: vesEndPointDetails\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-    cJSON_AddItemToObject(configObject, "ves-endpoint-details", vesEndPointDetails);
-
-    if (cJSON_AddStringToObject(vesEndPointDetails, "ves-endpoint-ip", "172.17.0.1") == NULL)
-    {
-        printf("Could not create JSON object: ves-endpoint-ip\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    if (cJSON_AddNumberToObject(vesEndPointDetails, "ves-endpoint-port", 30007) == NULL)
-    {
-        printf("Could not create JSON object: ves-endpoint-port\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    if (cJSON_AddStringToObject(vesEndPointDetails, "ves-endpoint-auth-method", "no-auth") == NULL)
-    {
-        printf("Could not create JSON object: ves-endpoint-auth-method\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    if (cJSON_AddStringToObject(vesEndPointDetails, "ves-endpoint-username", "") == NULL)
-    {
-        printf("Could not create JSON object: ves-endpoint-username\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    if (cJSON_AddStringToObject(vesEndPointDetails, "ves-endpoint-password", "") == NULL)
-    {
-        printf("Could not create JSON object: ves-endpoint-password\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    if (cJSON_AddStringToObject(vesEndPointDetails, "ves-endpoint-certificate", "") == NULL)
-    {
-        printf("Could not create JSON object: ves-endpoint-certificate\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    if (cJSON_AddFalseToObject(vesEndPointDetails, "ves-registration") == NULL)
-    {
-        printf("Could not create JSON object: ves-registration\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    cJSON *controllerDetails = cJSON_CreateObject();
-    if (controllerDetails == NULL)
-    {
-        printf("Could not create JSON object: controllerDetails\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-    cJSON_AddItemToObject(configObject, "controller-details", controllerDetails);
-
-    if (cJSON_AddStringToObject(controllerDetails, "controller-ip", "172.17.0.1") == NULL)
-    {
-        printf("Could not create JSON object: controller-ip\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    if (cJSON_AddNumberToObject(controllerDetails, "controller-port", 8181) == NULL)
-    {
-        printf("Could not create JSON object: controller-port\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    if (cJSON_AddNumberToObject(controllerDetails, "netconf-call-home-port", 6666) == NULL)
-    {
-        printf("Could not create JSON object: netconf-call-home-port\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    if (cJSON_AddStringToObject(controllerDetails, "controller-username", "admin") == NULL)
-    {
-        printf("Could not create JSON object: controller-username\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    if (cJSON_AddStringToObject(controllerDetails, "controller-password", "admin") == NULL)
-    {
-        printf("Could not create JSON object: controller-password\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    if (cJSON_AddNumberToObject(configObject, "ssh-connections", 1) == NULL)
-    {
-        printf("Could not create JSON object: ssh-connections\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    if (cJSON_AddNumberToObject(configObject, "tls-connections", 0) == NULL)
-    {
-        printf("Could not create JSON object: tls-connections\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    if (cJSON_AddFalseToObject(configObject, "netconf-call-home") == NULL)
-    {
-        printf("Could not create JSON object: netconf-call-home\n");
-        cJSON_Delete(configObject);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    char *config_string = NULL;
-
-    config_string = cJSON_PrintUnformatted(configObject);
-
-    writeConfigFile(config_string);
-
-    if (config_string != NULL)
-    {
-        free(config_string);
-        config_string = NULL;
-    }
-
-    if (configObject != NULL)
-    {
-        cJSON_Delete(configObject);
-    }
-
-    return SR_ERR_OK;
-}
-
-int getIntFromString(char *string, int def_value)
-{
-    int rc, value = def_value;
-    if (string != NULL)
-    {
-        rc = sscanf(string, "%d", &value);
-        if (rc != 1)
-        {
-            printf("Could not get the %s! Using the default 0...\n", string);
-            value = def_value;
-        }
-    }
-    return value;
-}
-
-int     getSshConnectionsFromConfigJson(void)
-{
-    char *stringConfig = readConfigFileInString();
-
-    if (stringConfig == NULL)
-    {
-        printf("Could not read JSON configuration file in string.");
-        return 0;
-    }
-
-    cJSON *jsonConfig = cJSON_Parse(stringConfig);
-    if (jsonConfig == NULL)
-    {
-        free(stringConfig);
-        const char *error_ptr = cJSON_GetErrorPtr();
-        if (error_ptr != NULL)
-        {
-            fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-        }
-        return SR_ERR_OPERATION_FAILED;
-    }
-    //we don't need the string anymore
-    free(stringConfig);
-    stringConfig = NULL;
-
-    cJSON *sshConnections = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ssh-connections");
-    if (!cJSON_IsNumber(sshConnections))
-    {
-        printf("Configuration JSON is not as expected: ssh-connections is not an object");
-        cJSON_Delete(jsonConfig);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    int num_of_ssh = (int)(sshConnections->valuedouble);
-
-    cJSON_Delete(jsonConfig);
-
-    return num_of_ssh;
-}
-
-int     getTlsConnectionsFromConfigJson(void)
-{
-    char *stringConfig = readConfigFileInString();
-
-    if (stringConfig == NULL)
-    {
-        printf("Could not read JSON configuration file in string.");
-        return 0;
-    }
-
-    cJSON *jsonConfig = cJSON_Parse(stringConfig);
-    if (jsonConfig == NULL)
-    {
-        free(stringConfig);
-        const char *error_ptr = cJSON_GetErrorPtr();
-        if (error_ptr != NULL)
-        {
-            fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
-        }
-        return SR_ERR_OPERATION_FAILED;
-    }
-    //we don't need the string anymore
-    free(stringConfig);
-    stringConfig = NULL;
-
-    cJSON *tlsConnections = cJSON_GetObjectItemCaseSensitive(jsonConfig, "tls-connections");
-    if (!cJSON_IsNumber(tlsConnections))
-    {
-        printf("Configuration JSON is not as expected: ssh-connections is not an object");
-        cJSON_Delete(jsonConfig);
-        return SR_ERR_OPERATION_FAILED;
-    }
-
-    int num_of_tls = (int)(tlsConnections->valuedouble);
-
-    cJSON_Delete(jsonConfig);
-
-    return num_of_tls;
-}
diff --git a/ntsimulator/src/ves-messages/CMakeLists.txt b/ntsimulator/src/ves-messages/CMakeLists.txt
deleted file mode 100644 (file)
index d761802..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-set (VES_MESSAGES_SOURCES
-    heartbeat.c
-)
-
-include_directories(
-    "/usr/include/x86_64-linux-gnu"
-    "/usr/local/include/cjson"
-    "${PROJECT_SOURCE_DIR}/inc/utils"
-)
-
-add_executable(ves-heartbeat ${VES_MESSAGES_SOURCES})
-target_link_libraries(ves-heartbeat utils)
-target_link_libraries(ves-heartbeat sysrepo)
-target_link_libraries(ves-heartbeat curl)
-target_link_libraries(ves-heartbeat cjson)
-target_link_libraries(ves-heartbeat pthread)
-
-install(TARGETS ves-heartbeat DESTINATION ${CMAKE_INSTALL_BINDIR})
\ No newline at end of file
diff --git a/ntsimulator/src/ves-messages/heartbeat.c b/ntsimulator/src/ves-messages/heartbeat.c
deleted file mode 100644 (file)
index be0093e..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-/*************************************************************************
-*
-* Copyright 2019 highstreet technologies GmbH and others
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*     http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-***************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <string.h>
-#include <time.h>
-#include <math.h>
-#include <sys/time.h>
-
-#include <pthread.h>
-
-#include "heartbeat.h"
-#include "sysrepo.h"
-#include "sysrepo/values.h"
-
-#include "utils.h"
-
-#define LINE_BUFSIZE 128
-#define SLEEP_BEFORE_PNF_AUTOREG 60
-
-volatile int exit_application = 0;
-
-pthread_mutex_t lock;
-
-static         CURL *curl;
-
-int _init_curl()
-{
-       curl = curl_easy_init();
-
-       if (curl == NULL) {
-               printf("cURL initialization error! Aborting call!\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       return SR_ERR_OK;
-}
-
-int cleanup_curl()
-{
-       if (curl != NULL)
-       {
-               curl_easy_cleanup(curl);
-       }
-
-       return SR_ERR_OK;
-}
-
-/*
- * Heartbeat payload example
- *
- * {
-  "event": {
-    "commonEventHeader": {
-      "domain": "heartbeat",
-      "eventId": "parallels-Parallels-Virtual-Platform_2019-10-24T10:25:25.514Z",
-      "eventName": "heartbeat_Controller",
-      "eventType": "Controller",
-      "sequence": 0,
-      "priority": "Low",
-      "reportingEntityId": "",
-      "reportingEntityName": "parallels-Parallels-Virtual-Platform",
-      "sourceId": "",
-      "sourceName": "parallels-Parallels-Virtual-Platform",
-      "startEpochMicrosec": 1571912725514,
-      "lastEpochMicrosec": 1571912725514,
-      "nfNamingCode": "sdn controller",
-      "nfVendorName": "sdn",
-      "timeZoneOffset": "+00:00",
-      "version": "4.0.1",
-      "vesEventListenerVersion":"7.0.1"
-    },
-    "heartbeatFields": {
-      "heartbeatFieldsVersion": "3.0",
-      "heartbeatInterval": 20,
-      "additionalFields": {
-        "eventTime": "2019-10-24T10:25:25.514Z"
-      }
-    }
-  }
-}
-*
-* */
-
-static int send_heartbeat(int heartbeat_interval)
-{
-       CURLcode res;
-       static int sequence_number = 0;
-
-       prepare_ves_message_curl(curl);
-
-       cJSON *postDataJson = cJSON_CreateObject();
-       if (postDataJson == NULL)
-       {
-               printf("Could not create JSON object: postDataJson\n");
-               return 1;
-       }
-
-       cJSON *event = cJSON_CreateObject();
-       if (event == NULL)
-       {
-               printf("Could not create JSON object: event\n");
-               return 1;
-       }
-       cJSON_AddItemToObject(postDataJson, "event", event);
-
-       char hostname[100];
-       sprintf(hostname, "%s", getenv("HOSTNAME"));
-
-       cJSON *commonEventHeader = vesCreateCommonEventHeader("heartbeat", "Controller", hostname, sequence_number++);
-       if (commonEventHeader == NULL)
-       {
-               printf("Could not create JSON object: commonEventHeader\n");
-               cJSON_Delete(postDataJson);
-               return 1;
-       }
-       cJSON_AddItemToObject(event, "commonEventHeader", commonEventHeader);
-
-       cJSON *heartbeatFields = vesCreateHeartbeatFields(heartbeat_interval);
-       if (heartbeatFields == NULL)
-       {
-               printf("Could not create JSON object: heartbeatFields\n");
-               cJSON_Delete(postDataJson);
-               return 1;
-       }
-       cJSON_AddItemToObject(event, "heartbeatFields", heartbeatFields);
-
-    char *post_data_string = NULL;
-
-       post_data_string = cJSON_PrintUnformatted(postDataJson);
-
-       printf("Post data JSON:\n%s\n", post_data_string);
-
-       if (postDataJson != NULL)
-       {
-               cJSON_Delete(postDataJson);
-       }
-
-       curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data_string);
-
-       res = curl_easy_perform(curl);
-
-       if (res != CURLE_OK)
-       {
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       return SR_ERR_OK;
-}
-
-static void
-sigint_handler(int signum)
-{
-    exit_application = 1;
-}
-
-static int send_pnf_registration_instance(char *hostname, int port, bool is_tls)
-{
-       CURLcode res;
-       static int sequence_number = 0;
-
-       prepare_ves_message_curl(curl);
-
-       cJSON *postDataJson = cJSON_CreateObject();
-       if (postDataJson == NULL)
-       {
-               printf("Could not create JSON object: postDataJson\n");
-               return 1;
-       }
-
-       cJSON *event = cJSON_CreateObject();
-       if (event == NULL)
-       {
-               printf("Could not create JSON object: event\n");
-               cJSON_Delete(postDataJson);
-               return 1;
-       }
-       cJSON_AddItemToObject(postDataJson, "event", event);
-
-       char source_name[100];
-       sprintf(source_name, "%s_%d", hostname, port);
-
-       cJSON *commonEventHeader = vesCreateCommonEventHeader("pnfRegistration", "EventType5G", source_name, sequence_number++);
-       if (commonEventHeader == NULL)
-       {
-               printf("Could not create JSON object: commonEventHeader\n");
-               cJSON_Delete(postDataJson);
-               return 1;
-       }
-       cJSON_AddItemToObject(event, "commonEventHeader", commonEventHeader);
-
-       cJSON *pnfRegistrationFields = vesCreatePnfRegistrationFields(port, is_tls);
-       if (pnfRegistrationFields == NULL)
-       {
-               printf("Could not create JSON object: pnfRegistrationFields\n");
-               cJSON_Delete(postDataJson);
-               return 1;
-       }
-       cJSON_AddItemToObject(event, "pnfRegistrationFields", pnfRegistrationFields);
-
-    char *post_data_string = NULL;
-
-       post_data_string = cJSON_PrintUnformatted(postDataJson);
-
-       printf("Post data JSON:\n%s\n", post_data_string);
-
-       if (postDataJson != NULL)
-       {
-               cJSON_Delete(postDataJson);
-       }
-
-       curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data_string);
-
-       res = curl_easy_perform(curl);
-
-       if (res != CURLE_OK)
-       {
-               printf("Failed to send cURL...\n");
-               return SR_ERR_OPERATION_FAILED;
-       }
-
-       return SR_ERR_OK;
-}
-
-static void *pnf_registration(void *arg)
-{
-       // delay the PNF Registration VES message, until anything else is initialized
-       printf("delay the PNF Registration VES message, until anything else is initialized");
-       sleep(SLEEP_BEFORE_PNF_AUTOREG);
-
-       int is_reg = getVesRegistrationFromConfigJson();
-
-       if (!is_reg)
-       {
-               //ves-registration object is set to False, we do not make an automatic PNF registration
-               printf("ves-registration object is set to False, we do not make an automatic PNF registration");
-               return NULL;
-       }
-
-       int rc = SR_ERR_OK, netconf_port_base = 0;
-       char *hostname_string = getenv("HOSTNAME");
-    int port = 0;
-
-    netconf_port_base = getIntFromString(getenv("NETCONF_BASE"), 0);
-
-       //TODO This is where we hardcoded: 7 devices will have SSH connections and 3 devices will have TLS connections
-       for (int i = 0; i < SSH_CONNECTIONS_PER_DEVICE; ++port, ++i)
-       {
-               pthread_mutex_lock(&lock);
-               rc = send_pnf_registration_instance(hostname_string, netconf_port_base + port, FALSE);
-               if (rc != SR_ERR_OK)
-               {
-                       printf("Could not send PNF Registration SSH message...\n");
-               }
-               pthread_mutex_unlock(&lock);
-       }
-       for (int i = 0; i < TLS_CONNECTIONS_PER_DEVICE; ++port, ++i)
-       {
-               pthread_mutex_lock(&lock);
-               rc = send_pnf_registration_instance(hostname_string, netconf_port_base + port, TRUE);
-               pthread_mutex_unlock(&lock);
-               if (rc != SR_ERR_OK)
-               {
-                       printf("Could not send PNF Registration TLS message...\n");
-               }
-       }
-
-       return NULL;
-}
-
-int
-main(int argc, char **argv)
-{
-    int rc = SR_ERR_OK;
-
-    int heartbeat_interval = 120; //seconds
-
-    setbuf(stdout, NULL);
-
-    if (pthread_mutex_init(&lock, NULL) != 0)
-       {
-               printf("Mutex init failed...\n");
-               goto cleanup;
-       }
-
-    pthread_t pnf_autoregistration_thread;
-       if(pthread_create(&pnf_autoregistration_thread, NULL, pnf_registration, NULL))
-       {
-               fprintf(stderr, "Could not create thread for pnf auto registration\n");
-               goto cleanup;
-       }
-
-    rc = _init_curl();
-    if (rc != SR_ERR_OK)
-    {
-        fprintf(stderr, "Could not initialize cURL: %s\n", sr_strerror(rc));
-        goto cleanup;
-    }
-
-    /* loop until ctrl-c is pressed / SIGINT is received */
-    signal(SIGINT, sigint_handler);
-    signal(SIGTERM, sigint_handler);
-    signal(SIGPIPE, SIG_IGN);
-
-    while (!exit_application)
-    {
-       heartbeat_interval = getVesHeartbeatPeriodFromConfigJson();
-
-       if (heartbeat_interval > 0)
-       {
-               pthread_mutex_lock(&lock);
-                       send_heartbeat(heartbeat_interval);
-                       pthread_mutex_unlock(&lock);
-                       sleep(heartbeat_interval);
-       }
-       else
-       {
-               sleep(1);
-       }
-    }
-
-    printf("Application exit requested, exiting.\n");
-
-cleanup:
-
-    rc = cleanup_curl();
-
-    return rc;
-}
-
diff --git a/ntsimulator/ubuntu_build.sh b/ntsimulator/ubuntu_build.sh
new file mode 100755 (executable)
index 0000000..d32ef57
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+docker-compose -f nts-ng-docker-image-build-ubuntu.yaml build --build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') 
diff --git a/ntsimulator/yang/auto-load-yangs.sh b/ntsimulator/yang/auto-load-yangs.sh
deleted file mode 100755 (executable)
index fe2a1c1..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/bin/bash
-################################################################################
-#
-# Copyright 2019 highstreet technologies GmbH and others
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-# 
-#     http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-################################################################################
-
-echo "Installing YANG models..."
-
-set -eu -o pipefail
-
-shopt -s failglob
-
-: ${SYSREPOCTL:=sysrepoctl}
-: ${SYSREPOCFG:=sysrepocfg}
-: ${SYSREPOAPPSTART:=/opt/dev/sysrepo/build/examples/application_example}
-
-declare -a excludedModules=()
-
-sleep 5
-
-pyang -f clearmust *.yang
-
-mapfile -t modelList < <(pyang -f depend --depend-recurse *.yang)
-
-for model in *.yang
-do
-  echo "Removing config false from $model..."
-  sed -i '/config false;/d' $model
-  echo "Removing mandatory true from $model..."
-  sed -i '/mandatory true;/d' $model
-done
-
-if [ ${#modelList[@]} -eq 0 ]; then
-  echo "No models present, nothing to do..."
-  exit 0
-else
-  for model in ${modelList[@]}
-  do
-    modelName=${model%".yang"}
-    
-    skip_model=false
-    
-    for excluded in ${excludedModules[@]}; do
-      if [ "$excluded" == "$modelName" ]; then
-        skip_model=true
-      fi
-    done
-
-    isSubmoduleOnly=$(pyang -f submodule --submodule-only $model)
-
-    if [ "$isSubmoduleOnly" == "True" ]; then
-      echo "Skipping installation of model $modelName because it only contains submodules..."
-      continue
-    fi
-    
-    if [ "$skip_model" = true ]; then
-      echo "Skipping installation of excluded model $modelName..."
-      continue
-    fi
-    
-    echo "Installing model: $model"
-    $SYSREPOCTL --install --yang=$model --owner=root:root --permissions=666
-    
-       mapfile -t featureList < <(pyang -f listfeature $model)
-  
-    if [ ${#featureList[@]} -eq 0 ]; then
-      echo "No features, nothing to do here..."
-    else
-      for feature in ${featureList[@]}
-      do
-        $SYSREPOCTL --feature-enable=$feature --module=$modelName
-      done
-    fi
-    
-    #if the YANG model contains only typedefs, we do not need to subscribe for datastore changes
-    isTypeOnly=$(pyang -f listfeature --is-type-only $model)
-    
-    if [ "$isTypeOnly" == "False" ]; then
-      printf "\n[program:$modelName]\ncommand=/opt/dev/sysrepo/build/examples/application_example $modelName\nautorestart=false\nredirect_stderr=true\nstartretries=1\npriority=4\n" >> /etc/supervisord.conf  
-    fi
-    
-  done
-fi
-
-# Fix for the NETCONF notifications
-echo "Fixing the NETCONF notifications..."
-mkdir -p /var/run/sysrepo-subscriptions/ietf-crypto-types
-
-echo "YANG models installation done!"
-
-exit 0
\ No newline at end of file
diff --git a/ntsimulator/yang/nts-manager/network-topology-simulator.xml b/ntsimulator/yang/nts-manager/network-topology-simulator.xml
deleted file mode 100644 (file)
index 157d8ef..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-<simulator-config xmlns="urn:onf:params:xml:ns:yang:network-topology-simulator">
-    <simulated-devices>0</simulated-devices>
-    <mounted-devices>0</mounted-devices>
-    <netconf-call-home>false</netconf-call-home>
-    <notification-config>
-        <fault-notification-delay-period>0</fault-notification-delay-period>
-        <ves-heartbeat-period>0</ves-heartbeat-period>
-        <is-netconf-available>true</is-netconf-available>
-        <is-ves-available>true</is-ves-available>
-    </notification-config>
-    <controller-details>
-        <controller-ip>172.17.0.1</controller-ip>
-        <controller-port>8181</controller-port>
-        <netconf-call-home-port>6666</netconf-call-home-port>
-        <controller-username>admin</controller-username>
-        <controller-password>admin</controller-password>
-    </controller-details>
-    <ves-endpoint-details>
-        <ves-endpoint-ip>172.17.0.1</ves-endpoint-ip>
-        <ves-endpoint-port>30007</ves-endpoint-port>
-        <ves-endpoint-auth-method>no-auth</ves-endpoint-auth-method>
-        <ves-registration>false</ves-registration>
-    </ves-endpoint-details>
-</simulator-config>
\ No newline at end of file
diff --git a/ntsimulator/yang/nts-manager/network-topology-simulator.yang b/ntsimulator/yang/nts-manager/network-topology-simulator.yang
deleted file mode 100644 (file)
index 203c931..0000000
+++ /dev/null
@@ -1,463 +0,0 @@
-module network-topology-simulator {
-  yang-version 1.1;
-  namespace "urn:onf:params:xml:ns:yang:network-topology-simulator";
-  prefix network-topology-simulator;
-
-  import ietf-inet-types {
-    prefix inet;
-  }
-
-  organization
-    "Melacon";
-  contact
-    "Web: <https://github.com/Melacon>
-     Editors:  Alex Stancu
-               <mailto:stancu.liviualex@gmail.com>";
-  description
-    "This module contains a collection of YANG definitions for managing the Network Topology Simulator.";
-
-revision 2020-05-14 {
-    description
-      "New RPC for generic NETCONF notification generation.";
-    reference
-      "O-RAN SC SIM project";
-  }
-  revision 2020-04-22 {
-    description
-      "Add configuration for number of SSH and TLS connections exposed by each simulated device.";
-    reference
-      "O-RAN SC SIM project";
-  }
-  revision 2020-04-13 {
-    description
-      "Change fault-notification-delay-period to leaf-list.";
-    reference
-      "O-RAN SC SIM project";
-  }
-  revision 2020-04-10 {
-    description
-      "Add notification count in status.";
-    reference
-      "O-RAN SC SIM project";
-  }
-  revision 2019-10-25 {
-    description
-      "Modify notifications. Add VES message configuration options.";
-    reference
-      "O-RAN SC SIM project";
-  }
-  revision 2019-06-07 {
-    description
-      "Modify controller details.";
-    reference
-      "O-RAN SC SIM project";
-  }
-  revision 2019-03-07 {
-    description
-      "Initial version";
-    reference
-      "O-RAN SC SIM project";
-  }
-
-  typedef operational-state-type {
-    type enumeration {
-      enum not-specified {
-        description
-          "none";
-      }
-      enum running {
-        description
-          "none";
-      }
-      enum created {
-        description
-          "none";
-      }
-      enum exited {
-        description
-          "none";
-      }
-    }
-    description
-      "The operation state of the simulated device.";
-  }
-
-  typedef authentication-method-type {
-    type enumeration {
-      enum no-auth {
-        description
-          "no security (http)";
-      }
-      enum cert-only {
-        description
-          "auth by certificate (https)";
-      }
-      enum basic-auth {
-        description
-          "auth by basic auth username and password (https)";
-      }
-      enum cert-basic-auth {
-        description
-          "auth by certificate and basic auth username / password (https)";
-      }
-    }
-    description
-      "The authentication method for VES messaging.";
-  }
-
-  typedef percent {
-    type decimal64 {
-      fraction-digits 2;
-      range "0 .. 100";
-    }
-    description
-      "Percentage";
-  }
-
-  grouping controller-details-type-g {
-    leaf controller-ip {
-      type inet:ip-address;
-      description
-        "The IP Address of the SDN Controller.";
-    }
-    leaf controller-port {
-      type inet:port-number;
-      description
-        "The Port of the SDN Controller.";
-    }
-    leaf netconf-call-home-port {
-      type inet:port-number;
-      description
-        "The NETCONF Call Home Port of the SDN Controller.";      
-    }
-    leaf controller-username {
-      type string;
-      description
-        "The Username of the SDN Controller.";
-    }
-    leaf controller-password {
-      type string;
-      description
-        "The Password of the SDN Controller.";
-    }
-    description
-      "none";
-  }
-
-  grouping simulated-devices-type-g {
-    leaf uuid {
-      type string;
-      description
-        "The UUID of the simulated device.";
-    }
-    leaf device-ip {
-      type string;
-      description
-        "The IP Address of the simulated device.";
-    }
-    leaf-list device-port {
-      type uint32;
-      description
-        "A NETCONF endpoint (port) of the simulated device.";
-    }
-    leaf is-mounted {
-      type boolean;
-      description
-        "Specifies if the simulated device is mounted in the SDN Controller.";
-    }
-    leaf operational-state {
-      type operational-state-type;
-      description
-        "Specifies the operational state of the simulated device.";
-    }
-    description
-      "none";
-  }
-
-  grouping notification-count-per-severity-g {
-    leaf normal {
-    type uint32;
-    description
-    "The number of normal notifications.";
-    }
-    leaf warning {
-    type uint32;
-    description
-    "The number of warning notifications.";
-    }
-    leaf minor {
-    type uint32;
-    description
-    "The number of minor notifications.";
-    }
-    leaf major {
-    type uint32;
-    description
-    "The number of major notifications.";
-    }
-    leaf critical {
-    type uint32;
-    description
-    "The number of normal notifications.";
-    }
-    description
-      "none";
-  }
-
-  container simulator-config {
-    presence "Enables NTS configuration.";
-    description
-      "Configuration container of the simulator.";
-    leaf simulated-devices {
-      type uint32;
-      default "0";
-      description
-        "The number of devices to be simulated.";
-    }
-    leaf mounted-devices {
-      type uint32;
-      must ". <= ../simulated-devices" {
-          error-message "The number of mounted devices cannot be greater that the number of simulated devices";
-      }
-      default "0";
-      description
-        "The number of devices to be mounted in ODL. The configured number should not exceed the number of mounted devices.";
-    }
-    leaf netconf-call-home {
-        type boolean;
-        default "false";
-        description
-          "Configuration of NETCONF Call Home feature. If set to 'true', the device will use the SDN controller details and try to connect to it via Call Home.";
-    }
-    container notification-config {
-      leaf-list fault-notification-delay-period {
-        type uint32;
-        min-elements 1;
-        max-elements 99;
-        ordered-by user;
-        description
-          "Defines a pattern of generating notifications, represented by the amount of time between two generated fault notifications. The pattern is circular, it restarts at the beginning after all the leaf-list items are being used.
-          E.g.: if the leaf-list contains three items: 4, 8 and 10, then a fault-notification will be generated, then after 4 seconds a new notification will be generaed, then after 8 seconds, then after 10 seconds, then again after 4 seconds etc.";
-      }
-      leaf ves-heartbeat-period {
-        type uint32;
-        default "0";
-        description
-          "Interval in seconds between two VES heartbeat messages. If the attribute is set to 0, heartbeat messages are not generated.";
-      }
-      leaf is-netconf-available {
-        type boolean;
-        default "true";
-        description
-          "If set to 'true', NETCONF notifications will be generated.";
-      }
-      leaf is-ves-available {
-        type boolean;
-        default "true";
-        description
-          "If set to 'true', VES messages will be generated.";
-      }
-      description
-        "none";
-    }
-    container controller-details {
-      uses controller-details-type-g;
-      description
-        "The connectivity details of the SDN Controller where we want to mount our simulated devices.";
-    }
-    container ves-endpoint-details {
-      must 'ves-registration = "false" or ../mounted-devices = 0' {
-        error-message "VES registration cannot be active while devices are still mounted to ODL not via VES.";
-      }
-      leaf ves-endpoint-ip {
-        type inet:ip-address;
-        description
-          "The IP Address of the VES Endpoint.";
-      }
-      leaf ves-endpoint-port {
-        type inet:port-number;
-        description
-          "The Port of the VES Endpoint.";
-      }
-      leaf ves-endpoint-auth-method {
-        type authentication-method-type;
-        default "no-auth";
-        description
-          "The type of the authentication to be used with the VES Endpoint.";
-      }
-      leaf ves-endpoint-username {
-        when "../ves-endpoint-auth-method = 'basic-auth' or ../ves-endpoint-auth-method = 'cert-basic-auth'";
-        type string;
-        description
-          "The Username to be used to authenticate to the VES Endpoint.";
-      }
-      leaf ves-endpoint-password {
-        when "../ves-endpoint-auth-method = 'basic-auth' or ../ves-endpoint-auth-method = 'cert-basic-auth'";
-        type string;
-        description
-          "The Password to be used to authenticate to the VES Endpoint.";
-      }
-      leaf ves-endpoint-certificate {
-        when "../ves-endpoint-auth-method = 'cert-only' or ../ves-endpoint-auth-method = 'cert-basic-auth'";
-        type string;
-        description
-          "The Certificate to be used to authenticate to the VES Endpoint.";
-      }
-      leaf ves-registration {
-        type boolean;
-        default "false";
-        description
-          "If this is set to 'True', the simulated devices will automatically send a pnfRegistration VES message when they start. This cannot be set to 'True' if we already have 'mounted-devices' greater that 0, because we already mounted the devices directly to ODL.";
-      }
-      description
-        "none";
-    }
-  }
-  container simulator-status {
-    config false;
-    container simulation-usage-details {
-      config false;
-      leaf running-simulated-devices {
-        type uint32;
-        description
-          "The current number of running simulated devices.";
-      }
-      leaf running-mounted-devices {
-        type uint32;
-        description
-          "The current number of running simulated devices that are mounted in ODL.";
-      }
-      leaf ssh-connections {
-        type uint32;
-        description
-          "The number of SSH connections that are exposed by each simulated device. This can be set through the ENV variable SshConnections when starting the NTS Manager.";
-      }
-      leaf tls-connections {
-        type uint32;
-        description
-          "The number of TLS connections that are exposed by each simulated device. This can be set through the ENV variable TlsConnections when starting the NTS Manager.";
-      }
-      leaf base-netconf-port {
-        type uint32;
-        default "30000";
-        description
-          "The starting port number for the NETCONF connections exposed.";
-      }
-      leaf cpu-usage {
-        type percent;
-        description
-          "Specifies the CPU load generated by this simulated device.";
-      }
-      leaf mem-usage {
-        type uint32;
-        description
-          "Specifies the RAM in MB used by this simulated device.";
-      }
-      description
-        "The details about the simulation, including resources consumed.";
-    }
-    container notification-count {
-        config false;
-        container total-ves-notifications {
-            config false;
-            uses  notification-count-per-severity-g;
-            description
-              "The total number of VES notifications that were sent by all the simulated devices managed by this NTS Manager instance.";
-        }
-        container total-netconf-notifications {
-            config false;
-            uses  notification-count-per-severity-g;
-            description
-              "The total number of NETCONF notifications that were sent by all the simulated devices managed by this NTS Manager instance.";
-        }
-        description 
-          "The total number of notifications sent by the devices managed by this NTS Manager instance.";
-        
-    }
-    list simulated-devices-list {
-      key "uuid";
-      config false;
-      uses simulated-devices-type-g;
-      container notification-count {
-        config false;
-        container ves-notifications {
-            config false;
-            uses  notification-count-per-severity-g;
-            description
-              "The total number of VES notifications that were sent by this simulated device.";
-        }
-        container netconf-notifications {
-            config false;
-            uses  notification-count-per-severity-g;
-            description
-              "The total number of NETCONF notifications that were sent by this simulated device.";
-        }
-        description 
-          "The total number of notifications sent by this simulated device.";
-        
-    }
-      description
-        "The list of the devices that are currently simulated.";
-    }
-    description
-      "State data container of the simulator.";
-  }
-
-  grouping notification-job-g {
-      leaf device-id {
-        type string;
-        mandatory true;
-        description
-          "Device to invoke the NETCONF notification. If it is not present, all simulated devices would invoke the notification.";
-      }
-      leaf yang-module-name {
-        type string;
-        mandatory true;
-        description
-          "Name of the YANG module containing the notification to be invoked.";
-      }
-      leaf notification-object {
-          type string;
-          mandatory true;
-          description
-            "A JSON string containing the notification object to be sent by the device.";
-      }
-      description
-        "Notification job object class.";
-  }
-
-  rpc restart-simulation {
-    description
-      "Operation to restart all the simulated devices with the new configuration of the simulator.";
-  }
-
-  rpc add-key-pair-to-odl {
-    description
-      "Operation to add a key pair signed by the NTS to OpenDaylight, such that it can connect to devices using TLS.";
-  }
-
-  rpc invoke-notification {
-    description
-      "Operation to generate a NETCONF notification from a device.";
-    input {
-      uses notification-job-g;
-    }
-    output {
-      leaf status {
-          type enumeration {
-            enum SUCCESS {
-            description
-                "This means that the RPC was successfully invoked.";
-            }
-            enum ERROR {
-            description
-                "This means that an error was encountered when invoking the notification.";
-            }
-          }
-        mandatory true;
-        description
-          "The status of the RPC.";
-      }
-    }
-  }
-}
diff --git a/ntsimulator/yang/o-ran-sc/o-ran-ru/ietf-alarms.yang b/ntsimulator/yang/o-ran-sc/o-ran-ru/ietf-alarms.yang
deleted file mode 100644 (file)
index 856320b..0000000
+++ /dev/null
@@ -1,1526 +0,0 @@
-module ietf-alarms {
-  yang-version 1.1;
-  namespace "urn:ietf:params:xml:ns:yang:ietf-alarms";
-  prefix al;
-
-  import ietf-yang-types {
-    prefix yang;
-    reference
-      "RFC 6991: Common YANG Data Types.";
-  }
-
-  organization
-    "IETF CCAMP Working Group";
-  contact
-    "WG Web:   <https://trac.ietf.org/trac/ccamp>
-     WG List:  <mailto:ccamp@ietf.org>
-
-     Editor:   Stefan Vallin
-               <mailto:stefan@wallan.se>
-
-     Editor:   Martin Bjorklund
-               <mailto:mbj@tail-f.com>";
-  description
-    "This module defines an interface for managing alarms.  Main
-     inputs to the module design are the 3GPP Alarm Integration
-     Reference Point (IRP), ITU-T X.733, and ANSI/ISA-18.2 alarm
-     standards.
-     Main features of this module include:
-
-       * Alarm list:
-                 A list of all alarms.  Cleared alarms stay in
-                 the list until explicitly purged.
-
-       * Operator actions on alarms:
-                 Acknowledging and closing alarms.
-
-       * Administrative actions on alarms:
-                 Purging alarms from the list according to specific
-                 criteria.
-
-       * Alarm inventory:
-                 A management application can read all
-                 alarm types implemented by the system.
-
-       * Alarm shelving:
-                 Shelving (blocking) alarms according
-                 to specific criteria.
-
-       * Alarm profiles:
-                 A management system can attach further
-                 information to alarm types, for example,
-                 overriding system-default severity
-                 levels.
-
-     This module uses a stateful view on alarms.  An alarm is a state
-     for a specific resource (note that an alarm is not a
-     notification).  An alarm type is a possible alarm state for a
-     resource.  For example, the tuple:
-
-       ('link-alarm', 'GigabitEthernet0/25')
-
-     is an alarm of type 'link-alarm' on the resource
-     'GigabitEthernet0/25'.
-
-     Alarm types are identified using YANG identities and an optional
-     string-based qualifier.  The string-based qualifier allows for
-     dynamic extension of the statically defined alarm types.  Alarm
-     types identify a possible alarm state and not the individual
-     notifications.  For example, the traditional 'link-down' and
-     'link-up' notifications are two notifications referring to the
-     same alarm type 'link-alarm'.
-
-     With this design, there is no ambiguity about how alarm and
-     alarm clear correlation should be performed; notifications that
-     report the same resource and alarm type are considered updates
-     of the same alarm, e.g., clearing an active alarm or changing
-     the severity of an alarm.  The instrumentation can update the
-     severity and alarm text on an existing alarm.  The above alarm
-     example can therefore look like the following:
-
-       (('link-alarm', 'GigabitEthernet0/25'),
-        warning,
-        'interface down while interface admin state is up')
-
-     There is a clear separation between updates on the alarm from
-     the underlying resource, like clear, and updates from an
-     operator, like acknowledging or closing an alarm:
-
-       (('link-alarm', 'GigabitEthernet0/25'),
-        warning,
-        'interface down while interface admin state is up',
-        cleared,
-        closed)
-
-     Administrative actions like removing closed alarms older than a
-     given time is supported.
-
-     This YANG module does not define how the underlying
-     instrumentation detects and clears the specific alarms.  That
-     belongs to the Standards Development Organization (SDO) or
-     enterprise that owns that specific technology.
-
-     The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL
-     NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED',
-     'MAY', and 'OPTIONAL' in this document are to be interpreted as
-     described in BCP 14 (RFC 2119) (RFC 8174) when, and only when,
-     they appear in all capitals, as shown here.
-
-     Copyright (c) 2019 IETF Trust and the persons identified as
-     authors of the code.  All rights reserved.
-
-     Redistribution and use in source and binary forms, with or
-     without modification, is permitted pursuant to, and subject to
-     the license terms contained in, the Simplified BSD License set
-     forth in Section 4.c of the IETF Trust's Legal Provisions
-     Relating to IETF Documents
-     (https://trustee.ietf.org/license-info).
-
-     This version of this YANG module is part of RFC 8632; see
-     the RFC itself for full legal notices.";
-
-  revision 2019-09-11 {
-    description
-      "Initial revision.";
-    reference
-      "RFC 8632: A YANG Data Model for Alarm Management";
-  }
-
-  /*
-   * Features
-   */
-
-  feature operator-actions {
-    description
-      "This feature indicates that the system supports operator
-       states on alarms.";
-  }
-
-  feature alarm-shelving {
-    description
-      "This feature indicates that the system supports shelving
-       (blocking) alarms.
-
-       Alarm shelving may have an impact on server processing
-       resources in order to match alarms against shelf
-       criteria.";
-  }
-
-  feature alarm-history {
-    description
-      "This feature indicates that the server maintains a history
-       of state changes for each alarm.  For example, if an alarm
-       toggles between cleared and active 10 times, these state
-       changes are present in a separate list in the alarm.
-
-       Keeping the alarm history may have an impact on server
-       memory resources.";
-  }
-
-  feature alarm-summary {
-    description
-      "This feature indicates that the server summarizes the number
-       of alarms per severity and operator state.";
-  }
-
-  feature alarm-profile {
-    description
-      "The system enables clients to configure further information
-       to each alarm type.";
-  }
-
-  feature severity-assignment {
-    description
-      "The system supports configurable alarm severity levels.";
-    reference
-      "ITU-T Recommendation M.3100:
-         Generic network information model
-       ITU-T Recommendation M.3160:
-         Generic, protocol-neutral management information model";
-  }
-
-  feature root-cause-analysis {
-    description
-      "The system supports identifying candidate root-cause
-       resources for an alarm, for example, a disk partition
-       root cause for a logger failure alarm.";
-  }
-
-  feature service-impact-analysis {
-    description
-      "The system supports identifying candidate-impacted
-       resources for an alarm, for example, an interface state change
-       resulting in a link alarm, which can refer to a link as being
-       impacted.";
-  }
-
-  feature alarm-correlation {
-    description
-      "The system supports correlating/grouping alarms
-       that belong together.";
-  }
-
-  /*
-   * Identities
-   */
-
-  identity alarm-type-id {
-    description
-      "Base identity for alarm types.  A unique identification of
-       the alarm, not including the resource.  Different resources
-       can share alarm types.  If the resource reports the same
-       alarm type, it is considered to be the same alarm.  The alarm
-       type is a simplification of the different X.733 and 3GPP Alarm
-       IRP correlation mechanisms, and it allows for
-       hierarchical extensions.
-
-       A string-based qualifier can be used in addition to the
-       identity in order to have different alarm types based on
-       information not known at design time, such as values in
-       textual SNMP Notification varbinds.
-
-       Standards and vendors can define sub-identities to clearly
-       identify specific alarm types.
-
-       This identity is abstract and MUST NOT be used for alarms.";
-  }
-
-  /*
-   * Common types
-   */
-
-  typedef resource {
-    type union {
-      type instance-identifier {
-        require-instance false;
-      }
-      type yang:object-identifier;
-      type string;
-      type yang:uuid;
-    }
-    description
-      "This is an identification of the alarming resource, such as an
-       interface.  It should be as fine-grained as possible to both
-       guide the operator and guarantee uniqueness of the alarms.
-
-       If the alarming resource is modeled in YANG, this type will
-       be an instance-identifier.
-
-       If the resource is an SNMP object, the type will be an
-       'object-identifier'.
-
-       If the resource is anything else, for example, a distinguished
-       name or a Common Information Model (CIM) path, this type will
-       be a string.
-
-       If the alarming object is identified by a Universally Unique
-       Identifier (UUID), use the uuid type.  Be cautious when using
-       this type, since a UUID is hard to use for an operator.
-
-       If the server supports several models, the precedence should
-       be in the order as given in the union definition.";
-  }
-
-  typedef resource-match {
-    type union {
-      type yang:xpath1.0;
-      type yang:object-identifier;
-      type string;
-    }
-    description
-      "This type is used to match resources of type 'resource'.
-       Since the type 'resource' is a union of different types, the
-       'resource-match' type is also a union of corresponding types.
-
-       If the type is given as an XPath 1.0 expression, a resource
-       of type 'instance-identifier' matches if the instance is part
-       of the node set that is the result of evaluating the XPath 1.0
-       expression.  For example, the XPath 1.0 expression:
-
-        /ietf-interfaces:interfaces/ietf-interfaces:interface
-            [ietf-interfaces:type='ianaift:ethernetCsmacd']
-
-       would match the resource instance-identifier:
-
-        /if:interfaces/if:interface[if:name='eth1'],
-
-       assuming that the interface 'eth1' is of type
-       'ianaift:ethernetCsmacd'.
-
-       If the type is given as an object identifier, a resource of
-       type 'object-identifier' matches if the match object
-       identifier is a prefix of the resource's object identifier.
-       For example, the value:
-
-        1.3.6.1.2.1.2.2
-
-       would match the resource object identifier:
-
-        1.3.6.1.2.1.2.2.1.1.5
-
-       If the type is given as an UUID or a string, it is interpreted
-       as an XML Schema regular expression, which matches a resource
-       of type 'yang:uuid' or 'string' if the given regular
-       expression matches the resource string.
-
-       If the type is given as an XPath expression, it is evaluated
-       in the following XPath context:
-
-         o  The set of namespace declarations is the set of prefix
-            and namespace pairs for all YANG modules implemented by
-            the server, where the prefix is the YANG module name and
-            the namespace is as defined by the 'namespace' statement
-            in the YANG module.
-
-            If a leaf of this type is encoded in XML, all namespace
-            declarations in scope on the leaf element are added to
-            the set of namespace declarations.  If a prefix found in
-            the XML is already present in the set of namespace
-            declarations, the namespace in the XML is used.
-
-         o  The set of variable bindings is empty.
-
-         o  The function library is the core function library, and
-            the functions are defined in Section 10 of RFC 7950.
-
-         o  The context node is the root node in the data tree.";
-    reference
-      "XML Schema Part 2: Datatypes Second Edition,
-         World Wide Web Consortium Recommendation
-         REC-xmlschema-2-20041028";
-  }
-
-  typedef alarm-text {
-    type string;
-    description
-      "The string used to inform operators about the alarm.  This
-       MUST contain enough information for an operator to be able to
-       understand the problem and how to resolve it.  If this string
-       contains structure, this format should be clearly documented
-       for programs to be able to parse that information.";
-  }
-
-  typedef severity {
-    type enumeration {
-      enum indeterminate {
-        value 2;
-        description
-          "Indicates that the severity level could not be
-           determined.  This level SHOULD be avoided.";
-      }
-      enum warning {
-        value 3;
-        description
-          "The 'warning' severity level indicates the detection of a
-           potential or impending service-affecting fault, before any
-           significant effects have been felt.  Action should be
-           taken to further diagnose (if necessary) and correct the
-           problem in order to prevent it from becoming a more
-           serious service-affecting fault.";
-      }
-      enum minor {
-        value 4;
-        description
-          "The 'minor' severity level indicates the existence of a
-           non-service-affecting fault condition and that corrective
-           action should be taken in order to prevent a more serious
-           (for example, service-affecting) fault.  Such a severity
-           can be reported, for example, when the detected alarm
-           condition is not currently degrading the capacity of the
-           resource.";
-      }
-      enum major {
-        value 5;
-        description
-          "The 'major' severity level indicates that a service-
-           affecting condition has developed and an urgent corrective
-           action is required.  Such a severity can be reported, for
-           example, when there is a severe degradation in the
-           capability of the resource and its full capability must be
-           restored.";
-      }
-      enum critical {
-        value 6;
-        description
-          "The 'critical' severity level indicates that a service-
-           affecting condition has occurred and an immediate
-           corrective action is required.  Such a severity can be
-           reported, for example, when a resource becomes totally out
-           of service and its capability must be restored.";
-      }
-    }
-    description
-      "The severity level of the alarm.  Note well that the value
-       'clear' is not included.  Whether or not an alarm is cleared
-       is a separate boolean flag.";
-    reference
-      "ITU-T Recommendation X.733: Information Technology
-         - Open Systems Interconnection
-         - System Management: Alarm Reporting Function";
-  }
-
-  typedef severity-with-clear {
-    type union {
-      type enumeration {
-        enum cleared {
-          value 1;
-          description
-            "The alarm is cleared by the instrumentation.";
-        }
-      }
-      type severity;
-    }
-    description
-      "The severity level of the alarm including clear.  This is used
-       only in notifications reporting state changes for an alarm.";
-  }
-
-  typedef writable-operator-state {
-    type enumeration {
-      enum none {
-        value 1;
-        description
-          "The alarm is not being taken care of.";
-      }
-      enum ack {
-        value 2;
-        description
-          "The alarm is being taken care of.  Corrective action not
-           taken yet or has failed";
-      }
-      enum closed {
-        value 3;
-        description
-          "Corrective action taken successfully.";
-      }
-    }
-    description
-      "Operator states on an alarm.  The 'closed' state indicates
-       that an operator considers the alarm being resolved.  This is
-       separate from the alarm's 'is-cleared' leaf.";
-  }
-
-  typedef operator-state {
-    type union {
-      type writable-operator-state;
-      type enumeration {
-        enum shelved {
-          value 4;
-          description
-            "The alarm is shelved.  Alarms in /alarms/shelved-alarms/
-             MUST be assigned this operator state by the server as
-             the last entry in the 'operator-state-change' list.  The
-             text for that entry SHOULD include the shelf name.";
-        }
-        enum un-shelved {
-          value 5;
-          description
-            "The alarm is moved back to 'alarm-list' from a shelf.
-             Alarms that are moved from /alarms/shelved-alarms/ to
-             /alarms/alarm-list MUST be assigned this state by the
-             server as the last entry in the 'operator-state-change'
-             list.  The text for that entry SHOULD include the shelf
-             name.";
-        }
-      }
-    }
-    description
-      "Operator states on an alarm.  The 'closed' state indicates
-       that an operator considers the alarm being resolved.  This is
-       separate from the alarm's 'is-cleared' leaf.";
-  }
-
-  /* Alarm type */
-
-  typedef alarm-type-id {
-    type identityref {
-      base alarm-type-id;
-    }
-    description
-      "Identifies an alarm type.  The description of the alarm type
-       id MUST indicate whether or not the alarm type is abstract.
-       An abstract alarm type is used as a base for other alarm type
-       ids and will not be used as a value for an alarm or be present
-       in the alarm inventory.";
-  }
-
-  typedef alarm-type-qualifier {
-    type string;
-    description
-      "If an alarm type cannot be fully specified at design time by
-       'alarm-type-id', this string qualifier is used in addition to
-       fully define a unique alarm type.
-
-       The definition of alarm qualifiers is considered to be part of
-       the instrumentation and is out of scope for this module.  An
-       empty string is used when this is part of a key.";
-  }
-
-  /*
-   * Groupings
-   */
-
-  grouping common-alarm-parameters {
-    description
-      "Common parameters for an alarm.
-
-       This grouping is used both in the alarm list and in the
-       notification representing an alarm-state change.";
-    leaf resource {
-      type resource;
-      mandatory true;
-      description
-        "The alarming resource.  See also 'alt-resource'.  This could
-         be, for example, a reference to the alarming interface";
-    }
-    leaf alarm-type-id {
-      type alarm-type-id;
-      mandatory true;
-      description
-        "This leaf and the leaf 'alarm-type-qualifier' together
-         provide a unique identification of the alarm type.";
-    }
-    leaf alarm-type-qualifier {
-      type alarm-type-qualifier;
-      description
-        "This leaf is used when the 'alarm-type-id' leaf cannot
-         uniquely identify the alarm type.  Normally, this is not the
-         case, and this leaf is the empty string.";
-    }
-    leaf-list alt-resource {
-      type resource;
-      description
-        "Used if the alarming resource is available over other
-         interfaces.  This field can contain SNMP OIDs, CIM paths, or
-         3GPP distinguished names, for example.";
-    }
-    list related-alarm {
-      if-feature "alarm-correlation";
-      key "resource alarm-type-id alarm-type-qualifier";
-      description
-        "References to related alarms.  Note that the related alarm
-         might have been purged from the alarm list.";
-      leaf resource {
-        type leafref {
-          path "/alarms/alarm-list/alarm/resource";
-          require-instance false;
-        }
-        description
-          "The alarming resource for the related alarm.";
-      }
-      leaf alarm-type-id {
-        type leafref {
-          path "/alarms/alarm-list/alarm"
-             + "[resource=current()/../resource]"
-             + "/alarm-type-id";
-          require-instance false;
-        }
-        description
-          "The alarm type identifier for the related alarm.";
-      }
-      leaf alarm-type-qualifier {
-        type leafref {
-          path "/alarms/alarm-list/alarm"
-             + "[resource=current()/../resource]"
-             + "[alarm-type-id=current()/../alarm-type-id]"
-             + "/alarm-type-qualifier";
-          require-instance false;
-        }
-        description
-          "The alarm qualifier for the related alarm.";
-      }
-    }
-    leaf-list impacted-resource {
-      if-feature "service-impact-analysis";
-      type resource;
-      description
-        "Resources that might be affected by this alarm.  If the
-         system creates an alarm on a resource and also has a mapping
-         to other resources that might be impacted, these resources
-         can be listed in this leaf-list.  In this way, the system
-         can create one alarm instead of several.  For example, if an
-         interface has an alarm, the 'impacted-resource' can
-         reference the aggregated port channels.";
-    }
-    leaf-list root-cause-resource {
-      if-feature "root-cause-analysis";
-      type resource;
-      description
-        "Resources that are candidates for causing the alarm.  If the
-         system has a mechanism to understand the candidate root
-         causes of an alarm, this leaf-list can be used to list the
-         root-cause candidate resources.  In this way, the system can
-         create one alarm instead of several.  An example might be a
-         logging system (alarm resource) that fails; the alarm can
-         reference the file system in the 'root-cause-resource'
-         leaf-list.  Note that the intended use is not to also send
-         an alarm with the 'root-cause-resource' as an alarming
-         resource.  The 'root-cause-resource' leaf-list is a hint and
-         should not also generate an alarm for the same problem.";
-    }
-  }
-
-  grouping alarm-state-change-parameters {
-    description
-      "Parameters for an alarm-state change.
-
-       This grouping is used both in the alarm list's status-change
-       list and in the notification representing an alarm-state
-       change.";
-    leaf time {
-      type yang:date-and-time;
-      mandatory true;
-      description
-        "The time the status of the alarm changed.  The value
-         represents the time the real alarm-state change appeared in
-         the resource and not when it was added to the alarm
-         list.  The /alarm-list/alarm/last-changed MUST be set to the
-         same value.";
-    }
-    leaf perceived-severity {
-      type severity-with-clear;
-      mandatory true;
-      description
-        "The severity of the alarm as defined by X.733.  Note that
-         this may not be the original severity since the alarm may
-         have changed severity.";
-      reference
-        "ITU-T Recommendation X.733: Information Technology
-           - Open Systems Interconnection
-           - System Management: Alarm Reporting Function";
-    }
-    leaf alarm-text {
-      type alarm-text;
-      mandatory true;
-      description
-        "A user-friendly text describing the alarm-state change.";
-      reference
-        "ITU-T Recommendation X.733: Information Technology
-           - Open Systems Interconnection
-           - System Management: Alarm Reporting Function";
-    }
-  }
-
-  grouping operator-parameters {
-    description
-      "This grouping defines parameters that can be changed by an
-       operator.";
-    leaf time {
-      type yang:date-and-time;
-      mandatory true;
-      description
-        "Timestamp for operator action on the alarm.";
-    }
-    leaf operator {
-      type string;
-      mandatory true;
-      description
-        "The name of the operator that has acted on this alarm.";
-    }
-    leaf state {
-      type operator-state;
-      mandatory true;
-      description
-        "The operator's view of the alarm state.";
-    }
-    leaf text {
-      type string;
-      description
-        "Additional optional textual information provided by the
-         operator.";
-    }
-  }
-
-  grouping resource-alarm-parameters {
-    description
-      "Alarm parameters that originate from the resource view.";
-    leaf is-cleared {
-      type boolean;
-      mandatory true;
-      description
-        "Indicates the current clearance state of the alarm.  An
-         alarm might toggle from active alarm to cleared alarm and
-         back to active again.";
-    }
-    leaf last-raised {
-      type yang:date-and-time;
-      mandatory true;
-      description
-        "An alarm may change severity level and toggle between
-         active and cleared during its lifetime.  This leaf indicates
-         the last time it was raised ('is-cleared' = 'false').";
-    }
-    leaf last-changed {
-      type yang:date-and-time;
-      mandatory true;
-      description
-        "A timestamp when the 'status-change' or
-         'operator-state-change' list was last changed.";
-    }
-    leaf perceived-severity {
-      type severity;
-      mandatory true;
-      description
-        "The last severity of the alarm.
-
-         If an alarm was raised with severity 'warning' but later
-         changed to 'major', this leaf will show 'major'.";
-    }
-    leaf alarm-text {
-      type alarm-text;
-      mandatory true;
-      description
-        "The last reported alarm text.  This text should contain
-         information for an operator to be able to understand the
-         problem and how to resolve it.";
-    }
-    list status-change {
-      if-feature "alarm-history";
-      key "time";
-      min-elements 1;
-      description
-        "A list of status-change events for this alarm.
-
-         The entry with latest timestamp in this list MUST
-         correspond to the leafs 'is-cleared', 'perceived-severity',
-         and 'alarm-text' for the alarm.
-
-         This list is ordered according to the timestamps of alarm
-         state changes.  The first item corresponds to the latest
-         state change.
-
-         The following state changes create an entry in this
-         list:
-         - changed severity (warning, minor, major, critical)
-         - clearance status; this also updates the 'is-cleared'
-           leaf
-         - alarm-text update";
-      uses alarm-state-change-parameters;
-    }
-  }
-
-  grouping filter-input {
-    description
-      "Grouping to specify a filter construct on alarm information.";
-    leaf alarm-clearance-status {
-      type enumeration {
-        enum any {
-          description
-            "Ignore alarm-clearance status.";
-        }
-        enum cleared {
-          description
-            "Filter cleared alarms.";
-        }
-        enum not-cleared {
-          description
-            "Filter not-cleared alarms.";
-        }
-      }
-      mandatory true;
-      description
-        "The clearance status of the alarm.";
-    }
-    container older-than {
-      presence "Age specification";
-      description
-        "Matches the 'last-status-change' leaf in the alarm.";
-      choice age-spec {
-        description
-          "Filter using date and time age.";
-        case seconds {
-          leaf seconds {
-            type uint16;
-            description
-              "Age expressed in seconds.";
-          }
-        }
-        case minutes {
-          leaf minutes {
-            type uint16;
-            description
-              "Age expressed in minutes.";
-          }
-        }
-        case hours {
-          leaf hours {
-            type uint16;
-            description
-              "Age expressed in hours.";
-          }
-        }
-        case days {
-          leaf days {
-            type uint16;
-            description
-              "Age expressed in days.";
-          }
-        }
-        case weeks {
-          leaf weeks {
-            type uint16;
-            description
-              "Age expressed in weeks.";
-          }
-        }
-      }
-    }
-    container severity {
-      presence "Severity filter";
-      choice sev-spec {
-        description
-          "Filter based on severity level.";
-        leaf below {
-          type severity;
-          description
-            "Severity less than this leaf.";
-        }
-        leaf is {
-          type severity;
-          description
-            "Severity level equal to this leaf.";
-        }
-        leaf above {
-          type severity;
-          description
-            "Severity level higher than this leaf.";
-        }
-      }
-      description
-        "Filter based on severity.";
-    }
-    container operator-state-filter {
-      if-feature "operator-actions";
-      presence "Operator state filter";
-      leaf state {
-        type operator-state;
-        description
-          "Filter on operator state.";
-      }
-      leaf user {
-        type string;
-        description
-          "Filter based on which operator.";
-      }
-      description
-        "Filter based on operator state.";
-    }
-  }
-
-  /*
-   * The /alarms data tree
-   */
-
-  container alarms {
-    description
-      "The top container for this module.";
-    container control {
-      description
-        "Configuration to control the alarm behavior.";
-      leaf max-alarm-status-changes {
-        type union {
-          type uint16;
-          type enumeration {
-            enum infinite {
-              description
-                "The status-change entries are accumulated
-                 infinitely.";
-            }
-          }
-        }
-        default "32";
-        description
-          "The 'status-change' entries are kept in a circular list
-           per alarm.  When this number is exceeded, the oldest
-           status change entry is automatically removed.  If the
-           value is 'infinite', the status-change entries are
-           accumulated infinitely.";
-      }
-      leaf notify-status-changes {
-        type enumeration {
-          enum all-state-changes {
-            description
-              "Send notifications for all status changes.";
-          }
-          enum raise-and-clear {
-            description
-              "Send notifications only for raise, clear, and
-               re-raise.  Notifications for severity-level changes or
-               alarm-text changes are not sent.";
-          }
-          enum severity-level {
-            description
-              "Only send notifications for alarm-state changes
-               crossing the level specified in
-               'notify-severity-level'.  Always send clear
-               notifications.";
-          }
-        }
-        must '. != "severity-level" or ../notify-severity-level' {
-          description
-            "When notify-status-changes is 'severity-level', a value
-             must be given for 'notify-severity-level'.";
-        }
-        default "all-state-changes";
-        description
-          "This leaf controls the notifications sent for alarm status
-           updates.  There are three options:
-
-           1.  Notifications are sent for all updates, severity-level
-               changes, and alarm-text changes.
-
-           2.  Notifications are only sent for alarm raise and clear.
-
-           3.  Notifications are sent for status changes equal to or
-               above the specified severity level.  Clear
-               notifications shall always be sent.  Notifications
-               shall also be sent for state changes that make an
-               alarm less severe than the specified level.
-
-           For example, in option 3, assume that the severity level
-           is set to major and that the alarm has the following state
-           changes:
-
-           [(Time, severity, clear)]:
-           [(T1, major, -), (T2, minor, -), (T3, warning, -),
-            (T4, minor, -), (T5, major, -), (T6, critical, -),
-            (T7, major.  -), (T8, major, clear)]
-
-           In that case, notifications will be sent at times
-           T1, T2, T5, T6, T7, and T8.";
-      }
-      leaf notify-severity-level {
-        when '../notify-status-changes = "severity-level"';
-        type severity;
-        description
-          "Only send notifications for alarm-state changes crossing
-           the specified level.  Always send clear notifications.";
-      }
-      container alarm-shelving {
-        if-feature "alarm-shelving";
-        description
-          "The 'alarm-shelving/shelf' list is used to shelve
-           (block/filter) alarms.  The conditions in the shelf
-           criteria are logically ANDed.  The first matching shelf is
-           used, and an alarm is shelved only for this first match.
-           Matching alarms MUST appear in the
-           /alarms/shelved-alarms/shelved-alarm list, and
-           non-matching /alarms MUST appear in the
-           /alarms/alarm-list/alarm list.  The server does not send
-           any notifications for shelved alarms.
-
-           The server MUST maintain states (e.g., severity
-           changes) for the shelved alarms.
-
-           Alarms that match the criteria shall have an
-           operator state 'shelved'.  When the shelf
-           configuration removes an alarm from the shelf, the server
-           shall add the operator state 'un-shelved'.";
-        list shelf {
-          key "name";
-          //ordered-by user;
-          leaf name {
-            type string;
-            description
-              "An arbitrary name for the alarm shelf.";
-          }
-          description
-            "Each entry defines the criteria for shelving alarms.
-             Criteria are ANDed.  If no criteria are specified,
-             all alarms will be shelved.";
-          leaf-list resource {
-            type resource-match;
-            description
-              "Shelve alarms for matching resources.";
-          }
-          list alarm-type {
-            key "alarm-type-id alarm-type-qualifier-match";
-            description
-              "Any alarm matching the combined criteria of
-               'alarm-type-id' and 'alarm-type-qualifier-match'
-               MUST be matched.";
-            leaf alarm-type-id {
-              type alarm-type-id;
-              description
-                "Shelve all alarms that have an 'alarm-type-id' that
-                 is equal to or derived from the given
-                 'alarm-type-id'.";
-            }
-            leaf alarm-type-qualifier-match {
-              type string;
-              description
-                "An XML Schema regular expression that is used to
-                 match an alarm type qualifier.  Shelve all alarms
-                 that match this regular expression for the alarm
-                 type qualifier.";
-              reference
-                "XML Schema Part 2: Datatypes Second Edition,
-                   World Wide Web Consortium Recommendation
-                   REC-xmlschema-2-20041028";
-            }
-          }
-          leaf description {
-            type string;
-            description
-              "An optional textual description of the shelf.  This
-               description should include the reason for shelving
-               these alarms.";
-          }
-        }
-      }
-    }
-    container alarm-inventory {
-      config false;
-      description
-        "The 'alarm-inventory/alarm-type' list contains all possible
-         alarm types for the system.
-
-         If the system knows for which resources a specific alarm
-         type can appear, it is also identified in the inventory.
-         The list also tells if each alarm type has a corresponding
-         clear state.  The inventory shall only contain concrete
-         alarm types.
-
-         The alarm inventory MUST be updated by the system when new
-         alarms can appear.  This can be the case when installing new
-         software modules or inserting new card types.  A
-         notification 'alarm-inventory-changed' is sent when the
-         inventory is changed.";
-      list alarm-type {
-        key "alarm-type-id alarm-type-qualifier";
-        description
-          "An entry in this list defines a possible alarm.";
-        leaf alarm-type-id {
-          type alarm-type-id;
-          description
-            "The statically defined alarm type identifier for this
-             possible alarm.";
-        }
-        leaf alarm-type-qualifier {
-          type alarm-type-qualifier;
-          description
-            "The optionally dynamically defined alarm type identifier
-             for this possible alarm.";
-        }
-        leaf-list resource {
-          type resource-match;
-          description
-            "Optionally, specifies for which resources the alarm type
-             is valid.";
-        }
-        leaf will-clear {
-          type boolean;
-          mandatory true;
-          description
-            "This leaf tells the operator if the alarm will be
-             cleared when the correct corrective action has been
-             taken.  Implementations SHOULD strive for detecting the
-             cleared state for all alarm types.
-
-             If this leaf is 'true', the operator can monitor the
-             alarm until it becomes cleared after the corrective
-             action has been taken.
-
-             If this leaf is 'false', the operator needs to validate
-             that the alarm is no longer active using other
-             mechanisms.  Alarms can lack a corresponding clear due
-             to missing instrumentation or no logical
-             corresponding clear state.";
-        }
-        leaf-list severity-level {
-          type severity;
-          description
-            "This leaf-list indicates the possible severity levels of
-             this alarm type.  Note well that 'clear' is not part of
-             the severity type.  In general, the severity level
-             should be defined by the instrumentation based on the
-             dynamic state, rather than being defined statically by
-             the alarm type, in order to provide a relevant severity
-             level based on dynamic state and context.  However, most
-             alarm types have a defined set of possible severity
-             levels, and this should be provided here.";
-        }
-        leaf description {
-          type string;
-          mandatory true;
-          description
-            "A description of the possible alarm.  It SHOULD include
-             information on possible underlying root causes and
-             corrective actions.";
-        }
-      }
-    }
-    container summary {
-      if-feature "alarm-summary";
-      config false;
-      description
-        "This container gives a summary of the number of alarms.";
-      list alarm-summary {
-        key "severity";
-        description
-          "A global summary of all alarms in the system.  The summary
-           does not include shelved alarms.";
-        leaf severity {
-          type severity;
-          description
-            "Alarm summary for this severity level.";
-        }
-        leaf total {
-          type yang:gauge32;
-          description
-            "Total number of alarms of this severity level.";
-        }
-        leaf not-cleared {
-          type yang:gauge32;
-          description
-            "Total number of alarms of this severity level
-             that are not cleared.";
-        }
-        leaf cleared {
-          type yang:gauge32;
-          description
-            "For this severity level, the number of alarms that are
-             cleared.";
-        }
-        leaf cleared-not-closed {
-          if-feature "operator-actions";
-          type yang:gauge32;
-          description
-            "For this severity level, the number of alarms that are
-             cleared but not closed.";
-        }
-        leaf cleared-closed {
-          if-feature "operator-actions";
-          type yang:gauge32;
-          description
-            "For this severity level, the number of alarms that are
-             cleared and closed.";
-        }
-        leaf not-cleared-closed {
-          if-feature "operator-actions";
-          type yang:gauge32;
-          description
-            "For this severity level, the number of alarms that are
-             not cleared but closed.";
-        }
-        leaf not-cleared-not-closed {
-          if-feature "operator-actions";
-          type yang:gauge32;
-          description
-            "For this severity level, the number of alarms that are
-             not cleared and not closed.";
-        }
-      }
-      leaf shelves-active {
-        if-feature "alarm-shelving";
-        type empty;
-        description
-          "This is a hint to the operator that there are active
-           alarm shelves.  This leaf MUST exist if the
-           /alarms/shelved-alarms/number-of-shelved-alarms is > 0.";
-      }
-    }
-    container alarm-list {
-      config false;
-      description
-        "The alarms in the system.";
-      leaf number-of-alarms {
-        type yang:gauge32;
-        description
-          "This object shows the total number of
-           alarms in the system, i.e., the total number
-           of entries in the alarm list.";
-      }
-      leaf last-changed {
-        type yang:date-and-time;
-        description
-          "A timestamp when the alarm list was last
-           changed.  The value can be used by a manager to
-           initiate an alarm resynchronization procedure.";
-      }
-      list alarm {
-        key "resource alarm-type-id alarm-type-qualifier";
-        description
-          "The list of alarms.  Each entry in the list holds one
-           alarm for a given alarm type and resource.  An alarm can
-           be updated from the underlying resource or by the user.
-           The following leafs are maintained by the resource:
-           'is-cleared', 'last-change', 'perceived-severity', and
-           'alarm-text'.  An operator can change 'operator-state' and
-           'operator-text'.
-
-           Entries appear in the alarm list the first time an alarm
-           becomes active for a given alarm type and resource.
-           Entries do not get deleted when the alarm is cleared.
-           Clear status is represented as a boolean flag.
-
-           Alarm entries are removed, i.e., purged, from the list by
-           an explicit purge action.  For example, purge all alarms
-           that are cleared and in closed operator state that are
-           older than 24 hours.  Purged alarms are removed from the
-           alarm list.  If the alarm resource state changes after a
-           purge, the alarm will reappear in the alarm list.
-
-           Systems may also remove alarms based on locally configured
-           policies; this is out of scope for this module.";
-        uses common-alarm-parameters;
-        leaf time-created {
-          type yang:date-and-time;
-          mandatory true;
-          description
-            "The timestamp when this alarm entry was created.  This
-             represents the first time the alarm appeared; it can
-             also represent that the alarm reappeared after a purge.
-             Further state changes of the same alarm do not change
-             this leaf; these changes will update the 'last-changed'
-             leaf.";
-        }
-        uses resource-alarm-parameters;
-        list operator-state-change {
-          if-feature "operator-actions";
-          key "time";
-          description
-            "This list is used by operators to indicate the state of
-             human intervention on an alarm.  For example, if an
-             operator has seen an alarm, the operator can add a new
-             item to this list indicating that the alarm is
-             acknowledged.";
-          uses operator-parameters;
-        }
-        action set-operator-state {
-          if-feature "operator-actions";
-          description
-            "This is a means for the operator to indicate the level
-             of human intervention on an alarm.";
-          input {
-            leaf state {
-              type writable-operator-state;
-              mandatory true;
-              description
-                "Set this operator state.";
-            }
-            leaf text {
-              type string;
-              description
-                "Additional optional textual information.";
-            }
-          }
-        }
-        notification operator-action {
-          if-feature "operator-actions";
-          description
-            "This notification is used to report that an operator
-             acted upon an alarm.";
-          uses operator-parameters;
-        }
-      }
-      action purge-alarms {
-        description
-          "This operation requests that the server delete entries
-           from the alarm list according to the supplied criteria.
-
-           Typically, this operation is used to delete alarms that
-           are in closed operator state and older than a specified
-           time.
-
-           The number of purged alarms is returned as an output
-           parameter.";
-        input {
-          uses filter-input;
-        }
-        output {
-          leaf purged-alarms {
-            type uint32;
-            description
-              "Number of purged alarms.";
-          }
-        }
-      }
-      action compress-alarms {
-        if-feature "alarm-history";
-        description
-          "This operation requests that the server compress
-           entries in the alarm list by removing all but the
-           latest 'status-change' entry for all matching alarms.
-           Conditions in the input are logically ANDed.  If no
-           input condition is given, all alarms are compressed.";
-        input {
-          leaf resource {
-            type resource-match;
-            description
-              "Compress the alarms matching this resource.";
-          }
-          leaf alarm-type-id {
-            type leafref {
-              path "/alarms/alarm-list/alarm/alarm-type-id";
-              require-instance false;
-            }
-            description
-              "Compress alarms with this 'alarm-type-id'.";
-          }
-          leaf alarm-type-qualifier {
-            type leafref {
-              path "/alarms/alarm-list/alarm/alarm-type-qualifier";
-              require-instance false;
-            }
-            description
-              "Compress the alarms with this
-               'alarm-type-qualifier'.";
-          }
-        }
-        output {
-          leaf compressed-alarms {
-            type uint32;
-            description
-              "Number of compressed alarm entries.";
-          }
-        }
-      }
-    }
-    container shelved-alarms {
-      if-feature "alarm-shelving";
-      config false;
-      description
-        "The shelved alarms.  Alarms appear here if they match the
-         criteria in /alarms/control/alarm-shelving.  This list does
-         not generate any notifications.  The list represents alarms
-         that are considered not relevant by the operator.  Alarms in
-         this list have an 'operator-state' of 'shelved'.  This
-         cannot be changed.";
-      leaf number-of-shelved-alarms {
-        type yang:gauge32;
-        description
-          "This object shows the total number of current
-           alarms, i.e., the total number of entries
-           in the alarm list.";
-      }
-      leaf shelved-alarms-last-changed {
-        type yang:date-and-time;
-        description
-          "A timestamp when the shelved-alarm list was last changed.
-           The value can be used by a manager to initiate an alarm
-           resynchronization procedure.";
-      }
-      list shelved-alarm {
-        key "resource alarm-type-id alarm-type-qualifier";
-        description
-          "The list of shelved alarms.  Shelved alarms can only be
-           updated from the underlying resource; no operator actions
-           are supported.";
-        uses common-alarm-parameters;
-        leaf shelf-name {
-          type leafref {
-            path "/alarms/control/alarm-shelving/shelf/name";
-            require-instance false;
-          }
-          description
-            "The name of the shelf.";
-        }
-        uses resource-alarm-parameters;
-        list operator-state-change {
-          if-feature "operator-actions";
-          key "time";
-          description
-            "This list is used by operators to indicate the state of
-             human intervention on an alarm.  For shelved alarms, the
-             system has set the list item in the list to 'shelved'.";
-          uses operator-parameters;
-        }
-      }
-      action purge-shelved-alarms {
-        description
-          "This operation requests that the server delete entries from
-           the shelved-alarm list according to the supplied criteria.
-           In the shelved-alarm list, it makes sense to delete alarms
-           that are not relevant anymore.
-
-           The number of purged alarms is returned as an output
-           parameter.";
-        input {
-          uses filter-input;
-        }
-        output {
-          leaf purged-alarms {
-            type uint32;
-            description
-              "Number of purged alarms.";
-          }
-        }
-      }
-      action compress-shelved-alarms {
-        if-feature "alarm-history";
-        description
-          "This operation requests that the server compress entries
-           in the shelved-alarm list by removing all but the latest
-           'status-change' entry for all matching shelved alarms.
-           Conditions in the input are logically ANDed.  If no input
-           condition is given, all alarms are compressed.";
-        input {
-          leaf resource {
-            type leafref {
-              path "/alarms/shelved-alarms/shelved-alarm/resource";
-              require-instance false;
-            }
-            description
-              "Compress the alarms with this resource.";
-          }
-          leaf alarm-type-id {
-            type leafref {
-              path "/alarms/shelved-alarms/shelved-alarm"
-                 + "/alarm-type-id";
-              require-instance false;
-            }
-            description
-              "Compress alarms with this 'alarm-type-id'.";
-          }
-          leaf alarm-type-qualifier {
-            type leafref {
-              path "/alarms/shelved-alarms/shelved-alarm"
-                 + "/alarm-type-qualifier";
-              require-instance false;
-            }
-            description
-              "Compress the alarms with this
-               'alarm-type-qualifier'.";
-          }
-        }
-        output {
-          leaf compressed-alarms {
-            type uint32;
-            description
-              "Number of compressed alarm entries.";
-          }
-        }
-      }
-    }
-    list alarm-profile {
-      if-feature "alarm-profile";
-      key "alarm-type-id alarm-type-qualifier-match resource";
-      //ordered-by user;
-      description
-        "This list is used to assign further information or
-         configuration for each alarm type.  This module supports a
-         mechanism where the client can override the system-default
-         alarm severity levels.  The 'alarm-profile' is also a useful
-         augmentation point for specific additions to alarm types.";
-      leaf alarm-type-id {
-        type alarm-type-id;
-        description
-          "The alarm type identifier to match.";
-      }
-      leaf alarm-type-qualifier-match {
-        type string;
-        description
-          "An XML Schema regular expression that is used to match the
-           alarm type qualifier.";
-        reference
-          "XML Schema Part 2: Datatypes Second Edition,
-             World Wide Web Consortium Recommendation
-             REC-xmlschema-2-20041028";
-      }
-      leaf resource {
-        type resource-match;
-        description
-          "Specifies which resources to match.";
-      }
-      leaf description {
-        type string;
-        mandatory true;
-        description
-          "A description of the alarm profile.";
-      }
-      container alarm-severity-assignment-profile {
-        if-feature "severity-assignment";
-        description
-          "The client can override the system-default severity
-           level.";
-        reference
-          "ITU-T Recommendation M.3100:
-             Generic network information model
-           ITU-T Recommendation M.3160:
-             Generic, protocol-neutral management information model";
-        leaf-list severity-level {
-          type severity;
-          //ordered-by user;
-          description
-            "Specifies the configured severity level(s) for the
-             matching alarm.  If the alarm has several severity
-             levels, the leaf-list shall be given in rising severity
-             order.  The original M3100/M3160 ASAP function only
-             allows for a one-to-one mapping between alarm type and
-             severity, but since YANG module supports stateful
-             alarms, the mapping must allow for several severity
-             levels.
-
-             Assume a high-utilization alarm type with two thresholds
-             with the system-default severity levels of threshold1 =
-             warning and threshold2 = minor.  Setting this leaf-list
-             to (minor, major) will assign the severity levels as
-             threshold1 = minor and threshold2 = major";
-        }
-      }
-    }
-  }
-
-  /*
-   * Notifications
-   */
-
-  notification alarm-notification {
-    description
-      "This notification is used to report a state change for an
-       alarm.  The same notification is used for reporting a newly
-       raised alarm, a cleared alarm, or changing the text and/or
-       severity of an existing alarm.";
-    uses common-alarm-parameters;
-    uses alarm-state-change-parameters;
-  }
-
-  notification alarm-inventory-changed {
-    description
-      "This notification is used to report that the list of possible
-       alarms has changed.  This can happen when, for example, a new
-       software module is installed or a new physical card is
-       inserted.";
-  }
-}
diff --git a/ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-alarms-v1.yang b/ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-alarms-v1.yang
deleted file mode 100644 (file)
index a55ed7c..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-module o-ran-sc-alarms-v1 {
-  yang-version 1.1;
-  namespace "urn:o-ran:sc:alarms:1.0";
-  prefix oal;
-
-  import o-ran-sc-root-v1 {
-    prefix root;
-  }
-  import ietf-alarms {
-    prefix al;
-    reference
-      "RFC 8632: A YANG Data Model for Alarm Management";
-  }
-
-  organization
-    "O-RAN Software Community";
-  contact
-    "www.o-ran-sc.org";
-  description
-    "This module augements the  o-ran-sc-controlled-element and  
-     o-ran-sc-controlled-function object by adding ietf-alarms.
-
-     Copyright 2020 the O-RAN Alliance.
-
-     Licensed under the Apache License, Version 2.0 (the 'License');
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an 'AS IS' BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.";
-
-  revision 2020-03-09 {
-    description
-      "initial revision";
-    reference
-      "O-RAN-OAM-Interface-Specification (O1)";
-  }
-
-  grouping alarms-grp {
-    list alarm-reference {
-      key "resource alarm-type-id alarm-type-qualifier";
-      config false;
-      description
-        "References to related alarms. Note that the related alarm
-         might have been purged from the alarm list.";
-      leaf resource {
-        type leafref {
-          path "/al:alarms/al:alarm-list/al:alarm/al:resource";
-          require-instance false;
-        }
-        description
-          "The alarming resource for the related alarm.";
-      }
-      leaf alarm-type-id {
-        type leafref {
-          path "/al:alarms/al:alarm-list/al:alarm"
-             + "[al:resource=current()/../resource]"
-             + "/al:alarm-type-id";
-          require-instance false;
-        }
-        description
-          "The alarm type identifier for the related alarm.";
-      }
-      leaf alarm-type-qualifier {
-        type leafref {
-          path "/al:alarms/al:alarm-list/al:alarm"
-             + "[al:resource=current()/../resource]"
-             + "[al:alarm-type-id=current()/../alarm-type-id]"
-             + "/al:alarm-type-qualifier";
-          require-instance false;
-        }
-        description
-          "The alarm qualifier for the related alarm.";
-      }
-    }
-    description 
-      "A group adding ietf-alarm references.";
-  }
-
-  augment "/root:controlled-element" {
-    uses alarms-grp;
-    description
-      "An augmentation, which adds ietf-alarms 
-       to root:controlled-element.";
-  }
-
-  augment "/root:controlled-element/root:controlled-function" {
-    uses alarms-grp;
-    description
-      "An augmentation, which adds ietf-alarms 
-       to root:controlled-function.";
-  }
-}
diff --git a/ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-common-alarms-v1.yang b/ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-common-alarms-v1.yang
deleted file mode 100644 (file)
index 930bba3..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-module o-ran-sc-common-alarms-v1 {
-  yang-version 1.1;
-  namespace "urn:o-ran-sc:alarms:1.0";
-  prefix osc-al;
-
-  import ietf-alarms {
-    prefix al;
-  }
-
-  organization
-    "O-RAN Software Community";
-  contact
-    "www.o-ran-sc.org";
-  description
-    "This module defines the alarm identities for the O-RAN-SC Components.
-
-     Copyright 2020 the O-RAN Software Community.
-
-     Licensed under the Apache License, Version 2.0 (the 'License');
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an 'AS IS' BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.";
-
-  revision 2020-01-18 {
-    description
-      "initial revision";
-    reference
-      "O-RAN-OAM-Interface-Specification (O1)";
-  }
-
-  identity alarm-type-id {
-    base al:alarm-type-id;
-    description
-      "An abstract alarm type use for all O-RAN-SC alarm types which are
-       common across the O-RAN managed functions.";
-  }
-
-  identity smo-o1-ves-collector-not-reachable {
-    base alarm-type-id;
-    description
-      "The configured VES end-point for asynchron messages is not reachable.
-       Instructions:
-         1) Verify the VES configuration on the O-RAN component.
-         2) Verify the connectivity between the O-RAN component and the
-            SMO in terms of routing and firewall settings along the path.
-         3) Check the credentials of the O-RAN component (user, password,
-            certificate). Did changes happen on SMO level recently?";
-  }
-}
diff --git a/ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-hardware-v1.yang b/ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-hardware-v1.yang
deleted file mode 100644 (file)
index fc08229..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-module o-ran-sc-hardware-v1 {
-  yang-version 1.1;
-  namespace "urn:o-ran:sc:hardware:1.0";
-  prefix ohw;
-
-  import o-ran-sc-root-v1 {
-    prefix root;
-  }
-  import ietf-hardware {
-    prefix hw;
-    reference
-      "RFC 8348: A YANG Data Model for Hardware Management";
-  }
-
-  organization
-    "O-RAN Software Community";
-  contact
-    "www.o-ran-sc.org";
-  description
-    "This module augements the  o-ran-sc-controlled-element and  
-     o-ran-sc-controlled-function object by adding ietf-hardware.
-
-     Copyright 2020 the O-RAN Alliance.
-
-     Licensed under the Apache License, Version 2.0 (the 'License');
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an 'AS IS' BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.";
-
-  revision 2020-03-09 {
-    description
-      "initial revision";
-    reference
-      "O-RAN-OAM-Interface-Specification (O1)";
-  }
-
-  /*
-   * Typedefs
-   */
-
-  typedef hardware-ref {
-    type leafref {
-      path "/hw:hardware/hw:component/hw:name";
-    }
-    description
-      "This type is used by data models that need to reference
-       hardware.";
-  }
-
-  /*
-   * Groupings
-   */
-
-  grouping hardware-grp {
-    leaf-list hardware-reference  {
-      type hardware-ref;
-      config false;
-      description 
-        "A list of ietf-hardware references using the hardware name as key.";
-    }
-    description 
-      "A group adding ietf-hardware references.";
-  }
-
-  /*
-   * Data nodes
-   */
-
-  augment "/root:controlled-element" {
-    uses hardware-grp;
-    description
-      "An augmentation, which adds ietf-hardware 
-       to root:controlled-element.";
-  }
-
-  augment "/root:controlled-element/root:controlled-function" {
-    uses hardware-grp;
-    description
-      "An augmentation, which adds ietf-hardware 
-       to root:controlled-function.";
-  }
-}
diff --git a/ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-interfaces-v1.yang b/ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-interfaces-v1.yang
deleted file mode 100644 (file)
index 4f54d43..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-module o-ran-sc-interfaces-v1 {
-  yang-version 1.1;
-  namespace "urn:o-ran:sc:interfaces:1.0";
-  prefix oif;
-
-  import o-ran-sc-root-v1 {
-    prefix root;
-  }
-  import ietf-interfaces {
-    prefix if;
-    reference
-      "RFC 8343: A YANG Data Model for Interface Management";
-  }
-
-  organization
-    "O-RAN Software Community";
-  contact
-    "www.o-ran-sc.org";
-  description
-    "This module augements the o-ran-sc-controlled-function object by adding
-     ietf-interfaces.
-
-     Copyright 2020 the O-RAN Alliance.
-
-     Licensed under the Apache License, Version 2.0 (the 'License');
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an 'AS IS' BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.";
-
-  revision 2020-03-09 {
-    description
-      "initial revision";
-    reference
-      "O-RAN-OAM-Interface-Specification (O1)";
-  }
-
-  identity a1-interface {
-    base if:interface-type;
-    description
-      "Represents an O-RAN A1 interface towards SMO.";
-    reference
-      "O-RAN OAM interface specification.";
-  }
-
-  identity e1-interface {
-    base if:interface-type;
-    description
-      "Represents an O-RAN E1 interface.";
-    reference
-      "O-RAN OAM interface specification.";
-  }
-
-  identity e2-interface {
-    base if:interface-type;
-    description
-      "Represents an O-RAN E2 interface towards Near Real Time RIC.";
-    reference
-      "O-RAN OAM interface specification.";
-  }
-
-  identity f1-interface {
-    base if:interface-type;
-    description
-      "Represents an O-RAN F1 interface.";
-    reference
-      "O-RAN OAM interface specification.";
-  }
-
-  identity o1-interface {
-    base if:interface-type;
-    description
-      "Represents an O-RAN OAM interface towards SMO.";
-    reference
-      "O-RAN OAM interface specification.";
-  }
-
-  identity open-fronthaul-interface {
-    base if:interface-type;
-    description
-      "Represents an O-RAN Open Fronthaul interface towards an O-DU.";
-    reference
-      "O-RAN OAM interface specification.";
-  }
-
-  grouping interfaces-grp {
-    leaf-list interface-reference  {
-      type if:interface-ref;
-      config false;
-      description 
-        "A list of ietf-interfaces references using the interface name as key.";
-    }
-    description 
-      "A group adding ietf-interface references.";
-  }
-  augment "/root:controlled-element/root:controlled-function" {
-    uses interfaces-grp;
-    description
-      "An augmentation, which adds ietf-interfaces 
-       to root:controlled-function.";
-  }
-}
diff --git a/ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-root-v1.yang b/ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-root-v1.yang
deleted file mode 100644 (file)
index 1acd553..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-module o-ran-sc-root-v1 {
-  yang-version 1.1;
-  namespace "urn:o-ran:sc:root:1.0";
-  prefix or;
-
-  import o-ran-sc-types-v1 {
-    prefix ot;
-  }
-  import ietf-yang-types {
-    prefix yang;
-    reference
-      "RFC 6991: Common YANG Data Types";
-  }
-
-  organization
-    "O-RAN Software Community";
-  contact
-    "www.o-ran-sc.org";
-  description
-    "This module defines the root controlled object classes for a
-     disaggregated RAN.
-
-     Copyright 2020 the O-RAN Alliance.
-
-     Licensed under the Apache License, Version 2.0 (the 'License');
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an 'AS IS' BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.";
-
-  revision 2020-02-20 {
-    description
-      "initial revision";
-    reference
-      "O-RAN-OAM-Interface-Specification (O1)";
-  }
-
-  // Groupings
-
-  grouping controlled-identifier-grp {
-    leaf authority-ref {
-      type ot:sized-printable-string;
-      description
-        "A name or indentifier referencing the authority to which is
-         responsable to create, modify or delete
-         the controlled identifier. ";
-    }
-    leaf identifer {
-      type string {
-        length "1..255";
-      }
-      description
-        "The external controlled identifier value for this controlled
-         object.";
-    }
-    description
-      "An object class specifiing an object identifier, which is caluculated
-       or generated by the consumer of the API..";
-  }
-
-  grouping state-grp {
-    leaf operational-state {
-      type identityref {
-        base ot:operational-state;
-      }
-      config false;
-      description
-        "The operational state is used to indicate whether or not the
-         resource is installed and working.";
-    }
-    leaf administrative-control {
-      type identityref {
-        base ot:administrative-control;
-      }
-      description
-        "The administrative-control state provides control of the
-         availability of specific resources without modification to the
-         provisioning of those resources.
-         The value is the current control target. The actual
-         administrative-state may or may not be at target.";
-    }
-    leaf administrative-state {
-      type identityref {
-        base ot:administrative-state;
-      }
-      config false;
-      description
-        "Shows whether or not the client has permission to use or has a
-         prohibition against using the resource.
-         The administrative state expresses usage permissions for
-         specific resources without modification to the provisioning
-         of those resources.";
-    }
-    leaf lifecycle-state {
-      type identityref {
-        base ot:lifecycle-state;
-      }
-      description
-        "Used to track the planned deployment, allocation to clients and
-         withdrawal of resources.";
-    }
-    description
-      "Provides general state attributes.";
-  }
-
-  grouping control-base-grp {
-    leaf identifier {
-      type yang:uuid;
-      mandatory true;
-      description
-        "The network wide unique identifier an object. The value will
-          never change and maybe used as reference even long time after
-          the object instance itself was deleted.
-          The value is calculated of generated by the provider of this
-          API.";
-    }
-    list controlled-identifier {
-      key "authority-ref";
-      uses controlled-identifier-grp;
-      description
-        "A list of external controlled identifiers, set by an external
-         authority. There must not be any function implemented on the
-         API provider itself next to updating the list on request and
-         storing it persistently. ";
-    }
-    leaf name {
-      type ot:sized-printable-string;
-      description
-        "A user defined human readable identifier. The value may chance
-         during the lifetime of the object and must not be used by any
-         software for references.";
-    }
-    leaf label {
-      type string {
-        length "1..64";
-      }
-      description
-        "A human readable value that is not expected to be unique and is
-         allowed to change. A label carries no semantics with respect to
-         the purpose of the object and has no effect on the object
-         behavior or state.";
-    }
-    uses state-grp;
-    description
-      "The control-base object class representation an abstract object class,
-       which all is used by all important control object classes.";
-  }
-
-  container controlled-element {
-    presence "Enables O-RAN";
-    uses control-base-grp;
-    list controlled-function {
-      key "identifier";
-      uses control-base-grp;
-      leaf function-type {
-        type identityref {
-          base ot:control-function-type;
-        }
-        description
-          "The reference to the O-RAN Alliance functions of the OAM
-           Architecture specification.";
-      }
-      description
-        "A list of abstract object classes which needs to be
-         augmented by the authority of providing the function.";
-    }
-    description
-      "The root container of an element (network-element,
-       manged-element, network-function, ...). it groups the
-       functions provided by the element. in a most disaggregated RAN
-       the each element provides only one function.";
-  }
-}
diff --git a/ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-ru-alarms-v1.yang b/ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-ru-alarms-v1.yang
deleted file mode 100644 (file)
index c52414d..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-module o-ran-sc-ru-alarms-v1 {
-  yang-version 1.1;
-  namespace "urn:o-ran-sc:ru:alarms:1.0";
-  prefix osc-ru-al;
-
-  import ietf-alarms {
-    prefix al;
-  }
-
-  organization
-    "O-RAN Software Community";
-  contact
-    "www.o-ran-sc.org";
-  description
-    "This module defines the alarm identities for the O-RAN-SC Components.
-
-     Copyright 2020 the O-RAN Software Community.
-
-     Licensed under the Apache License, Version 2.0 (the 'License');
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an 'AS IS' BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.";
-
-  revision 2020-01-18 {
-    description
-      "initial revision";
-    reference
-      "O-RAN-OAM-Interface-Specification (O1)";
-  }
-
-  identity alarm-type-id {
-    base al:alarm-type-id;
-    description
-      "An abstract alarm type used for all O-RAN-SC specific alarm types for
-       Managed Function O-RU.";
-  }
-
-  identity huston-we-have-a-problem {
-    base alarm-type-id;
-    description
-      "A generic alarm which is under development and analysis,
-       must not happen in production environment.
-       Instructions:
-         Create an JIRA issue and provide the following intormation:
-         - SMO version, build number or git hash
-         - O-RU version, build number or git hash
-         - A procedure to reproduce the alarm.";
-  }
-}
diff --git a/ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-ru-v1.yang b/ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-ru-v1.yang
deleted file mode 100644 (file)
index 1566ec9..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-module o-ran-sc-ru-v1 {
-  yang-version 1.1;
-  namespace "urn:o-ran:sc:radio-unit:1.0";
-  prefix oru;
-
-  import o-ran-sc-root-v1 {
-    prefix root;
-  }
-  import o-ran-sc-types-v1 {
-    prefix ot;
-  }
-
-  organization
-    "O-RAN Software Community";
-  contact
-    "www.o-ran.org";
-  description
-    "This module contains the O-RAN Software Community RadioUnit specific
-     O1 interface APIs.
-
-     Copyright 2020 the O-RAN Alliance.
-
-     Licensed under the Apache License, Version 2.0 (the 'License');
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an 'AS IS' BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.";
-
-  revision 2020-02-20 {
-    description
-      "initial revision";
-    reference
-      "O-RAN-OAM-Interface-Specification (O1)";
-  }
-
-  // identity
-
-  identity o-ru {
-    base ot:control-function-type;
-    description
-      "TODO: Nice description";
-  }
-
-  // grouping
-
-  grouping o-ru-specific-grp {
-    description
-      "TODO: add your specific leafs, lists, containers here.";
-  }
-
-  // Inherit from controlled-function
-  augment "/root:controlled-element/root:controlled-function" {
-    when "derived-from-or-self(./root:function-type, 'oru:o-ru')";
-    uses o-ru-specific-grp;
-    description
-      "TODO: Nice description";
-  }
-}
diff --git a/ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-types-v1.yang b/ntsimulator/yang/o-ran-sc/o-ran-ru/o-ran-sc-types-v1.yang
deleted file mode 100644 (file)
index 5bf46d9..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-module o-ran-sc-types-v1 {
-    yang-version 1.1;
-    namespace "urn:o-ran:sc:types:1.0";
-    prefix ot;
-
-    organization
-      "O-RAN Software Community";
-    contact
-      "www.o-ran-sc.org";
-    description
-      "This module defines common type definitions related to O-RAN.
-       
-       Copyright 2020 the O-RAN Alliance.
-       
-       Licensed under the Apache License, Version 2.0 (the 'License');
-       you may not use this file except in compliance with the License.
-       You may obtain a copy of the License at
-       
-       http://www.apache.org/licenses/LICENSE-2.0
-       
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an 'AS IS' BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-       See the License for the specific language governing permissions and
-       limitations under the License.";
-
-    revision 2020-02-20 {
-        description
-          "initial revision";
-        reference
-          "O-RAN-OAM-Interface-Specification (O1)";
-    }
-
-    // Identity
-    identity control-element-type {
-        description
-          "Base identity for the different and upcoming control-element types.";
-    }
-
-    identity e-node-b {
-        base control-element-type;
-        description
-          "Indicates a control element representing an eNodeB.";
-        reference
-          "O-RAN OAM Architecture Specification";
-    }
-
-    identity g-node-b {
-        base control-element-type;
-        description
-          "Indicates a managed element representing an gNodeB.";
-        reference
-          "O-RAN OAM Architecture Specification";
-    }
-
-    identity control-function-type {
-        description
-          "Base identity for the different and upcoming control-function types.";
-    }
-
-    // administrative-state
-    identity administrative-state {
-        description
-          "The administrative state is used to show whether use of a resource
-           is allowed or prohibited.
-           The administrative state can be observed and directly controlled by
-           certain operational roles.
-           Typically, only a user in the provider context with administrative
-           privileges is allowed to write the administrative state,
-           any other users are restricted to read only.";
-        reference
-          "ftp://www.3gpp.org/tsg_ran/WG3_Iu/TSGR3_07/Docs/Pdfs/R3-99b77.PDF";
-    }
-
-    identity administrative-state-locked {
-        base administrative-state;
-        description
-          "Users are administratively prohibited from making use of the
-           resource.";
-    }
-
-    identity administrative-state-unlocked {
-        base administrative-state;
-        description
-          "Users are allowed to use the resource.";
-    }
-
-    identity administrative-state-shutting-down {
-        base administrative-state;
-        description
-          "The entity is administratively restricted to existing instances of
-           use only. There may be specific actions to remove existing uses.
-           No new instances of use can be enabled.
-           The resource automatically transitions to “locked” when the last
-           user quits.
-           The administrative state is not visible in the client context.
-           The life cycle state “pending removal” should be used to indicate to
-           the client that the provider intends to remove the resource.";
-    }
-
-    // administrative-control
-    identity administrative-control {
-        description
-          "Reflects the current control action when the entity is not in the
-           desired state.";
-    }
-
-    identity administrative-control-unlock {
-        base administrative-control;
-        description
-          "The intention is for the entity to become unlocked.
-           The entity may already be UNLOCKED.";
-    }
-
-    identity administrative-control-lock-passive {
-        base administrative-control;
-        description
-          "The intention is for the entity to become locked but no effort is
-           expected to move to the Locked state (the state will be achieved once
-           all users stop using the resource).
-           The entity may be LOCKED.";
-    }
-
-    identity administrative-control-lock-active {
-        base administrative-control;
-        description
-          "The intention is for the entity to become locked and it is expected
-           that effort will be made to move to the Locked state (users will be
-           actively removed).
-           The entity may already be LOCKED.";
-    }
-
-    identity administrative-control-lock-immediate {
-        base administrative-control;
-        description
-          "The intention is for the entity to become locked and it is expected
-           to move to the Locked state immediately (users will be force removed).
-           The entity may already be LOCKED.";
-    }
-
-    identity administrative-control-quiescent {
-        base administrative-control;
-        description
-          "The administrative state is at a stable value (LOCKED/UNLOCKED) and
-           no action is being taken.";
-    }
-
-    // operational-state
-    identity operational-state {
-        description
-          "The operational state base identity to be used to indicate whether
-           or not the resource is installed and working.";
-        reference
-          "https://www.3gpp.org/ftp/tsg_ran/WG3_Iu/TSGR3_06/Docs/Pdfs/r3-99994.pdf";
-    }
-
-    identity operational-state-disabled {
-        base operational-state;
-        description
-          "The resource is unable to meet the SLA of the user of the resource.
-           If no (explicit) SLA is defined the resource is disabled if it is
-           totally inoperable and unable to provide service to the user.";
-    }
-
-    identity operational-state-enabled {
-        base operational-state;
-        description
-          "The resource is partially or fully operable and available for use.";
-    }
-
-    identity lifecycle-state {
-        description
-          "This state is used to track the planned deployment, allocation to
-           clients and withdrawal of resources.";
-    }
-
-    identity lifecycle-state-planned {
-        base lifecycle-state;
-        description
-          "The resource is planned but is not present in the network.
-           Should include a 'time' when the resources are expected to be
-           installed.";
-    }
-
-    identity lifecycle-state-potential-available {
-        base lifecycle-state;
-        description
-          "The supporting resources are present in the network but are shared
-           with other clients; or require further configuration before they can
-           be used; or both.
-           (1) When a potential resource is configured and allocated to a
-               client it is moved to the INSTALLED state for that client.
-           (2) If the potential resource has been consumed (e.g. allocated to
-               another client) it is moved to the POTENTIAL BUSY state for all
-               other clients.";
-    }
-
-    identity lifecycle-state-potential-busy {
-        base lifecycle-state;
-        description
-          "The supporting resources are present in the network but have been
-           allocated to other clients.";
-    }
-
-    identity lifecycle-state-installed {
-        base lifecycle-state;
-        description
-          "The resource is present in the network and is capable of providing
-           the service.";
-    }
-
-    identity lifecycle-state-pending-removal {
-        base lifecycle-state;
-        description
-          "The resource has been marked for removal. Should include a 'time'
-           when the resources are expected to be removed.";
-    }
-
-    // Type definitions
-    typedef e2ap-protocol-type {
-        // TODO switch to identity
-        type enumeration {
-            enum not-specified {
-                description
-                  "None";
-            }
-            enum x2-setup-request {
-                description
-                  "X2 setup request";
-            }
-            enum endc-x2-setup-request {
-                description
-                  "ENDC X2 setup request";
-            }
-        }
-        description
-          "The E2AP protocol setup types";
-    }
-
-    typedef connection-status-type {
-        // TODO swtitch to identity
-        type enumeration {
-            enum not-specified {
-                description
-                  "None";
-            }
-            enum connected {
-                description
-                  "Connected";
-            }
-            enum connecting {
-                description
-                  "Connecting";
-            }
-            enum disconnected {
-                description
-                  "Disconnected";
-            }
-            enum setup-failed {
-                description
-                  "Setup failed";
-            }
-            enum shutting-down {
-                description
-                  "Shutting down";
-            }
-            enum shutdown {
-                description
-                  "Shutdown";
-            }
-        }
-        description
-          "The connection status of gNB";
-    }
-
-    typedef sized-printable-string {
-        type string {
-            length "1..63";
-            pattern
-              '[\\x20-\\x7E]';
-        }
-        description
-          "A string of printable ASCII characters with a size of
-           1 to 64 characters.";
-    }
-}
diff --git a/ntsimulator/yang/sysrepo-configuration-load.sh b/ntsimulator/yang/sysrepo-configuration-load.sh
deleted file mode 100755 (executable)
index 379ea70..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/bin/bash
-################################################################################
-#
-# Copyright 2019 highstreet technologies GmbH and others
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-# 
-#     http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-################################################################################
-
-sleep 20
-
-echo "Loading data into sysrepo..."
-
-result=$(netopeer2-cli <<-END
-       knownhosts --del 0
-    knownhosts --del 0
-END
-)
-
-SSH_PUB_KEY_MELACON="$(cat /home/netconf/.ssh/melacon.server.key.pub)"
-
-echo "Writing the public key to the known_hosts..."
-echo "[127.0.0.1]:830 $SSH_PUB_KEY_MELACON" > /root/.ssh/known_hosts
-
-pyang -f sample-xml-skeleton --sample-xml-list-entries 2 *.yang
-
-result=$(netopeer2-cli <<-END
-    auth keys add /home/netconf/.ssh/melacon.server.key.pub /home/netconf/.ssh/melacon.server.key
-       connect --host 127.0.0.1 --login netconf
-       user-rpc --content=/opt/dev/yang/edit_config_operation.xml
-       disconnect
-END
-)
-
-count=1
-
-while [[ $count -le 100 ]] && [[ "$result" != "OK" ]]
-do
-  ((count++))
-  pyang -f sample-xml-skeleton --sample-xml-list-entries 2 *.yang
-  
-  result=$(netopeer2-cli <<-END
-       connect --host 127.0.0.1 --login netconf
-       user-rpc --content=edit_config_operation.xml
-       disconnect
-END
-)
-done
-
-echo "Finished loading data into sysrepo. Removing edit-config XML..."
-rm -f /opt/dev/yang/edit_config_operation.xml
-
-echo "Done..."
-exit 0
\ No newline at end of file
diff --git a/ntsimulator/yang/x-ran/iana-hardware.yang b/ntsimulator/yang/x-ran/iana-hardware.yang
deleted file mode 100755 (executable)
index 52bcaf3..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-module iana-hardware {
-yang-version 1.1;
-namespace "urn:ietf:params:xml:ns:yang:iana-hardware";
-prefix ianahw;
-
-organization "IANA";
-contact
-  "        Internet Assigned Numbers Authority
-   Postal: ICANN
-           12025 Waterfront Drive, Suite 300
-           Los Angeles, CA  90094-2536
-           United States of America
-   Tel:    +1 310 301 5800
-   E-Mail: iana@iana.org>";
-
-description
-  "IANA-defined identities for hardware class.
-   The latest revision of this YANG module can be obtained from
-   the IANA website.
-   Requests for new values should be made to IANA via
-   email (iana@iana.org).
-   Copyright (c) 2018 IETF Trust and the persons identified as
-   authors of the code.  All rights reserved.
-   Redistribution and use in source and binary forms, with or
-   without modification, is permitted pursuant to, and subject
-   to the license terms contained in, the Simplified BSD License
-   set forth in Section 4.c of the IETF Trust's Legal Provisions
-   Relating to IETF Documents
-   (https://trustee.ietf.org/license-info).
-   The initial version of this YANG module is part of RFC 8348;
-   see the RFC itself for full legal notices.";
-reference
-  "https://www.iana.org/assignments/yang-parameters";
-
-revision 2018-03-13 {
-  description
-    "Initial revision.";
-  reference
-    "RFC 8348: A YANG Data Model for Hardware Management";
-}
-
-/*
- * Identities
- */
-
-identity hardware-class {
-  description
-    "This identity is the base for all hardware class
-     identifiers.";
-}
-
-identity unknown {
-  base ianahw:hardware-class;
-  description
-    "This identity is applicable if the hardware class is unknown
-     to the server.";
-}
-
-identity chassis {
-  base ianahw:hardware-class;
-  description
-    "This identity is applicable if the hardware class is an
-     overall container for networking equipment.  Any class of
-     physical component, except a stack, may be contained within a
-     chassis; a chassis may only be contained within a stack.";
-}
-
-identity backplane {
-  base ianahw:hardware-class;
-  description
-    "This identity is applicable if the hardware class is some sort
-     of device for aggregating and forwarding networking traffic,
-     such as a shared backplane in a modular ethernet switch.  Note
-     that an implementation may model a backplane as a single
-     physical component, which is actually implemented as multiple
-     discrete physical components (within a chassis or stack).";
-}
-
-identity container {
-  base ianahw:hardware-class;
-  description
-    "This identity is applicable if the hardware class is capable
-     of containing one or more removable physical entities,
-     possibly of different types.  For example, each (empty or
-     full) slot in a chassis will be modeled as a container.  Note
-     that all removable physical components should be modeled
-     within a container component, such as field-replaceable
-     modules, fans, or power supplies.  Note that all known
-     containers should be modeled by the agent, including empty
-     containers.";
-}
-
-identity power-supply {
-  base ianahw:hardware-class;
-  description
-    "This identity is applicable if the hardware class is a
-     power-supplying component.";
-}
-
-identity fan {
-  base ianahw:hardware-class;
-  description
-    "This identity is applicable if the hardware class is a fan or
-     other heat-reduction component.";
-}
-
-identity sensor {
-  base ianahw:hardware-class;
-  description
-    "This identity is applicable if the hardware class is some sort
-     of sensor, such as a temperature sensor within a router
-     chassis.";
-}
-
-identity module {
-  base ianahw:hardware-class;
-  description
-    "This identity is applicable if the hardware class is some sort
-     of self-contained sub-system.  If a module component is
-     removable, then it should be modeled within a container
-     component; otherwise, it should be modeled directly within
-     another physical component (e.g., a chassis or another
-     module).";
-}
-
-identity port {
-  base ianahw:hardware-class;
-  description
-    "This identity is applicable if the hardware class is some sort
-     of networking port capable of receiving and/or transmitting
-     networking traffic.";
-}
-
-identity stack {
-  base ianahw:hardware-class;
-  description
-    "This identity is applicable if the hardware class is some sort
-     of super-container (possibly virtual) intended to group
-     together multiple chassis entities.  A stack may be realized
-     by a virtual cable, a real interconnect cable attached to
-     multiple chassis, or multiple interconnect cables.  A stack
-     should not be modeled within any other physical components,
-     but a stack may be contained within another stack.  Only
-     chassis components should be contained within a stack.";
-}
-
-identity cpu {
-  base ianahw:hardware-class;
-  description
-    "This identity is applicable if the hardware class is some sort
-     of central processing unit.";
-}
-
-identity energy-object {
-  base ianahw:hardware-class;
-  description
-    "This identity is applicable if the hardware class is some sort
-     of energy object, i.e., it is a piece of equipment that is
-     part of or attached to a communications network that is
-     monitored, it is controlled, or it aids in the management of
-     another device for Energy Management.";
-}
-
-identity battery {
-  base ianahw:hardware-class;
-  description
-    "This identity is applicable if the hardware class is some sort
-     of battery.";
-}
-
-identity storage-drive {
-  base ianahw:hardware-class;
-  description
-    "This identity is applicable if the hardware class is some sort
-     of component with data storage capability as its main
-     functionality, e.g., hard disk drive (HDD), solid-state device
-     (SSD), solid-state hybrid drive (SSHD), object storage device
-     (OSD), or other.";
-}
-}
diff --git a/ntsimulator/yang/x-ran/ietf-hardware.yang b/ntsimulator/yang/x-ran/ietf-hardware.yang
deleted file mode 100755 (executable)
index f444e26..0000000
+++ /dev/null
@@ -1,1141 +0,0 @@
-module ietf-hardware {
-yang-version 1.1;
-namespace "urn:ietf:params:xml:ns:yang:ietf-hardware";
-prefix hw;
-
-import ietf-inet-types {
-  prefix inet;
-}
-import ietf-yang-types {
-  prefix yang;
-}
-import iana-hardware {
-  prefix ianahw;
-}
-
-organization
-  "IETF NETMOD (Network Modeling) Working Group";
-
-contact
-  "WG Web:   <https://datatracker.ietf.org/wg/netmod/>
-   WG List:  <mailto:netmod@ietf.org>
-   Editor:   Andy Bierman
-             <mailto:andy@yumaworks.com>
-   Editor:   Martin Bjorklund
-             <mailto:mbj@tail-f.com>
-   Editor:   Jie Dong
-             <mailto:jie.dong@huawei.com>
-   Editor:   Dan Romascanu
-             <mailto:dromasca@gmail.com>";
-
-description
-  "This module contains a collection of YANG definitions for
-   managing hardware.
-   This data model is designed for the Network Management Datastore
-   Architecture (NMDA) defined in RFC 8342.
-   Copyright (c) 2018 IETF Trust and the persons identified as
-   authors of the code.  All rights reserved.
-   Redistribution and use in source and binary forms, with or
-   without modification, is permitted pursuant to, and subject
-   to the license terms contained in, the Simplified BSD License
-   set forth in Section 4.c of the IETF Trust's Legal Provisions
-   Relating to IETF Documents
-   (https://trustee.ietf.org/license-info).
-   This version of this YANG module is part of RFC 8348; see
-   the RFC itself for full legal notices.";
-
-revision 2018-03-13 {
-  description
-    "Initial revision.";
-  reference
-    "RFC 8348: A YANG Data Model for Hardware Management";
-}
-
-/*
- * Features
- */
-
-feature entity-mib {
-  description
-    "This feature indicates that the device implements
-     the ENTITY-MIB.";
-  reference
-    "RFC 6933: Entity MIB (Version 4)";
-}
-
-feature hardware-state {
-  description
-    "Indicates that ENTITY-STATE-MIB objects are supported";
-  reference
-    "RFC 4268: Entity State MIB";
-}
-
-feature hardware-sensor {
-  description
-    "Indicates that ENTITY-SENSOR-MIB objects are supported";
-  reference
-    "RFC 3433: Entity Sensor Management Information Base";
-}
-
-/*
- * Typedefs
- */
-
-typedef admin-state {
-  type enumeration {
-    enum unknown {
-      value 1;
-      description
-        "The resource is unable to report administrative state.";
-    }
-    enum locked {
-      value 2;
-      description
-        "The resource is administratively prohibited from use.";
-    }
-    enum shutting-down {
-      value 3;
-      description
-        "The resource usage is administratively limited to current
-         instances of use.";
-    }
-    enum unlocked {
-      value 4;
-      description
-        "The resource is not administratively prohibited from
-         use.";
-    }
-  }
-  description
-    "Represents the various possible administrative states.";
-  reference
-    "RFC 4268: Entity State MIB - EntityAdminState";
-}
-
-typedef oper-state {
-  type enumeration {
-    enum unknown {
-      value 1;
-      description
-        "The resource is unable to report its operational state.";
-    }
-    enum disabled {
-      value 2;
-      description
-        "The resource is totally inoperable.";
-    }
-    enum enabled {
-      value 3;
-
-      description
-        "The resource is partially or fully operable.";
-    }
-    enum testing {
-      value 4;
-      description
-        "The resource is currently being tested and cannot
-         therefore report whether or not it is operational.";
-    }
-  }
-  description
-    "Represents the possible values of operational states.";
-  reference
-    "RFC 4268: Entity State MIB - EntityOperState";
-}
-
-typedef usage-state {
-  type enumeration {
-    enum unknown {
-      value 1;
-      description
-        "The resource is unable to report usage state.";
-    }
-    enum idle {
-      value 2;
-      description
-        "The resource is servicing no users.";
-    }
-    enum active {
-      value 3;
-      description
-        "The resource is currently in use, and it has sufficient
-         spare capacity to provide for additional users.";
-    }
-    enum busy {
-      value 4;
-      description
-        "The resource is currently in use, but it currently has no
-         spare capacity to provide for additional users.";
-    }
-  }
-  description
-    "Represents the possible values of usage states.";
-  reference
-    "RFC 4268: Entity State MIB -  EntityUsageState";
-}
-
-typedef alarm-state {
-  type bits {
-    bit unknown {
-      position 0;
-      description
-        "The resource is unable to report alarm state.";
-    }
-    bit under-repair {
-      position 1;
-      description
-        "The resource is currently being repaired, which, depending
-         on the implementation, may make the other values in this
-         bit string not meaningful.";
-    }
-    bit critical {
-      position 2;
-      description
-        "One or more critical alarms are active against the
-         resource.";
-    }
-    bit major {
-      position 3;
-      description
-        "One or more major alarms are active against the
-         resource.";
-    }
-    bit minor {
-      position 4;
-      description
-        "One or more minor alarms are active against the
-         resource.";
-    }
-    bit warning {
-      position 5;
-      description
-        "One or more warning alarms are active against the
-         resource.";
-    }
-    bit indeterminate {
-      position 6;
-      description
-        "One or more alarms of whose perceived severity cannot be
-         determined are active against this resource.";
-    }
-  }
-  description
-    "Represents the possible values of alarm states.  An alarm is a
-     persistent indication of an error or warning condition.
-     When no bits of this attribute are set, then no active alarms
-     are known against this component and it is not under repair.";
-  reference
-    "RFC 4268: Entity State MIB - EntityAlarmStatus";
-}
-
-typedef standby-state {
-  type enumeration {
-    enum unknown {
-      value 1;
-      description
-        "The resource is unable to report standby state.";
-    }
-    enum hot-standby {
-      value 2;
-      description
-        "The resource is not providing service, but it will be
-         immediately able to take over the role of the resource to
-         be backed up, without the need for initialization
-         activity, and will contain the same information as the
-         resource to be backed up.";
-    }
-    enum cold-standby {
-      value 3;
-      description
-        "The resource is to back up another resource, but it will
-         not be immediately able to take over the role of a
-         resource to be backed up and will require some
-         initialization activity.";
-    }
-    enum providing-service {
-      value 4;
-      description
-        "The resource is providing service.";
-    }
-  }
-  description
-    "Represents the possible values of standby states.";
-  reference
-    "RFC 4268: Entity State MIB - EntityStandbyStatus";
-}
-
-typedef sensor-value-type {
-  type enumeration {
-    enum other {
-      value 1;
-      description
-        "A measure other than those listed below.";
-    }
-    enum unknown {
-      value 2;
-      description
-        "An unknown measurement or arbitrary, relative numbers";
-    }
-    enum volts-AC {
-      value 3;
-      description
-        "A measure of electric potential (alternating current).";
-    }
-    enum volts-DC {
-      value 4;
-      description
-        "A measure of electric potential (direct current).";
-    }
-    enum amperes {
-      value 5;
-      description
-        "A measure of electric current.";
-    }
-    enum watts {
-      value 6;
-      description
-        "A measure of power.";
-    }
-    enum hertz {
-      value 7;
-      description
-        "A measure of frequency.";
-    }
-    enum celsius {
-      value 8;
-      description
-        "A measure of temperature.";
-    }
-    enum percent-RH {
-      value 9;
-      description
-        "A measure of percent relative humidity.";
-    }
-    enum rpm {
-      value 10;
-      description
-        "A measure of shaft revolutions per minute.";
-    }
-    enum cmm {
-      value 11;
-      description
-        "A measure of cubic meters per minute (airflow).";
-    }
-    enum truth-value {
-      value 12;
-      description
-        "Value is one of 1 (true) or 2 (false)";
-    }
-  }
-  description
-    "A node using this data type represents the sensor measurement
-     data type associated with a physical sensor value.  The actual
-     data units are determined by examining a node of this type
-     together with the associated sensor-value-scale node.
-     A node of this type SHOULD be defined together with nodes of
-     type sensor-value-scale and type sensor-value-precision.
-     These three types are used to identify the semantics of a node
-     of type sensor-value.";
-  reference
-    "RFC 3433: Entity Sensor Management Information Base -
-               EntitySensorDataType";
-}
-
-typedef sensor-value-scale {
-  type enumeration {
-    enum yocto {
-      value 1;
-      description
-        "Data scaling factor of 10^-24.";
-    }
-    enum zepto {
-      value 2;
-      description
-        "Data scaling factor of 10^-21.";
-    }
-    enum atto {
-      value 3;
-      description
-        "Data scaling factor of 10^-18.";
-    }
-    enum femto {
-      value 4;
-      description
-        "Data scaling factor of 10^-15.";
-    }
-    enum pico {
-      value 5;
-      description
-        "Data scaling factor of 10^-12.";
-    }
-    enum nano {
-      value 6;
-      description
-        "Data scaling factor of 10^-9.";
-    }
-    enum micro {
-      value 7;
-      description
-        "Data scaling factor of 10^-6.";
-    }
-    enum milli {
-      value 8;
-      description
-        "Data scaling factor of 10^-3.";
-    }
-    enum units {
-      value 9;
-      description
-        "Data scaling factor of 10^0.";
-    }
-    enum kilo {
-      value 10;
-      description
-        "Data scaling factor of 10^3.";
-    }
-    enum mega {
-      value 11;
-      description
-        "Data scaling factor of 10^6.";
-    }
-    enum giga {
-      value 12;
-      description
-        "Data scaling factor of 10^9.";
-    }
-    enum tera {
-      value 13;
-      description
-        "Data scaling factor of 10^12.";
-    }
-    enum peta {
-      value 14;
-      description
-        "Data scaling factor of 10^15.";
-    }
-    enum exa {
-      value 15;
-      description
-        "Data scaling factor of 10^18.";
-    }
-    enum zetta {
-      value 16;
-      description
-        "Data scaling factor of 10^21.";
-    }
-    enum yotta {
-      value 17;
-      description
-        "Data scaling factor of 10^24.";
-    }
-  }
-  description
-    "A node using this data type represents a data scaling factor,
-     represented with an International System of Units (SI) prefix.
-     The actual data units are determined by examining a node of
-     this type together with the associated sensor-value-type.
-     A node of this type SHOULD be defined together with nodes of
-     type sensor-value-type and type sensor-value-precision.
-     Together, associated nodes of these three types are used to
-     identify the semantics of a node of type sensor-value.";
-  reference
-    "RFC 3433: Entity Sensor Management Information Base -
-               EntitySensorDataScale";
-}
-
-typedef sensor-value-precision {
-  type int8 {
-    range "-8 .. 9";
-  }
-  description
-    "A node using this data type represents a sensor value
-     precision range.
-     A node of this type SHOULD be defined together with nodes of
-     type sensor-value-type and type sensor-value-scale.  Together,
-     associated nodes of these three types are used to identify the
-     semantics of a node of type sensor-value.
-     If a node of this type contains a value in the range 1 to 9,
-     it represents the number of decimal places in the fractional
-     part of an associated sensor-value fixed-point number.
-     If a node of this type contains a value in the range -8 to -1,
-     it represents the number of accurate digits in the associated
-     sensor-value fixed-point number.
-     The value zero indicates the associated sensor-value node is
-     not a fixed-point number.
-     Server implementers must choose a value for the associated
-     sensor-value-precision node so that the precision and accuracy
-     of the associated sensor-value node is correctly indicated.
-     For example, a component representing a temperature sensor
-     that can measure 0 to 100 degrees C in 0.1 degree
-     increments, +/- 0.05 degrees, would have a
-     sensor-value-precision value of '1', a sensor-value-scale
-     value of 'units', and a sensor-value ranging from '0' to
-     '1000'.  The sensor-value would be interpreted as
-     'degrees C * 10'.";
-  reference
-    "RFC 3433: Entity Sensor Management Information Base -
-               EntitySensorPrecision";
-}
-
-typedef sensor-value {
-  type int32 {
-    range "-1000000000 .. 1000000000";
-  }
-  description
-   "A node using this data type represents a sensor value.
-    A node of this type SHOULD be defined together with nodes of
-    type sensor-value-type, type sensor-value-scale, and
-    type sensor-value-precision.  Together, associated nodes of
-    those three types are used to identify the semantics of a node
-    of this data type.
-    The semantics of a node using this data type are determined by
-    the value of the associated sensor-value-type node.
-    If the associated sensor-value-type node is equal to 'voltsAC',
-    'voltsDC', 'amperes', 'watts', 'hertz', 'celsius', or 'cmm',
-    then a node of this type MUST contain a fixed-point number
-    ranging from -999,999,999 to +999,999,999.  The value
-    -1000000000 indicates an underflow error.  The value
-    +1000000000 indicates an overflow error.  The
-    sensor-value-precision indicates how many fractional digits
-    are represented in the associated sensor-value node.
-    If the associated sensor-value-type node is equal to
-    'percentRH', then a node of this type MUST contain a number
-    ranging from 0 to 100.
-    If the associated sensor-value-type node is equal to 'rpm',
-    then a node of this type MUST contain a number ranging from
-    -999,999,999 to +999,999,999.
-    If the associated sensor-value-type node is equal to
-    'truth-value', then a node of this type MUST contain either the
-    value 1 (true) or the value 2 (false).
-    If the associated sensor-value-type node is equal to 'other' or
-    'unknown', then a node of this type MUST contain a number
-    ranging from -1000000000 to 1000000000.";
-  reference
-    "RFC 3433: Entity Sensor Management Information Base -
-               EntitySensorValue";
-}
-
-typedef sensor-status {
-  type enumeration {
-    enum ok {
-      value 1;
-      description
-        "Indicates that the server can obtain the sensor value.";
-    }
-    enum unavailable {
-      value 2;
-      description
-        "Indicates that the server presently cannot obtain the
-         sensor value.";
-    }
-    enum nonoperational {
-      value 3;
-      description
-        "Indicates that the server believes the sensor is broken.
-         The sensor could have a hard failure (disconnected wire)
-         or a soft failure such as out-of-range, jittery, or wildly
-         fluctuating readings.";
-    }
-  }
-  description
-    "A node using this data type represents the operational status
-     of a physical sensor.";
-  reference
-    "RFC 3433: Entity Sensor Management Information Base -
-               EntitySensorStatus";
-}
-
-/*
- * Data nodes
- */
-
-container hardware {
-  description
-    "Data nodes representing components.
-     If the server supports configuration of hardware components,
-     then this data model is instantiated in the configuration
-     datastores supported by the server.  The leaf-list 'datastore'
-     for the module 'ietf-hardware' in the YANG library provides
-     this information.";
-
-  leaf last-change {
-    type yang:date-and-time;
-    config false;
-    description
-      "The time the '/hardware/component' list changed in the
-       operational state.";
-  }
-
-  list component {
-    key name;
-    description
-      "List of components.
-       When the server detects a new hardware component, it
-       initializes a list entry in the operational state.
-       If the server does not support configuration of hardware
-       components, list entries in the operational state are
-       initialized with values for all nodes as detected by the
-       implementation.
-       Otherwise, this procedure is followed:
-         1. If there is an entry in the '/hardware/component' list
-            in the intended configuration with values for the nodes
-            'class', 'parent', and 'parent-rel-pos' that are equal
-            to the detected values, then the list entry in the
-            operational state is initialized with the configured
-            values, including the 'name'.
-         2. Otherwise (i.e., there is no matching configuration
-            entry), the list entry in the operational state is
-            initialized with values for all nodes as detected by
-            the implementation.
-       If the '/hardware/component' list in the intended
-       configuration is modified, then the system MUST behave as if
-       it re-initializes itself and follow the procedure in (1).";
-    reference
-      "RFC 6933: Entity MIB (Version 4) - entPhysicalEntry";
-
-    leaf name {
-      type string;
-      description
-        "The name assigned to this component.
-         This name is not required to be the same as
-         entPhysicalName.";
-    }
-
-    leaf class {
-      type identityref {
-        base ianahw:hardware-class;
-      }
-      mandatory true;
-      description
-        "An indication of the general hardware type of the
-         component.";
-      reference
-        "RFC 6933: Entity MIB (Version 4) - entPhysicalClass";
-    }
-
-    leaf physical-index {
-      if-feature entity-mib;
-      type int32 {
-        range "1..2147483647";
-      }
-      config false;
-      description
-        "The entPhysicalIndex for the entPhysicalEntry represented
-         by this list entry.";
-      reference
-        "RFC 6933: Entity MIB (Version 4) - entPhysicalIndex";
-    }
-
-    leaf description {
-      type string;
-      config false;
-      description
-        "A textual description of the component.  This node should
-         contain a string that identifies the manufacturer's name
-         for the component and should be set to a distinct value
-         for each version or model of the component.";
-      reference
-        "RFC 6933: Entity MIB (Version 4) - entPhysicalDescr";
-    }
-
-    leaf parent {
-      type leafref {
-        path "../../component/name";
-        require-instance false;
-      }
-      description
-        "The name of the component that physically contains this
-         component.
-         If this leaf is not instantiated, it indicates that this
-         component is not contained in any other component.
-         In the event that a physical component is contained by
-         more than one physical component (e.g., double-wide
-         modules), this node contains the name of one of these
-         components.  An implementation MUST use the same name
-         every time this node is instantiated.";
-      reference
-        "RFC 6933: Entity MIB (Version 4) - entPhysicalContainedIn";
-    }
-
-    leaf parent-rel-pos {
-      type int32 {
-        range "0 .. 2147483647";
-      }
-      description
-        "An indication of the relative position of this child
-         component among all its sibling components.  Sibling
-         components are defined as components that:
-           o share the same value of the 'parent' node and
-           o share a common base identity for the 'class' node.
-         Note that the last rule gives implementations flexibility
-         in how components are numbered.  For example, some
-         implementations might have a single number series for all
-         components derived from 'ianahw:port', while some others
-         might have different number series for different
-         components with identities derived from 'ianahw:port' (for
-         example, one for registered jack 45 (RJ45) and one for
-         small form-factor pluggable (SFP)).";
-
-      reference
-        "RFC 6933: Entity MIB (Version 4) -
-                   entPhysicalParentRelPos";
-    }
-
-    leaf-list contains-child {
-      type leafref {
-        path "../../component/name";
-      }
-      config false;
-      description
-        "The name of the contained component.";
-      reference
-        "RFC 6933: Entity MIB (Version 4) - entPhysicalChildIndex";
-    }
-
-    leaf hardware-rev {
-      type string;
-      config false;
-      description
-        "The vendor-specific hardware revision string for the
-         component.  The preferred value is the hardware revision
-         identifier actually printed on the component itself (if
-         present).";
-      reference
-        "RFC 6933: Entity MIB (Version 4) -
-                   entPhysicalHardwareRev";
-    }
-
-    leaf firmware-rev {
-      type string;
-      config false;
-      description
-        "The vendor-specific firmware revision string for the
-         component.";
-      reference
-        "RFC 6933: Entity MIB (Version 4) -
-                   entPhysicalFirmwareRev";
-    }
-
-    leaf software-rev {
-      type string;
-      config false;
-
-      description
-        "The vendor-specific software revision string for the
-         component.";
-      reference
-        "RFC 6933: Entity MIB (Version 4) -
-                   entPhysicalSoftwareRev";
-    }
-
-    leaf serial-num {
-      type string;
-      config false;
-      description
-        "The vendor-specific serial number string for the
-         component.  The preferred value is the serial number
-         string actually printed on the component itself (if
-         present).";
-      reference
-        "RFC 6933: Entity MIB (Version 4) - entPhysicalSerialNum";
-    }
-
-    leaf mfg-name {
-      type string;
-      config false;
-      description
-        "The name of the manufacturer of this physical component.
-         The preferred value is the manufacturer name string
-         actually printed on the component itself (if present).
-         Note that comparisons between instances of the
-         'model-name', 'firmware-rev', 'software-rev', and
-         'serial-num' nodes are only meaningful amongst components
-         with the same value of 'mfg-name'.
-         If the manufacturer name string associated with the
-         physical component is unknown to the server, then this
-         node is not instantiated.";
-      reference
-        "RFC 6933: Entity MIB (Version 4) - entPhysicalMfgName";
-    }
-
-    leaf model-name {
-      type string;
-      config false;
-      description
-        "The vendor-specific model name identifier string
-         associated with this physical component.  The preferred
-         value is the customer-visible part number, which may be
-         printed on the component itself.
-         If the model name string associated with the physical
-         component is unknown to the server, then this node is not
-         instantiated.";
-      reference
-        "RFC 6933: Entity MIB (Version 4) - entPhysicalModelName";
-    }
-
-    leaf alias {
-      type string;
-      description
-        "An 'alias' name for the component, as specified by a
-         network manager, that provides a non-volatile 'handle' for
-         the component.
-         If no configured value exists, the server MAY set the
-         value of this node to a locally unique value in the
-         operational state.
-         A server implementation MAY map this leaf to the
-         entPhysicalAlias MIB object.  Such an implementation needs
-         to use some mechanism to handle the differences in size
-         and characters allowed between this leaf and
-         entPhysicalAlias.  The definition of such a mechanism is
-         outside the scope of this document.";
-      reference
-        "RFC 6933: Entity MIB (Version 4) - entPhysicalAlias";
-    }
-
-    leaf asset-id {
-      type string;
-      description
-        "This node is a user-assigned asset tracking identifier for
-         the component.
-         A server implementation MAY map this leaf to the
-         entPhysicalAssetID MIB object.  Such an implementation
-         needs to use some mechanism to handle the differences in
-         size and characters allowed between this leaf and
-         entPhysicalAssetID.  The definition of such a mechanism is
-         outside the scope of this document.";
-      reference
-        "RFC 6933: Entity MIB (Version 4) - entPhysicalAssetID";
-    }
-
-    leaf is-fru {
-      type boolean;
-      config false;
-
-      description
-        "This node indicates whether or not this component is
-         considered a 'field-replaceable unit' by the vendor.  If
-         this node contains the value 'true', then this component
-         identifies a field-replaceable unit.  For all components
-         that are permanently contained within a field-replaceable
-         unit, the value 'false' should be returned for this
-         node.";
-      reference
-        "RFC 6933: Entity MIB (Version 4) - entPhysicalIsFRU";
-    }
-
-    leaf mfg-date {
-      type yang:date-and-time;
-      config false;
-      description
-        "The date of manufacturing of the managed component.";
-      reference
-        "RFC 6933: Entity MIB (Version 4) - entPhysicalMfgDate";
-    }
-
-    leaf-list uri {
-      type inet:uri;
-      description
-        "This node contains identification information about the
-         component.";
-      reference
-        "RFC 6933: Entity MIB (Version 4) - entPhysicalUris";
-    }
-
-    leaf uuid {
-      type yang:uuid;
-      config false;
-      description
-        "A Universally Unique Identifier of the component.";
-      reference
-        "RFC 6933: Entity MIB (Version 4) - entPhysicalUUID";
-    }
-
-    container state {
-      if-feature hardware-state;
-      description
-        "State-related nodes";
-      reference
-        "RFC 4268: Entity State MIB";
-
-      leaf state-last-changed {
-        type yang:date-and-time;
-        config false;
-        description
-          "The date and time when the value of any of the
-           admin-state, oper-state, usage-state, alarm-state, or
-           standby-state changed for this component.
-           If there has been no change since the last
-           re-initialization of the local system, this node
-           contains the date and time of local system
-           initialization.  If there has been no change since the
-           component was added to the local system, this node
-           contains the date and time of the insertion.";
-        reference
-          "RFC 4268: Entity State MIB - entStateLastChanged";
-      }
-
-      leaf admin-state {
-        type admin-state;
-        description
-          "The administrative state for this component.
-           This node refers to a component's administrative
-           permission to service both other components within its
-           containment hierarchy as well other users of its
-           services defined by means outside the scope of this
-           module.
-           Some components exhibit only a subset of the remaining
-           administrative state values.  Some components cannot be
-           locked; hence, this node exhibits only the 'unlocked'
-           state.  Other components cannot be shut down gracefully;
-           hence, this node does not exhibit the 'shutting-down'
-           state.";
-        reference
-          "RFC 4268: Entity State MIB - entStateAdmin";
-      }
-
-      leaf oper-state {
-        type oper-state;
-        config false;
-        description
-          "The operational state for this component.
-           Note that this node does not follow the administrative
-           state.  An administrative state of 'down' does not
-           predict an operational state of 'disabled'.
-           Note that some implementations may not be able to
-           accurately report oper-state while the admin-state node
-           has a value other than 'unlocked'.  In these cases, this
-           node MUST have a value of 'unknown'.";
-        reference
-          "RFC 4268: Entity State MIB - entStateOper";
-      }
-
-      leaf usage-state {
-        type usage-state;
-        config false;
-        description
-          "The usage state for this component.
-           This node refers to a component's ability to service
-           more components in a containment hierarchy.
-           Some components will exhibit only a subset of the usage
-           state values.  Components that are unable to ever
-           service any components within a containment hierarchy
-           will always have a usage state of 'busy'.  In some
-           cases, a component will be able to support only one
-           other component within its containment hierarchy and
-           will therefore only exhibit values of 'idle' and
-           'busy'.";
-        reference
-          "RFC 4268: Entity State MIB - entStateUsage";
-      }
-
-      leaf alarm-state {
-        type alarm-state;
-        config false;
-        description
-          "The alarm state for this component.  It does not
-           include the alarms raised on child components within its
-           containment hierarchy.";
-        reference
-          "RFC 4268: Entity State MIB - entStateAlarm";
-      }
-
-      leaf standby-state {
-        type standby-state;
-        config false;
-        description
-          "The standby state for this component.
-           Some components will exhibit only a subset of the
-           remaining standby state values.  If this component
-           cannot operate in a standby role, the value of this node
-           will always be 'providing-service'.";
-        reference
-          "RFC 4268: Entity State MIB - entStateStandby";
-      }
-    }
-
-    container sensor-data {
-      when 'derived-from-or-self(../class,
-                                 "ianahw:sensor")' {
-        description
-          "Sensor data nodes present for any component of type
-           'sensor'";
-      }
-      if-feature hardware-sensor;
-      config false;
-
-      description
-        "Sensor-related nodes.";
-      reference
-        "RFC 3433: Entity Sensor Management Information Base";
-
-      leaf value {
-        type sensor-value;
-        description
-          "The most recent measurement obtained by the server
-           for this sensor.
-           A client that periodically fetches this node should also
-           fetch the nodes 'value-type', 'value-scale', and
-           'value-precision', since they may change when the value
-           is changed.";
-        reference
-          "RFC 3433: Entity Sensor Management Information Base -
-                     entPhySensorValue";
-      }
-
-      leaf value-type {
-        type sensor-value-type;
-        description
-          "The type of data units associated with the
-           sensor value";
-        reference
-          "RFC 3433: Entity Sensor Management Information Base -
-                     entPhySensorType";
-      }
-      leaf value-scale {
-        type sensor-value-scale;
-        description
-          "The (power of 10) scaling factor associated
-           with the sensor value";
-        reference
-          "RFC 3433: Entity Sensor Management Information Base -
-                     entPhySensorScale";
-      }
-
-      leaf value-precision {
-        type sensor-value-precision;
-        description
-          "The number of decimal places of precision
-           associated with the sensor value";
-        reference
-          "RFC 3433: Entity Sensor Management Information Base -
-                     entPhySensorPrecision";
-      }
-
-      leaf oper-status {
-        type sensor-status;
-        description
-          "The operational status of the sensor.";
-        reference
-          "RFC 3433: Entity Sensor Management Information Base -
-                     entPhySensorOperStatus";
-      }
-
-      leaf units-display {
-        type string;
-        description
-          "A textual description of the data units that should be
-           used in the display of the sensor value.";
-        reference
-          "RFC 3433: Entity Sensor Management Information Base -
-                     entPhySensorUnitsDisplay";
-      }
-
-      leaf value-timestamp {
-        type yang:date-and-time;
-        description
-          "The time the status and/or value of this sensor was last
-           obtained by the server.";
-        reference
-          "RFC 3433: Entity Sensor Management Information Base -
-                     entPhySensorValueTimeStamp";
-      }
-      leaf value-update-rate {
-        type uint32;
-        units "milliseconds";
-        description
-          "An indication of the frequency that the server updates
-           the associated 'value' node, represented in
-           milliseconds.  The value zero indicates:
-            - the sensor value is updated on demand (e.g.,
-              when polled by the server for a get-request),
-            - the sensor value is updated when the sensor
-              value changes (event-driven), or
-            - the server does not know the update rate.";
-        reference
-          "RFC 3433: Entity Sensor Management Information Base -
-                     entPhySensorValueUpdateRate";
-      }
-    }
-  }
-}
-
-/*
- * Notifications
- */
-
-notification hardware-state-change {
-  description
-    "A hardware-state-change notification is generated when the
-     value of /hardware/last-change changes in the operational
-     state.";
-  reference
-    "RFC 6933: Entity MIB (Version 4) - entConfigChange";
-}
-
-notification hardware-state-oper-enabled {
-  if-feature hardware-state;
-  description
-    "A hardware-state-oper-enabled notification signifies that a
-     component has transitioned into the 'enabled' state.";
-
-  leaf name {
-    type leafref {
-      path "/hardware/component/name";
-    }
-
-    description
-      "The name of the component that has transitioned into the
-       'enabled' state.";
-  }
-  leaf admin-state {
-    type leafref {
-      path "/hardware/component/state/admin-state";
-    }
-    description
-      "The administrative state for the component.";
-  }
-  leaf alarm-state {
-    type leafref {
-      path "/hardware/component/state/alarm-state";
-    }
-    description
-      "The alarm state for the component.";
-  }
-  reference
-    "RFC 4268: Entity State MIB - entStateOperEnabled";
-}
-
-notification hardware-state-oper-disabled {
-  if-feature hardware-state;
-  description
-    "A hardware-state-oper-disabled notification signifies that a
-     component has transitioned into the 'disabled' state.";
-
-  leaf name {
-    type leafref {
-      path "/hardware/component/name";
-    }
-    description
-      "The name of the component that has transitioned into the
-       'disabled' state.";
-  }
-  leaf admin-state {
-    type leafref {
-      path "/hardware/component/state/admin-state";
-    }
-    description
-      "The administrative state for the component.";
-  }
-  leaf alarm-state {
-    type leafref {
-      path "/hardware/component/state/alarm-state";
-    }
-
-    description
-      "The alarm state for the component.";
-  }
-  reference
-    "RFC 4268: Entity State MIB - entStateOperDisabled";
-}
-
-}
diff --git a/ntsimulator/yang/x-ran/ietf-interfaces.yang b/ntsimulator/yang/x-ran/ietf-interfaces.yang
deleted file mode 100644 (file)
index 8dae9d3..0000000
+++ /dev/null
@@ -1,1073 +0,0 @@
-module ietf-interfaces {
-  yang-version 1.1;
-  namespace "urn:ietf:params:xml:ns:yang:ietf-interfaces";
-  prefix if;
-
-  import ietf-yang-types {
-    prefix yang;
-  }
-
-  organization
-    "IETF NETMOD (Network Modeling) Working Group";
-
-  contact
-    "WG Web:   <https://datatracker.ietf.org/wg/netmod/>
-     WG List:  <mailto:netmod@ietf.org>
-     Editor:   Martin Bjorklund
-               <mailto:mbj@tail-f.com>";
-
-  description
-    "This module contains a collection of YANG definitions for
-     managing network interfaces.
-     Copyright (c) 2018 IETF Trust and the persons identified as
-     authors of the code.  All rights reserved.
-     Redistribution and use in source and binary forms, with or
-     without modification, is permitted pursuant to, and subject
-     to the license terms contained in, the Simplified BSD License
-     set forth in Section 4.c of the IETF Trust's Legal Provisions
-     Relating to IETF Documents
-     (https://trustee.ietf.org/license-info).
-     This version of this YANG module is part of RFC 8343; see
-     the RFC itself for full legal notices.";
-
-  revision 2018-02-20 {
-    description
-      "Updated to support NMDA.";
-    reference
-      "RFC 8343: A YANG Data Model for Interface Management";
-  }
-
-  revision 2014-05-08 {
-    description
-      "Initial revision.";
-    reference
-      "RFC 7223: A YANG Data Model for Interface Management";
-  }
-
-  /*
-   * Typedefs
-   */
-
-  typedef interface-ref {
-    type leafref {
-      path "/if:interfaces/if:interface/if:name";
-    }
-    description
-      "This type is used by data models that need to reference
-       interfaces.";
-  }
-
-  /*
-   * Identities
-   */
-
-  identity interface-type {
-    description
-      "Base identity from which specific interface types are
-       derived.";
-  }
-
-  /*
-   * Features
-   */
-
-  feature arbitrary-names {
-    description
-      "This feature indicates that the device allows user-controlled
-       interfaces to be named arbitrarily.";
-  }
-  feature pre-provisioning {
-    description
-      "This feature indicates that the device supports
-       pre-provisioning of interface configuration, i.e., it is
-       possible to configure an interface whose physical interface
-       hardware is not present on the device.";
-  }
-  feature if-mib {
-    description
-      "This feature indicates that the device implements
-       the IF-MIB.";
-    reference
-      "RFC 2863: The Interfaces Group MIB";
-  }
-
-  /*
-   * Data nodes
-   */
-
-  container interfaces {
-    description
-      "Interface parameters.";
-
-    list interface {
-      key "name";
-
-      description
-        "The list of interfaces on the device.
-         The status of an interface is available in this list in the
-         operational state.  If the configuration of a
-         system-controlled interface cannot be used by the system
-         (e.g., the interface hardware present does not match the
-         interface type), then the configuration is not applied to
-         the system-controlled interface shown in the operational
-         state.  If the configuration of a user-controlled interface
-         cannot be used by the system, the configured interface is
-         not instantiated in the operational state.
-         System-controlled interfaces created by the system are
-         always present in this list in the operational state,
-         whether or not they are configured.";
-
-     leaf name {
-        type string;
-        description
-          "The name of the interface.
-           A device MAY restrict the allowed values for this leaf,
-           possibly depending on the type of the interface.
-           For system-controlled interfaces, this leaf is the
-           device-specific name of the interface.
-           If a client tries to create configuration for a
-           system-controlled interface that is not present in the
-           operational state, the server MAY reject the request if
-           the implementation does not support pre-provisioning of
-           interfaces or if the name refers to an interface that can
-           never exist in the system.  A Network Configuration
-           Protocol (NETCONF) server MUST reply with an rpc-error
-           with the error-tag 'invalid-value' in this case.
-           If the device supports pre-provisioning of interface
-           configuration, the 'pre-provisioning' feature is
-           advertised.
-           If the device allows arbitrarily named user-controlled
-           interfaces, the 'arbitrary-names' feature is advertised.
-           When a configured user-controlled interface is created by
-           the system, it is instantiated with the same name in the
-           operational state.
-           A server implementation MAY map this leaf to the ifName
-           MIB object.  Such an implementation needs to use some
-           mechanism to handle the differences in size and characters
-           allowed between this leaf and ifName.  The definition of
-           such a mechanism is outside the scope of this document.";
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifName";
-      }
-
-      leaf description {
-        type string;
-        description
-          "A textual description of the interface.
-           A server implementation MAY map this leaf to the ifAlias
-           MIB object.  Such an implementation needs to use some
-           mechanism to handle the differences in size and characters
-           allowed between this leaf and ifAlias.  The definition of
-           such a mechanism is outside the scope of this document.
-           Since ifAlias is defined to be stored in non-volatile
-           storage, the MIB implementation MUST map ifAlias to the
-           value of 'description' in the persistently stored
-           configuration.";
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifAlias";
-      }
-
-      leaf type {
-        type identityref {
-          base interface-type;
-        }
-        mandatory true;
-        description
-          "The type of the interface.
-           When an interface entry is created, a server MAY
-           initialize the type leaf with a valid value, e.g., if it
-           is possible to derive the type from the name of the
-           interface.
-           If a client tries to set the type of an interface to a
-           value that can never be used by the system, e.g., if the
-           type is not supported or if the type does not match the
-           name of the interface, the server MUST reject the request.
-           A NETCONF server MUST reply with an rpc-error with the
-           error-tag 'invalid-value' in this case.";
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifType";
-      }
-
-      leaf enabled {
-        type boolean;
-        default "true";
-        description
-          "This leaf contains the configured, desired state of the
-           interface.
-           Systems that implement the IF-MIB use the value of this
-           leaf in the intended configuration to set
-           IF-MIB.ifAdminStatus to 'up' or 'down' after an ifEntry
-           has been initialized, as described in RFC 2863.
-           Changes in this leaf in the intended configuration are
-           reflected in ifAdminStatus.";
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifAdminStatus";
-      }
-
-      leaf link-up-down-trap-enable {
-        if-feature if-mib;
-        type enumeration {
-          enum enabled {
-            value 1;
-            description
-              "The device will generate linkUp/linkDown SNMP
-               notifications for this interface.";
-          }
-          enum disabled {
-            value 2;
-            description
-              "The device will not generate linkUp/linkDown SNMP
-               notifications for this interface.";
-          }
-        }
-        description
-          "Controls whether linkUp/linkDown SNMP notifications
-           should be generated for this interface.
-           If this node is not configured, the value 'enabled' is
-           operationally used by the server for interfaces that do
-           not operate on top of any other interface (i.e., there are
-           no 'lower-layer-if' entries), and 'disabled' otherwise.";
-        reference
-          "RFC 2863: The Interfaces Group MIB -
-                     ifLinkUpDownTrapEnable";
-      }
-
-      leaf admin-status {
-        if-feature if-mib;
-        type enumeration {
-          enum up {
-            value 1;
-            description
-              "Ready to pass packets.";
-          }
-          enum down {
-            value 2;
-            description
-              "Not ready to pass packets and not in some test mode.";
-          }
-          enum testing {
-            value 3;
-            description
-              "In some test mode.";
-          }
-        }
-        config false;
-        mandatory true;
-        description
-          "The desired state of the interface.
-           This leaf has the same read semantics as ifAdminStatus.";
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifAdminStatus";
-      }
-
-      leaf oper-status {
-        type enumeration {
-          enum up {
-            value 1;
-            description
-              "Ready to pass packets.";
-          }
-          enum down {
-            value 2;
-
-            description
-              "The interface does not pass any packets.";
-          }
-          enum testing {
-            value 3;
-            description
-              "In some test mode.  No operational packets can
-               be passed.";
-          }
-          enum unknown {
-            value 4;
-            description
-              "Status cannot be determined for some reason.";
-          }
-          enum dormant {
-            value 5;
-            description
-              "Waiting for some external event.";
-          }
-          enum not-present {
-            value 6;
-            description
-              "Some component (typically hardware) is missing.";
-          }
-          enum lower-layer-down {
-            value 7;
-            description
-              "Down due to state of lower-layer interface(s).";
-          }
-        }
-        config false;
-        mandatory true;
-        description
-          "The current operational state of the interface.
-           This leaf has the same semantics as ifOperStatus.";
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifOperStatus";
-      }
-
-      leaf last-change {
-        type yang:date-and-time;
-        config false;
-        description
-          "The time the interface entered its current operational
-           state.  If the current state was entered prior to the
-           last re-initialization of the local network management
-           subsystem, then this node is not present.";
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifLastChange";
-      }
-
-      leaf if-index {
-        if-feature if-mib;
-        type int32 {
-          range "1..2147483647";
-        }
-        config false;
-        mandatory true;
-        description
-          "The ifIndex value for the ifEntry represented by this
-           interface.";
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifIndex";
-      }
-
-      leaf phys-address {
-        type yang:phys-address;
-        config false;
-        description
-          "The interface's address at its protocol sub-layer.  For
-           example, for an 802.x interface, this object normally
-           contains a Media Access Control (MAC) address.  The
-           interface's media-specific modules must define the bit
-           and byte ordering and the format of the value of this
-           object.  For interfaces that do not have such an address
-           (e.g., a serial line), this node is not present.";
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifPhysAddress";
-      }
-
-      leaf-list higher-layer-if {
-        type interface-ref;
-        config false;
-        description
-          "A list of references to interfaces layered on top of this
-           interface.";
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifStackTable";
-      }
-
-      leaf-list lower-layer-if {
-        type interface-ref;
-        config false;
-
-        description
-          "A list of references to interfaces layered underneath this
-           interface.";
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifStackTable";
-      }
-
-      leaf speed {
-        type yang:gauge64;
-        units "bits/second";
-        config false;
-        description
-            "An estimate of the interface's current bandwidth in bits
-             per second.  For interfaces that do not vary in
-             bandwidth or for those where no accurate estimation can
-             be made, this node should contain the nominal bandwidth.
-             For interfaces that have no concept of bandwidth, this
-             node is not present.";
-        reference
-          "RFC 2863: The Interfaces Group MIB -
-                     ifSpeed, ifHighSpeed";
-      }
-
-      container statistics {
-        config false;
-        description
-          "A collection of interface-related statistics objects.";
-
-        leaf discontinuity-time {
-          type yang:date-and-time;
-          mandatory true;
-          description
-            "The time on the most recent occasion at which any one or
-             more of this interface's counters suffered a
-             discontinuity.  If no such discontinuities have occurred
-             since the last re-initialization of the local management
-             subsystem, then this node contains the time the local
-             management subsystem re-initialized itself.";
-        }
-
-        leaf in-octets {
-          type yang:counter64;
-          description
-            "The total number of octets received on the interface,
-             including framing characters.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB - ifHCInOctets";
-        }
-
-        leaf in-unicast-pkts {
-          type yang:counter64;
-          description
-            "The number of packets, delivered by this sub-layer to a
-             higher (sub-)layer, that were not addressed to a
-             multicast or broadcast address at this sub-layer.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts";
-        }
-
-        leaf in-broadcast-pkts {
-          type yang:counter64;
-          description
-            "The number of packets, delivered by this sub-layer to a
-             higher (sub-)layer, that were addressed to a broadcast
-             address at this sub-layer.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB -
-                       ifHCInBroadcastPkts";
-        }
-
-        leaf in-multicast-pkts {
-          type yang:counter64;
-          description
-            "The number of packets, delivered by this sub-layer to a
-             higher (sub-)layer, that were addressed to a multicast
-             address at this sub-layer.  For a MAC-layer protocol,
-             this includes both Group and Functional addresses.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB -
-                       ifHCInMulticastPkts";
-        }
-
-        leaf in-discards {
-          type yang:counter32;
-          description
-            "The number of inbound packets that were chosen to be
-             discarded even though no errors had been detected to
-             prevent their being deliverable to a higher-layer
-             protocol.  One possible reason for discarding such a
-             packet could be to free up buffer space.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB - ifInDiscards";
-        }
-
-        leaf in-errors {
-          type yang:counter32;
-          description
-            "For packet-oriented interfaces, the number of inbound
-             packets that contained errors preventing them from being
-             deliverable to a higher-layer protocol.  For character-
-             oriented or fixed-length interfaces, the number of
-             inbound transmission units that contained errors
-             preventing them from being deliverable to a higher-layer
-             protocol.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB - ifInErrors";
-        }
-
-        leaf in-unknown-protos {
-          type yang:counter32;
-
-          description
-            "For packet-oriented interfaces, the number of packets
-             received via the interface that were discarded because
-             of an unknown or unsupported protocol.  For
-             character-oriented or fixed-length interfaces that
-             support protocol multiplexing, the number of
-             transmission units received via the interface that were
-             discarded because of an unknown or unsupported protocol.
-             For any interface that does not support protocol
-             multiplexing, this counter is not present.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos";
-        }
-
-        leaf out-octets {
-          type yang:counter64;
-          description
-            "The total number of octets transmitted out of the
-             interface, including framing characters.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB - ifHCOutOctets";
-        }
-
-        leaf out-unicast-pkts {
-          type yang:counter64;
-          description
-            "The total number of packets that higher-level protocols
-             requested be transmitted and that were not addressed
-             to a multicast or broadcast address at this sub-layer,
-             including those that were discarded or not sent.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts";
-        }
-
-        leaf out-broadcast-pkts {
-          type yang:counter64;
-          description
-            "The total number of packets that higher-level protocols
-             requested be transmitted and that were addressed to a
-             broadcast address at this sub-layer, including those
-             that were discarded or not sent.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB -
-                       ifHCOutBroadcastPkts";
-        }
-
-        leaf out-multicast-pkts {
-          type yang:counter64;
-          description
-            "The total number of packets that higher-level protocols
-             requested be transmitted and that were addressed to a
-             multicast address at this sub-layer, including those
-             that were discarded or not sent.  For a MAC-layer
-             protocol, this includes both Group and Functional
-             addresses.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB -
-                       ifHCOutMulticastPkts";
-        }
-
-        leaf out-discards {
-          type yang:counter32;
-          description
-            "The number of outbound packets that were chosen to be
-             discarded even though no errors had been detected to
-             prevent their being transmitted.  One possible reason
-             for discarding such a packet could be to free up buffer
-             space.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB - ifOutDiscards";
-        }
-
-        leaf out-errors {
-          type yang:counter32;
-          description
-            "For packet-oriented interfaces, the number of outbound
-             packets that could not be transmitted because of errors.
-             For character-oriented or fixed-length interfaces, the
-             number of outbound transmission units that could not be
-             transmitted because of errors.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB - ifOutErrors";
-        }
-      }
-
-    }
-  }
-
-  /*
-   * Legacy typedefs
-   */
-
-  typedef interface-state-ref {
-    type leafref {
-      path "/if:interfaces-state/if:interface/if:name";
-    }
-    status deprecated;
-    description
-      "This type is used by data models that need to reference
-       the operationally present interfaces.";
-  }
-
-  /*
-   * Legacy operational state data nodes
-   */
-
-  container interfaces-state {
-    config false;
-    status deprecated;
-    description
-      "Data nodes for the operational state of interfaces.";
-
-    list interface {
-      key "name";
-      status deprecated;
-
-      description
-        "The list of interfaces on the device.
-         System-controlled interfaces created by the system are
-         always present in this list, whether or not they are
-         configured.";
-
-      leaf name {
-        type string;
-        status deprecated;
-        description
-          "The name of the interface.
-           A server implementation MAY map this leaf to the ifName
-           MIB object.  Such an implementation needs to use some
-           mechanism to handle the differences in size and characters
-           allowed between this leaf and ifName.  The definition of
-           such a mechanism is outside the scope of this document.";
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifName";
-      }
-
-      leaf type {
-        type identityref {
-          base interface-type;
-        }
-        mandatory true;
-        status deprecated;
-        description
-          "The type of the interface.";
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifType";
-      }
-
-      leaf admin-status {
-        if-feature if-mib;
-        type enumeration {
-          enum up {
-            value 1;
-            description
-              "Ready to pass packets.";
-          }
-          enum down {
-            value 2;
-            description
-              "Not ready to pass packets and not in some test mode.";
-          }
-          enum testing {
-            value 3;
-            description
-              "In some test mode.";
-          }
-        }
-        mandatory true;
-        status deprecated;
-        description
-          "The desired state of the interface.
-           This leaf has the same read semantics as ifAdminStatus.";
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifAdminStatus";
-      }
-
-      leaf oper-status {
-        type enumeration {
-          enum up {
-            value 1;
-            description
-              "Ready to pass packets.";
-          }
-          enum down {
-            value 2;
-            description
-              "The interface does not pass any packets.";
-          }
-          enum testing {
-            value 3;
-            description
-              "In some test mode.  No operational packets can
-               be passed.";
-          }
-          enum unknown {
-            value 4;
-            description
-              "Status cannot be determined for some reason.";
-          }
-          enum dormant {
-            value 5;
-            description
-              "Waiting for some external event.";
-          }
-          enum not-present {
-            value 6;
-            description
-              "Some component (typically hardware) is missing.";
-          }
-          enum lower-layer-down {
-            value 7;
-            description
-              "Down due to state of lower-layer interface(s).";
-          }
-        }
-        mandatory true;
-        status deprecated;
-        description
-          "The current operational state of the interface.
-           This leaf has the same semantics as ifOperStatus.";
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifOperStatus";
-      }
-
-      leaf last-change {
-        type yang:date-and-time;
-        status deprecated;
-        description
-          "The time the interface entered its current operational
-           state.  If the current state was entered prior to the
-           last re-initialization of the local network management
-           subsystem, then this node is not present.";
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifLastChange";
-      }
-
-      leaf if-index {
-        if-feature if-mib;
-        type int32 {
-          range "1..2147483647";
-        }
-        mandatory true;
-        status deprecated;
-        description
-          "The ifIndex value for the ifEntry represented by this
-           interface.";
-
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifIndex";
-      }
-
-      leaf phys-address {
-        type yang:phys-address;
-        status deprecated;
-        description
-          "The interface's address at its protocol sub-layer.  For
-           example, for an 802.x interface, this object normally
-           contains a Media Access Control (MAC) address.  The
-           interface's media-specific modules must define the bit
-           and byte ordering and the format of the value of this
-           object.  For interfaces that do not have such an address
-           (e.g., a serial line), this node is not present.";
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifPhysAddress";
-      }
-
-      leaf-list higher-layer-if {
-        type interface-state-ref;
-        status deprecated;
-        description
-          "A list of references to interfaces layered on top of this
-           interface.";
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifStackTable";
-      }
-
-      leaf-list lower-layer-if {
-        type interface-state-ref;
-        status deprecated;
-        description
-          "A list of references to interfaces layered underneath this
-           interface.";
-        reference
-          "RFC 2863: The Interfaces Group MIB - ifStackTable";
-      }
-
-      leaf speed {
-        type yang:gauge64;
-        units "bits/second";
-        status deprecated;
-        description
-            "An estimate of the interface's current bandwidth in bits
-             per second.  For interfaces that do not vary in
-             bandwidth or for those where no accurate estimation can
-             be made, this node should contain the nominal bandwidth.
-             For interfaces that have no concept of bandwidth, this
-             node is not present.";
-        reference
-          "RFC 2863: The Interfaces Group MIB -
-                     ifSpeed, ifHighSpeed";
-      }
-
-      container statistics {
-        status deprecated;
-        description
-          "A collection of interface-related statistics objects.";
-
-        leaf discontinuity-time {
-          type yang:date-and-time;
-          mandatory true;
-          status deprecated;
-          description
-            "The time on the most recent occasion at which any one or
-             more of this interface's counters suffered a
-             discontinuity.  If no such discontinuities have occurred
-             since the last re-initialization of the local management
-             subsystem, then this node contains the time the local
-             management subsystem re-initialized itself.";
-        }
-
-        leaf in-octets {
-          type yang:counter64;
-          status deprecated;
-          description
-            "The total number of octets received on the interface,
-             including framing characters.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB - ifHCInOctets";
-        }
-
-        leaf in-unicast-pkts {
-          type yang:counter64;
-          status deprecated;
-          description
-            "The number of packets, delivered by this sub-layer to a
-             higher (sub-)layer, that were not addressed to a
-             multicast or broadcast address at this sub-layer.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts";
-        }
-
-        leaf in-broadcast-pkts {
-          type yang:counter64;
-          status deprecated;
-          description
-            "The number of packets, delivered by this sub-layer to a
-             higher (sub-)layer, that were addressed to a broadcast
-             address at this sub-layer.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB -
-                       ifHCInBroadcastPkts";
-        }
-
-        leaf in-multicast-pkts {
-          type yang:counter64;
-          status deprecated;
-          description
-            "The number of packets, delivered by this sub-layer to a
-             higher (sub-)layer, that were addressed to a multicast
-             address at this sub-layer.  For a MAC-layer protocol,
-             this includes both Group and Functional addresses.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB -
-                       ifHCInMulticastPkts";
-        }
-
-        leaf in-discards {
-          type yang:counter32;
-          status deprecated;
-
-          description
-            "The number of inbound packets that were chosen to be
-             discarded even though no errors had been detected to
-             prevent their being deliverable to a higher-layer
-             protocol.  One possible reason for discarding such a
-             packet could be to free up buffer space.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB - ifInDiscards";
-        }
-
-        leaf in-errors {
-          type yang:counter32;
-          status deprecated;
-          description
-            "For packet-oriented interfaces, the number of inbound
-             packets that contained errors preventing them from being
-             deliverable to a higher-layer protocol.  For character-
-             oriented or fixed-length interfaces, the number of
-             inbound transmission units that contained errors
-             preventing them from being deliverable to a higher-layer
-             protocol.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB - ifInErrors";
-        }
-
-        leaf in-unknown-protos {
-          type yang:counter32;
-          status deprecated;
-          description
-            "For packet-oriented interfaces, the number of packets
-             received via the interface that were discarded because
-             of an unknown or unsupported protocol.  For
-             character-oriented or fixed-length interfaces that
-             support protocol multiplexing, the number of
-             transmission units received via the interface that were
-             discarded because of an unknown or unsupported protocol.
-             For any interface that does not support protocol
-             multiplexing, this counter is not present.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos";
-        }
-
-        leaf out-octets {
-          type yang:counter64;
-          status deprecated;
-          description
-            "The total number of octets transmitted out of the
-             interface, including framing characters.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB - ifHCOutOctets";
-        }
-
-        leaf out-unicast-pkts {
-          type yang:counter64;
-          status deprecated;
-          description
-            "The total number of packets that higher-level protocols
-             requested be transmitted and that were not addressed
-             to a multicast or broadcast address at this sub-layer,
-             including those that were discarded or not sent.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts";
-        }
-
-        leaf out-broadcast-pkts {
-          type yang:counter64;
-          status deprecated;
-
-          description
-            "The total number of packets that higher-level protocols
-             requested be transmitted and that were addressed to a
-             broadcast address at this sub-layer, including those
-             that were discarded or not sent.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB -
-                       ifHCOutBroadcastPkts";
-        }
-
-        leaf out-multicast-pkts {
-          type yang:counter64;
-          status deprecated;
-          description
-            "The total number of packets that higher-level protocols
-             requested be transmitted and that were addressed to a
-             multicast address at this sub-layer, including those
-             that were discarded or not sent.  For a MAC-layer
-             protocol, this includes both Group and Functional
-             addresses.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB -
-                       ifHCOutMulticastPkts";
-        }
-
-        leaf out-discards {
-          type yang:counter32;
-          status deprecated;
-          description
-            "The number of outbound packets that were chosen to be
-             discarded even though no errors had been detected to
-             prevent their being transmitted.  One possible reason
-             for discarding such a packet could be to free up buffer
-             space.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB - ifOutDiscards";
-        }
-
-        leaf out-errors {
-          type yang:counter32;
-          status deprecated;
-          description
-            "For packet-oriented interfaces, the number of outbound
-             packets that could not be transmitted because of errors.
-             For character-oriented or fixed-length interfaces, the
-             number of outbound transmission units that could not be
-             transmitted because of errors.
-             Discontinuities in the value of this counter can occur
-             at re-initialization of the management system and at
-             other times as indicated by the value of
-             'discontinuity-time'.";
-          reference
-            "RFC 2863: The Interfaces Group MIB - ifOutErrors";
-        }
-      }
-    }
-  }
-}
diff --git a/ntsimulator/yang/x-ran/ietf-yang-types.yang b/ntsimulator/yang/x-ran/ietf-yang-types.yang
deleted file mode 100755 (executable)
index 45b8c55..0000000
+++ /dev/null
@@ -1,435 +0,0 @@
-module ietf-yang-types {
-
-namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types";
-prefix "yang";
-
-organization
- "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
-
-contact
- "WG Web:   <http://tools.ietf.org/wg/netmod/>
-  WG List:  <mailto:netmod@ietf.org>
-  WG Chair: David Kessens
-            <mailto:david.kessens@nsn.com>
-  WG Chair: Juergen Schoenwaelder
-            <mailto:j.schoenwaelder@jacobs-university.de>
-  Editor:   Juergen Schoenwaelder
-            <mailto:j.schoenwaelder@jacobs-university.de>";
-
-description
- "This module contains a collection of generally useful derived
-  YANG data types.
-  Copyright (c) 2013 IETF Trust and the persons identified as
-  authors of the code.  All rights reserved.
-  Redistribution and use in source and binary forms, with or
-  without modification, is permitted pursuant to, and subject
-  to the license terms contained in, the Simplified BSD License
-  set forth in Section 4.c of the IETF Trust's Legal Provisions
-  Relating to IETF Documents
-  (http://trustee.ietf.org/license-info).
-  This version of this YANG module is part of RFC 6991; see
-  the RFC itself for full legal notices.";
-
-revision 2013-07-15 {
-  description
-   "This revision adds the following new data types:
-    - yang-identifier
-    - hex-string
-    - uuid
-    - dotted-quad";
-  reference
-   "RFC 6991: Common YANG Data Types";
-}
-
-revision 2010-09-24 {
-  description
-   "Initial revision.";
-  reference
-   "RFC 6021: Common YANG Data Types";
-}
-
-/*** collection of counter and gauge types ***/
-
-typedef counter32 {
-  type uint32;
-  description
-   "The counter32 type represents a non-negative integer
-    that monotonically increases until it reaches a
-    maximum value of 2^32-1 (4294967295 decimal), when it
-    wraps around and starts increasing again from zero.
-    Counters have no defined 'initial' value, and thus, a
-    single value of a counter has (in general) no information
-    content.  Discontinuities in the monotonically increasing
-    value normally occur at re-initialization of the
-    management system, and at other times as specified in the
-    description of a schema node using this type.  If such
-    other times can occur, for example, the creation of
-    a schema node of type counter32 at times other than
-    re-initialization, then a corresponding schema node
-    should be defined, with an appropriate type, to indicate
-    the last discontinuity.
-    The counter32 type should not be used for configuration
-    schema nodes.  A default statement SHOULD NOT be used in
-    combination with the type counter32.
-    In the value set and its semantics, this type is equivalent
-    to the Counter32 type of the SMIv2.";
-  reference
-   "RFC 2578: Structure of Management Information Version 2
-              (SMIv2)";
-}
-
-typedef zero-based-counter32 {
-  type yang:counter32;
-  default "0";
-  description
-   "The zero-based-counter32 type represents a counter32
-    that has the defined 'initial' value zero.
-    A schema node of this type will be set to zero (0) on creation
-    and will thereafter increase monotonically until it reaches
-    a maximum value of 2^32-1 (4294967295 decimal), when it
-    wraps around and starts increasing again from zero.
-    Provided that an application discovers a new schema node
-    of this type within the minimum time to wrap, it can use the
-    'initial' value as a delta.  It is important for a management
-    station to be aware of this minimum time and the actual time
-    between polls, and to discard data if the actual time is too
-    long or there is no defined minimum time.
-    In the value set and its semantics, this type is equivalent
-    to the ZeroBasedCounter32 textual convention of the SMIv2.";
-  reference
-    "RFC 4502: Remote Network Monitoring Management Information
-               Base Version 2";
-}
-
-typedef counter64 {
-  type uint64;
-  description
-   "The counter64 type represents a non-negative integer
-    that monotonically increases until it reaches a
-    maximum value of 2^64-1 (18446744073709551615 decimal),
-    when it wraps around and starts increasing again from zero.
-    Counters have no defined 'initial' value, and thus, a
-    single value of a counter has (in general) no information
-    content.  Discontinuities in the monotonically increasing
-    value normally occur at re-initialization of the
-    management system, and at other times as specified in the
-    description of a schema node using this type.  If such
-    other times can occur, for example, the creation of
-    a schema node of type counter64 at times other than
-    re-initialization, then a corresponding schema node
-    should be defined, with an appropriate type, to indicate
-    the last discontinuity.
-    The counter64 type should not be used for configuration
-    schema nodes.  A default statement SHOULD NOT be used in
-    combination with the type counter64.
-    In the value set and its semantics, this type is equivalent
-    to the Counter64 type of the SMIv2.";
-  reference
-   "RFC 2578: Structure of Management Information Version 2
-              (SMIv2)";
-}
-
-typedef zero-based-counter64 {
-  type yang:counter64;
-  default "0";
-  description
-   "The zero-based-counter64 type represents a counter64 that
-    has the defined 'initial' value zero.
-    A schema node of this type will be set to zero (0) on creation
-    and will thereafter increase monotonically until it reaches
-    a maximum value of 2^64-1 (18446744073709551615 decimal),
-    when it wraps around and starts increasing again from zero.
-    Provided that an application discovers a new schema node
-    of this type within the minimum time to wrap, it can use the
-    'initial' value as a delta.  It is important for a management
-    station to be aware of this minimum time and the actual time
-    between polls, and to discard data if the actual time is too
-    long or there is no defined minimum time.
-    In the value set and its semantics, this type is equivalent
-    to the ZeroBasedCounter64 textual convention of the SMIv2.";
-  reference
-   "RFC 2856: Textual Conventions for Additional High Capacity
-              Data Types";
-}
-
-typedef gauge32 {
-  type uint32;
-  description
-   "The gauge32 type represents a non-negative integer, which
-    may increase or decrease, but shall never exceed a maximum
-    value, nor fall below a minimum value.  The maximum value
-    cannot be greater than 2^32-1 (4294967295 decimal), and
-    the minimum value cannot be smaller than 0.  The value of
-    a gauge32 has its maximum value whenever the information
-    being modeled is greater than or equal to its maximum
-    value, and has its minimum value whenever the information
-    being modeled is smaller than or equal to its minimum value.
-    If the information being modeled subsequently decreases
-    below (increases above) the maximum (minimum) value, the
-    gauge32 also decreases (increases).
-    In the value set and its semantics, this type is equivalent
-    to the Gauge32 type of the SMIv2.";
-  reference
-   "RFC 2578: Structure of Management Information Version 2
-              (SMIv2)";
-}
-
-typedef gauge64 {
-  type uint64;
-  description
-   "The gauge64 type represents a non-negative integer, which
-    may increase or decrease, but shall never exceed a maximum
-    value, nor fall below a minimum value.  The maximum value
-    cannot be greater than 2^64-1 (18446744073709551615), and
-    the minimum value cannot be smaller than 0.  The value of
-    a gauge64 has its maximum value whenever the information
-    being modeled is greater than or equal to its maximum
-    value, and has its minimum value whenever the information
-    being modeled is smaller than or equal to its minimum value.
-    If the information being modeled subsequently decreases
-    below (increases above) the maximum (minimum) value, the
-    gauge64 also decreases (increases).
-    In the value set and its semantics, this type is equivalent
-    to the CounterBasedGauge64 SMIv2 textual convention defined
-    in RFC 2856";
-  reference
-   "RFC 2856: Textual Conventions for Additional High Capacity
-              Data Types";
-}
-
-/*** collection of identifier-related types ***/
-
-typedef object-identifier {
-  type string {
-    pattern '(([0-1](\.[1-3]?[0-9]))|(2\.(0|([1-9]\d*))))'
-          + '(\.(0|([1-9]\d*)))*';
-  }
-  description
-   "The object-identifier type represents administratively
-    assigned names in a registration-hierarchical-name tree.
-    Values of this type are denoted as a sequence of numerical
-    non-negative sub-identifier values.  Each sub-identifier
-    value MUST NOT exceed 2^32-1 (4294967295).  Sub-identifiers
-    are separated by single dots and without any intermediate
-    whitespace.
-    The ASN.1 standard restricts the value space of the first
-    sub-identifier to 0, 1, or 2.  Furthermore, the value space
-    of the second sub-identifier is restricted to the range
-    0 to 39 if the first sub-identifier is 0 or 1.  Finally,
-    the ASN.1 standard requires that an object identifier
-    has always at least two sub-identifiers.  The pattern
-    captures these restrictions.
-    Although the number of sub-identifiers is not limited,
-    module designers should realize that there may be
-    implementations that stick with the SMIv2 limit of 128
-    sub-identifiers.
-    This type is a superset of the SMIv2 OBJECT IDENTIFIER type
-    since it is not restricted to 128 sub-identifiers.  Hence,
-    this type SHOULD NOT be used to represent the SMIv2 OBJECT
-    IDENTIFIER type; the object-identifier-128 type SHOULD be
-    used instead.";
-  reference
-   "ISO9834-1: Information technology -- Open Systems
-    Interconnection -- Procedures for the operation of OSI
-    Registration Authorities: General procedures and top
-    arcs of the ASN.1 Object Identifier tree";
-}
-
-typedef object-identifier-128 {
-  type object-identifier {
-    pattern '\d*(\.\d*){1,127}';
-  }
-  description
-   "This type represents object-identifiers restricted to 128
-    sub-identifiers.
-    In the value set and its semantics, this type is equivalent
-    to the OBJECT IDENTIFIER type of the SMIv2.";
-  reference
-   "RFC 2578: Structure of Management Information Version 2
-              (SMIv2)";
-}
-
-typedef yang-identifier {
-  type string {
-    length "1..max";
-    pattern '[a-zA-Z_][a-zA-Z0-9\-_.]*';
-    pattern '.|..|[^xX].*|.[^mM].*|..[^lL].*';
-  }
-  description
-    "A YANG identifier string as defined by the 'identifier'
-     rule in Section 12 of RFC 6020.  An identifier must
-     start with an alphabetic character or an underscore
-     followed by an arbitrary sequence of alphabetic or
-     numeric characters, underscores, hyphens, or dots.
-     A YANG identifier MUST NOT start with any possible
-     combination of the lowercase or uppercase character
-     sequence 'xml'.";
-  reference
-    "RFC 6020: YANG - A Data Modeling Language for the Network
-               Configuration Protocol (NETCONF)";
-}
-
-/*** collection of types related to date and time***/
-
-typedef date-and-time {
-  type string {
-    pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?'
-          + '(Z|[\+\-]\d{2}:\d{2})';
-  }
-  description
-   "The date-and-time type is a profile of the ISO 8601
-    standard for representation of dates and times using the
-    Gregorian calendar.  The profile is defined by the
-    date-time production in Section 5.6 of RFC 3339.
-    The date-and-time type is compatible with the dateTime XML
-    schema type with the following notable exceptions:
-    (a) The date-and-time type does not allow negative years.
-    (b) The date-and-time time-offset -00:00 indicates an unknown
-        time zone (see RFC 3339) while -00:00 and +00:00 and Z
-        all represent the same time zone in dateTime.
-    (c) The canonical format (see below) of data-and-time values
-        differs from the canonical format used by the dateTime XML
-        schema type, which requires all times to be in UTC using
-        the time-offset 'Z'.
-    This type is not equivalent to the DateAndTime textual
-    convention of the SMIv2 since RFC 3339 uses a different
-    separator between full-date and full-time and provides
-    higher resolution of time-secfrac.
-    The canonical format for date-and-time values with a known time
-    zone uses a numeric time zone offset that is calculated using
-    the device's configured known offset to UTC time.  A change of
-    the device's offset to UTC time will cause date-and-time values
-    to change accordingly.  Such changes might happen periodically
-    in case a server follows automatically daylight saving time
-    (DST) time zone offset changes.  The canonical format for
-    date-and-time values with an unknown time zone (usually
-    referring to the notion of local time) uses the time-offset
-    -00:00.";
-  reference
-   "RFC 3339: Date and Time on the Internet: Timestamps
-    RFC 2579: Textual Conventions for SMIv2
-    XSD-TYPES: XML Schema Part 2: Datatypes Second Edition";
-}
-
-typedef timeticks {
-  type uint32;
-  description
-   "The timeticks type represents a non-negative integer that
-    represents the time, modulo 2^32 (4294967296 decimal), in
-    hundredths of a second between two epochs.  When a schema
-    node is defined that uses this type, the description of
-    the schema node identifies both of the reference epochs.
-    In the value set and its semantics, this type is equivalent
-    to the TimeTicks type of the SMIv2.";
-  reference
-   "RFC 2578: Structure of Management Information Version 2
-              (SMIv2)";
-}
-
-typedef timestamp {
-  type yang:timeticks;
-  description
-   "The timestamp type represents the value of an associated
-    timeticks schema node at which a specific occurrence
-    happened.  The specific occurrence must be defined in the
-    description of any schema node defined using this type.  When
-    the specific occurrence occurred prior to the last time the
-    associated timeticks attribute was zero, then the timestamp
-    value is zero.  Note that this requires all timestamp values
-    to be reset to zero when the value of the associated timeticks
-    attribute reaches 497+ days and wraps around to zero.
-    The associated timeticks schema node must be specified
-    in the description of any schema node using this type.
-    In the value set and its semantics, this type is equivalent
-    to the TimeStamp textual convention of the SMIv2.";
-  reference
-   "RFC 2579: Textual Conventions for SMIv2";
-}
-
-/*** collection of generic address types ***/
-
-typedef phys-address {
-  type string {
-    pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?';
-  }
-
-  description
-   "Represents media- or physical-level addresses represented
-    as a sequence octets, each octet represented by two hexadecimal
-    numbers.  Octets are separated by colons.  The canonical
-    representation uses lowercase characters.
-    In the value set and its semantics, this type is equivalent
-    to the PhysAddress textual convention of the SMIv2.";
-  reference
-   "RFC 2579: Textual Conventions for SMIv2";
-}
-
-typedef mac-address {
-  type string {
-    pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}';
-  }
-  description
-   "The mac-address type represents an IEEE 802 MAC address.
-    The canonical representation uses lowercase characters.
-    In the value set and its semantics, this type is equivalent
-    to the MacAddress textual convention of the SMIv2.";
-  reference
-   "IEEE 802: IEEE Standard for Local and Metropolitan Area
-              Networks: Overview and Architecture
-    RFC 2579: Textual Conventions for SMIv2";
-}
-
-/*** collection of XML-specific types ***/
-
-typedef xpath1.0 {
-  type string;
-  description
-   "This type represents an XPATH 1.0 expression.
-    When a schema node is defined that uses this type, the
-    description of the schema node MUST specify the XPath
-    context in which the XPath expression is evaluated.";
-  reference
-   "XPATH: XML Path Language (XPath) Version 1.0";
-}
-
-/*** collection of string types ***/
-
-typedef hex-string {
-  type string {
-    pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?';
-  }
-  description
-   "A hexadecimal string with octets represented as hex digits
-    separated by colons.  The canonical representation uses
-    lowercase characters.";
-}
-
-typedef uuid {
-  type string {
-    pattern '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-'
-          + '[0-9a-fA-F]{4}-[0-9a-fA-F]{12}';
-  }
-  description
-   "A Universally Unique IDentifier in the string representation
-    defined in RFC 4122.  The canonical representation uses
-    lowercase characters.
-    The following is an example of a UUID in string representation:
-    f81d4fae-7dec-11d0-a765-00a0c91e6bf6
-    ";
-  reference
-   "RFC 4122: A Universally Unique IDentifier (UUID) URN
-              Namespace";
-}
-
-typedef dotted-quad {
-  type string {
-    pattern
-      '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
-    + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])';
-  }
-  description
-    "An unsigned 32-bit number expressed in the dotted-quad
-     notation, i.e., four octets written as decimal numbers
-     and separated with the '.' (full stop) character.";
-}
-}