From 032ff22ef20b59950a8b5fae8d2ba6d03e93ac93 Mon Sep 17 00:00:00 2001 From: Wojciech Sliwka Date: Wed, 10 Jul 2019 13:48:52 +0200 Subject: Opensourcing new version of Simulator Additional info in README.md Issue-ID: INT-1134 Signed-off-by: Wojciech Sliwka Change-Id: I06d41fd3f361b7a451b30b702882810e4136a129 --- test/mocks/pnfsimulator/.gitignore | 7 +- test/mocks/pnfsimulator/README.md | 68 - .../mocks/pnfsimulator/checkstyle-suppressions.xml | 46 + test/mocks/pnfsimulator/config/config.json | 54 - test/mocks/pnfsimulator/config/netconf.env | 5 - .../deployment/PnP_PNF_sim_heat_template.yml | 118 - .../PnP_PNF_sim_heat_template_Ubuntu_16_04.yml | 165 -- test/mocks/pnfsimulator/docker-compose.yml | 83 - .../mocks/pnfsimulator/ftpes/files/ftpes-noone.txt | 1 - .../pnfsimulator/ftpes/files/onap/ftpes-onap.txt | 1 - .../pnfsimulator/ftpes/pure-ftpd/tls/pure-ftpd.pem | 49 - .../ftpes/pure-ftpd/userpass/pureftpd.passwd | 1 - .../ftpes/vsftpd/configuration/vsftpd_ssl.conf | 56 - test/mocks/pnfsimulator/ftpes/vsftpd/tls/cert.der | Bin 962 -> 0 bytes .../pnfsimulator/ftpes/vsftpd/tls/cert.pkcs12 | Bin 2565 -> 0 bytes .../pnfsimulator/ftpes/vsftpd/tls/keystore.jks | Bin 2312 -> 0 bytes .../pnfsimulator/ftpes/vsftpd/tls/truststore.jks | Bin 1250 -> 0 bytes .../mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd.crt | 23 - .../mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd.key | 28 - .../mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd.pem | 50 - .../pnfsimulator/ftpes/vsftpd/tls/vsftpd_crt.pem | 23 - .../pnfsimulator/ftpes/vsftpd/tls/vsftpd_key.pem | 27 - .../ftpes/vsftpd/tls/vsftpd_keys_generator.sh | 49 - .../pnfsimulator/json_schema/input_validator.json | 198 -- .../output_validator_ves_schema_30.0.1.json | 2432 -------------------- .../pnfsimulator/netconf/pnf-simulator.data.xml | 4 - test/mocks/pnfsimulator/netconf/pnf-simulator.yang | 9 - test/mocks/pnfsimulator/netconfsimulator/README.md | 276 +++ .../netconfsimulator/config/netconf.env | 5 + .../netconfsimulator/docker-compose.yml | 96 + .../netconfsimulator/docker/Dockerfile | 4 + .../netconfsimulator/ftpes/files/ftpes-noone.txt | 0 .../ftpes/files/onap/ftpes-onap.txt | 0 .../netconfsimulator/ftpes/tls/pure-ftpd.pem | 49 + .../ftpes/userpass/pureftpd.passwd | 1 + .../netconfsimulator/netconf/__init__.py | 19 + .../netconf/initialize_netopeer.sh | 54 + .../netconfsimulator/netconf/load_server_certs.xml | 40 + .../netconfsimulator/netconf/newmodel.xml | 24 + .../netconfsimulator/netconf/newmodel.yang | 9 + .../netconf/pnf-simulator.data.xml | 24 + .../netconfsimulator/netconf/pnf-simulator.yang | 9 + .../netconfsimulator/netconf/set-up-xmls.py | 153 ++ .../netconf/test_yang_loader_server.py | 121 + .../netconfsimulator/netconf/tls_listen.xml | 48 + .../netconfsimulator/netconf/yang_loader_server.py | 172 ++ .../netopeer-change-saver-native/Application.cpp | 74 + .../netopeer-change-saver-native/Application.h | 43 + .../netopeer-change-saver-native/CMakeLists.txt | 20 + .../netopeer-change-saver-native/KafkaWrapper.cpp | 105 + .../netopeer-change-saver-native/KafkaWrapper.h | 44 + .../SysrepoCallback.cpp | 108 + .../netopeer-change-saver-native/SysrepoCallback.h | 42 + .../netopeer-change-saver-native/libsysrepo-cpp.so | Bin 0 -> 442112 bytes .../netopeer-change-saver-native/main.cpp | 48 + .../netopeer-change-saver-native/sysrepo.h | 2015 ++++++++++++++++ .../sysrepo/Connection.hpp | 63 + .../sysrepo/Internal.hpp | 80 + .../sysrepo/Session.hpp | 245 ++ .../sysrepo/Struct.hpp | 514 +++++ .../sysrepo/Sysrepo.hpp | 177 ++ .../netopeer-change-saver-native/sysrepo/Tree.hpp | 176 ++ .../netopeer-change-saver-native/sysrepo/Xpath.hpp | 97 + .../netopeer-change-saver-native/sysrepo/plugins.h | 139 ++ .../netopeer-change-saver-native/sysrepo/trees.h | 226 ++ .../netopeer-change-saver-native/sysrepo/values.h | 196 ++ .../netopeer-change-saver-native/sysrepo/xpath.h | 232 ++ test/mocks/pnfsimulator/netconfsimulator/pom.xml | 278 +++ .../org/onap/netconfsimulator/Configuration.java | 34 + .../main/java/org/onap/netconfsimulator/Main.java | 31 + .../org/onap/netconfsimulator/SwaggerConfig.java | 43 + .../org/onap/netconfsimulator/kafka/Config.java | 70 + .../onap/netconfsimulator/kafka/MessageDTO.java | 31 + .../netconfsimulator/kafka/StoreController.java | 59 + .../onap/netconfsimulator/kafka/StoreService.java | 91 + .../kafka/listener/KafkaListenerEntry.java | 36 + .../kafka/listener/KafkaListenerHandler.java | 67 + .../netconfsimulator/kafka/model/KafkaMessage.java | 37 + .../netconfcore/NetconfController.java | 111 + .../configuration/NetconfBeanConfiguration.java | 60 + .../configuration/NetconfConfigurationEditor.java | 50 + .../configuration/NetconfConfigurationReader.java | 57 + .../configuration/NetconfConfigurationService.java | 76 + .../configuration/NetconfConfigurationTO.java | 32 + .../configuration/NetconfConnectionParams.java | 37 + .../configuration/NetconfSessionHelper.java | 37 + .../netconfcore/model/LoadModelResponse.java | 40 + .../model/NetconfModelLoaderService.java | 104 + .../netconfsimulator/websocket/EndpointConfig.java | 46 + .../websocket/NetconfEndpoint.java | 95 + .../websocket/message/NetconfMessageEncoder.java | 34 + .../websocket/message/NetconfMessageListener.java | 51 + .../src/main/resources/application.properties | 8 + .../test/java/integration/NetconfFunctionsIT.java | 211 ++ .../java/integration/NetconfSimulatorClient.java | 150 ++ .../kafka/EmbeddedKafkaConfig.java | 69 + .../kafka/StoreControllerTest.java | 86 + .../netconfsimulator/kafka/StoreServiceTest.java | 103 + .../kafka/listener/KafkaListenerHandlerTest.java | 87 + .../netconfcore/NetconfControllerTest.java | 172 ++ .../NetconfConfigurationEditorTest.java | 69 + .../NetconfConfigurationReaderTest.java | 94 + .../NetconfConfigurationServiceTest.java | 102 + .../model/NetconfModelLoaderServiceTest.java | 121 + .../websocket/NetconfEndpointTest.java | 135 ++ .../message/NetconfMessageListenerTest.java | 73 + .../src/test/resources/application-it.properties | 0 .../src/test/resources/initialConfig.xml | 23 + .../src/test/resources/invalidXmlFile.xml | 23 + .../src/test/resources/newYangModel.yang | 8 + .../src/test/resources/updatedConfig.xml | 24 + .../test/resources/updatedConfigForCmHistory.xml | 24 + .../netconfsimulator/ssh/ssh_host_rsa_key | 49 + .../netconfsimulator/ssh/ssh_host_rsa_key.pub | 1 + .../mocks/pnfsimulator/netconfsimulator/tls/ca.crt | 24 + .../netconfsimulator/tls/server_cert.crt | 24 + .../netconfsimulator/tls/server_key.pem | 27 + .../pnfsimulator/netopeer_tls_cfg/entrypoint.sh | 2 - .../pnfsimulator/netopeer_tls_cfg/mynetconf.data | 10 - .../pnfsimulator/netopeer_tls_cfg/mynetconf.yang | 26 - .../netopeer_tls_cfg/test_server_key.pem | 27 - .../netopeer_tls_cfg/test_server_key.pem.pub | 9 - .../pnfsimulator/netopeer_tls_cfg/update_tls.sh | 32 - test/mocks/pnfsimulator/pnfsimulator/.gitignore | 4 + test/mocks/pnfsimulator/pnfsimulator/README.md | 299 +++ .../pnfsimulator/pnfsimulator/config/config.json | 9 + .../pnfsimulator/pnfsimulator/db/pnf_simulator.js | 28 + .../deployment/PnP_PNF_sim_heat_template.yml | 118 + .../pnfsimulator/pnfsimulator/docker-compose.yml | 36 + .../pnfsimulator/pnfsimulator/docker/Dockerfile | 8 + .../docker/certificates/AAF_RootCA.crt | 31 + .../pnfsimulator/docker/certificates/dcaelocal.crt | 20 + .../pnfsimulator/pnfsimulator/integration/pom.xml | 130 ++ .../org/onap/pnfsimulator/integration/Main.java | 35 + .../integration/VesSimulatorController.java | 59 + .../integration/VesSimulatorService.java | 36 + .../src/main/resources/application.properties | 1 + .../integration/src/main/resources/keystore | Bin 0 -> 2196 bytes .../integration/BasicAvailabilityTest.java | 235 ++ .../integration/OptionalTemplatesTest.java | 204 ++ .../integration/SearchInTemplatesTest.java | 269 +++ .../integration/TemplatesManagementTest.java | 175 ++ .../integration/TestConfiguration.java | 36 + .../integration/suites/DockerBasedTestsSuite.java | 46 + .../src/test/resources/application.properties | 6 + .../src/test/resources/templates/notification.json | 45 + .../resources/templates/overwrite_template.json | 6 + .../resources/templates/overwritten_template.json | 6 + .../src/test/resources/templates/registration.json | 36 + .../templates/search/complicated_template.json | 43 + .../templates/search/simple_template.json | 12 + .../templates/search/template_with_array.json | 23 + .../templates/search/template_with_booleans.json | 12 + .../templates/search/template_with_floats.json | 13 + .../templates/search/template_with_ints.json | 12 + .../test/resources/templates/upload_template.json | 6 + test/mocks/pnfsimulator/pnfsimulator/pom.xml | 366 +++ .../pnfsimulator/src/assembly/resources.xml | 57 + .../src/main/java/org/onap/pnfsimulator/Main.java | 57 + .../java/org/onap/pnfsimulator/SwaggerConfig.java | 43 + .../main/java/org/onap/pnfsimulator/db/Row.java | 34 + .../java/org/onap/pnfsimulator/db/Storage.java | 41 + .../org/onap/pnfsimulator/event/EventData.java | 76 + .../pnfsimulator/event/EventDataRepository.java | 26 + .../onap/pnfsimulator/event/EventDataService.java | 63 + .../pnfsimulator/filesystem/WatcherConfig.java | 39 + .../filesystem/WatcherEventProcessor.java | 110 + .../pnfsimulator/filesystem/WatcherService.java | 44 + .../pnfsimulator/filesystem/WatcherThread.java | 81 + .../onap/pnfsimulator/logging/MDCVariables.java | 35 + .../pnfsimulator/rest/SimulatorController.java | 211 ++ .../onap/pnfsimulator/rest/TemplateController.java | 105 + .../onap/pnfsimulator/rest/model/FullEvent.java | 48 + .../onap/pnfsimulator/rest/model/SearchExp.java | 42 + .../pnfsimulator/rest/model/SimulatorParams.java | 46 + .../pnfsimulator/rest/model/SimulatorRequest.java | 51 + .../pnfsimulator/rest/model/TemplateRequest.java | 42 + .../org/onap/pnfsimulator/rest/util/DateUtil.java | 35 + .../rest/util/JsonObjectDeserializer.java | 42 + .../pnfsimulator/rest/util/ResponseBuilder.java | 62 + .../pnfsimulator/simulator/DBTemplateReader.java | 49 + .../simulator/EventNotFoundException.java | 28 + .../simulator/FilesystemTemplateReader.java | 54 + .../pnfsimulator/simulator/IncrementProvider.java | 26 + .../simulator/IncrementProviderImpl.java | 47 + .../pnfsimulator/simulator/JsonTokenProcessor.java | 134 ++ .../pnfsimulator/simulator/KeywordsExtractor.java | 118 + .../pnfsimulator/simulator/KeywordsHandler.java | 72 + .../simulator/KeywordsValueProvider.java | 80 + .../pnfsimulator/simulator/SimulatorService.java | 117 + .../pnfsimulator/simulator/TemplatePatcher.java | 53 + .../pnfsimulator/simulator/TemplateReader.java | 28 + .../simulator/client/HttpClientAdapter.java | 26 + .../simulator/client/HttpClientAdapterImpl.java | 95 + .../client/utils/ssl/SslSupportLevel.java | 81 + .../pnfsimulator/simulator/keywords/Keyword.java | 74 + .../simulator/keywords/NonParameterKeyword.java | 65 + .../simulator/keywords/SingleParameterKeyword.java | 73 + .../simulator/keywords/TwoParameterKeyword.java | 80 + .../pnfsimulator/simulator/scheduler/EventJob.java | 88 + .../simulator/scheduler/EventScheduler.java | 116 + .../simulator/scheduler/QuartzConfiguration.java | 38 + .../simulatorconfig/SimulatorConfig.java | 49 + .../simulatorconfig/SimulatorConfigRepository.java | 26 + .../simulatorconfig/SimulatorConfigService.java | 52 + .../template/FsToDbTemplateSynchronizer.java | 74 + .../org/onap/pnfsimulator/template/Template.java | 92 + .../pnfsimulator/template/TemplateRepository.java | 26 + .../pnfsimulator/template/TemplateService.java | 81 + .../template/search/IllegalJsonValueException.java | 28 + .../pnfsimulator/template/search/JsonUtils.java | 104 + .../template/search/TemplateSearchHelper.java | 95 + .../handler/PrimitiveValueCriteriaBuilder.java | 103 + .../search/viewmodel/FlatTemplateContent.java | 45 + .../template/search/viewmodel/KeyValuePair.java | 40 + .../src/main/resources/application.properties | 7 + .../pnfsimulator/src/main/resources/logback.xml | 70 + .../pnfsimulator/event/EventDataServiceTest.java | 133 ++ .../filesystem/InMemoryTemplateStorage.java | 71 + .../filesystem/WatcherEventProcessorTest.java | 124 + .../pnfsimulator/rest/SimulatorControllerTest.java | 211 ++ .../pnfsimulator/rest/TemplateControllerTest.java | 256 +++ .../onap/pnfsimulator/rest/util/DateUtilTest.java | 38 + .../rest/util/ResponseBuilderTest.java | 65 + .../simulator/IncrementProviderImplTest.java | 78 + .../KeywordsExtractorInvalidRandomIntegerTest.java | 67 + .../KeywordsExtractorInvalidRandomStringTest.java | 67 + .../KeywordsExtractorInvalidTimestampTest.java | 65 + .../KeywordsExtractorValidRandomIntegerTest.java | 66 + ...dsExtractorValidRandomPrimitiveIntegerTest.java | 66 + .../KeywordsExtractorValidRandomStringTest.java | 69 + ...ywordsExtractorValidTimestampPrimitiveTest.java | 66 + .../KeywordsExtractorValidTimestampTest.java | 67 + .../simulator/KeywordsHandlerTest.java | 304 +++ .../simulator/KeywordsValueProviderTest.java | 81 + .../simulator/SimulatorServiceTest.java | 226 ++ .../simulator/TemplatePatcherTest.java | 164 ++ .../pnfsimulator/simulator/TemplateReaderTest.java | 51 + .../client/HttpClientAdapterImplTest.java | 97 + .../client/utils/ssl/SslSupportLevelTest.java | 52 + .../simulator/scheduler/EventJobTest.java | 90 + .../simulator/scheduler/EventSchedulerTest.java | 143 ++ .../SimulatorConfigServiceTest.java | 104 + .../pnfsimulator/template/TemplateServiceTest.java | 152 ++ .../template/search/JsonUtilsTest.java | 166 ++ .../template/search/TemplateSearchHelperTest.java | 160 ++ .../handler/PrimitiveValueCriteriaBuilderTest.java | 75 + .../src/test/resources/application.properties | 1 + .../src/test/resources/logback-test.xml | 69 + .../pnfsimulator/simulator/filesystem/test1.json | 8 + .../simulator/invalidJsonStructureEvent.json | 1 + .../simulator/validExampleMeasurementEvent.json | 89 + .../pnfsimulator/templates/measurement.json | 45 + .../pnfsimulator/templates/notification.json | 40 + .../pnfsimulator/templates/registration.json | 33 + test/mocks/pnfsimulator/pom.xml | 397 +--- test/mocks/pnfsimulator/sftp/sftp-file.txt | 2 - test/mocks/pnfsimulator/simulator-cli/.gitignore | 7 + test/mocks/pnfsimulator/simulator-cli/README.md | 304 +++ .../pnfsimulator/simulator-cli/cli/__init__.py | 19 + .../simulator-cli/cli/client/__init__.py | 19 + .../simulator-cli/cli/client/tailf_client.py | 59 + .../simulator-cli/cli/data/logging.ini | 20 + .../simulator-cli/cli/netconf_simulator.py | 278 +++ .../simulator-cli/cli/pnf_simulator.py | 374 +++ .../pnfsimulator/simulator-cli/requirements.txt | 23 + test/mocks/pnfsimulator/simulator-cli/setup.py | 34 + .../pnfsimulator/simulator-cli/tests/__init__.py | 19 + .../tests/resources/notification.json | 15 + .../simulator-cli/tests/test_netconf_simulator.py | 165 ++ .../simulator-cli/tests/test_pnf_simulator.py | 270 +++ .../simulator-cli/tests/test_tailf_client.py | 47 + test/mocks/pnfsimulator/simulator.sh | 184 -- test/mocks/pnfsimulator/src/assembly/resources.xml | 82 - .../src/main/java/org/onap/pnfsimulator/Main.java | 49 - .../onap/pnfsimulator/logging/MDCVariables.java | 35 - .../pnfsimulator/message/JSONObjectFactory.java | 85 - .../onap/pnfsimulator/message/MessageBuilder.java | 81 - .../pnfsimulator/message/MessageConstants.java | 81 - .../onap/pnfsimulator/message/MessageProvider.java | 42 - .../NetconfConfigurationCheckingTask.java | 61 - .../netconfmonitor/NetconfMonitorService.java | 73 - .../NetconfMonitorServiceConfiguration.java | 112 - .../netconf/NetconfConfigurationCache.java | 34 - .../netconf/NetconfConfigurationReader.java | 40 - .../netconf/NetconfConfigurationWriter.java | 51 - .../netconf/NetconfConnectionParams.java | 45 - .../pnfsimulator/rest/SimulatorController.java | 211 -- .../org/onap/pnfsimulator/rest/util/DateUtil.java | 35 - .../pnfsimulator/rest/util/ResponseBuilder.java | 62 - .../org/onap/pnfsimulator/simulator/Simulator.java | 151 -- .../pnfsimulator/simulator/SimulatorFactory.java | 83 - .../simulator/client/HttpClientAdapter.java | 26 - .../simulator/client/HttpClientAdapterImpl.java | 89 - .../simulator/validation/JSONValidator.java | 66 - .../simulator/validation/ValidationException.java | 28 - .../src/main/resources/application.properties | 1 - .../pnfsimulator/src/main/resources/logback.xml | 50 - .../message/JSONObjectFactoryTest.java | 73 - .../pnfsimulator/message/MessageProviderTest.java | 120 - .../NetconfConfigurationCheckingTaskTest.java | 94 - .../NetconfMonitorServiceConfigurationTest.java | 72 - .../netconfmonitor/NetconfMonitorServiceTest.java | 73 - .../netconf/NetconfConfigurationCacheTest.java | 38 - .../netconf/NetconfConfigurationReaderTest.java | 70 - .../netconf/NetconfConfigurationWriterTest.java | 67 - .../pnfsimulator/rest/SimulatorControllerTest.java | 173 -- .../onap/pnfsimulator/rest/util/DateUtilTest.java | 38 - .../rest/util/ResponseBuilderTest.java | 65 - .../pnfsimulator/simulator/ResourceReader.java | 45 - .../simulator/SimulatorFactoryTest.java | 91 - .../onap/pnfsimulator/simulator/SimulatorTest.java | 92 - .../client/HttpClientAdapterImplTest.java | 71 - .../simulator/validation/JSONValidatorTest.java | 123 - .../src/test/resources/invalid-test-schema.json | 19 - .../src/test/resources/logback-test.xml | 49 - .../MessageProviderTest/notificationParams.json | 6 - .../MessageProviderTest/pnfRegistrationParams.json | 6 - .../SimulatorControllerTest/incorrectJson.json | 12 - .../SimulatorControllerTest/pnfRegistration.json | 24 - .../invalidPnfRegistrationParams1.json | 14 - .../invalidPnfRegistrationParams2.json | 15 - .../invalidPnfRegistrationParams3.json | 14 - .../invalidSimulatorParams.json | 4 - .../validCommonEventHeaderParams.json | 8 - .../validNotificationParams.json | 20 - .../validPnfRegistrationParams.json | 10 - .../SimulatorFactoryTest/validSimulatorParams.json | 5 - .../src/test/resources/valid-test-schema.json | 19 - test/mocks/pnfsimulator/ssh/ssh_host_rsa_key | 49 - test/mocks/pnfsimulator/ssh/ssh_host_rsa_key.pub | 1 - 331 files changed, 20680 insertions(+), 7323 deletions(-) delete mode 100644 test/mocks/pnfsimulator/README.md create mode 100644 test/mocks/pnfsimulator/checkstyle-suppressions.xml delete mode 100644 test/mocks/pnfsimulator/config/config.json delete mode 100644 test/mocks/pnfsimulator/config/netconf.env delete mode 100644 test/mocks/pnfsimulator/deployment/PnP_PNF_sim_heat_template.yml delete mode 100644 test/mocks/pnfsimulator/deployment/PnP_PNF_sim_heat_template_Ubuntu_16_04.yml delete mode 100644 test/mocks/pnfsimulator/docker-compose.yml delete mode 100644 test/mocks/pnfsimulator/ftpes/files/ftpes-noone.txt delete mode 100644 test/mocks/pnfsimulator/ftpes/files/onap/ftpes-onap.txt delete mode 100755 test/mocks/pnfsimulator/ftpes/pure-ftpd/tls/pure-ftpd.pem delete mode 100755 test/mocks/pnfsimulator/ftpes/pure-ftpd/userpass/pureftpd.passwd delete mode 100644 test/mocks/pnfsimulator/ftpes/vsftpd/configuration/vsftpd_ssl.conf delete mode 100644 test/mocks/pnfsimulator/ftpes/vsftpd/tls/cert.der delete mode 100644 test/mocks/pnfsimulator/ftpes/vsftpd/tls/cert.pkcs12 delete mode 100644 test/mocks/pnfsimulator/ftpes/vsftpd/tls/keystore.jks delete mode 100644 test/mocks/pnfsimulator/ftpes/vsftpd/tls/truststore.jks delete mode 100644 test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd.crt delete mode 100644 test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd.key delete mode 100644 test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd.pem delete mode 100644 test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd_crt.pem delete mode 100644 test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd_key.pem delete mode 100644 test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd_keys_generator.sh delete mode 100644 test/mocks/pnfsimulator/json_schema/input_validator.json delete mode 100644 test/mocks/pnfsimulator/json_schema/output_validator_ves_schema_30.0.1.json delete mode 100644 test/mocks/pnfsimulator/netconf/pnf-simulator.data.xml delete mode 100644 test/mocks/pnfsimulator/netconf/pnf-simulator.yang create mode 100644 test/mocks/pnfsimulator/netconfsimulator/README.md create mode 100644 test/mocks/pnfsimulator/netconfsimulator/config/netconf.env create mode 100644 test/mocks/pnfsimulator/netconfsimulator/docker-compose.yml create mode 100644 test/mocks/pnfsimulator/netconfsimulator/docker/Dockerfile create mode 100644 test/mocks/pnfsimulator/netconfsimulator/ftpes/files/ftpes-noone.txt create mode 100644 test/mocks/pnfsimulator/netconfsimulator/ftpes/files/onap/ftpes-onap.txt create mode 100755 test/mocks/pnfsimulator/netconfsimulator/ftpes/tls/pure-ftpd.pem create mode 100755 test/mocks/pnfsimulator/netconfsimulator/ftpes/userpass/pureftpd.passwd create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netconf/__init__.py create mode 100755 test/mocks/pnfsimulator/netconfsimulator/netconf/initialize_netopeer.sh create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netconf/load_server_certs.xml create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netconf/newmodel.xml create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netconf/newmodel.yang create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netconf/pnf-simulator.data.xml create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netconf/pnf-simulator.yang create mode 100755 test/mocks/pnfsimulator/netconfsimulator/netconf/set-up-xmls.py create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netconf/test_yang_loader_server.py create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netconf/tls_listen.xml create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netconf/yang_loader_server.py create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/Application.cpp create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/Application.h create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/CMakeLists.txt create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/KafkaWrapper.cpp create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/KafkaWrapper.h create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/SysrepoCallback.cpp create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/SysrepoCallback.h create mode 100755 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/libsysrepo-cpp.so create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/main.cpp create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo.h create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Connection.hpp create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Internal.hpp create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Session.hpp create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Struct.hpp create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Sysrepo.hpp create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Tree.hpp create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Xpath.hpp create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/plugins.h create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/trees.h create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/values.h create mode 100644 test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/xpath.h create mode 100644 test/mocks/pnfsimulator/netconfsimulator/pom.xml create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/Configuration.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/Main.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/SwaggerConfig.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/Config.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/MessageDTO.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreController.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreService.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerEntry.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerHandler.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/model/KafkaMessage.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/NetconfController.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfBeanConfiguration.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationEditor.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationReader.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationService.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationTO.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConnectionParams.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfSessionHelper.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/LoadModelResponse.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/NetconfModelLoaderService.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/EndpointConfig.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/NetconfEndpoint.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageEncoder.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageListener.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/main/resources/application.properties create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/test/java/integration/NetconfFunctionsIT.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/test/java/integration/NetconfSimulatorClient.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/EmbeddedKafkaConfig.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/StoreControllerTest.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/StoreServiceTest.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerHandlerTest.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/NetconfControllerTest.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationEditorTest.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationReaderTest.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationServiceTest.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/model/NetconfModelLoaderServiceTest.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/websocket/NetconfEndpointTest.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/websocket/message/NetconfMessageListenerTest.java create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/test/resources/application-it.properties create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/test/resources/initialConfig.xml create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/test/resources/invalidXmlFile.xml create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/test/resources/newYangModel.yang create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/test/resources/updatedConfig.xml create mode 100644 test/mocks/pnfsimulator/netconfsimulator/src/test/resources/updatedConfigForCmHistory.xml create mode 100644 test/mocks/pnfsimulator/netconfsimulator/ssh/ssh_host_rsa_key create mode 100644 test/mocks/pnfsimulator/netconfsimulator/ssh/ssh_host_rsa_key.pub create mode 100644 test/mocks/pnfsimulator/netconfsimulator/tls/ca.crt create mode 100644 test/mocks/pnfsimulator/netconfsimulator/tls/server_cert.crt create mode 100644 test/mocks/pnfsimulator/netconfsimulator/tls/server_key.pem delete mode 100755 test/mocks/pnfsimulator/netopeer_tls_cfg/entrypoint.sh delete mode 100644 test/mocks/pnfsimulator/netopeer_tls_cfg/mynetconf.data delete mode 100644 test/mocks/pnfsimulator/netopeer_tls_cfg/mynetconf.yang delete mode 100644 test/mocks/pnfsimulator/netopeer_tls_cfg/test_server_key.pem delete mode 100644 test/mocks/pnfsimulator/netopeer_tls_cfg/test_server_key.pem.pub delete mode 100755 test/mocks/pnfsimulator/netopeer_tls_cfg/update_tls.sh create mode 100644 test/mocks/pnfsimulator/pnfsimulator/.gitignore create mode 100644 test/mocks/pnfsimulator/pnfsimulator/README.md create mode 100644 test/mocks/pnfsimulator/pnfsimulator/config/config.json create mode 100644 test/mocks/pnfsimulator/pnfsimulator/db/pnf_simulator.js create mode 100644 test/mocks/pnfsimulator/pnfsimulator/deployment/PnP_PNF_sim_heat_template.yml create mode 100644 test/mocks/pnfsimulator/pnfsimulator/docker-compose.yml create mode 100644 test/mocks/pnfsimulator/pnfsimulator/docker/Dockerfile create mode 100644 test/mocks/pnfsimulator/pnfsimulator/docker/certificates/AAF_RootCA.crt create mode 100644 test/mocks/pnfsimulator/pnfsimulator/docker/certificates/dcaelocal.crt create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/pom.xml create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/Main.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorController.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorService.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/main/resources/application.properties create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/main/resources/keystore create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/BasicAvailabilityTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/OptionalTemplatesTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/SearchInTemplatesTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/TemplatesManagementTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/TestConfiguration.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/suites/DockerBasedTestsSuite.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/application.properties create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/notification.json create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/overwrite_template.json create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/overwritten_template.json create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/registration.json create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/complicated_template.json create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/simple_template.json create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/template_with_array.json create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/template_with_booleans.json create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/template_with_floats.json create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/template_with_ints.json create mode 100644 test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/upload_template.json create mode 100644 test/mocks/pnfsimulator/pnfsimulator/pom.xml create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/assembly/resources.xml create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/Main.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/SwaggerConfig.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/db/Row.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/db/Storage.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventData.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventDataRepository.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventDataService.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherConfig.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessor.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherService.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherThread.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/logging/MDCVariables.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/SimulatorController.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/TemplateController.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/FullEvent.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/SearchExp.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/SimulatorParams.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/SimulatorRequest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/TemplateRequest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/util/DateUtil.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/util/JsonObjectDeserializer.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/util/ResponseBuilder.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/DBTemplateReader.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/EventNotFoundException.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/FilesystemTemplateReader.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/IncrementProvider.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/IncrementProviderImpl.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/JsonTokenProcessor.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/KeywordsExtractor.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandler.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/KeywordsValueProvider.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/SimulatorService.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/TemplatePatcher.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/TemplateReader.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapter.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImpl.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslSupportLevel.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/keywords/Keyword.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/keywords/NonParameterKeyword.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/keywords/SingleParameterKeyword.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/keywords/TwoParameterKeyword.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventJob.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventScheduler.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/scheduler/QuartzConfiguration.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfig.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigRepository.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigService.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/FsToDbTemplateSynchronizer.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/Template.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/TemplateRepository.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/TemplateService.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/IllegalJsonValueException.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/JsonUtils.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/TemplateSearchHelper.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/handler/PrimitiveValueCriteriaBuilder.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/viewmodel/FlatTemplateContent.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/viewmodel/KeyValuePair.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/resources/application.properties create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/main/resources/logback.xml create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/event/EventDataServiceTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/filesystem/InMemoryTemplateStorage.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessorTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/rest/SimulatorControllerTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/rest/TemplateControllerTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/rest/util/DateUtilTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/rest/util/ResponseBuilderTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/IncrementProviderImplTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidRandomIntegerTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidRandomStringTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidTimestampTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomIntegerTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomPrimitiveIntegerTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomStringTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidTimestampPrimitiveTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidTimestampTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsHandlerTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsValueProviderTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/SimulatorServiceTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/TemplatePatcherTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/TemplateReaderTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImplTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslSupportLevelTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/scheduler/EventJobTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/scheduler/EventSchedulerTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigServiceTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/template/TemplateServiceTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/template/search/JsonUtilsTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/template/search/TemplateSearchHelperTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/java/org/onap/pnfsimulator/template/search/handler/PrimitiveValueCriteriaBuilderTest.java create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/resources/application.properties create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/resources/logback-test.xml create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/filesystem/test1.json create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/invalidJsonStructureEvent.json create mode 100644 test/mocks/pnfsimulator/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/validExampleMeasurementEvent.json create mode 100644 test/mocks/pnfsimulator/pnfsimulator/templates/measurement.json create mode 100644 test/mocks/pnfsimulator/pnfsimulator/templates/notification.json create mode 100644 test/mocks/pnfsimulator/pnfsimulator/templates/registration.json delete mode 100644 test/mocks/pnfsimulator/sftp/sftp-file.txt create mode 100644 test/mocks/pnfsimulator/simulator-cli/.gitignore create mode 100644 test/mocks/pnfsimulator/simulator-cli/README.md create mode 100644 test/mocks/pnfsimulator/simulator-cli/cli/__init__.py create mode 100644 test/mocks/pnfsimulator/simulator-cli/cli/client/__init__.py create mode 100644 test/mocks/pnfsimulator/simulator-cli/cli/client/tailf_client.py create mode 100644 test/mocks/pnfsimulator/simulator-cli/cli/data/logging.ini create mode 100755 test/mocks/pnfsimulator/simulator-cli/cli/netconf_simulator.py create mode 100755 test/mocks/pnfsimulator/simulator-cli/cli/pnf_simulator.py create mode 100644 test/mocks/pnfsimulator/simulator-cli/requirements.txt create mode 100644 test/mocks/pnfsimulator/simulator-cli/setup.py create mode 100644 test/mocks/pnfsimulator/simulator-cli/tests/__init__.py create mode 100644 test/mocks/pnfsimulator/simulator-cli/tests/resources/notification.json create mode 100644 test/mocks/pnfsimulator/simulator-cli/tests/test_netconf_simulator.py create mode 100644 test/mocks/pnfsimulator/simulator-cli/tests/test_pnf_simulator.py create mode 100644 test/mocks/pnfsimulator/simulator-cli/tests/test_tailf_client.py delete mode 100755 test/mocks/pnfsimulator/simulator.sh delete mode 100644 test/mocks/pnfsimulator/src/assembly/resources.xml delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/Main.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/logging/MDCVariables.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/message/JSONObjectFactory.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/message/MessageBuilder.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/message/MessageConstants.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/message/MessageProvider.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/netconfmonitor/NetconfConfigurationCheckingTask.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/netconfmonitor/NetconfMonitorService.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/netconfmonitor/NetconfMonitorServiceConfiguration.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/netconfmonitor/netconf/NetconfConfigurationCache.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/netconfmonitor/netconf/NetconfConfigurationReader.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/netconfmonitor/netconf/NetconfConfigurationWriter.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/netconfmonitor/netconf/NetconfConnectionParams.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/SimulatorController.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/util/DateUtil.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/util/ResponseBuilder.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/Simulator.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/SimulatorFactory.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapter.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImpl.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/validation/JSONValidator.java delete mode 100644 test/mocks/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/validation/ValidationException.java delete mode 100644 test/mocks/pnfsimulator/src/main/resources/application.properties delete mode 100644 test/mocks/pnfsimulator/src/main/resources/logback.xml delete mode 100644 test/mocks/pnfsimulator/src/test/java/org/onap/pnfsimulator/message/JSONObjectFactoryTest.java delete mode 100644 test/mocks/pnfsimulator/src/test/java/org/onap/pnfsimulator/message/MessageProviderTest.java delete mode 100644 test/mocks/pnfsimulator/src/test/java/org/onap/pnfsimulator/netconfmonitor/NetconfConfigurationCheckingTaskTest.java delete mode 100644 test/mocks/pnfsimulator/src/test/java/org/onap/pnfsimulator/netconfmonitor/NetconfMonitorServiceConfigurationTest.java delete mode 100644 test/mocks/pnfsimulator/src/test/java/org/onap/pnfsimulator/netconfmonitor/NetconfMonitorServiceTest.java delete mode 100644 test/mocks/pnfsimulator/src/test/java/org/onap/pnfsimulator/netconfmonitor/netconf/NetconfConfigurationCacheTest.java delete mode 100644 test/mocks/pnfsimulator/src/test/java/org/onap/pnfsimulator/netconfmonitor/netconf/NetconfConfigurationReaderTest.java delete mode 100644 test/mocks/pnfsimulator/src/test/java/org/onap/pnfsimulator/netconfmonitor/netconf/NetconfConfigurationWriterTest.java delete mode 100644 test/mocks/pnfsimulator/src/test/java/org/onap/pnfsimulator/rest/SimulatorControllerTest.java delete mode 100644 test/mocks/pnfsimulator/src/test/java/org/onap/pnfsimulator/rest/util/DateUtilTest.java delete mode 100644 test/mocks/pnfsimulator/src/test/java/org/onap/pnfsimulator/rest/util/ResponseBuilderTest.java delete mode 100644 test/mocks/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/ResourceReader.java delete mode 100644 test/mocks/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/SimulatorFactoryTest.java delete mode 100644 test/mocks/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/SimulatorTest.java delete mode 100644 test/mocks/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImplTest.java delete mode 100644 test/mocks/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/validation/JSONValidatorTest.java delete mode 100644 test/mocks/pnfsimulator/src/test/resources/invalid-test-schema.json delete mode 100644 test/mocks/pnfsimulator/src/test/resources/logback-test.xml delete mode 100644 test/mocks/pnfsimulator/src/test/resources/org/onap/pnfsimulator/message/MessageProviderTest/notificationParams.json delete mode 100644 test/mocks/pnfsimulator/src/test/resources/org/onap/pnfsimulator/message/MessageProviderTest/pnfRegistrationParams.json delete mode 100644 test/mocks/pnfsimulator/src/test/resources/org/onap/pnfsimulator/rest/SimulatorControllerTest/incorrectJson.json delete mode 100644 test/mocks/pnfsimulator/src/test/resources/org/onap/pnfsimulator/rest/SimulatorControllerTest/pnfRegistration.json delete mode 100644 test/mocks/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/SimulatorFactoryTest/invalidPnfRegistrationParams1.json delete mode 100644 test/mocks/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/SimulatorFactoryTest/invalidPnfRegistrationParams2.json delete mode 100644 test/mocks/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/SimulatorFactoryTest/invalidPnfRegistrationParams3.json delete mode 100644 test/mocks/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/SimulatorFactoryTest/invalidSimulatorParams.json delete mode 100644 test/mocks/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/SimulatorFactoryTest/validCommonEventHeaderParams.json delete mode 100644 test/mocks/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/SimulatorFactoryTest/validNotificationParams.json delete mode 100644 test/mocks/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/SimulatorFactoryTest/validPnfRegistrationParams.json delete mode 100644 test/mocks/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/SimulatorFactoryTest/validSimulatorParams.json delete mode 100644 test/mocks/pnfsimulator/src/test/resources/valid-test-schema.json delete mode 100644 test/mocks/pnfsimulator/ssh/ssh_host_rsa_key delete mode 100644 test/mocks/pnfsimulator/ssh/ssh_host_rsa_key.pub diff --git a/test/mocks/pnfsimulator/.gitignore b/test/mocks/pnfsimulator/.gitignore index 3fa204a3b..daf6cf225 100644 --- a/test/mocks/pnfsimulator/.gitignore +++ b/test/mocks/pnfsimulator/.gitignore @@ -1,4 +1,3 @@ -.idea -target -*.iml -logs +**/*.iml +**/.idea +**/target \ No newline at end of file diff --git a/test/mocks/pnfsimulator/README.md b/test/mocks/pnfsimulator/README.md deleted file mode 100644 index 8c27bd474..000000000 --- a/test/mocks/pnfsimulator/README.md +++ /dev/null @@ -1,68 +0,0 @@ -# PNF Simulator -Simulator that generates VES events related to PNF PNP integration. - -##Downloading simulator -Official version of simulator can be downloaded for public ONAP docker registry as image. -*docker login -u anonymous -p anonymous nexus3.onap.org:10003* - -Another option is to checkout PNF Simulator project from ONAP Git repository. - -##Usage of simulator - -###Configuration -The configuration for simulator is stored in */config/config.json* file. -It contains all parameters for simulation such as duration time,interval between messages and values of the configurable fields of VES message. -If you want to change duration or value of message sending to VES collector you just need to edit this file. -The message that is being sent to VES is built inside the simulator and it's content can be found in log of the simulator. -Proper config must contain *simulatorParams*, *commonEventHeaderParams* and *pnfRegistrationParams* or notificationParams. - -###Running simulator -The recommended way is to checkout PNF Simulator project from ONAP Git repository and use *simulator*.sh script. -If you copy *simulator.sh* script to another location, keep in mind to copy also *docker-compose.yml* and directories: *config,json_schema and netconf*. -In order to run simulator, invoke ./simulator.sh start -You may be asked for providing password for ypur user during startup. -Script downloads if necessary needed Docker images and runs instances of these images. -The easiest way is to download or generate PNF Simulator zip archive with all needed configuration files. - -###Logging -It is possible to get access to logs by invocation of *./simulator.sh* logs. -The content of the logs is related to the last simulator run. -Every start of simulator will generate new logs. - -###SFTP support -PNF Simulator allows to serve files via SFTP server. SFTP server has predefined user sftp-user. -Connection to SFTP server is being done with usage of SSH keys. Private key is stored in *ssh* directory. -In order to download *sftp-file.txt* file simply run *sftp -P 2222 -i ssh/ssh_host_rsa_key sftp-user@localhost:sftp/sftp-file.txt* -In order to add a new file (e.g. test.zip), put the file into *sftp* directory and run simulator. -After that again execute sftp command: *sftp -P 2222 -i ssh/ssh_host_rsa_key sftp-user@localhost:sftp/test.zip* -In order to disable usage of SSH keys and start using password, change in *docker-compose.yml* service *sftp-service* entry *command* from *sftp-user::1001* to *sftp-user:password:1001* - -###FTPES support -PNF Simulator allows to serve files via FTPES server. FTPES server has predefined user *onap* with password *pano*. - -####FTPES support with TLS enabled -By default TLS support is enabled. In order to verify connection, please use *FileZilla* for testing. - -####FTPES support for TLS disabled -For local testing TLS may be disabled, but it's not recommended. -In order to set up such configuration, comment or remove in *ftpes-server* service section in *docker-compose.yml* following entries: -- *./ftpes/tls/:/etc/ssl/private/* -- *ADDED_FLAGS: --tls=2* - -After that execute *./simulator.sh stop* and when it's finished *./simulator.sh start* . - -In order to connect execute command *ftp -p localhost 2221* and, when requested, provide user and password. -In order to download a file execute, while still being logged in, *get file-name-to-be-downloaded*. - -###FTPES support for VSFTPD server -PNF Simulator allows to serve files via FTPES VSFTPD server. VSFTPD server has predefined user *onap* with password *pano*. -By default TLS support is enabled. Required certificates and keys are generated via vsftpd_certs_keys_generator.sh and located in ./ftpes/vsftpd/tls/ . -We can generate our own certificates and keys using that script and passing 'secret' password when you are asked for entering keystore password. In other cases just press ENTER to go on. -Configuration of VSFTPD server is located in ./ftpes/vsftpd/configuration/vsftpd_ssl.conf . -Docker-compose contains VSFTPD server image with it's configurations. - -In order to verify connection, please use *FileZilla* for testing. - -###Developer mode -For development of PNF Simulator, run *simulator.sh* start-dev in order to run minimal necessary set of supporting services such as Netopeer of FTP servers. -After that it is possible to run PNF Simulator from IDE. diff --git a/test/mocks/pnfsimulator/checkstyle-suppressions.xml b/test/mocks/pnfsimulator/checkstyle-suppressions.xml new file mode 100644 index 000000000..8d9560789 --- /dev/null +++ b/test/mocks/pnfsimulator/checkstyle-suppressions.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + diff --git a/test/mocks/pnfsimulator/config/config.json b/test/mocks/pnfsimulator/config/config.json deleted file mode 100644 index 636e0132e..000000000 --- a/test/mocks/pnfsimulator/config/config.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "simulatorParams": { - "vesServerUrl": "http://VES-HOST:VES-PORT/eventListener/v7", - "testDuration": "10", - "messageInterval": "1" - }, - "commonEventHeaderParams": { - "eventName": "pnfRegistration_Nokia_5gDu", - "nfNamingCode": "gNB", - "nfcNamingCode": "oam", - "sourceName": "NOK6061ZW3", - "sourceId": "val13", - "reportingEntityName": "NOK6061ZW3" - }, - "pnfRegistrationParams": { - "serialNumber": "6061ZW3", - "vendorName": "Nokia", - "oamV4IpAddress": "val3", - "oamV6IpAddress": "val4", - "unitFamily": "BBU", - "modelNumber": "val6", - "softwareVersion": "val7", - "unitType": "val8", - "additionalFields": { - "attachmentPoint": "bla-bla-30-3", - "svlan": "1005", - "cvlan": "678" - } - }, - "notificationParams": { - "changeIdentifier": "PM_MEAS_FILES", - "changeType": "FileReady", - "arrayOfNamedHashMap": [ - { - "name": "A20161221.1031-1041.bin.gz", - "hashMap": { - "location": "ftpes://192.169.0.1:22/ftp/rop/A20161224.1030-1045.bin.gz", - "compression": "gzip", - "fileFormatType": "org.3GPP.32.435#measCollec", - "fileFormatVersion": "V10" - } - }, - { - "name": "A20161222.1042-1102.bin.gz", - "hashMap": { - "location": "ftpes://192.168.0.102:22/ftp/rop/A20161224.1045-1100.bin.gz", - "compression": "gzip", - "fileFormatType": "org.3GPP.32.435#measCollec", - "fileFormatVersion": "V10" - } - } - ] - } -} diff --git a/test/mocks/pnfsimulator/config/netconf.env b/test/mocks/pnfsimulator/config/netconf.env deleted file mode 100644 index 6cf310a27..000000000 --- a/test/mocks/pnfsimulator/config/netconf.env +++ /dev/null @@ -1,5 +0,0 @@ -NETCONF_ADDRESS=netopeer -NETCONF_PORT=830 -NETCONF_MODEL=pnf-simulator -NETCONF_MAIN_CONTAINER=config -TZ=Europe/Warsaw diff --git a/test/mocks/pnfsimulator/deployment/PnP_PNF_sim_heat_template.yml b/test/mocks/pnfsimulator/deployment/PnP_PNF_sim_heat_template.yml deleted file mode 100644 index 4bf6758d9..000000000 --- a/test/mocks/pnfsimulator/deployment/PnP_PNF_sim_heat_template.yml +++ /dev/null @@ -1,118 +0,0 @@ -description: Heat template that deploys PnP PNF simulator -heat_template_version: '2013-05-23' -parameters: - flavor_name: {description: Type of instance (flavor) to be used, label: Flavor, - type: string} - image_name: {description: Image to be used for compute instance, label: Image name - or ID, type: string} - key_name: {description: Public/Private key pair name, label: Key pair name, type: string} - public_net_id: {description: Public network that enables remote connection to VNF, - label: Public network name or ID, type: string} - private_net_id: {type: string, description: Private network id, label: Private network name or ID} - private_subnet_id: {type: string, description: Private subnet id, label: Private subnetwork name or ID} - proxy: {type: string, description: Proxy, label: Proxy, default: ""} -resources: - PNF_PnP_simualtor: - type: OS::Nova::Server - properties: - key_name: { get_param: key_name } - image: { get_param: image_name } - flavor: { get_param: flavor_name } - networks: - - port: { get_resource: PNF_PnP_simualtor_port0 } - user_data_format: RAW - user_data: - str_replace: - template: | - #!/bin/bash - - set_versions () { - DOCKER_COMPOSE_VERSION=1.22.0 - } - - - enable_root_ssh () { - sed -i 's/PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config - sed -i 's/PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config - service sshd restart - echo -e "arthur\narthur" | passwd root - } - - update_os () { - dnf -y install fedora-upgrade - } - - docker_remove () { - dnf -y remove docker \ - docker-client \ - docker-client-latest \ - docker-common \ - docker-latest \ - docker-latest-logrotate \ - docker-logrotate \ - docker-selinux \ - docker-engine-selinux \ - docker-engine - } - - docker_install_and_configure () { - dnf -y install dnf-plugins-core - dnf config-manager \ - --add-repo \ - https://download.docker.com/linux/fedora/docker-ce.repo - dnf -y install docker-ce - systemctl start docker - mkdir -p /etc/systemd/system/docker.service.d/ - cat > /etc/systemd/system/docker.service.d/override.conf<< EOF - [Service] - Environment="HTTP_PROXY=$proxy" - Environment="HTTPS_PROXY=$proxy" - EOF - systemctl daemon-reload - systemctl restart docker - } - docker_compose_install () { - curl -L https://github.com/docker/compose/releases/download/$DOCKER_COMPOSE_VERSION/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose - chmod +x /usr/local/bin/docker-compose - } - pnf_sim_file_checkout () { - cd /root; git clone https://gerrit.onap.org/r/integration - printf "{\n "simulatorParams": {\n "vesServerUrl": "http://VES-HOST:VES-PORT/eventListener/v7",\n "testDuration": "10",\n "messageInterval": "1"\n },\n "commonEventHeaderParams": {\n "eventName": "pnfRegistration_Nokia_5gDu",\n "nfNamingCode": "gNB",\n "nfcNamingCode": "oam",\n "sourceName": "NOK6061ZW3",\n "sourceId": "val13",\n "reportingEntityName": "NOK6061ZW3"\n },\n "pnfRegistrationParams": {\n "serialNumber": "6061ZW3",\n "vendorName": "Nokia",\n "oamV4IpAddress": "val3",\n "oamV6IpAddress": "val4",\n "unitFamily": "BBU",\n "modelNumber": "val6",\n "softwareVersion": "val7",\n "unitType": "val8"\n }\n}" > integration/test/mocks/pnfsimulator/config/config.json - } - - start_simulator () { - docker login -u docker -p docker nexus3.onap.org:10003 - cd ~/integration/test/mocks/pnfsimulator - ./simulator.sh start - } - - set_versions - enable_root_ssh - update_os - docker_remove - docker_install_and_configure - docker_compose_install - pnf_sim_file_checkout - start_simulator - params: - $proxy: { get_param: proxy } - PNF_PnP_simualtor_port0: - type: OS::Neutron::Port - properties: - network_id: { get_param: private_net_id } - security_groups: - - default - fixed_ips: - - subnet_id: { get_param: private_subnet_id } - PNF_PnP_simualtor_public: - type: OS::Neutron::FloatingIP - properties: - floating_network_id: { get_param: public_net_id } - port_id: { get_resource: PNF_PnP_simualtor_port0 } -outputs: - PNF_PnP_simualtor_private_ip: - description: IP address of PNF_PnP_simualtor in private network - value: { get_attr: [ PNF_PnP_simualtor, first_address ] } - PNF_PnP_simualtor_public_ip: - description: Floating IP address of PNF_PnP_simualtor in public network - value: { get_attr: [ PNF_PnP_simualtor_public, floating_ip_address ] } \ No newline at end of file diff --git a/test/mocks/pnfsimulator/deployment/PnP_PNF_sim_heat_template_Ubuntu_16_04.yml b/test/mocks/pnfsimulator/deployment/PnP_PNF_sim_heat_template_Ubuntu_16_04.yml deleted file mode 100644 index 5dd8e6d58..000000000 --- a/test/mocks/pnfsimulator/deployment/PnP_PNF_sim_heat_template_Ubuntu_16_04.yml +++ /dev/null @@ -1,165 +0,0 @@ -description: Heat template that deploys PnP PNF simulator -heat_template_version: '2013-05-23' -outputs: - PNF_PnP_simualtor_private_ip: - description: IP address of PNF_PnP_simualtor in private network - value: - get_attr: [PNF_PnP_simualtor, first_address] - PNF_PnP_simualtor_public_ip: - description: Floating IP address of PNF_PnP_simualtor in public network - value: - get_attr: [PNF_PnP_simualtor_public, floating_ip_address] -parameters: - flavor_name: - description: Type of instance (flavor) to be used - label: Flavor - type: string - image_name: - description: Ubuntu 16.04 image to be used - label: Image name or ID - type: string - key_name: - description: Public/Private key pair name - label: Key pair name - type: string - private_net_id: - description: Private network id - label: Private network name or ID - type: string - private_subnet_id: - description: Private subnet id - label: Private subnetwork name or ID - type: string - public_net_id: - description: Public network that enables remote connection to VNF - label: Public network name or ID - type: string - security_group: - default: default - description: Security group to be used - label: Security Groups - type: string - proxy: - default: '' - description: Proxy - label: Proxy - type: string - correlation_id: - default: 'someId' - description: Correlation ID - label: Correlation ID - type: string - VES-HOST: - default: 'VES-HOST' - description: VES collector host ip - label: VES ip - type: string - VES-PORT: - default: 'VES-PORT' - description: VES collector host port - label: VES port - type: string -resources: - PNF_PnP_simualtor: - properties: - flavor: - get_param: flavor_name - image: - get_param: image_name - key_name: - get_param: key_name - networks: - - port: - get_resource: PNF_PnP_simualtor_port0 - user_data: - str_replace: - params: - $proxy: - get_param: proxy - $VES-PORT: - get_param: VES-PORT - $VES-HOST: - get_param: VES-HOST - $correlation_id: - get_param: correlation_id - template: | - #!/bin/bash - - set_versions () { - DOCKER_VERSION=17.03 - DOCKER_COMPOSE_VERSION=1.22.0 - PROTOBUF_VERSION=3.6.1 - } - - enable_root_ssh () { - sed -i 's/PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config - sed -i 's/PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config - service sshd restart - echo -e "onap\nonap" | passwd root - } - - update_os () { - rm -rf /var/lib/apt/lists/* - apt-get clean - apt-get update - } - - docker_install_and_configure () { - curl "https://releases.rancher.com/install-docker/$DOCKER_VERSION.sh" | sh - mkdir -p /etc/systemd/system/docker.service.d/ - cat > /etc/systemd/system/docker.service.d/docker.conf << EOF - [Service] - ExecStart= - ExecStart=/usr/bin/dockerd -H fd:// --insecure-registry=nexus3.onap.org:10003 - Environment="HTTP_PROXY=$proxy" - Environment="HTTPS_PROXY=$proxy" - EOF - systemctl daemon-reload - systemctl restart docker - apt-mark hold docker-ce - docker login -u docker -p docker nexus3.onap.org:10003 - } - - docker_compose_install () { - curl -L "https://github.com/docker/compose/releases/download/$DOCKER_COMPOSE_VERSION/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose - chmod +x /usr/local/bin/docker-compose - } - - pnf_sim_file_checkout () { - cd /root; git clone https://gerrit.onap.org/r/integration - printf "{\n \"simulatorParams\": {\n \"vesServerUrl\": \"http://$VES-HOST:$VES-PORT/eventListener/v7\",\n \"testDuration\": \"10\",\n \"messageInterval\": \"1\"\n },\n \"commonEventHeaderParams\": {\n \"eventName\": \"pnfRegistration_Nokia_5gDu\",\n \"nfNamingCode\": \"gNB\",\n \"nfcNamingCode\": \"oam\",\n \"sourceName\": \"$correlation_id\",\n \"sourceId\": \"val13\",\n \"reportingEntityName\": \"NOK6061ZW3\"\n },\n \"pnfRegistrationParams\": {\n \"serialNumber\": \"6061ZW3\",\n \"vendorName\": \"Nokia\",\n \"oamV4IpAddress\": \"val3\",\n \"oamV6IpAddress\": \"val4\",\n \"unitFamily\": \"BBU\",\n \"modelNumber\": \"val6\",\n \"softwareVersion\": \"val7\",\n \"unitType\": \"val8\"\n }\n}" > integration/test/mocks/pnfsimulator/config/config.json - } - - start_simulator () { - docker login -u docker -p docker nexus3.onap.org:10003 - cd ~/integration/test/mocks/pnfsimulator - ./simulator.sh start - } - - set_versions - enable_root_ssh - update_os - docker_install_and_configure - docker_compose_install - pnf_sim_file_checkout - start_simulator - - type: OS::Nova::Server - PNF_PnP_simualtor_port0: - properties: - fixed_ips: - - subnet_id: - get_param: private_subnet_id - network_id: - get_param: private_net_id - security_groups: - - get_param: security_group - type: OS::Neutron::Port - PNF_PnP_simualtor_public: - properties: - floating_network_id: - get_param: public_net_id - port_id: - get_resource: PNF_PnP_simualtor_port0 - type: OS::Neutron::FloatingIP - diff --git a/test/mocks/pnfsimulator/docker-compose.yml b/test/mocks/pnfsimulator/docker-compose.yml deleted file mode 100644 index bbb983fd4..000000000 --- a/test/mocks/pnfsimulator/docker-compose.yml +++ /dev/null @@ -1,83 +0,0 @@ -version: '3' - -services: - pnf-simulator: - container_name: pnf-simulator - image: nexus3.onap.org:10003/onap/pnf-simulator:4.0.0-SNAPSHOT - ports: - - "5000:5000" - volumes: - - ./logs:/var/log - - ./json_schema:/json_schema - env_file: - - ./config/netconf.env - restart: on-failure - depends_on: - - netopeer - - netopeer: - container_name: netopeer - image: sysrepo/sysrepo-netopeer2:latest - ports: - - "830:830" - - "6513:6513" - volumes: - - ./netconf:/netconf - - ./netopeer_tls_cfg:/netopeer_tls_cfg - env_file: - - ./config/netconf.env - restart: on-failure - depends_on: - - sftp-server - - ftpes-server-pure-ftpd - - ftpes-server-vsftpd - command: bash -c "/netopeer_tls_cfg/entrypoint.sh" - - sftp-server: - container_name: sftp-server - image: atmoz/sftp:alpine - ports: - - "2222:22" - volumes: - - ./sftp:/home/sftp-user/sftp - - ./ssh/ssh_host_rsa_key.pub:/home/sftp-user/.ssh/keys/ssh_host_rsa_key.pub:ro - restart: on-failure - command: sftp-user::1001 - - ftpes-server-pure-ftpd: - container_name: ftpes-server-pure-ftpd - image: stilliard/pure-ftpd:latest - ports: - - "2221:21" - - "30000-30009:30000-30009" - volumes: - - ./ftpes/files:/home/ftpusers/onap - - ./ftpes/pure-ftpd/userpass/:/etc/pure-ftpd/passwd/ - - ./ftpes/pure-ftpd/tls/:/etc/ssl/private/ - environment: - PUBLICHOST: localhost - ADDED_FLAGS: --tls=2 - FTP_USER_HOME: onap - restart: on-failure - - ftpes-server-vsftpd: - container_name: ftpes-server-vsftpd - image: docker.io/panubo/vsftpd - ports: - - "8221:21" - - "8001-8010:8001-8010" - environment: - FTP_USER: onap - FTP_PASSWORD: pano - PASV_ADDRESS: localhost - PASV_MIN_PORT: 8001 - PASV_MAX_PORT: 8010 - volumes: - - ./ftpes/vsftpd/tls/vsftpd.crt:/etc/ssl/private/vsftpd.crt:ro - - ./ftpes/vsftpd/tls/vsftpd.key:/etc/ssl/private/vsftpd.key:ro - - ./ftpes/vsftpd/configuration/vsftpd_ssl.conf:/etc/vsftpd_ssl.conf:ro - - ./ftpes/files/onap/ftpes-onap.txt:/home/vsftpd/onap/ftpes-onap.txt:ro - - ./ftpes/files/onap/ftpes-onap.txt:/srv/ftpes-onap.txt:ro - restart: on-failure - command: vsftpd /etc/vsftpd_ssl.conf - diff --git a/test/mocks/pnfsimulator/ftpes/files/ftpes-noone.txt b/test/mocks/pnfsimulator/ftpes/files/ftpes-noone.txt deleted file mode 100644 index 3f1caaed7..000000000 --- a/test/mocks/pnfsimulator/ftpes/files/ftpes-noone.txt +++ /dev/null @@ -1 +0,0 @@ -sample message \ No newline at end of file diff --git a/test/mocks/pnfsimulator/ftpes/files/onap/ftpes-onap.txt b/test/mocks/pnfsimulator/ftpes/files/onap/ftpes-onap.txt deleted file mode 100644 index 8e78dac41..000000000 --- a/test/mocks/pnfsimulator/ftpes/files/onap/ftpes-onap.txt +++ /dev/null @@ -1 +0,0 @@ -sample message v2 \ No newline at end of file diff --git a/test/mocks/pnfsimulator/ftpes/pure-ftpd/tls/pure-ftpd.pem b/test/mocks/pnfsimulator/ftpes/pure-ftpd/tls/pure-ftpd.pem deleted file mode 100755 index 0ce676efa..000000000 --- a/test/mocks/pnfsimulator/ftpes/pure-ftpd/tls/pure-ftpd.pem +++ /dev/null @@ -1,49 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDHbSk5/cABTpCt -q54QyTkhuhb84nEz5ztKL0hY56fsVtAA2gSAde+qV9YwUIuReOUhAF4RVVt2Lkn/ -1R0yX+0IjrXnO7jYzDj6QhgyqYKb3iQlvShZMMQ7qihn8qBxobk7+O10x6VLS2L8 -WYpQxGXu7T1qXbw10RhrqG8nbXYX+aHMsv9zMt9OYqKSI073OZR2vk3K49Uqcurj -sXuRJOa10MRsxgA726pr8OLWAWejsoFaqP2fQS3HeT2RnAqPyAgPc0P6n7gxo0JU -U5dPnrPbsvfdegIFxfc57oZXrLz7nYXkJEcjYTBFSQ+JAaRfx9kNXZ7Gft7EAMyF -BLemY/0VAgMBAAECggEARD9bSHlKaCgW4xhEM8JpRt2EWG62BukvJSghPiupD/x1 -mpUBzWSO7GC68DXgTZxt7WlOx+fKMRuOP3sTTtX9LFyKa+PIUokxRpOv7EaOaAER -pciiMkO6JCELSueBeOG7noaF3N0l+CqIaYvLBfDwYV/XELubWV+BV/aAc6HGNFWi -4bjM+BOBLQstrEeJh2jVylzv4CTtlTs2pwiHFSyrHhudTk5nnATAHn1gi+X42v1A -zk3UfqADZJmMI0/Roup4YPZ3+6zUzDN2i+qasHexL0OKIjRcSqpgqQoIeKEbKKfw -sOgiWIR2Xvj7EJmhzJlWgKjk8OLs/7U4QpnD+s0agQKBgQDu3ojqKNWnPHy0Nupm -tmAs28WLK76R0iZeAd2nwsU2K6lnm9z5o2ab3ffTJVB9kAetKJa3UerKskF/qF9C -MtjlEn6F++uYFitpLjQevnyrKSqFqbzytDXrQlk+gZLglmi6YylT5k9qLSREAu55 -XS/wbm9XU2Q7sl8oTnZHXptT7QKBgQDVunvqdDn1FaNU9EwQCGPS3QGu+go22xkM -4Rs2CoHWfqmhGOo8lJKBElDqsXvxggrZLWJe/1lgnELT/9aXS8QLWBnZxpTj9wfd -igH+CJc3mWnLThmUGdSV/tuHon2IdQ8/1CiGSwIr9kYCnStidUtOXjIbgc6kUTTi -5wtIGHh4yQKBgQDXJ/0dJbDklRgiX4CdCdLxNPfnlnxt7mN+s6GK1WY7l/JcD8ln -1qW66aGrP2YT42L2tqOi9hdNgmh66xb6ksBI/XKXjsWz1Ow/Lk3mD2BN76OMh8pY -trgGc1ndcmrw/qnQkTcNilqn4YdT92wER0rB/0cs2kFjgBQ0QxBI0s+INQKBgA6Y -2fW9UmgGvk0DEl7V89tm9MJ6mU/9zswuY6lhNlTr+bHi/bx9eTQPiC8/R/PKqesD -SoCqd/Q9N+M6yfEzX4RW1A0nnuui54qd7lznQUyu0abtApo22WoVKfEti91SAWSe -nNXvMYrHGyj6iwgCcs47aLiwOOjIExCcLw0RfsjhAoGAc1zaRbrtjjh66FJYjLiJ -Q6EXfm31ptaQQUn5rQyHMD2VRlajCYV+fv75tezf2dQvJcqHYWrEuY8U+OTbB1TB -IEqN8ETUeLegl5RgvWoyWinqdbv/0d9LtwVBdtiEQLoYumD934mshEDgzCOOjrBe -Salcd1vc6y6NiFooPlvloXQ= ------END PRIVATE KEY----- ------BEGIN CERTIFICATE----- -MIIDYDCCAkigAwIBAgIJAMH2upKd2yAJMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV -BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX -aWRnaXRzIFB0eSBMdGQwHhcNMTgwOTEwMTI1ODE2WhcNMzgwOTA1MTI1ODE2WjBF -MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 -ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEAx20pOf3AAU6QraueEMk5IboW/OJxM+c7Si9IWOen7FbQANoEgHXvqlfW -MFCLkXjlIQBeEVVbdi5J/9UdMl/tCI615zu42Mw4+kIYMqmCm94kJb0oWTDEO6oo -Z/KgcaG5O/jtdMelS0ti/FmKUMRl7u09al28NdEYa6hvJ212F/mhzLL/czLfTmKi -kiNO9zmUdr5NyuPVKnLq47F7kSTmtdDEbMYAO9uqa/Di1gFno7KBWqj9n0Etx3k9 -kZwKj8gID3ND+p+4MaNCVFOXT56z27L33XoCBcX3Oe6GV6y8+52F5CRHI2EwRUkP -iQGkX8fZDV2exn7exADMhQS3pmP9FQIDAQABo1MwUTAdBgNVHQ4EFgQUt51lQ+ab -MTq+w2U/knCsIPb3wrkwHwYDVR0jBBgwFoAUt51lQ+abMTq+w2U/knCsIPb3wrkw -DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAQ69AktYLQ+VRbojz -zC0XQ2M1FAkfJI2P0LvPoYxZgId2CnZW3sMIdnJdF+KjvOqeGyFmw+hn8WkoKiWj -0sxuGmrWt5t+5bF2wcq0CtTeF1/o6DsRhRiJBzmcLe81ItrN6emZSg96xCKzkHBZ -3nF4fG88vtiYgD932lMStDqQzSTx0FsCGpGaKh9xDmKvlP24NWdM9gyOEsRbDvqd -vS1Q45Jx0jzkp7X5d0casqBWIZak3z0EVdK7c8Y/GxxTcWfIMINCl9+F9kpTA/ZX -uARYzrPWaBfDBi2r5acWi/AHJM3U+LgzO5nCKa+38vtjNw3NtbslA4InQ5cU2B8X -QN8NlQ== ------END CERTIFICATE----- diff --git a/test/mocks/pnfsimulator/ftpes/pure-ftpd/userpass/pureftpd.passwd b/test/mocks/pnfsimulator/ftpes/pure-ftpd/userpass/pureftpd.passwd deleted file mode 100755 index 7961e710d..000000000 --- a/test/mocks/pnfsimulator/ftpes/pure-ftpd/userpass/pureftpd.passwd +++ /dev/null @@ -1 +0,0 @@ -onap:$6$Guq6OMhBdNZ6nTk0$7dLt6hOrAv.in36jzWGd5UgWeDqN3CuKjrzJ.izRTdgZRTszeNYbT2dk7UDh9CLD7pohnB0.k1NSZmRIUB/ID/:1001:1001::/home/ftpusers/onap/./:::::::::::: diff --git a/test/mocks/pnfsimulator/ftpes/vsftpd/configuration/vsftpd_ssl.conf b/test/mocks/pnfsimulator/ftpes/vsftpd/configuration/vsftpd_ssl.conf deleted file mode 100644 index 3e9cd7c66..000000000 --- a/test/mocks/pnfsimulator/ftpes/vsftpd/configuration/vsftpd_ssl.conf +++ /dev/null @@ -1,56 +0,0 @@ -# Server Config -anonymous_enable=NO -local_enable=YES -write_enable=YES -local_umask=022 -dirmessage_enable=YES - -# Security and User auth -chroot_local_user=YES -pam_service_name=vsftpd_virtual -virtual_use_local_privs=YES -chmod_enable=NO -user_config_dir=/etc/vsftpd/user_conf -user_sub_token=$USER -#local_root=/srv/$USER -local_root=/srv/ -userlist_enable=NO -allow_writeable_chroot=YES - -# Logging -log_ftp_protocol=YES -xferlog_enable=YES -xferlog_std_format=YES -#xferlog_file=/dev/stdout -syslog_enable=NO -dual_log_enable=YES - -# Remap all login users to this username -guest_enable=YES -guest_username=ftp -hide_ids=YES - -# Networking -connect_from_port_20=NO -listen=YES -tcp_wrappers=YES -pasv_min_port=8001 -pasv_max_port=8010 - -# SSL -ssl_enable=Yes -require_ssl_reuse=NO -force_local_data_ssl=YES -force_local_logins_ssl=YES -ssl_ciphers=HIGH -allow_anon_ssl=NO - -ssl_tlsv1=YES -ssl_sslv2=YES -ssl_sslv3=YES -rsa_cert_file=/etc/ssl/private/vsftpd.crt -rsa_private_key_file=/etc/ssl/private/vsftpd.key - -#require_cert=YES -#ssl_request_cert=YES -#ca_certs_file=/home/vsftpd/onap/client.crt \ No newline at end of file diff --git a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/cert.der b/test/mocks/pnfsimulator/ftpes/vsftpd/tls/cert.der deleted file mode 100644 index 24ac26c69..000000000 Binary files a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/cert.der and /dev/null differ diff --git a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/cert.pkcs12 b/test/mocks/pnfsimulator/ftpes/vsftpd/tls/cert.pkcs12 deleted file mode 100644 index 3983e748a..000000000 Binary files a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/cert.pkcs12 and /dev/null differ diff --git a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/keystore.jks b/test/mocks/pnfsimulator/ftpes/vsftpd/tls/keystore.jks deleted file mode 100644 index 6285f8e9e..000000000 Binary files a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/keystore.jks and /dev/null differ diff --git a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/truststore.jks b/test/mocks/pnfsimulator/ftpes/vsftpd/tls/truststore.jks deleted file mode 100644 index 81872195d..000000000 Binary files a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/truststore.jks and /dev/null differ diff --git a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd.crt b/test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd.crt deleted file mode 100644 index 0aaee0eec..000000000 --- a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd.crt +++ /dev/null @@ -1,23 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDvjCCAqagAwIBAgIJAJJp49NkLrvBMA0GCSqGSIb3DQEBCwUAMHQxCzAJBgNV -BAYTAlBMMRQwEgYDVQQIDAtEb2xueSBTbGFzazEQMA4GA1UEBwwHV3JvY2xhdzEV -MBMGA1UECgwMUm9vdCBDb21wYW55MRYwFAYDVQQLDA1JVCBEZXBhcnRtZW50MQ4w -DAYDVQQDDAVOb2tpYTAeFw0xODEwMjYwOTE5NTFaFw0xOTEwMjYwOTE5NTFaMHQx -CzAJBgNVBAYTAlBMMRQwEgYDVQQIDAtEb2xueSBTbGFzazEQMA4GA1UEBwwHV3Jv -Y2xhdzEVMBMGA1UECgwMUm9vdCBDb21wYW55MRYwFAYDVQQLDA1JVCBEZXBhcnRt -ZW50MQ4wDAYDVQQDDAVOb2tpYTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBALvjq8cuNmfZe8S0ONp0LvSx1fgdWaARuGTcTgjLlV+8ng7f4eVodj8bn5BI -cChjMjMc+8YfCLdZJxOl36/8pdIOe1pHGBgjJ5uPIFg0ESuVSN15azodw5ESGA2v -Nhc4QlynLH/W5SsGRlkN0t9yRvGLb+uSrRqDtAFc448//qgTIsBYBl0cLoU4uMaj -iSaxqEpBZPJSAOnof1XV4ZEXTE2lm/HHepa5RozlgYgCzF21m5k2inGN3p9NYdkN -nq0ahl12j/GCuabwVblUnQPAUZzLtV9CtZkuPRdwnkLFGEMNVGsYWh+KAb2q7fr3 -9BNsqdWtIdX8CS30/KBMplSr/6UCAwEAAaNTMFEwHQYDVR0OBBYEFKTTrBaUlhXo -kaD2n2CbtVT/+vV8MB8GA1UdIwQYMBaAFKTTrBaUlhXokaD2n2CbtVT/+vV8MA8G -A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ8VwmT28OF5+wKooFbJ -oxhOp80dEaBHOuoBkIqiQFS3Bf3lhUcue+sqWWN2D/vSosQpIUImXPrnjAogGT8p -HCnh0eblY89Q62wtGtdhDWPdrmZ198MOQifaIKTDLDE0viLGtCC+aBOATEjm/K2O -e2lFxYVckZw7wEnbWoQCYxEE9qczxBjkStPhF3RqyorbxVQKfSKlo1bspTCwB3pW -LpXcY6OP8ZL0v46HExy1d9pAsh0gcWDyG812/86AdYEeoaV7QJh2B9fRRAuFve9S -GWEEtxPobvXfLL6QOFiacSwmyqckuMxgYGpAcJSVYoA1r9xNJA24SO68We9EaCty -7WU= ------END CERTIFICATE----- diff --git a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd.key b/test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd.key deleted file mode 100644 index 43af86505..000000000 --- a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQC746vHLjZn2XvE -tDjadC70sdX4HVmgEbhk3E4Iy5VfvJ4O3+HlaHY/G5+QSHAoYzIzHPvGHwi3WScT -pd+v/KXSDntaRxgYIyebjyBYNBErlUjdeWs6HcOREhgNrzYXOEJcpyx/1uUrBkZZ -DdLfckbxi2/rkq0ag7QBXOOPP/6oEyLAWAZdHC6FOLjGo4kmsahKQWTyUgDp6H9V -1eGRF0xNpZvxx3qWuUaM5YGIAsxdtZuZNopxjd6fTWHZDZ6tGoZddo/xgrmm8FW5 -VJ0DwFGcy7VfQrWZLj0XcJ5CxRhDDVRrGFofigG9qu369/QTbKnVrSHV/Akt9Pyg -TKZUq/+lAgMBAAECggEBALrgl9pkfHiOOCxNlL6zEIEQ4GEH0D0FYwHunS7iTpAK -aqsgwu4KGJJsRyia4/NHtoZgLYvBEkpKwjMoqHPCNqvW+5mvXKelT5/Jm8IfB3Tx -5qdiPORw9jM0a/gwbPxrWJYPMJN2ijlg5FdvCG52m1lj9s239bSJimBQo4W3gPJp -YXCN+cO7DMpaIsvTpFnQUyiRxzbqmWD/dI51/GdsQUkjM5VRTXtv9D+RCaVE/Gyd -cdzHOm6MuULEeuaWtoUKux6v94xoQDhf4p9AECDowzEeHmvJ6qEQzantnEUtJNsI -+47sP8IZE0qs9lCcrJHeK37aO1IS39VY2BeAR6XkR4ECgYEA48NfVTTmKN6sNDGa -aVgkDalATdHPFhitKAvBPBR1R/eCz37gdGX19DNYShiXBny2XEkuyY8chuhUmBMV -A5OrIMLoF0ByvsZXEaghhBirFsmXTjc3gAhFz6r6oSDM/dYs5pFYSR+gnnl/WALA -8Y82FxdKA9d5gkeAGY5GvmO9L7sCgYEA0y7Ny9s3VvDr2oU89ujdGviUkiDxstis -vajsg3BojJweid7WjL0Gv1/wtwiPtZkCZSnaKv6Q2zxSZ1OJpWvff5TbjG/WfzXu -fkITnkFzF8klQswkge7uRryI0NJBFLzgl3sWGJwHNuNmRaw7i5Ie9OhXE0NzH9B+ -Aixx3TwKKB8CgYEAjOBTHwjRM4ZHTSFBONdjtW9ybq/PPwOUVqiupNKimBjnuB/q -BRTrxFfdzDbZcxHAWeSKI/F425joegeTf9rehi0IERmz33webrVnxaTcbgPSqnZM -xcxYIdLHotH++SJ4M0TDLrd5SYwsz+skHEVQV4f4J9gnOAWxnhz6dNiMM/ECgYEA -pypkYxr62kpJGCfh0z0PULs2t9l2GXEkg9kEpyLCz5MBJXeMc8lpXvGt1OTlBQXC -fJu9g80Qk0pTnFDnI1eZih8mDyu0KexiBfV+HAaI+WoSoaaAu42LddjloA7ez3CX -g7E+E2rm1w74NOyaEegvswN7cdcxeRyLsmLGGy7ch1cCgYEAnbv8i9Mt0FzCqX5O -yr1JehLoQWz4RqIibtEcjk7cQFjhUUx5UqnRHS6DAinL9vh92G/3JYsX/Ur2k2f9 -nl/y3clx5hjQubEt18lu8oi76dRRD3HBb6JA4rnZBvG3cpu9zy3Ik3hxMLdxGvfN -ciDoTou+NnAuP0e3KTDyTe+1MMc= ------END PRIVATE KEY----- diff --git a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd.pem b/test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd.pem deleted file mode 100644 index 96e5ed63a..000000000 --- a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd.pem +++ /dev/null @@ -1,50 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpgIBAAKCAQEAu+Orxy42Z9l7xLQ42nQu9LHV+B1ZoBG4ZNxOCMuVX7yeDt/h -5Wh2PxufkEhwKGMyMxz7xh8It1knE6Xfr/yl0g57WkcYGCMnm48gWDQRK5VI3Xlr -Oh3DkRIYDa82FzhCXKcsf9blKwZGWQ3S33JG8Ytv65KtGoO0AVzjjz/+qBMiwFgG -XRwuhTi4xqOJJrGoSkFk8lIA6eh/VdXhkRdMTaWb8cd6lrlGjOWBiALMXbWbmTaK -cY3en01h2Q2erRqGXXaP8YK5pvBVuVSdA8BRnMu1X0K1mS49F3CeQsUYQw1Uaxha -H4oBvart+vf0E2yp1a0h1fwJLfT8oEymVKv/pQIDAQABAoIBAQC64JfaZHx4jjgs -TZS+sxCBEOBhB9A9BWMB7p0u4k6QCmqrIMLuChiSbEcomuPzR7aGYC2LwRJKSsIz -KKhzwjar1vuZr1ynpU+fyZvCHwd08eanYjzkcPYzNGv4MGz8a1iWDzCTdoo5YORX -bwhudptZY/bNt/W0iYpgUKOFt4DyaWFwjfnDuwzKWiLL06RZ0FMokcc26plg/3SO -dfxnbEFJIzOVUU17b/Q/kQmlRPxsnXHcxzpujLlCxHrmlraFCrser/eMaEA4X+Kf -QBAg6MMxHh5ryeqhEM2p7ZxFLSTbCPuO7D/CGRNKrPZQnKyR3it+2jtSEt/VWNgX -gEel5EeBAoGBAOPDX1U05ijerDQxmmlYJA2pQE3RzxYYrSgLwTwUdUf3gs9+4HRl -9fQzWEoYlwZ8tlxJLsmPHIboVJgTFQOTqyDC6BdAcr7GVxGoIYQYqxbJl043N4AI -Rc+q+qEgzP3WLOaRWEkfoJ55f1gCwPGPNhcXSgPXeYJHgBmORr5jvS+7AoGBANMu -zcvbN1bw69qFPPbo3Rr4lJIg8bLYrL2o7INwaIycHone1oy9Br9f8LcIj7WZAmUp -2ir+kNs8UmdTiaVr33+U24xv1n817n5CE55BcxfJJULMJIHu7ka8iNDSQRS84Jd7 -FhicBzbjZkWsO4uSHvToVxNDcx/QfgIscd08CigfAoGBAIzgUx8I0TOGR00hQTjX -Y7Vvcm6vzz8DlFaorqTSopgY57gf6gUU68RX3cw22XMRwFnkiiPxeNuY6HoHk3/a -3oYtCBEZs998Hm61Z8Wk3G4D0qp2TMXMWCHSx6LR/vkieDNEwy63eUmMLM/rJBxF -UFeH+CfYJzgFsZ4c+nTYjDPxAoGBAKcqZGMa+tpKSRgn4dM9D1C7NrfZdhlxJIPZ -BKciws+TASV3jHPJaV7xrdTk5QUFwnybvYPNEJNKU5xQ5yNXmYofJg8rtCnsYgX1 -fhwGiPlqEqGmgLuNi3XY5aAO3s9wl4OxPhNq5tcO+DTsmhHoL7MDe3HXMXkci7Ji -xhsu3IdXAoGBAJ27/IvTLdBcwql+Tsq9SXoS6EFs+EaiIm7RHI5O3EBY4VFMeVKp -0R0ugwIpy/b4fdhv9yWLF/1K9pNn/Z5f8t3JceYY0LmxLdfJbvKIu+nUUQ9xwW+i -QOK52Qbxt3Kbvc8tyJN4cTC3cRr3zXIg6E6LvjZwLj9Htykw8k3vtTDH ------END RSA PRIVATE KEY----- ------BEGIN CERTIFICATE----- -MIIDvjCCAqagAwIBAgIJAJJp49NkLrvBMA0GCSqGSIb3DQEBCwUAMHQxCzAJBgNV -BAYTAlBMMRQwEgYDVQQIDAtEb2xueSBTbGFzazEQMA4GA1UEBwwHV3JvY2xhdzEV -MBMGA1UECgwMUm9vdCBDb21wYW55MRYwFAYDVQQLDA1JVCBEZXBhcnRtZW50MQ4w -DAYDVQQDDAVOb2tpYTAeFw0xODEwMjYwOTE5NTFaFw0xOTEwMjYwOTE5NTFaMHQx -CzAJBgNVBAYTAlBMMRQwEgYDVQQIDAtEb2xueSBTbGFzazEQMA4GA1UEBwwHV3Jv -Y2xhdzEVMBMGA1UECgwMUm9vdCBDb21wYW55MRYwFAYDVQQLDA1JVCBEZXBhcnRt -ZW50MQ4wDAYDVQQDDAVOb2tpYTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBALvjq8cuNmfZe8S0ONp0LvSx1fgdWaARuGTcTgjLlV+8ng7f4eVodj8bn5BI -cChjMjMc+8YfCLdZJxOl36/8pdIOe1pHGBgjJ5uPIFg0ESuVSN15azodw5ESGA2v -Nhc4QlynLH/W5SsGRlkN0t9yRvGLb+uSrRqDtAFc448//qgTIsBYBl0cLoU4uMaj -iSaxqEpBZPJSAOnof1XV4ZEXTE2lm/HHepa5RozlgYgCzF21m5k2inGN3p9NYdkN -nq0ahl12j/GCuabwVblUnQPAUZzLtV9CtZkuPRdwnkLFGEMNVGsYWh+KAb2q7fr3 -9BNsqdWtIdX8CS30/KBMplSr/6UCAwEAAaNTMFEwHQYDVR0OBBYEFKTTrBaUlhXo -kaD2n2CbtVT/+vV8MB8GA1UdIwQYMBaAFKTTrBaUlhXokaD2n2CbtVT/+vV8MA8G -A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ8VwmT28OF5+wKooFbJ -oxhOp80dEaBHOuoBkIqiQFS3Bf3lhUcue+sqWWN2D/vSosQpIUImXPrnjAogGT8p -HCnh0eblY89Q62wtGtdhDWPdrmZ198MOQifaIKTDLDE0viLGtCC+aBOATEjm/K2O -e2lFxYVckZw7wEnbWoQCYxEE9qczxBjkStPhF3RqyorbxVQKfSKlo1bspTCwB3pW -LpXcY6OP8ZL0v46HExy1d9pAsh0gcWDyG812/86AdYEeoaV7QJh2B9fRRAuFve9S -GWEEtxPobvXfLL6QOFiacSwmyqckuMxgYGpAcJSVYoA1r9xNJA24SO68We9EaCty -7WU= ------END CERTIFICATE----- diff --git a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd_crt.pem b/test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd_crt.pem deleted file mode 100644 index 0aaee0eec..000000000 --- a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd_crt.pem +++ /dev/null @@ -1,23 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDvjCCAqagAwIBAgIJAJJp49NkLrvBMA0GCSqGSIb3DQEBCwUAMHQxCzAJBgNV -BAYTAlBMMRQwEgYDVQQIDAtEb2xueSBTbGFzazEQMA4GA1UEBwwHV3JvY2xhdzEV -MBMGA1UECgwMUm9vdCBDb21wYW55MRYwFAYDVQQLDA1JVCBEZXBhcnRtZW50MQ4w -DAYDVQQDDAVOb2tpYTAeFw0xODEwMjYwOTE5NTFaFw0xOTEwMjYwOTE5NTFaMHQx -CzAJBgNVBAYTAlBMMRQwEgYDVQQIDAtEb2xueSBTbGFzazEQMA4GA1UEBwwHV3Jv -Y2xhdzEVMBMGA1UECgwMUm9vdCBDb21wYW55MRYwFAYDVQQLDA1JVCBEZXBhcnRt -ZW50MQ4wDAYDVQQDDAVOb2tpYTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBALvjq8cuNmfZe8S0ONp0LvSx1fgdWaARuGTcTgjLlV+8ng7f4eVodj8bn5BI -cChjMjMc+8YfCLdZJxOl36/8pdIOe1pHGBgjJ5uPIFg0ESuVSN15azodw5ESGA2v -Nhc4QlynLH/W5SsGRlkN0t9yRvGLb+uSrRqDtAFc448//qgTIsBYBl0cLoU4uMaj -iSaxqEpBZPJSAOnof1XV4ZEXTE2lm/HHepa5RozlgYgCzF21m5k2inGN3p9NYdkN -nq0ahl12j/GCuabwVblUnQPAUZzLtV9CtZkuPRdwnkLFGEMNVGsYWh+KAb2q7fr3 -9BNsqdWtIdX8CS30/KBMplSr/6UCAwEAAaNTMFEwHQYDVR0OBBYEFKTTrBaUlhXo -kaD2n2CbtVT/+vV8MB8GA1UdIwQYMBaAFKTTrBaUlhXokaD2n2CbtVT/+vV8MA8G -A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ8VwmT28OF5+wKooFbJ -oxhOp80dEaBHOuoBkIqiQFS3Bf3lhUcue+sqWWN2D/vSosQpIUImXPrnjAogGT8p -HCnh0eblY89Q62wtGtdhDWPdrmZ198MOQifaIKTDLDE0viLGtCC+aBOATEjm/K2O -e2lFxYVckZw7wEnbWoQCYxEE9qczxBjkStPhF3RqyorbxVQKfSKlo1bspTCwB3pW -LpXcY6OP8ZL0v46HExy1d9pAsh0gcWDyG812/86AdYEeoaV7QJh2B9fRRAuFve9S -GWEEtxPobvXfLL6QOFiacSwmyqckuMxgYGpAcJSVYoA1r9xNJA24SO68We9EaCty -7WU= ------END CERTIFICATE----- diff --git a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd_key.pem b/test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd_key.pem deleted file mode 100644 index 2003df7c7..000000000 --- a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd_key.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpgIBAAKCAQEAu+Orxy42Z9l7xLQ42nQu9LHV+B1ZoBG4ZNxOCMuVX7yeDt/h -5Wh2PxufkEhwKGMyMxz7xh8It1knE6Xfr/yl0g57WkcYGCMnm48gWDQRK5VI3Xlr -Oh3DkRIYDa82FzhCXKcsf9blKwZGWQ3S33JG8Ytv65KtGoO0AVzjjz/+qBMiwFgG -XRwuhTi4xqOJJrGoSkFk8lIA6eh/VdXhkRdMTaWb8cd6lrlGjOWBiALMXbWbmTaK -cY3en01h2Q2erRqGXXaP8YK5pvBVuVSdA8BRnMu1X0K1mS49F3CeQsUYQw1Uaxha -H4oBvart+vf0E2yp1a0h1fwJLfT8oEymVKv/pQIDAQABAoIBAQC64JfaZHx4jjgs -TZS+sxCBEOBhB9A9BWMB7p0u4k6QCmqrIMLuChiSbEcomuPzR7aGYC2LwRJKSsIz -KKhzwjar1vuZr1ynpU+fyZvCHwd08eanYjzkcPYzNGv4MGz8a1iWDzCTdoo5YORX -bwhudptZY/bNt/W0iYpgUKOFt4DyaWFwjfnDuwzKWiLL06RZ0FMokcc26plg/3SO -dfxnbEFJIzOVUU17b/Q/kQmlRPxsnXHcxzpujLlCxHrmlraFCrser/eMaEA4X+Kf -QBAg6MMxHh5ryeqhEM2p7ZxFLSTbCPuO7D/CGRNKrPZQnKyR3it+2jtSEt/VWNgX -gEel5EeBAoGBAOPDX1U05ijerDQxmmlYJA2pQE3RzxYYrSgLwTwUdUf3gs9+4HRl -9fQzWEoYlwZ8tlxJLsmPHIboVJgTFQOTqyDC6BdAcr7GVxGoIYQYqxbJl043N4AI -Rc+q+qEgzP3WLOaRWEkfoJ55f1gCwPGPNhcXSgPXeYJHgBmORr5jvS+7AoGBANMu -zcvbN1bw69qFPPbo3Rr4lJIg8bLYrL2o7INwaIycHone1oy9Br9f8LcIj7WZAmUp -2ir+kNs8UmdTiaVr33+U24xv1n817n5CE55BcxfJJULMJIHu7ka8iNDSQRS84Jd7 -FhicBzbjZkWsO4uSHvToVxNDcx/QfgIscd08CigfAoGBAIzgUx8I0TOGR00hQTjX -Y7Vvcm6vzz8DlFaorqTSopgY57gf6gUU68RX3cw22XMRwFnkiiPxeNuY6HoHk3/a -3oYtCBEZs998Hm61Z8Wk3G4D0qp2TMXMWCHSx6LR/vkieDNEwy63eUmMLM/rJBxF -UFeH+CfYJzgFsZ4c+nTYjDPxAoGBAKcqZGMa+tpKSRgn4dM9D1C7NrfZdhlxJIPZ -BKciws+TASV3jHPJaV7xrdTk5QUFwnybvYPNEJNKU5xQ5yNXmYofJg8rtCnsYgX1 -fhwGiPlqEqGmgLuNi3XY5aAO3s9wl4OxPhNq5tcO+DTsmhHoL7MDe3HXMXkci7Ji -xhsu3IdXAoGBAJ27/IvTLdBcwql+Tsq9SXoS6EFs+EaiIm7RHI5O3EBY4VFMeVKp -0R0ugwIpy/b4fdhv9yWLF/1K9pNn/Z5f8t3JceYY0LmxLdfJbvKIu+nUUQ9xwW+i -QOK52Qbxt3Kbvc8tyJN4cTC3cRr3zXIg6E6LvjZwLj9Htykw8k3vtTDH ------END RSA PRIVATE KEY----- diff --git a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd_keys_generator.sh b/test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd_keys_generator.sh deleted file mode 100644 index ef66bd0b4..000000000 --- a/test/mocks/pnfsimulator/ftpes/vsftpd/tls/vsftpd_keys_generator.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash -echo 'Generating credetials for FTPES server and DFC client...' - -#ganerate certificate&privatekey (vsftpd.crt, vsftpd.key) with password: secret -openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout vsftpd.key -out vsftpd.crt -subj "/C=PL/ST=Dolny Slask/L=Wroclaw/O=Root Company/OU=IT Department/CN=Nokia" -#convert crt to pem -openssl x509 -in vsftpd.crt -out vsftpd_crt.pem -outform PEM -#convert key to pem -openssl rsa -in vsftpd.key -out vsftpd_key.pem -outform PEM -#marge key and cert into one pem file -cat vsftpd_key.pem vsftpd_crt.pem > vsftpd.pem - -#generate keystore -openssl pkcs12 -export -out cert.pkcs12 -in vsftpd_crt.pem -inkey vsftpd_key.pem -java -cp ./jetty-6.1.26.jar org.mortbay.jetty.security.PKCS12Import cert.pkcs12 keystore.jks - -#generate truststore -openssl x509 -in vsftpd_crt.pem -out cert.der -outform der -keytool -importcert -alias cert -file cert.der -keystore truststore.jks - -sudo chown root * -sudo chmod 664 * - -echo "You have generated your key in the keystore, and your certificate in the truststore." - -##WITH PASSPHRASE -#echo 'Generating credetials for FTPES server and DFC client...' -# -##ganerate certificate&privatekey (vsftpd.crt, vsftpd.key) with password: secret -#openssl req -x509 -days 365 -newkey rsa:2048 -keyout vsftpd.key -out vsftpd.crt -subj "/C=PL/ST=Dolny Slask/L=Wroclaw/O=Root Company/OU=IT Department/CN=Nokia" --passout pass:secret -##convert crt to pem -#openssl x509 -in vsftpd.crt -out vsftpd_crt.pem -outform PEM -##convert key to pem -#openssl rsa -in vsftpd.key -out vsftpd_key.pem -outform PEM -passin pass:secret -##marge key and cert into one pem file -#cat vsftpd_key.pem vsftpd_crt.pem > vsftpd.pem -# -##generate keystore -#openssl pkcs12 -export -out cert.pkcs12 -in vsftpd_crt.pem -inkey vsftpd_key.pem -passout pass:secret -#java -cp ./jetty-6.1.26.jar org.mortbay.jetty.security.PKCS12Import cert.pkcs12 keystore.jks -# -##generate truststore -#openssl x509 -in vsftpd_crt.pem -out cert.der -outform der -#keytool -importcert -alias cert -file cert.der -keystore truststore.jks -storepass secret -# -#sudo chown root * -#sudo chmod 664 * -# -#echo "You have generated your key in the keystore, and your certificate in the truststore." \ No newline at end of file diff --git a/test/mocks/pnfsimulator/json_schema/input_validator.json b/test/mocks/pnfsimulator/json_schema/input_validator.json deleted file mode 100644 index 679e11abf..000000000 --- a/test/mocks/pnfsimulator/json_schema/input_validator.json +++ /dev/null @@ -1,198 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "simulatorParams": { - "type": "object", - "properties": { - "vesServerUrl": { - "type": "string" - }, - "testDuration": { - "type": "string" - }, - "messageInterval": { - "type": "string" - } - }, - "required": [ - "vesServerUrl", - "testDuration", - "messageInterval" - ] - }, - "commonEventHeaderParams": { - "type": "object", - "properties": { - "eventName": { - "type": "string" - }, - "nfNamingCode": { - "type": "string" - }, - "nfcNamingCode": { - "type": "string" - }, - "sourceName": { - "type": "string" - }, - "sourceId": { - "type": "string" - }, - "reportingEntityName": { - "type": "string" - } - }, - "required": [ - "eventName", - "sourceName", - "sourceId", - "reportingEntityName" - ] - }, - - - "pnfRegistrationParams": { - "type": "object", - "properties": { - "serialNumber": { - "type": "string" - }, - "vendorName": { - "type": "string" - }, - "oamV4IpAddress": { - "type": "string" - }, - "oamV6IpAddress": { - "type": "string" - }, - "unitFamily": { - "type": "string" - }, - "modelNumber": { - "type": "string" - }, - "softwareVersion": { - "type": "string" - }, - "unitType": { - "type": "string" - }, - "additionalFields": { - "type": "object" - } - } - }, - "notificationParams": { - "type": "object", - "properties": { - "changeIdentifier": { - "type": "string" - }, - "changeType": { - "type": "string" - }, - "arrayOfNamedHashMap": { - "type": "array", - "items": [ - { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "hashMap": { - "type": "object", - "properties": { - "location": { - "type": "string" - }, - "compression": { - "type": "string" - }, - "fileFormatType": { - "type": "string" - }, - "fileFormatVersion": { - "type": "string" - } - }, - "required": [ - "location", - "compression", - "fileFormatType", - "fileFormatVersion" - ] - } - }, - "required": [ - "name", - "hashMap" - ] - }, - { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "hashMap": { - "type": "object", - "properties": { - "location": { - "type": "string" - }, - "compression": { - "type": "string" - }, - "fileFormatType": { - "type": "string" - }, - "fileFormatVersion": { - "type": "string" - } - }, - "required": [ - "location", - "compression", - "fileFormatType", - "fileFormatVersion" - ] - } - }, - "required": [ - "name", - "hashMap" - ] - } - ] - } - }, - "required": [ - "changeIdentifier", - "changeType", - "arrayOfNamedHashMap" - ] - } - }, - - "oneOf": [ - { - "required": [ - "simulatorParams", - "commonEventHeaderParams", - "pnfRegistrationParams" - ] - }, - { - "required": [ - "simulatorParams", - "commonEventHeaderParams", - "notificationParams" - ] - } - ] - - -} diff --git a/test/mocks/pnfsimulator/json_schema/output_validator_ves_schema_30.0.1.json b/test/mocks/pnfsimulator/json_schema/output_validator_ves_schema_30.0.1.json deleted file mode 100644 index 385ba25e3..000000000 --- a/test/mocks/pnfsimulator/json_schema/output_validator_ves_schema_30.0.1.json +++ /dev/null @@ -1,2432 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "title": "VES Event Listener Common Event Format", - "type": "object", - "properties": { - "event": {"$ref": "#/definitions/event"}, - "eventList": {"$ref": "#/definitions/eventList"} - }, - - "definitions": { - "schemaHeaderBlock": { - "description": "schema date, version, author and associated API", - "type": "object", - "properties": { - "associatedApi": { - "description": "VES Event Listener", - "type": "string" - }, - "lastUpdatedBy": { - "description": "re2947", - "type": "string" - }, - "schemaDate": { - "description": "July 31, 2018", - "type": "string" - }, - "schemaVersion": { - "description": "30.0.1", - "type": "number" - } - } - }, - "schemaLicenseAndCopyrightNotice": { - "description": "Copyright (c) 2018, AT&T Intellectual Property. All rights reserved", - "type": "object", - "properties": { - "apacheLicense2.0": { - "description": "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:", - "type": "string" - }, - "licenseUrl": { - "description": "http://www.apache.org/licenses/LICENSE-2.0", - "type": "string" - }, - "asIsClause": { - "description": "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.", - "type": "string" - }, - "permissionsAndLimitations": { - "description": "See the License for the specific language governing permissions and limitations under the License.", - "type": "string" - } - } - }, - "arrayOfJsonObject": { - "description": "array of json objects described by name, schema and other meta-information", - "type": "array", - "items": { - "$ref": "#/definitions/jsonObject" - } - }, - "arrayOfNamedHashMap": { - "description": "array of named hashMaps", - "type": "array", - "items": { - "$ref": "#/definitions/namedHashMap" - } - }, - "codecsInUse": { - "description": "number of times an identified codec was used over the measurementInterval", - "type": "object", - "properties": { - "codecIdentifier": { "type": "string" }, - "numberInUse": { "type": "integer" } - }, - "additionalProperties": false, - "required": [ "codecIdentifier", "numberInUse" ] - }, - "commonEventHeader": { - "description": "fields common to all events", - "type": "object", - "properties": { - "domain": { - "description": "the eventing domain associated with the event", - "type": "string", - "enum": [ - "fault", - "heartbeat", - "measurement", - "mobileFlow", - "notification", - "other", - "pnfRegistration", - "sipSignaling", - "stateChange", - "syslog", - "thresholdCrossingAlert", - "voiceQuality" - ] - }, - "eventId": { - "description": "event key that is unique to the event source", - "type": "string" - }, - "eventName": { - "description": "unique event name", - "type": "string" - }, - "eventType": { - "description": "for example - applicationNf, guestOS, hostOS, platform", - "type": "string" - }, - "internalHeaderFields": { "$ref": "#/definitions/internalHeaderFields" }, - "lastEpochMicrosec": { - "description": "the latest unix time aka epoch time associated with the event from any component--as microseconds elapsed since 1 Jan 1970 not including leap seconds", - "type": "number" - }, - "nfcNamingCode": { - "description": "3 character network function component type, aligned with vfc naming standards", - "type": "string" - }, - "nfNamingCode": { - "description": "4 character network function type, aligned with nf naming standards", - "type": "string" - }, - "nfVendorName": { - "description": "network function vendor name", - "type": "string" - }, - "priority": { - "description": "processing priority", - "type": "string", - "enum": [ - "High", - "Medium", - "Normal", - "Low" - ] - }, - "reportingEntityId": { - "description": "UUID identifying the entity reporting the event, for example an OAM VM; must be populated by the ATT enrichment process", - "type": "string" - }, - "reportingEntityName": { - "description": "name of the entity reporting the event, for example, an EMS name; may be the same as sourceName", - "type": "string" - }, - "sequence": { - "description": "ordering of events communicated by an event source instance or 0 if not needed", - "type": "integer" - }, - "sourceId": { - "description": "UUID identifying the entity experiencing the event issue; must be populated by the ATT enrichment process", - "type": "string" - }, - "sourceName": { - "description": "name of the entity experiencing the event issue", - "type": "string" - }, - "startEpochMicrosec": { - "description": "the earliest unix time aka epoch time associated with the event from any component--as microseconds elapsed since 1 Jan 1970 not including leap seconds", - "type": "number" - }, - "timeZoneOffset": { - "description": "UTC offset for the local time zone of the device as UTC+/-hh.mm", - "type": "string" - }, - "version": { - "description": "version of the event header", - "type": "string", - "enum": [ "4.0.1" ] - }, - "vesEventListenerVersion": { - "description": "version of the VES Event Listener API", - "type": "string", - "enum": [ "7.0.1" ] - } - }, - "additionalProperties": false, - "required": [ "domain", "eventId", "eventName", "lastEpochMicrosec", - "priority", "reportingEntityName", "sequence", "sourceName", - "startEpochMicrosec", "version", "vesEventListenerVersion" ] - }, - "counter": { - "description": "performance counter", - "type": "object", - "properties": { - "criticality": { "type": "string", "enum": [ "CRIT", "MAJ" ] }, - "hashMap": { "$ref": "#/definitions/hashMap" }, - "thresholdCrossed": { "type": "string" } - }, - "additionalProperties": false, - "required": [ "criticality", "hashMap", "thresholdCrossed" ] - }, - "cpuUsage": { - "description": "usage of an identified CPU", - "type": "object", - "properties": { - "cpuCapacityContention": { - "description": "the amount of time the CPU cannot run due to contention, in milliseconds over the measurementInterval", - "type": "number" - }, - "cpuDemandAvg": { - "description": "the total CPU time that the NF/NFC/VM could use if there was no contention, in milliseconds over the measurementInterval", - "type": "number" - }, - "cpuDemandMhz": { - "description": "CPU demand in megahertz", - "type": "number" - }, - "cpuDemandPct": { - "description": "CPU demand as a percentage of the provisioned capacity", - "type": "number" - }, - "cpuIdentifier": { - "description": "cpu identifer", - "type": "string" - }, - "cpuIdle": { - "description": "percentage of CPU time spent in the idle task", - "type": "number" - }, - "cpuLatencyAvg": { - "description": "percentage of time the VM is unable to run because it is contending for access to the physical CPUs", - "type": "number" - }, - "cpuOverheadAvg": { - "description": "the overhead demand above available allocations and reservations, in milliseconds over the measurementInterval", - "type": "number" - }, - "cpuSwapWaitTime": { - "description": "swap wait time. in milliseconds over the measurementInterval", - "type": "number" - }, - "cpuUsageInterrupt": { - "description": "percentage of time spent servicing interrupts", - "type": "number" - }, - "cpuUsageNice": { - "description": "percentage of time spent running user space processes that have been niced", - "type": "number" - }, - "cpuUsageSoftIrq": { - "description": "percentage of time spent handling soft irq interrupts", - "type": "number" - }, - "cpuUsageSteal": { - "description": "percentage of time spent in involuntary wait which is neither user, system or idle time and is effectively time that went missing", - "type": "number" - }, - "cpuUsageSystem": { - "description": "percentage of time spent on system tasks running the kernel", - "type": "number" - }, - "cpuUsageUser": { - "description": "percentage of time spent running un-niced user space processes", - "type": "number" - }, - "cpuWait": { - "description": "percentage of CPU time spent waiting for I/O operations to complete", - "type": "number" - }, - "percentUsage": { - "description": "aggregate cpu usage of the virtual machine on which the xNFC reporting the event is running", - "type": "number" - } - }, - "additionalProperties": false, - "required": [ "cpuIdentifier", "percentUsage" ] - }, - "diskUsage": { - "description": "usage of an identified disk", - "type": "object", - "properties": { - "diskBusResets": { - "description": "number of bus resets over the measurementInterval", - "type": "number" - }, - "diskCommandsAborted": { - "description": "number of disk commands aborted over the measurementInterval", - "type": "number" - }, - "diskCommandsAvg": { - "description": "average number of commands per second over the measurementInterval", - "type": "number" - }, - "diskFlushRequests": { - "description": "total flush requests of the disk cache over the measurementInterval", - "type": "number" - }, - "diskFlushTime": { - "description": "milliseconds spent on disk cache flushing over the measurementInterval", - "type": "number" - }, - "diskIdentifier": { - "description": "disk identifier", - "type": "string" - }, - "diskIoTimeAvg": { - "description": "milliseconds spent doing input/output operations over 1 sec; treat this metric as a device load percentage where 1000ms matches 100% load; provide the average over the measurement interval", - "type": "number" - }, - "diskIoTimeLast": { - "description": "milliseconds spent doing input/output operations over 1 sec; treat this metric as a device load percentage where 1000ms matches 100% load; provide the last value measurement within the measurement interval", - "type": "number" - }, - "diskIoTimeMax": { - "description": "milliseconds spent doing input/output operations over 1 sec; treat this metric as a device load percentage where 1000ms matches 100% load; provide the maximum value measurement within the measurement interval", - "type": "number" - }, - "diskIoTimeMin": { - "description": "milliseconds spent doing input/output operations over 1 sec; treat this metric as a device load percentage where 1000ms matches 100% load; provide the minimum value measurement within the measurement interval", - "type": "number" - }, - "diskMergedReadAvg": { - "description": "number of logical read operations that were merged into physical read operations, e.g., two logical reads were served by one physical disk access; provide the average measurement within the measurement interval", - "type": "number" - }, - "diskMergedReadLast": { - "description": "number of logical read operations that were merged into physical read operations, e.g., two logical reads were served by one physical disk access; provide the last value measurement within the measurement interval", - "type": "number" - }, - "diskMergedReadMax": { - "description": "number of logical read operations that were merged into physical read operations, e.g., two logical reads were served by one physical disk access; provide the maximum value measurement within the measurement interval", - "type": "number" - }, - "diskMergedReadMin": { - "description": "number of logical read operations that were merged into physical read operations, e.g., two logical reads were served by one physical disk access; provide the minimum value measurement within the measurement interval", - "type": "number" - }, - "diskMergedWriteAvg": { - "description": "number of logical write operations that were merged into physical write operations, e.g., two logical writes were served by one physical disk access; provide the average measurement within the measurement interval", - "type": "number" - }, - "diskMergedWriteLast": { - "description": "number of logical write operations that were merged into physical write operations, e.g., two logical writes were served by one physical disk access; provide the last value measurement within the measurement interval", - "type": "number" - }, - "diskMergedWriteMax": { - "description": "number of logical write operations that were merged into physical write operations, e.g., two logical writes were served by one physical disk access; provide the maximum value measurement within the measurement interval", - "type": "number" - }, - "diskMergedWriteMin": { - "description": "number of logical write operations that were merged into physical write operations, e.g., two logical writes were served by one physical disk access; provide the minimum value measurement within the measurement interval", - "type": "number" - }, - "diskOctetsReadAvg": { - "description": "number of octets per second read from a disk or partition; provide the average measurement within the measurement interval", - "type": "number" - }, - "diskOctetsReadLast": { - "description": "number of octets per second read from a disk or partition; provide the last measurement within the measurement interval", - "type": "number" - }, - "diskOctetsReadMax": { - "description": "number of octets per second read from a disk or partition; provide the maximum measurement within the measurement interval", - "type": "number" - }, - "diskOctetsReadMin": { - "description": "number of octets per second read from a disk or partition; provide the minimum measurement within the measurement interval", - "type": "number" - }, - "diskOctetsWriteAvg": { - "description": "number of octets per second written to a disk or partition; provide the average measurement within the measurement interval", - "type": "number" - }, - "diskOctetsWriteLast": { - "description": "number of octets per second written to a disk or partition; provide the last measurement within the measurement interval", - "type": "number" - }, - "diskOctetsWriteMax": { - "description": "number of octets per second written to a disk or partition; provide the maximum measurement within the measurement interval", - "type": "number" - }, - "diskOctetsWriteMin": { - "description": "number of octets per second written to a disk or partition; provide the minimum measurement within the measurement interval", - "type": "number" - }, - "diskOpsReadAvg": { - "description": "number of read operations per second issued to the disk; provide the average measurement within the measurement interval", - "type": "number" - }, - "diskOpsReadLast": { - "description": "number of read operations per second issued to the disk; provide the last measurement within the measurement interval", - "type": "number" - }, - "diskOpsReadMax": { - "description": "number of read operations per second issued to the disk; provide the maximum measurement within the measurement interval", - "type": "number" - }, - "diskOpsReadMin": { - "description": "number of read operations per second issued to the disk; provide the minimum measurement within the measurement interval", - "type": "number" - }, - "diskOpsWriteAvg": { - "description": "number of write operations per second issued to the disk; provide the average measurement within the measurement interval", - "type": "number" - }, - "diskOpsWriteLast": { - "description": "number of write operations per second issued to the disk; provide the last measurement within the measurement interval", - "type": "number" - }, - "diskOpsWriteMax": { - "description": "number of write operations per second issued to the disk; provide the maximum measurement within the measurement interval", - "type": "number" - }, - "diskOpsWriteMin": { - "description": "number of write operations per second issued to the disk; provide the minimum measurement within the measurement interval", - "type": "number" - }, - "diskPendingOperationsAvg": { - "description": "queue size of pending I/O operations per second; provide the average measurement within the measurement interval", - "type": "number" - }, - "diskPendingOperationsLast": { - "description": "queue size of pending I/O operations per second; provide the last measurement within the measurement interval", - "type": "number" - }, - "diskPendingOperationsMax": { - "description": "queue size of pending I/O operations per second; provide the maximum measurement within the measurement interval", - "type": "number" - }, - "diskPendingOperationsMin": { - "description": "queue size of pending I/O operations per second; provide the minimum measurement within the measurement interval", - "type": "number" - }, - "diskReadCommandsAvg": { - "description": "average number of read commands issued per second to the disk over the measurementInterval", - "type": "number" - }, - "diskTime": { - "description": "nanoseconds spent on disk cache reads/writes within the measurement interval", - "type": "number" - }, - "diskTimeReadAvg": { - "description": "milliseconds a read operation took to complete; provide the average measurement within the measurement interval", - "type": "number" - }, - "diskTimeReadLast": { - "description": "milliseconds a read operation took to complete; provide the last measurement within the measurement interval", - "type": "number" - }, - "diskTimeReadMax": { - "description": "milliseconds a read operation took to complete; provide the maximum measurement within the measurement interval", - "type": "number" - }, - "diskTimeReadMin": { - "description": "milliseconds a read operation took to complete; provide the minimum measurement within the measurement interval", - "type": "number" - }, - "diskTimeWriteAvg": { - "description": "milliseconds a write operation took to complete; provide the average measurement within the measurement interval", - "type": "number" - }, - "diskTimeWriteLast": { - "description": "milliseconds a write operation took to complete; provide the last measurement within the measurement interval", - "type": "number" - }, - "diskTimeWriteMax": { - "description": "milliseconds a write operation took to complete; provide the maximum measurement within the measurement interval", - "type": "number" - }, - "diskTimeWriteMin": { - "description": "milliseconds a write operation took to complete; provide the minimum measurement within the measurement interval", - "type": "number" - }, - "diskTotalReadLatencyAvg": { - "description": "average read time from the perspective of a Guest OS: sum of the Kernel Read Latency and Physical Device Read Latency in milliseconds over the measurement interval", - "type": "number" - }, - "diskTotalWriteLatencyAvg": { - "description": "average write time from the perspective of a Guest OS: sum of the Kernel Write Latency and Physical Device Write Latency in milliseconds over the measurement interval", - "type": "number" - }, - "diskWeightedIoTimeAvg": { - "description": "measure in ms over 1 sec of both I/O completion time and the backlog that may be accumulating; value is the average within the collection interval", - "type": "number" - }, - "diskWeightedIoTimeLast": { - "description": "measure in ms over 1 sec of both I/O completion time and the backlog that may be accumulating; value is the last within the collection interval", - "type": "number" - }, - "diskWeightedIoTimeMax": { - "description": "measure in ms over 1 sec of both I/O completion time and the backlog that may be accumulating; value is the maximum within the collection interval", - "type": "number" - }, - "diskWeightedIoTimeMin": { - "description": "measure in ms over 1 sec of both I/O completion time and the backlog that may be accumulating; value is the minimum within the collection interval", - "type": "number" - }, - "diskWriteCommandsAvg": { - "description": "average number of write commands issued per second to the disk over the measurementInterval", - "type": "number" - } - }, - "additionalProperties": false, - "required": [ "diskIdentifier" ] - }, - "endOfCallVqmSummaries": { - "description": "provides end of call voice quality metrics", - "type": "object", - "properties": { - "adjacencyName": { - "description": " adjacency name", - "type": "string" - }, - "endpointAverageJitter": { - "description": "endpoint average jitter", - "type": "number" - }, - "endpointDescription": { - "description": "either Caller or Callee", - "type": "string", - "enum": ["Caller", "Callee"] - }, - "endpointMaxJitter": { - "description": "endpoint maximum jitter", - "type": "number" - }, - "endpointRtpOctetsDiscarded": { - "description": "", - "type": "number" - }, - "endpointRtpOctetsLost": { - "description": "endpoint RTP octets lost", - "type": "number" - }, - "endpointRtpOctetsReceived": { - "description": "", - "type": "number" - }, - "endpointRtpOctetsSent": { - "description": "", - "type": "number" - }, - "endpointRtpPacketsDiscarded": { - "description": "", - "type": "number" - }, - "endpointRtpPacketsLost": { - "description": "endpoint RTP packets lost", - "type": "number" - }, - "endpointRtpPacketsReceived": { - "description": "", - "type": "number" - }, - "endpointRtpPacketsSent": { - "description": "", - "type": "number" - }, - "localAverageJitter": { - "description": "Local average jitter", - "type": "number" - }, - "localAverageJitterBufferDelay": { - "description": "Local average jitter delay", - "type": "number" - }, - "localMaxJitter": { - "description": "Local maximum jitter", - "type": "number" - }, - "localMaxJitterBufferDelay": { - "description": "Local maximum jitter delay", - "type": "number" - }, - "localRtpOctetsDiscarded": { - "description": "", - "type": "number" - }, - "localRtpOctetsLost": { - "description": "Local RTP octets lost", - "type": "number" - }, - "localRtpOctetsReceived": { - "description": "", - "type": "number" - }, - "localRtpOctetsSent": { - "description": "", - "type": "number" - }, - "localRtpPacketsDiscarded": { - "description": "", - "type": "number" - }, - "localRtpPacketsLost": { - "description": "Local RTP packets lost", - "type": "number" - }, - "localRtpPacketsReceived": { - "description": "", - "type": "number" - }, - "localRtpPacketsSent": { - "description": "", - "type": "number" - }, - "mosCqe": { - "description": "1-5 1dp", - "type": "number" - }, - "oneWayDelay": { - "description": "one-way path delay in milliseconds", - "type": "number" - }, - "packetLossPercent": { - "description" : "Calculated percentage packet loss based on Endpoint RTP packets lost (as reported in RTCP) and Local RTP packets sent. Direction is based on Endpoint description (Caller, Callee). Decimal (2 dp)", - "type": "number" - }, - "rFactor": { - "description": "0-100", - "type": "number" - }, - "roundTripDelay": { - "description": "millisecs", - "type": "number" - } - }, - "additionalProperties": false, - "required": [ "adjacencyName", "endpointDescription" ] - }, - "event": { - "description": "the root level of the common event format", - "type": "object", - "properties": { - "commonEventHeader": { "$ref": "#/definitions/commonEventHeader" }, - "faultFields": { "$ref": "#/definitions/faultFields" }, - "heartbeatFields": { "$ref": "#/definitions/heartbeatFields" }, - "measurementFields": { "$ref": "#/definitions/measurementFields" }, - "mobileFlowFields": { "$ref": "#/definitions/mobileFlowFields" }, - "notificationFields": { "$ref": "#/definitions/notificationFields" }, - "otherFields": { "$ref": "#/definitions/otherFields" }, - "pnfRegistrationFields": { "$ref": "#/definitions/pnfRegistrationFields" }, - "sipSignalingFields": { "$ref": "#/definitions/sipSignalingFields" }, - "stateChangeFields": { "$ref": "#/definitions/stateChangeFields" }, - "syslogFields": { "$ref": "#/definitions/syslogFields" }, - "thresholdCrossingAlertFields": { "$ref": "#/definitions/thresholdCrossingAlertFields" }, - "voiceQualityFields": { "$ref": "#/definitions/voiceQualityFields" } - }, - "additionalProperties": false, - "required": [ "commonEventHeader" ] - }, - "eventList": { - "description": "array of events", - "type": "array", - "items": { - "$ref": "#/definitions/event" - } - }, - "faultFields": { - "description": "fields specific to fault events", - "type": "object", - "properties": { - "alarmAdditionalInformation": { "$ref": "#/definitions/hashMap" }, - "alarmCondition": { - "description": "alarm condition reported by the device", - "type": "string" - }, - "alarmInterfaceA": { - "description": "card, port, channel or interface name of the device generating the alarm", - "type": "string" - }, - "eventCategory": { - "description": "Event category, for example: license, link, routing, security, signaling", - "type": "string" - }, - "eventSeverity": { - "description": "event severity", - "type": "string", - "enum": [ - "CRITICAL", - "MAJOR", - "MINOR", - "WARNING", - "NORMAL" - ] - }, - "eventSourceType": { - "description": "type of event source; examples: card, host, other, port, portThreshold, router, slotThreshold, switch, virtualMachine, virtualNetworkFunction", - "type": "string" - }, - "faultFieldsVersion": { - "description": "version of the faultFields block", - "type": "string", - "enum": [ "4.0" ] - }, - "specificProblem": { - "description": "short description of the alarm or problem", - "type": "string" - }, - "vfStatus": { - "description": "virtual function status enumeration", - "type": "string", - "enum": [ - "Active", - "Idle", - "Preparing to terminate", - "Ready to terminate", - "Requesting termination" - ] - } - }, - "additionalProperties": false, - "required": [ "alarmCondition", "eventSeverity", "eventSourceType", - "faultFieldsVersion", "specificProblem", "vfStatus" ] - }, - "filesystemUsage": { - "description": "disk usage of an identified virtual machine in gigabytes and/or gigabytes per second", - "type": "object", - "properties": { - "blockConfigured": { "type": "number" }, - "blockIops": { "type": "number" }, - "blockUsed": { "type": "number" }, - "ephemeralConfigured": { "type": "number" }, - "ephemeralIops": { "type": "number" }, - "ephemeralUsed": { "type": "number" }, - "filesystemName": { "type": "string" } - }, - "additionalProperties": false, - "required": [ "blockConfigured", "blockIops", "blockUsed", "ephemeralConfigured", - "ephemeralIops", "ephemeralUsed", "filesystemName" ] - }, - "gtpPerFlowMetrics": { - "description": "Mobility GTP Protocol per flow metrics", - "type": "object", - "properties": { - "avgBitErrorRate": { - "description": "average bit error rate", - "type": "number" - }, - "avgPacketDelayVariation": { - "description": "Average packet delay variation or jitter in milliseconds for received packets: Average difference between the packet timestamp and time received for all pairs of consecutive packets", - "type": "number" - }, - "avgPacketLatency": { - "description": "average delivery latency", - "type": "number" - }, - "avgReceiveThroughput": { - "description": "average receive throughput", - "type": "number" - }, - "avgTransmitThroughput": { - "description": "average transmit throughput", - "type": "number" - }, - "durConnectionFailedStatus": { - "description": "duration of failed state in milliseconds, computed as the cumulative time between a failed echo request and the next following successful error request, over this reporting interval", - "type": "number" - }, - "durTunnelFailedStatus": { - "description": "Duration of errored state, computed as the cumulative time between a tunnel error indicator and the next following non-errored indicator, over this reporting interval", - "type": "number" - }, - "flowActivatedBy": { - "description": "Endpoint activating the flow", - "type": "string" - }, - "flowActivationEpoch": { - "description": "Time the connection is activated in the flow (connection) being reported on, or transmission time of the first packet if activation time is not available", - "type": "number" - }, - "flowActivationMicrosec": { - "description": "Integer microseconds for the start of the flow connection", - "type": "number" - }, - "flowActivationTime": { - "description": "time the connection is activated in the flow being reported on, or transmission time of the first packet if activation time is not available; with RFC 2822 compliant format: Sat, 13 Mar 2010 11:29:05 -0800", - "type": "string" - }, - "flowDeactivatedBy": { - "description": "Endpoint deactivating the flow", - "type": "string" - }, - "flowDeactivationEpoch": { - "description": "Time for the start of the flow connection, in integer UTC epoch time aka UNIX time", - "type": "number" - }, - "flowDeactivationMicrosec": { - "description": "Integer microseconds for the start of the flow connection", - "type": "number" - }, - "flowDeactivationTime": { - "description": "Transmission time of the first packet in the flow connection being reported on; with RFC 2822 compliant format: Sat, 13 Mar 2010 11:29:05 -0800", - "type": "string" - }, - "flowStatus": { - "description": "connection status at reporting time as a working / inactive / failed indicator value", - "type": "string" - }, - "gtpConnectionStatus": { - "description": "Current connection state at reporting time", - "type": "string" - }, - "gtpTunnelStatus": { - "description": "Current tunnel state at reporting time", - "type": "string" - }, - "ipTosCountList": { "$ref": "#/definitions/hashMap" }, - "ipTosList": { - "description": "Array of unique IP Type-of-Service values observed in the flow where values range from '0' to '255'", - "type": "array", - "items": { - "type": "string" - } - }, - "largePacketRtt": { - "description": "large packet round trip time", - "type": "number" - }, - "largePacketThreshold": { - "description": "large packet threshold being applied", - "type": "number" - }, - "maxPacketDelayVariation": { - "description": "Maximum packet delay variation or jitter in milliseconds for received packets: Maximum of the difference between the packet timestamp and time received for all pairs of consecutive packets", - "type": "number" - }, - "maxReceiveBitRate": { - "description": "maximum receive bit rate", - "type": "number" - }, - "maxTransmitBitRate": { - "description": "maximum transmit bit rate", - "type": "number" - }, - "mobileQciCosCountList": { "$ref": "#/definitions/hashMap" }, - "mobileQciCosList": { - "description": "Array of unique LTE QCI or UMTS class-of-service values observed in the flow", - "type": "array", - "items": { - "type": "string" - } - }, - "numActivationFailures": { - "description": "Number of failed activation requests, as observed by the reporting node", - "type": "number" - }, - "numBitErrors": { - "description": "number of errored bits", - "type": "number" - }, - "numBytesReceived": { - "description": "number of bytes received, including retransmissions", - "type": "number" - }, - "numBytesTransmitted": { - "description": "number of bytes transmitted, including retransmissions", - "type": "number" - }, - "numDroppedPackets": { - "description": "number of received packets dropped due to errors per virtual interface", - "type": "number" - }, - "numGtpEchoFailures": { - "description": "Number of Echo request path failures where failed paths are defined in 3GPP TS 29.281 sec 7.2.1 and 3GPP TS 29.060 sec. 11.2", - "type": "number" - }, - "numGtpTunnelErrors": { - "description": "Number of tunnel error indications where errors are defined in 3GPP TS 29.281 sec 7.3.1 and 3GPP TS 29.060 sec. 11.1", - "type": "number" - }, - "numHttpErrors": { - "description": "Http error count", - "type": "number" - }, - "numL7BytesReceived": { - "description": "number of tunneled layer 7 bytes received, including retransmissions", - "type": "number" - }, - "numL7BytesTransmitted": { - "description": "number of tunneled layer 7 bytes transmitted, excluding retransmissions", - "type": "number" - }, - "numLostPackets": { - "description": "number of lost packets", - "type": "number" - }, - "numOutOfOrderPackets": { - "description": "number of out-of-order packets", - "type": "number" - }, - "numPacketErrors": { - "description": "number of errored packets", - "type": "number" - }, - "numPacketsReceivedExclRetrans": { - "description": "number of packets received, excluding retransmission", - "type": "number" - }, - "numPacketsReceivedInclRetrans": { - "description": "number of packets received, including retransmission", - "type": "number" - }, - "numPacketsTransmittedInclRetrans": { - "description": "number of packets transmitted, including retransmissions", - "type": "number" - }, - "numRetries": { - "description": "number of packet retries", - "type": "number" - }, - "numTimeouts": { - "description": "number of packet timeouts", - "type": "number" - }, - "numTunneledL7BytesReceived": { - "description": "number of tunneled layer 7 bytes received, excluding retransmissions", - "type": "number" - }, - "roundTripTime": { - "description": "round trip time", - "type": "number" - }, - "tcpFlagCountList": { "$ref": "#/definitions/hashMap" }, - "tcpFlagList": { - "description": "Array of unique TCP Flags observed in the flow", - "type": "array", - "items": { - "type": "string" - } - }, - "timeToFirstByte": { - "description": "Time in milliseconds between the connection activation and first byte received", - "type": "number" - } - }, - "additionalProperties": false, - "required": [ "avgBitErrorRate", "avgPacketDelayVariation", "avgPacketLatency", - "avgReceiveThroughput", "avgTransmitThroughput", - "flowActivationEpoch", "flowActivationMicrosec", - "flowDeactivationEpoch", "flowDeactivationMicrosec", - "flowDeactivationTime", "flowStatus", - "maxPacketDelayVariation", "numActivationFailures", - "numBitErrors", "numBytesReceived", "numBytesTransmitted", - "numDroppedPackets", "numL7BytesReceived", - "numL7BytesTransmitted", "numLostPackets", - "numOutOfOrderPackets", "numPacketErrors", - "numPacketsReceivedExclRetrans", - "numPacketsReceivedInclRetrans", - "numPacketsTransmittedInclRetrans", - "numRetries", "numTimeouts", "numTunneledL7BytesReceived", - "roundTripTime", "timeToFirstByte" - ] - }, - "hashMap": { - "description": "an associative array which is an array of key:value pairs", - "type": "object", - "additionalProperties": { "type": "string" }, - "default": {} - }, - "heartbeatFields": { - "description": "optional field block for fields specific to heartbeat events", - "type": "object", - "properties": { - "additionalFields": { "$ref": "#/definitions/hashMap" }, - "heartbeatFieldsVersion": { - "description": "version of the heartbeatFields block", - "type": "string", - "enum": [ "3.0" ] - }, - "heartbeatInterval": { - "description": "current heartbeat interval in seconds", - "type": "integer" - } - }, - "additionalProperties": false, - "required": [ "heartbeatFieldsVersion", "heartbeatInterval" ] - }, - "hugePages": { - "description": "metrics on system hugepages", - "type": "object", - "properties": { - "bytesFree": { - "description": "number of free hugepages in bytes", - "type": "number" - }, - "bytesUsed": { - "description": "number of used hugepages in bytes", - "type": "number" - }, - "hugePagesIdentifier": { - "description": "hugePages identifier", - "type": "number" - }, - "percentFree": { - "description": "number of free hugepages in percent", - "type": "number" - }, - "percentUsed": { - "description": "number of free hugepages in percent", - "type": "number" - }, - "vmPageNumberFree": { - "description": "number of free vmPages in numbers", - "type": "number" - }, - "vmPageNumberUsed": { - "description": "number of used vmPages in numbers", - "type": "number" - } - }, - "additionalProperties": false, - "required": [ "hugePagesIdentifier" ] - }, - "internalHeaderFields": { - "description": "enrichment fields for internal VES Event Listener service use only, not supplied by event sources", - "type": "object" - }, - "ipmi": { - "description": "intelligent platform management interface metrics", - "type": "object", - "properties": { - "exitAirTemperature": { - "description": "system fan exit air flow temperature in celsius", - "type": "number" - }, - "frontPanelTemperature": { - "description": "front panel temperature in celsius", - "type": "number" - }, - "ioModuleTemperature": { - "description": "io module temperature in celsius", - "type": "number" - }, - "ipmiBaseboardTemperatureArray": { - "description": "array of ipmiBaseboardTemperature objects", - "type": "array", - "items": { - "$ref": "#/definitions/ipmiBaseboardTemperature" - } - }, - "ipmiBaseboardVoltageRegulatorArray": { - "description": "array of ipmiBaseboardVoltageRegulator objects", - "type": "array", - "items": { - "$ref": "#/definitions/ipmiBaseboardVoltageRegulator" - } - }, - "ipmiBatteryArray": { - "description": "array of ipmiBattery objects", - "type": "array", - "items": { - "$ref": "#/definitions/ipmiBattery" - } - }, - "ipmiFanArray": { - "description": "array of ipmiFan objects", - "type": "array", - "items": { - "$ref": "#/definitions/ipmiFan" - } - }, - "ipmiHsbpArray": { - "description": "array of ipmiHsbp objects", - "type": "array", - "items": { - "$ref": "#/definitions/ipmiHsbp" - } - }, - "ipmiGlobalAggregateTemperatureMarginArray": { - "description": "array of ipmiGlobalAggregateTemperatureMargin objects", - "type": "array", - "items": { - "$ref": "#/definitions/ipmiGlobalAggregateTemperatureMargin" - } - }, - "ipmiNicArray": { - "description": "array of ipmiNic objects", - "type": "array", - "items": { - "$ref": "#/definitions/ipmiNic" - } - }, - "ipmiPowerSupplyArray": { - "description": "array of ipmiPowerSupply objects", - "type": "array", - "items": { - "$ref": "#/definitions/ipmiPowerSupply" - } - }, - "ipmiProcessorArray": { - "description": "array of ipmiProcessor objects", - "type": "array", - "items": { - "$ref": "#/definitions/ipmiProcessor" - } - }, - "systemAirflow": { - "description": "airfflow in cubic feet per minute (cfm)", - "type": "number" - } - }, - "additionalProperties": false - }, - "ipmiBaseboardTemperature": { - "description": "intelligent platform management interface (ipmi) baseboard temperature metrics", - "type": "object", - "properties": { - "baseboardTemperatureIdentifier": { - "description": "identifier for the location where the temperature is taken", - "type": "string" - }, - "baseboardTemperature": { - "description": "baseboard temperature in celsius", - "type": "number" - } - }, - "additionalProperties": false, - "required": [ "baseboardTemperatureIdentifier" ] - }, - "ipmiBaseboardVoltageRegulator": { - "description": "intelligent platform management interface (ipmi) baseboard voltage regulator metrics", - "type": "object", - "properties": { - "baseboardVoltageRegulatorIdentifier": { - "description": "identifier for the baseboard voltage regulator", - "type": "string" - }, - "voltageRegulatorTemperature": { - "description": "voltage regulator temperature in celsius", - "type": "number" - } - }, - "additionalProperties": false, - "required": [ "baseboardVoltageRegulatorIdentifier" ] - }, - "ipmiBattery": { - "description": "intelligent platform management interface (ipmi) battery metrics", - "type": "object", - "properties": { - "batteryIdentifier": { - "description": "identifier for the battery", - "type": "string" - }, - "batteryType": { - "description": "type of battery", - "type": "string" - }, - "batteryVoltageLevel": { - "description": "battery voltage level", - "type": "number" - } - }, - "additionalProperties": false, - "required": [ "batteryIdentifier" ] - }, - "ipmiFan": { - "description": "intelligent platform management interface (ipmi) fan metrics", - "type": "object", - "properties": { - "fanIdentifier": { - "description": "identifier for the fan", - "type": "string" - }, - "fanSpeed": { - "description": "fan speed in revolutions per minute (rpm)", - "type": "number" - } - }, - "additionalProperties": false, - "required": [ "fanIdentifier" ] - }, - "ipmiGlobalAggregateTemperatureMargin": { - "description": "intelligent platform management interface (ipmi) global aggregate temperature margin", - "type": "object", - "properties": { - "ipmiGlobalAggregateTemperatureMarginIdentifier": { - "description": "identifier for the ipmi global aggregate temperature margin metrics", - "type": "string" - }, - "globalAggregateTemperatureMargin": { - "description": "the difference between the current global aggregate temperature, in celsius, and the global aggregate throttling thermal trip point", - "type": "number" - } - }, - "additionalProperties": false, - "required": [ "ipmiGlobalAggregateTemperatureMarginIdentifier", "globalAggregateTemperatureMargin" ] - }, - "ipmiHsbp": { - "description": "intelligent platform management interface (ipmi) hot swap backplane power metrics", - "type": "object", - "properties": { - "hsbpIdentifier": { - "description": "identifier for the hot swap backplane power unit", - "type": "string" - }, - "hsbpTemperature": { - "description": "hot swap backplane power temperature in celsius", - "type": "number" - } - }, - "additionalProperties": false, - "required": [ "hsbpIdentifier" ] - }, - "ipmiNic": { - "description": "intelligent platform management interface (ipmi) network interface control card (nic) metrics", - "type": "object", - "properties": { - "nicIdentifier": { - "description": "identifier for the network interface control card", - "type": "string" - }, - "nicTemperature": { - "description": "nic temperature in celsius", - "type": "number" - } - }, - "additionalProperties": false, - "required": [ "nicIdentifier" ] - }, - "ipmiPowerSupply": { - "description": "intelligent platform management interface (ipmi) power supply metrics", - "type": "object", - "properties": { - "powerSupplyIdentifier": { - "description": "identifier for the power supply", - "type": "string" - }, - "powerSupplyInputPower": { - "description": "input power in watts", - "type": "number" - }, - "powerSupplyCurrentOutputPercent": { - "description": "current output voltage as a percentage of the design specified level", - "type": "number" - }, - "powerSupplyTemperature": { - "description": "power supply temperature in celsius", - "type": "number" - } - }, - "additionalProperties": false, - "required": [ "powerSupplyIdentifier" ] - }, - "ipmiProcessor": { - "description": "intelligent platform management interface processor metrics", - "type": "object", - "properties": { - "processorIdentifier": { - "description": "identifier for an ipmi processor", - "type": "string" - }, - "processorThermalControlPercent": { - "description": "io module temperature in celsius", - "type": "number" - }, - "processorDtsThermalMargin": { - "description": "front panel temperature in celsius", - "type": "number" - }, - "processorDimmAggregateThermalMarginArray": { - "description": "array of processorDimmAggregateThermalMargin objects", - "type": "array", - "items": { - "$ref": "#/definitions/processorDimmAggregateThermalMargin" - } - } - }, - "additionalProperties": false, - "required": [ "processorIdentifier" ] - }, - "jsonObject": { - "description": "json object schema, name and other meta-information along with one or more object instances", - "type": "object", - "properties": { - "objectInstances": { - "description": "one or more instances of the jsonObject", - "type": "array", - "items": { - "$ref": "#/definitions/jsonObjectInstance" - } - }, - "objectName": { - "description": "name of the JSON Object", - "type": "string" - }, - "objectSchema": { - "description": "json schema for the object", - "type": "string" - }, - "objectSchemaUrl": { - "description": "Url to the json schema for the object", - "type": "string" - }, - "nfSubscribedObjectName": { - "description": "name of the object associated with the nfSubscriptonId", - "type": "string" - }, - "nfSubscriptionId": { - "description": "identifies an openConfig telemetry subscription on a network function, which configures the network function to send complex object data associated with the jsonObject", - "type": "string" - } - }, - "additionalProperties": false, - "required": [ "objectInstances", "objectName" ] - }, - "jsonObjectInstance": { - "description": "meta-information about an instance of a jsonObject along with the actual object instance", - "type": "object", - "properties": { - "jsonObject": { "$ref": "#/definitions/jsonObject" }, - "objectInstance": { - "description": "an instance conforming to the jsonObject objectSchema", - "type": "object" - }, - "objectInstanceEpochMicrosec": { - "description": "the unix time aka epoch time associated with this objectInstance--as microseconds elapsed since 1 Jan 1970 not including leap seconds", - "type": "number" - }, - "objectKeys": { - "description": "an ordered set of keys that identifies this particular instance of jsonObject", - "type": "array", - "items": { - "$ref": "#/definitions/key" - } - } - }, - "additionalProperties": false - }, - "key": { - "description": "tuple which provides the name of a key along with its value and relative order", - "type": "object", - "properties": { - "keyName": { - "description": "name of the key", - "type": "string" - }, - "keyOrder": { - "description": "relative sequence or order of the key with respect to other keys", - "type": "integer" - }, - "keyValue": { - "description": "value of the key", - "type": "string" - } - }, - "additionalProperties": false, - "required": [ "keyName" ] - }, - "latencyBucketMeasure": { - "description": "number of counts falling within a defined latency bucket", - "type": "object", - "properties": { - "countsInTheBucket": { "type": "number" }, - "highEndOfLatencyBucket": { "type": "number" }, - "lowEndOfLatencyBucket": { "type": "number" } - }, - "additionalProperties": false, - "required": [ "countsInTheBucket" ] - }, - "load": { - "description": "/proc/loadavg cpu utilization and io utilization metrics", - "type": "object", - "properties": { - "longTerm": { - "description": "number of jobs in the run queue (state R, cpu utilization) or waiting for disk I/O (state D, io utilization) averaged over 15 minutes using /proc/loadavg", - "type": "number" - }, - "midTerm": { - "description": "number of jobs in the run queue (state R, cpu utilization) or waiting for disk I/O (state D, io utilization) averaged over 5 minutes using /proc/loadavg", - "type": "number" - }, - "shortTerm": { - "description": "number of jobs in the run queue (state R, cpu utilization) or waiting for disk I/O (state D, io utilization) averaged over 1 minute using /proc/loadavg", - "type": "number" - } - }, - "additionalProperties": false - }, - "machineCheckException": { - "description": "metrics on vm machine check exceptions", - "type": "object", - "properties": { - "correctedMemoryErrors": { - "description": "total hardware errors that were corrected by the hardware (e.g. data corruption corrected via  ECC) over the measurementInterval", - "type": "number" - }, - "correctedMemoryErrorsIn1Hr": { - "description": "total hardware errors that were corrected by the hardware over the last one hour", - "type": "number" - }, - "uncorrectedMemoryErrors": { - "description": "total uncorrected hardware errors that were detected by the hardware (e.g., causing data corruption) over the measurementInterval", - "type": "number" - }, - "uncorrectedMemoryErrorsIn1Hr": { - "description": "total uncorrected hardware errors that were detected by the hardware over the last one hour", - "type": "number" - }, - "vmIdentifier": { - "description": "virtual machine identifier associated with the machine check exception", - "type": "string" - } - }, - "additionalProperties": false, - "required": [ "vmIdentifier" ] - }, - "measurementFields": { - "description": "measurement fields", - "type": "object", - "properties": { - "additionalFields": { "$ref": "#/definitions/hashMap" }, - "additionalMeasurements": {"$ref": "#/definitions/arrayOfNamedHashMap"}, - "additionalObjects": {"$ref": "#/definitions/arrayOfJsonObject"}, - "codecUsageArray": { - "description": "array of codecs in use", - "type": "array", - "items": { - "$ref": "#/definitions/codecsInUse" - } - }, - "concurrentSessions": { - "description": "peak concurrent sessions for the VM or xNF over the measurementInterval", - "type": "integer" - }, - "configuredEntities": { - "description": "over the measurementInterval, peak total number of: users, subscribers, devices, adjacencies, etc., for the VM, or subscribers, devices, etc., for the xNF", - "type": "integer" - }, - "cpuUsageArray": { - "description": "usage of an array of CPUs", - "type": "array", - "items": { - "$ref": "#/definitions/cpuUsage" - } - }, - "diskUsageArray": { - "description": "usage of an array of disks", - "type": "array", - "items": { - "$ref": "#/definitions/diskUsage" - } - }, - "featureUsageArray": { "$ref": "#/definitions/hashMap" }, - "filesystemUsageArray": { - "description": "filesystem usage of the VM on which the xNFC reporting the event is running", - "type": "array", - "items": { - "$ref": "#/definitions/filesystemUsage" - } - }, - "hugePagesArray": { - "description": "array of metrics on hugepPages", - "type": "array", - "items": { - "$ref": "#/definitions/hugePages" - } - }, - "ipmi": { "$ref": "#/definitions/ipmi" }, - "latencyDistribution": { - "description": "array of integers representing counts of requests whose latency in milliseconds falls within per-xNF configured ranges", - "type": "array", - "items": { - "$ref": "#/definitions/latencyBucketMeasure" - } - }, - "loadArray": { - "description": "array of system load metrics", - "type": "array", - "items": { - "$ref": "#/definitions/load" - } - }, - "machineCheckExceptionArray": { - "description": "array of machine check exceptions", - "type": "array", - "items": { - "$ref": "#/definitions/machineCheckException" - } - }, - "meanRequestLatency": { - "description": "mean seconds required to respond to each request for the VM on which the xNFC reporting the event is running", - "type": "number" - }, - "measurementInterval": { - "description": "interval over which measurements are being reported in seconds", - "type": "number" - }, - "measurementFieldsVersion": { - "description": "version of the measurementFields block", - "type": "string", - "enum": [ "4.0" ] - }, - "memoryUsageArray": { - "description": "memory usage of an array of VMs", - "type": "array", - "items": { - "$ref": "#/definitions/memoryUsage" - } - }, - "numberOfMediaPortsInUse": { - "description": "number of media ports in use", - "type": "integer" - }, - "requestRate": { - "description": "peak rate of service requests per second to the xNF over the measurementInterval", - "type": "number" - }, - "nfcScalingMetric": { - "description": "represents busy-ness of the network function from 0 to 100 as reported by the xNFC", - "type": "integer" - }, - "nicPerformanceArray": { - "description": "usage of an array of network interface cards", - "type": "array", - "items": { - "$ref": "#/definitions/nicPerformance" - } - }, - "processStatsArray": { - "description": "array of metrics on system processes", - "type": "array", - "items": { - "$ref": "#/definitions/processStats" - } - } - }, - "additionalProperties": false, - "required": [ "measurementInterval", "measurementFieldsVersion" ] - }, - "memoryUsage": { - "description": "memory usage of an identified virtual machine", - "type": "object", - "properties": { - "memoryBuffered": { - "description": "kibibytes of temporary storage for raw disk blocks", - "type": "number" - }, - "memoryCached": { - "description": "kibibytes of memory used for cache", - "type": "number" - }, - "memoryConfigured": { - "description": "kibibytes of memory configured in the virtual machine on which the xNFC reporting the event is running", - "type": "number" - }, - "memoryDemand": { - "description": "host demand in kibibytes", - "type": "number" - }, - "memoryFree": { - "description": "kibibytes of physical RAM left unused by the system", - "type": "number" - }, - "memoryLatencyAvg": { - "description": "Percentage of time the VM is waiting to access swapped or compressed memory", - "type": "number" - }, - "memorySharedAvg": { - "description": "shared memory in kilobytes", - "type": "number" - }, - "memorySlabRecl": { - "description": "the part of the slab that can be reclaimed such as caches measured in kibibytes", - "type": "number" - }, - "memorySlabUnrecl": { - "description": "the part of the slab that cannot be reclaimed even when lacking memory measured in kibibytes", - "type": "number" - }, - "memorySwapInAvg": { - "description": "Amount of memory swapped-in from host cache in kibibytes", - "type": "number" - }, - "memorySwapInRateAvg": { - "description": "rate at which memory is swapped from disk into active memory during the interval in kilobytes per second", - "type": "number" - }, - "memorySwapOutAvg": { - "description": "Amount of memory swapped-out to host cache in kibibytes", - "type": "number" - }, - "memorySwapOutRateAvg": { - "description": "rate at which memory is being swapped from active memory to disk during the current interval in kilobytes per second", - "type": "number" - }, - "memorySwapUsedAvg": { - "description": "space used for caching swapped pages in the host cache in kibibytes", - "type": "number" - }, - "memoryUsed": { - "description": "total memory minus the sum of free, buffered, cached and slab memory measured in kibibytes", - "type": "number" - }, - "percentMemoryUsage": { - "description": "Percentage of memory usage; value = (memoryUsed / (memoryUsed + memoryFree) x 100 if denomintor is nonzero, or 0, if otherwise", - "type": "number" - }, - "vmIdentifier": { - "description": "virtual machine identifier associated with the memory metrics", - "type": "string" - } - }, - "additionalProperties": false, - "required": [ "memoryFree", "memoryUsed", "vmIdentifier" ] - }, - "mobileFlowFields": { - "description": "mobileFlow fields", - "type": "object", - "properties": { - "additionalFields": { "$ref": "#/definitions/hashMap" }, - "applicationType": { - "description": "Application type inferred", - "type": "string" - }, - "appProtocolType": { - "description": "application protocol", - "type": "string" - }, - "appProtocolVersion": { - "description": "application protocol version", - "type": "string" - }, - "cid": { - "description": "cell id", - "type": "string" - }, - "connectionType": { - "description": "Abbreviation referencing a 3GPP reference point e.g., S1-U, S11, etc", - "type": "string" - }, - "ecgi": { - "description": "Evolved Cell Global Id", - "type": "string" - }, - "flowDirection": { - "description": "Flow direction, indicating if the reporting node is the source of the flow or destination for the flow", - "type": "string" - }, - "gtpPerFlowMetrics": { "$ref": "#/definitions/gtpPerFlowMetrics" }, - "gtpProtocolType": { - "description": "GTP protocol", - "type": "string" - }, - "gtpVersion": { - "description": "GTP protocol version", - "type": "string" - }, - "httpHeader": { - "description": "HTTP request header, if the flow connects to a node referenced by HTTP", - "type": "string" - }, - "imei": { - "description": "IMEI for the subscriber UE used in this flow, if the flow connects to a mobile device", - "type": "string" - }, - "imsi": { - "description": "IMSI for the subscriber UE used in this flow, if the flow connects to a mobile device", - "type": "string" - }, - "ipProtocolType": { - "description": "IP protocol type e.g., TCP, UDP, RTP...", - "type": "string" - }, - "ipVersion": { - "description": "IP protocol version e.g., IPv4, IPv6", - "type": "string" - }, - "lac": { - "description": "location area code", - "type": "string" - }, - "mcc": { - "description": "mobile country code", - "type": "string" - }, - "mnc": { - "description": "mobile network code", - "type": "string" - }, - "mobileFlowFieldsVersion": { - "description": "version of the mobileFlowFields block", - "type": "string", - "enum": [ "4.0" ] - }, - "msisdn": { - "description": "MSISDN for the subscriber UE used in this flow, as an integer, if the flow connects to a mobile device", - "type": "string" - }, - "otherEndpointIpAddress": { - "description": "IP address for the other endpoint, as used for the flow being reported on", - "type": "string" - }, - "otherEndpointPort": { - "description": "IP Port for the reporting entity, as used for the flow being reported on", - "type": "integer" - }, - "otherFunctionalRole": { - "description": "Functional role of the other endpoint for the flow being reported on e.g., MME, S-GW, P-GW, PCRF...", - "type": "string" - }, - "rac": { - "description": "routing area code", - "type": "string" - }, - "radioAccessTechnology": { - "description": "Radio Access Technology e.g., 2G, 3G, LTE", - "type": "string" - }, - "reportingEndpointIpAddr": { - "description": "IP address for the reporting entity, as used for the flow being reported on", - "type": "string" - }, - "reportingEndpointPort": { - "description": "IP port for the reporting entity, as used for the flow being reported on", - "type": "integer" - }, - "sac": { - "description": "service area code", - "type": "string" - }, - "samplingAlgorithm": { - "description": "Integer identifier for the sampling algorithm or rule being applied in calculating the flow metrics if metrics are calculated based on a sample of packets, or 0 if no sampling is applied", - "type": "integer" - }, - "tac": { - "description": "transport area code", - "type": "string" - }, - "tunnelId": { - "description": "tunnel identifier", - "type": "string" - }, - "vlanId": { - "description": "VLAN identifier used by this flow", - "type": "string" - } - }, - "additionalProperties": false, - "required": [ "flowDirection", "gtpPerFlowMetrics", "ipProtocolType", "ipVersion", - "mobileFlowFieldsVersion", "otherEndpointIpAddress", "otherEndpointPort", - "reportingEndpointIpAddr", "reportingEndpointPort" ] - }, - "namedHashMap": { - "description": "a hashMap which is associated with and described by a name", - "type": "object", - "properties": { - "name": { "type": "string" }, - "hashMap": { "$ref": "#/definitions/hashMap" } - }, - "additionalProperties": false, - "required": [ "name", "hashMap" ] - }, - "nicPerformance": { - "description": "describes the performance and errors of an identified network interface card", - "type": "object", - "properties": { - "administrativeState": { - "description": "administrative state", - "type": "string", - "enum": [ "inService", "outOfService" ] - }, - "nicIdentifier": { - "description": "nic identification", - "type": "string" - }, - "operationalState": { - "description": "operational state", - "type": "string", - "enum": [ "inService", "outOfService" ] - }, - "receivedBroadcastPacketsAccumulated": { - "description": "Cumulative count of broadcast packets received as read at the end of the measurement interval", - "type": "number" - }, - "receivedBroadcastPacketsDelta": { - "description": "Count of broadcast packets received within the measurement interval", - "type": "number" - }, - "receivedDiscardedPacketsAccumulated": { - "description": "Cumulative count of discarded packets received as read at the end of the measurement interval", - "type": "number" - }, - "receivedDiscardedPacketsDelta": { - "description": "Count of discarded packets received within the measurement interval", - "type": "number" - }, - "receivedErrorPacketsAccumulated": { - "description": "Cumulative count of error packets received as read at the end of the measurement interval", - "type": "number" - }, - "receivedErrorPacketsDelta": { - "description": "Count of error packets received within the measurement interval", - "type": "number" - }, - "receivedMulticastPacketsAccumulated": { - "description": "Cumulative count of multicast packets received as read at the end of the measurement interval", - "type": "number" - }, - "receivedMulticastPacketsDelta": { - "description": "Count of multicast packets received within the measurement interval", - "type": "number" - }, - "receivedOctetsAccumulated": { - "description": "Cumulative count of octets received as read at the end of the measurement interval", - "type": "number" - }, - "receivedOctetsDelta": { - "description": "Count of octets received within the measurement interval", - "type": "number" - }, - "receivedTotalPacketsAccumulated": { - "description": "Cumulative count of all packets received as read at the end of the measurement interval", - "type": "number" - }, - "receivedPercentDiscard": { - "description": "Percentage of discarded packets received; value = (receivedDiscardedPacketsDelta / receivedTotalPacketsDelta) x 100, if denominator is nonzero, or 0, if otherwise", - "type": "number" - }, - "receivedPercentError": { - "description": "Percentage of error packets received; value = (receivedErrorPacketsDelta / receivedTotalPacketsDelta) x 100, if denominator is nonzero, or 0, if otherwise.", - "type": "number" - }, - "receivedTotalPacketsDelta": { - "description": "Count of all packets received within the measurement interval", - "type": "number" - }, - "receivedUnicastPacketsAccumulated": { - "description": "Cumulative count of unicast packets received as read at the end of the measurement interval", - "type": "number" - }, - "receivedUnicastPacketsDelta": { - "description": "Count of unicast packets received within the measurement interval", - "type": "number" - }, - "receivedUtilization": { - "description": "Percentage of utilization received; value = (receivedOctetsDelta / (speed x (lastEpochMicrosec - startEpochMicrosec))) x 100, if denominator is nonzero, or 0, if otherwise", - "type": "number" - }, - "speed": { - "description": "Speed configured in mbps", - "type": "number" - }, - "transmittedBroadcastPacketsAccumulated": { - "description": "Cumulative count of broadcast packets transmitted as read at the end of the measurement interval", - "type": "number" - }, - "transmittedBroadcastPacketsDelta": { - "description": "Count of broadcast packets transmitted within the measurement interval", - "type": "number" - }, - "transmittedDiscardedPacketsAccumulated": { - "description": "Cumulative count of discarded packets transmitted as read at the end of the measurement interval", - "type": "number" - }, - "transmittedDiscardedPacketsDelta": { - "description": "Count of discarded packets transmitted within the measurement interval", - "type": "number" - }, - "transmittedErrorPacketsAccumulated": { - "description": "Cumulative count of error packets transmitted as read at the end of the measurement interval", - "type": "number" - }, - "transmittedErrorPacketsDelta": { - "description": "Count of error packets transmitted within the measurement interval", - "type": "number" - }, - "transmittedMulticastPacketsAccumulated": { - "description": "Cumulative count of multicast packets transmitted as read at the end of the measurement interval", - "type": "number" - }, - "transmittedMulticastPacketsDelta": { - "description": "Count of multicast packets transmitted within the measurement interval", - "type": "number" - }, - "transmittedOctetsAccumulated": { - "description": "Cumulative count of octets transmitted as read at the end of the measurement interval", - "type": "number" - }, - "transmittedOctetsDelta": { - "description": "Count of octets transmitted within the measurement interval", - "type": "number" - }, - "transmittedTotalPacketsAccumulated": { - "description": "Cumulative count of all packets transmitted as read at the end of the measurement interval", - "type": "number" - }, - "transmittedTotalPacketsDelta": { - "description": "Count of all packets transmitted within the measurement interval", - "type": "number" - }, - "transmittedUnicastPacketsAccumulated": { - "description": "Cumulative count of unicast packets transmitted as read at the end of the measurement interval", - "type": "number" - }, - "transmittedUnicastPacketsDelta": { - "description": "Count of unicast packets transmitted within the measurement interval", - "type": "number" - }, - "transmittedPercentDiscard": { - "description": "Percentage of discarded packets transmitted; value = (transmittedDiscardedPacketsDelta / transmittedTotalPacketsDelta) x 100, if denominator is nonzero, or 0, if otherwise", - "type": "number" - }, - "transmittedPercentError": { - "description": "Percentage of error packets received; value = (transmittedErrorPacketsDelta / transmittedTotalPacketsDelta) x 100, if denominator is nonzero, or 0, if otherwise", - "type": "number" - }, - "transmittedUtilization": { - "description": "Percentage of utilization transmitted; value = (transmittedOctetsDelta / (speed x (lastEpochMicrosec - startEpochMicrosec))) x 100, if denominator is nonzero, or 0, if otherwise.", - "type": "number" - }, - "valuesAreSuspect": { - "description": "Indicates whether vNicPerformance values are likely inaccurate due to counter overflow or other condtions", - "type": "string", - "enum": [ "true", "false" ] - } - }, - "additionalProperties": false, - "required": [ "nicIdentifier", "valuesAreSuspect" ] - }, - "notificationFields": { - "description": "notification fields", - "type": "object", - "properties": { - "additionalFields": { "$ref": "#/definitions/hashMap" }, - "arrayOfNamedHashMap": {"$ref": "#/definitions/arrayOfNamedHashMap"}, - "changeContact": { - "description": "identifier for a contact related to the change", - "type": "string" - }, - "changeIdentifier": { - "description": "system or session identifier associated with the change", - "type": "string" - }, - "changeType": { - "description": "describes what has changed for the entity", - "type": "string" - }, - "newState": { - "description": "new state of the entity", - "type": "string" - }, - "oldState": { - "description": "previous state of the entity", - "type": "string" - }, - "notificationFieldsVersion": { - "description": "version of the notificationFields block", - "type": "string", - "enum": [ "2.0" ] - }, - "stateInterface": { - "description": "card or port name of the entity that changed state", - "type": "string" - } - }, - "additionalProperties": false, - "required": [ "changeIdentifier", "changeType", "notificationFieldsVersion" ] - }, - "otherFields": { - "description": "fields for events belonging to the 'other' domain of the commonEventHeader domain enumeration", - "type": "object", - "properties": { - "arrayOfNamedHashMap": {"$ref": "#/definitions/arrayOfNamedHashMap"}, - "hashMap": {"$ref": "#/definitions/hashMap"}, - "jsonObjects": {"$ref": "#/definitions/arrayOfJsonObject"}, - "otherFieldsVersion": { - "description": "version of the otherFields block", - "type": "string", - "enum": [ "3.0" ] - } - }, - "additionalProperties": false, - "required": [ "otherFieldsVersion" ] - }, - "pnfRegistrationFields": { - "description": "hardware device registration fields", - "type": "object", - "properties": { - "additionalFields": { "$ref": "#/definitions/hashMap" }, - "lastServiceDate": { - "description": "TS 32.692 dateOfLastService = date of last service; e.g. 15022017", - "type": "string" - }, - "macAddress": { - "description": "MAC address of OAM interface of the unit", - "type": "string" - }, - "manufactureDate": { - "description": "TS 32.692 dateOfManufacture = manufacture date of the unit; 24032016", - "type": "string" - }, - "modelNumber": { - "description": "TS 32.692 versionNumber = version of the unit from vendor; e.g. AJ02. Maps to AAI equip-model", - "type": "string" - }, - "oamV4IpAddress": { - "description": "IPv4 m-plane IP address to be used by the manager to contact the PNF", - "type": "string" - }, - "oamV6IpAddress": { - "description": "IPv6 m-plane IP address to be used by the manager to contact the PNF", - "type": "string" - }, - "pnfRegistrationFieldsVersion": { - "description": "version of the pnfRegistrationFields block", - "type": "string", - "enum": [ "2.0" ] - }, - "serialNumber": { - "description": "TS 32.692 serialNumber = serial number of the unit; e.g. 6061ZW3", - "type": "string" - }, - "softwareVersion": { - "description": "TS 32.692 swName = active SW running on the unit; e.g. 5gDUv18.05.201", - "type": "string" - }, - "unitFamily": { - "description": "TS 32.692 vendorUnitFamilyType = general type of HW unit; e.g. BBU", - "type": "string" - }, - "unitType": { - "description": "TS 32.692 vendorUnitTypeNumber = vendor name for the unit; e.g. Airscale", - "type": "string" - }, - "vendorName": { - "description": "TS 32.692 vendorName = name of manufacturer; e.g. Nokia. Maps to AAI equip-vendor", - "type": "string" - } - }, - "additionalProperties": false, - "required": [ "pnfRegistrationFieldsVersion" ] - }, - "processorDimmAggregateThermalMargin": { - "description": "intelligent platform management interface (ipmi) processor dual inline memory module aggregate thermal margin metrics", - "type": "object", - "properties": { - "processorDimmAggregateThermalMarginIdentifier": { - "description": "identifier for the aggregate thermal margin metrics from the processor dual inline memory module", - "type": "string" - }, - "thermalMargin": { - "description": "the difference between the DIMM's current temperature, in celsius, and the DIMM's throttling thermal trip point", - "type": "number" - } - }, - "additionalProperties": false, - "required": [ "processorDimmAggregateThermalMarginIdentifier", "thermalMargin" ] - }, - "processStats": { - "description": "metrics on system processes", - "type": "object", - "properties": { - "forkRate": { - "description": "the number of threads created since the last reboot", - "type": "number" - }, - "processIdentifier": { - "description": "processIdentifier", - "type": "string" - }, - "psStateBlocked": { - "description": "the number of processes in a blocked state", - "type": "number" - }, - "psStatePaging": { - "description": "the number of processes in a paging state", - "type": "number" - }, - "psStateRunning": { - "description": "the number of processes in a running state", - "type": "number" - }, - "psStateSleeping": { - "description": "the number of processes in a sleeping state", - "type": "number" - }, - "psStateStopped": { - "description": "the number of processes in a stopped state", - "type": "number" - }, - "psStateZombie": { - "description": "the number of processes in a zombie state", - "type": "number" - } - }, - "additionalProperties": false, - "required": [ "processIdentifier" ] - }, - "requestError": { - "description": "standard request error data structure", - "type": "object", - "properties": { - "messageId": { - "description": "Unique message identifier of the format ABCnnnn where ABC is either SVC for Service Exceptions or POL for Policy Exception", - "type": "string" - }, - "text": { - "description": "Message text, with replacement variables marked with %n, where n is an index into the list of elements, starting at 1", - "type": "string" - }, - "url": { - "description": "Hyperlink to a detailed error resource e.g., an HTML page for browser user agents", - "type": "string" - }, - "variables": { - "description": "List of zero or more strings that represent the contents of the variables used by the message text", - "type": "string" - } - }, - "additionalProperties": false, - "required": [ "messageId", "text" ] - }, - "sipSignalingFields": { - "description": "sip signaling fields", - "type": "object", - "properties": { - "additionalInformation": { "$ref": "#/definitions/hashMap"}, - "compressedSip": { - "description": "the full SIP request/response including headers and bodies", - "type": "string" - }, - "correlator": { - "description": "this is the same for all events on this call", - "type": "string" - }, - "localIpAddress": { - "description": "IP address on xNF", - "type": "string" - }, - "localPort": { - "description": "port on xNF", - "type": "string" - }, - "remoteIpAddress": { - "description": "IP address of peer endpoint", - "type": "string" - }, - "remotePort": { - "description": "port of peer endpoint", - "type": "string" - }, - "sipSignalingFieldsVersion": { - "description": "version of the sipSignalingFields block", - "type": "string", - "enum": [ "3.0" ] - }, - "summarySip": { - "description": "the SIP Method or Response ('INVITE', '200 OK', 'BYE', etc)", - "type": "string" - }, - "vendorNfNameFields": { - "$ref": "#/definitions/vendorNfNameFields" - } - }, - "additionalProperties": false, - "required": [ "correlator", "localIpAddress", "localPort", "remoteIpAddress", - "remotePort", "sipSignalingFieldsVersion", "vendorNfNameFields" ] - }, - "stateChangeFields": { - "description": "stateChange fields", - "type": "object", - "properties": { - "additionalFields": { "$ref": "#/definitions/hashMap" }, - "newState": { - "description": "new state of the entity", - "type": "string", - "enum": [ - "inService", - "maintenance", - "outOfService" - ] - }, - "oldState": { - "description": "previous state of the entity", - "type": "string", - "enum": [ - "inService", - "maintenance", - "outOfService" - ] - }, - "stateChangeFieldsVersion": { - "description": "version of the stateChangeFields block", - "type": "string", - "enum": [ "4.0" ] - }, - "stateInterface": { - "description": "card or port name of the entity that changed state", - "type": "string" - } - }, - "additionalProperties": false, - "required": [ "newState", "oldState", "stateChangeFieldsVersion", "stateInterface" ] - }, - "syslogFields": { - "description": "sysLog fields", - "type": "object", - "properties": { - "additionalFields": { "$ref": "#/definitions/hashMap" }, - "eventSourceHost": { - "description": "hostname of the device", - "type": "string" - }, - "eventSourceType": { - "description": "type of event source; examples: other, router, switch, host, card, port, slotThreshold, portThreshold, virtualMachine, virtualNetworkFunction", - "type": "string" - }, - "syslogFacility": { - "description": "numeric code from 0 to 23 for facility--see table in documentation", - "type": "integer" - }, - "syslogFieldsVersion": { - "description": "version of the syslogFields block", - "type": "string", - "enum": [ "4.0" ] - }, - "syslogMsg": { - "description": "syslog message", - "type": "string" - }, - "syslogMsgHost": { - "description": "hostname parsed from non-VES syslog message", - "type": "string" - }, - "syslogPri": { - "description": "0-192 combined severity and facility", - "type": "integer" - }, - "syslogProc": { - "description": "identifies the application that originated the message", - "type": "string" - }, - "syslogProcId": { - "description": "a change in the value of this field indicates a discontinuity in syslog reporting", - "type": "number" - }, - "syslogSData": { - "description": "syslog structured data consisting of a structured data Id followed by a set of key value pairs", - "type": "string" - }, - "syslogSdId": { - "description": "0-32 char in format name@number for example ourSDID@32473", - "type": "string" - }, - "syslogSev": { - "description": "numerical Code for severity derived from syslogPri as remaider of syslogPri / 8", - "type": "string", - "enum": [ - "Alert", - "Critical", - "Debug", - "Emergency", - "Error", - "Info", - "Notice", - "Warning" - ] - }, - "syslogTag": { - "description": "msgId indicating the type of message such as TCPOUT or TCPIN; NILVALUE should be used when no other value can be provided", - "type": "string" - }, - "syslogTs": { - "description": "timestamp parsed from non-VES syslog message", - "type": "string" - }, - "syslogVer": { - "description": "IANA assigned version of the syslog protocol specification - typically 1", - "type": "number" - } - }, - "additionalProperties": false, - "required": [ "eventSourceType", "syslogFieldsVersion", "syslogMsg", "syslogTag" ] - }, - "thresholdCrossingAlertFields": { - "description": "fields specific to threshold crossing alert events", - "type": "object", - "properties": { - "additionalFields": { "$ref": "#/definitions/hashMap"}, - "additionalParameters": { - "description": "performance counters", - "type": "array", - "items": { - "$ref": "#/definitions/counter" - } - }, - "alertAction": { - "description": "Event action", - "type": "string", - "enum": [ - "CLEAR", - "CONT", - "SET" - ] - }, - "alertDescription": { - "description": "Unique short alert description such as IF-SHUB-ERRDROP", - "type": "string" - }, - "alertType": { - "description": "Event type", - "type": "string", - "enum": [ - "CARD-ANOMALY", - "ELEMENT-ANOMALY", - "INTERFACE-ANOMALY", - "SERVICE-ANOMALY" - ] - }, - "alertValue": { - "description": "Calculated API value (if applicable)", - "type": "string" - }, - "associatedAlertIdList": { - "description": "List of eventIds associated with the event being reported", - "type": "array", - "items": { "type": "string" } - }, - "collectionTimestamp": { - "description": "Time when the performance collector picked up the data; with RFC 2822 compliant format: Sat, 13 Mar 2010 11:29:05 -0800", - "type": "string" - }, - "dataCollector": { - "description": "Specific performance collector instance used", - "type": "string" - }, - "elementType": { - "description": "type of network element - internal ATT field", - "type": "string" - }, - "eventSeverity": { - "description": "event severity or priority", - "type": "string", - "enum": [ - "CRITICAL", - "MAJOR", - "MINOR", - "WARNING", - "NORMAL" - ] - }, - "eventStartTimestamp": { - "description": "Time closest to when the measurement was made; with RFC 2822 compliant format: Sat, 13 Mar 2010 11:29:05 -0800", - "type": "string" - }, - "interfaceName": { - "description": "Physical or logical port or card (if applicable)", - "type": "string" - }, - "networkService": { - "description": "network name - internal ATT field", - "type": "string" - }, - "possibleRootCause": { - "description": "Reserved for future use", - "type": "string" - }, - "thresholdCrossingFieldsVersion": { - "description": "version of the thresholdCrossingAlertFields block", - "type": "string", - "enum": [ "4.0" ] - } - }, - "additionalProperties": false, - "required": [ - "additionalParameters", - "alertAction", - "alertDescription", - "alertType", - "collectionTimestamp", - "eventSeverity", - "eventStartTimestamp", - "thresholdCrossingFieldsVersion" - ] - }, - "vendorNfNameFields": { - "description": "provides vendor, nf and nfModule identifying information", - "type": "object", - "properties": { - "vendorName": { - "description": "network function vendor name", - "type": "string" - }, - "nfModuleName": { - "description": "name of the nfModule generating the event", - "type": "string" - }, - "nfName": { - "description": "name of the network function generating the event", - "type": "string" - } - }, - "additionalProperties": false, - "required": [ "vendorName" ] - }, - "voiceQualityFields": { - "description": "provides statistics related to customer facing voice products", - "type": "object", - "properties": { - "additionalInformation": { "$ref": "#/definitions/hashMap"}, - "calleeSideCodec": { - "description": "callee codec for the call", - "type": "string" - }, - "callerSideCodec": { - "description": "caller codec for the call", - "type": "string" - }, - "correlator": { - "description": "this is the same for all events on this call", - "type": "string" - }, - "endOfCallVqmSummaries": { - "$ref": "#/definitions/endOfCallVqmSummaries" - }, - "phoneNumber": { - "description": "phone number associated with the correlator", - "type": "string" - }, - "midCallRtcp": { - "description": "Base64 encoding of the binary RTCP data excluding Eth/IP/UDP headers", - "type": "string" - }, - "vendorNfNameFields": { - "$ref": "#/definitions/vendorNfNameFields" - }, - "voiceQualityFieldsVersion": { - "description": "version of the voiceQualityFields block", - "type": "string", - "enum": [ "4.0" ] - } - }, - "additionalProperties": false, - "required": [ "calleeSideCodec", "callerSideCodec", "correlator", "midCallRtcp", - "vendorNfNameFields", "voiceQualityFieldsVersion" ] - } - } -} \ No newline at end of file diff --git a/test/mocks/pnfsimulator/netconf/pnf-simulator.data.xml b/test/mocks/pnfsimulator/netconf/pnf-simulator.data.xml deleted file mode 100644 index 9d648bba7..000000000 --- a/test/mocks/pnfsimulator/netconf/pnf-simulator.data.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 42 - 35 - diff --git a/test/mocks/pnfsimulator/netconf/pnf-simulator.yang b/test/mocks/pnfsimulator/netconf/pnf-simulator.yang deleted file mode 100644 index d7fc2f26e..000000000 --- a/test/mocks/pnfsimulator/netconf/pnf-simulator.yang +++ /dev/null @@ -1,9 +0,0 @@ -module pnf-simulator { - namespace "http://nokia.com/pnf-simulator"; - prefix config; - container config { - config true; - leaf itemValue1 {type uint32;} - leaf itemValue2 {type uint32;} - } -} diff --git a/test/mocks/pnfsimulator/netconfsimulator/README.md b/test/mocks/pnfsimulator/netconfsimulator/README.md new file mode 100644 index 000000000..94bcd760f --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/README.md @@ -0,0 +1,276 @@ +# Netconf Simulator +A simulator that is able to receive and print history of CM configurations. + +## Required software +To run the simulator, the following software should be installed: +- JDK 1.8 +- Maven +- docker +- docker-compose + +### API +Simulator exposes both HTTP and native netconf interface. + +### Running simulator +In order to run simulator, invoke *mvn clean install docker:build* to build required images. +Add executable permission to initialize_netopeer.sh (by executing `sudo chmod +x netconf/initialize_netopeer.sh`) +and then invoke *docker-compose up* command. +In case of copying simulator files to another location, keep in mind to copy also *docker-compose.yml* and directories: *config, templates, netopeer-change-saver-native and netconf*. + +#### Restarting +Restarting simulator can be done by first typing *docker-compose restart* in terminal. + +#### Shutting down +The command *docker-compose down* can be used to shut the simulator down. + +## Usage of simulator + +### Netconf TLS support +Embedded netconf server supports connections over TLS on port 6513. Default server and CA certificate have been taken from Netopeer2 repository: https://github.com/CESNET/Netopeer2/tree/master/server/configuration/tls + +Mentioned Github repository contains sample client certificate, which works out of the box. +#### Replacing server certificates +In order to replace TLS certificates with third-party ones, the following naming schema must be followed: +* CA certificate file should be named 'ca.crt' +* Netconf server certificate file should be named 'server_cert.crt' +* Netconf server keyfile file should be named 'server_key.pem' + +Certificates and keys should follow PEM formatting guidelines. +Prepared files should be placed under _tls/_ directory (existing files must be overwritten). +After copying, it is necessary to restart the Netconf Simulator (please refer to [restarting simulator](restarting) guide). + +This is a sample curl command to test client connection (the example assumes that Netconf Simulator runs on 127.0.0.1): +``` +curl -k -v https://127.0.0.1:6513 --cacert ca.crt --key client.key --cert client.crt +``` + + +### Capturing netconf configuration changes + +The netconfsimulator tool will intercept changes in netconf configuration, done by edit-config command (invoked through simulator's edit-configuration endpoint or directly through exposed netconf-compliant interface). The following changes are intercepted: +- creating new item +- moving an item +- modifying an item +- deleting an item + +Each captured change contains fully qualified parameter name (including xpath - namespace and container name) + +#### REST API usage with examples + +Application of native netconf operations on YANG model is covered by REST API layer. +Example invocation of operations with its requests and results are presented below. +For basic edit-config and get config actions, response is in plain XML format, whereas stored data that can be accessed via API is returned in JSON format. + +**Load new YANG model** +http method: POST +``` +URL: http::9000/netconf/model/ +``` +request: file content to be sent as multipart (form data) +``` +module pnf-simulator { + namespace "http://onap.org/pnf-simulator"; + prefix config; + container config { + config true; + leaf itemValue1 {type uint32;} + leaf itemValue2 {type uint32;} + leaf itemValue3 {type uint32;} + leaf-list allow-user { + type string; + ordered-by user; + description "A sample list of user names."; + } + } +} +``` + +**Delete existing YANG model** +http method: DELETE +``` +URL: http::9000/netconf/model/ +``` +request body should be empty. +response: a HTTP 200 code indicating successful operation or 400/500 in case of errors. + +**Get all running configurations** +http method: GET +``` +URL: http::9000/netconf/get +``` +response: plain XML +``` + + 2781 + 3782 + 3333 + + + 2781 + 3782 + 3333 + +``` + +**Get running configuration** +http method: GET +``` +URL: http::9000/netconf/get/'moduleName'/'container' +``` +response: plain XML +``` + + 2781 + 3782 + 3333 + +``` + +**Edit configuration** +To edit configuration XML file must be prepared. No plain request body is used here, +request content must be passed as multipart file (form data) with file name/key='editConfigXml' and file content in XML format + +http method: POST +``` +URL: http::9000/netconf/edit-config +``` +request: file content to be sent as multipart (form data) +``` + + 2781 + 3782 + 3333 + +``` + +response: actual, running configuration after editing config: +``` + + 2781 + 3782 + 3333 +" +``` + +Captured change, that can be obtained from db also via REST API: + +http method: GET +``` +URL: http://:9000/store/less?offset=1 +``` +response: +``` +[{"timestamp": 1542877413979, "configuration": "CREATED: /pnf-simulator:config/itemValue3 = 3333"}] +``` + +Notice: if new value is the same as the old one, the change won’t be intercepted (because there is no state change). This is a limitation of used netconf implementation (Netopeer2). + +**Modify request** +http method: POST +``` +URL: http::9000/netconf/edit-config +``` +file content to be sent as multipart (form data): +``` + + 111 + 222 + +``` + +response: actual, running configuration after editing config: +``` + + 111 + 222 +" +``` + +Captured change: +http method: GET +``` +URL: http://:9000/store/less?offset=2 +``` +``` +[{"timestamp": 1542877413979, "configuration": "MODIFIED: : old value: /pnf-simulator:config/itemValue1 = 2781, new value: /pnf-simulator:config/itemValue1 = 111", + {"timestamp": 1542877413979, "configuration": "MODIFIED: : old value: /pnf-simulator:config/itemValue2 = 3782, new value: /pnf-simulator:config/itemValue2 = 222"}] +``` + +**Move request** (inserting a value into leaf-list which in turn rearranges remaining elements) +http method: POST +``` +URL: http::9000/netconf/edit-config +``` +file content to be sent as multipart (form data): +``` + + mike + +``` + +Captured change: +http method: GET +``` +URL: http://:9000/store/less?offset=2 +``` +``` +[{"timestamp": 1542877413979, "configuration": "CREATED: /pnf-simulator:config/allow-user = mike"}, + {"timestamp": 1542877413979, "configuration": "MOVED: /pnf-simulator:config/allow-user = mike after /pnf-simulator:config/allow-user = alice"}] +``` + +**Delete request** +http method: POST +``` +URL: http::9000/netconf/edit-config +``` +file content to be sent as multipart (form data): +``` + + 1111 + + +``` + +Captured change: +http method: GET +``` +URL: http://:9000/store/less?offset=1 +``` +``` +[{"timestamp": 1542877413979, "configuration": "DELETED: /pnf-simulator:config/itemValue2 = 222"}] +``` + +Getting all configuration changes: +http method: GET +``` +URL: http://:9000/store/cm-history +``` +response: +``` +[{"timestamp":1542877413979,"configuration":"MODIFIED: : old value: /pnf-simulator:config/itemValue1 = 2781, new value: /pnf-simulator:config/itemValue1 = 111"}, + {"timestamp":1542877413979,"configuration":"MODIFIED: : old value: /pnf-simulator:config/itemValue2 = 3782, new value: /pnf-simulator:config/itemValue2 = 222"}, + {"timestamp":1542877414000,"configuration":"CREATED: : /pnf-simulator:config/itemValue3 = 3333"}, + {"timestamp":1542877414104,"configuration":"CREATED: : CREATED: /pnf-simulator:config/allow-user = mike"} + {"timestamp":1542877414107,"configuration":"MOVED: /pnf-simulator:config/allow-user = mike after /pnf-simulator:config/allow-user = alice"}, + {"timestamp":1542877414275,"configuration":"DELETED: /pnf-simulator:config/itemValue2 = 222"}] +``` + +### Logging + +### Swagger + +## Developers Guide + +### Integration tests +Integration tests use docker-compose for setting up cluster with all services. +Those tests are not part of build pipeline, but can be run manually by invoking *mvn verify -DskipITs=false* from project command line. +Tests can be found in netconfsimulator project in src/integration directory. + +## Troubleshooting +Q: Simulator throws errors after shutting down with *docker-compose down* or *docker-compose restart* + +A: Remove docker containers that were left after stopping the simulator with the following commands: +``` +docker stop $(docker ps | grep netconfsimulator | awk '{print $1;}') +docker rm $(docker ps -a | grep netconfsimulator | awk '{print $1;}') +``` diff --git a/test/mocks/pnfsimulator/netconfsimulator/config/netconf.env b/test/mocks/pnfsimulator/netconfsimulator/config/netconf.env new file mode 100644 index 000000000..6cf310a27 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/config/netconf.env @@ -0,0 +1,5 @@ +NETCONF_ADDRESS=netopeer +NETCONF_PORT=830 +NETCONF_MODEL=pnf-simulator +NETCONF_MAIN_CONTAINER=config +TZ=Europe/Warsaw diff --git a/test/mocks/pnfsimulator/netconfsimulator/docker-compose.yml b/test/mocks/pnfsimulator/netconfsimulator/docker-compose.yml new file mode 100644 index 000000000..fd3339162 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/docker-compose.yml @@ -0,0 +1,96 @@ +version: '3' + +services: + zookeeper: + image: wurstmeister/zookeeper + ports: + - "2181:2181" + networks: + - netconfnetwork + + kafka1: + image: wurstmeister/kafka:1.1.0 + ports: + - "9092:9092" + hostname: kafka1 + networks: + - netconfnetwork + environment: + KAFKA_ADVERTISED_PORT: 9092 + KAFKA_ADVERTISED_HOST_NAME: kafka1 + KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 + KAFKA_CREATE_TOPICS: "config:1:1" + KAFKA_DELETE_RETENTION_MS: 604800000 + KAFKA_LOG_CLEANER_DELETE_RETENTION_MS: 604800000 + depends_on: + - zookeeper + + netconf-simulator: + image: nexus3.onap.org:10003/onap/netconfsimulator:5.0.0-SNAPSHOT + ports: + - "9000:8080" + restart: on-failure + hostname: netconf-simulator + networks: + - netconfnetwork + depends_on: + - zookeeper + - kafka1 + - netopeer + + netopeer: + image: sysrepo/sysrepo-netopeer2:latest + ports: + - "830:830" + - "5002:5002" + - "6513:6513" + volumes: + - ./netconf:/netconf + - ./netopeer-change-saver-native:/netopeer-change-saver + - ./tls:/tls + env_file: + - ./config/netconf.env + restart: on-failure + networks: + - netconfnetwork + depends_on: + - sftp-server + - ftpes-server + environment: + http_proxy: ${http_proxy} + https_proxy: ${https_proxy} + command: + - /netconf/initialize_netopeer.sh + + sftp-server: + image: atmoz/sftp:alpine + ports: + - "2222:22" + volumes: + - ./sftp:/home/sftp-user/sftp + - ./ssh/ssh_host_rsa_key.pub:/home/sftp-user/.ssh/keys/ssh_host_rsa_key.pub + networks: + - netconfnetwork + restart: on-failure + command: sftp-user::1001 + + ftpes-server: + image: stilliard/pure-ftpd:latest + ports: + - "2221:21" + - "30000-30009:30000-30009" + volumes: + - ./ftpes/files:/home/ftpusers/onap + - ./ftpes/userpass/:/etc/pure-ftpd/passwd/ + - ./ftpes/tls/:/etc/ssl/private/ + networks: + - netconfnetwork + environment: + PUBLICHOST: localhost + ADDED_FLAGS: --tls=2 + FTP_USER_HOME: onap + restart: on-failure + +networks: + netconfnetwork: + driver: bridge diff --git a/test/mocks/pnfsimulator/netconfsimulator/docker/Dockerfile b/test/mocks/pnfsimulator/netconfsimulator/docker/Dockerfile new file mode 100644 index 000000000..0e25fd310 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/docker/Dockerfile @@ -0,0 +1,4 @@ +FROM openjdk:8-jre-alpine +ADD libs /app/libs +ADD netconfsimulator-5.0.0-SNAPSHOT.jar /app/netconf-simulator.jar +CMD java -cp /app/libs/*:/app/netconf-simulator.jar org.onap.netconfsimulator.Main diff --git a/test/mocks/pnfsimulator/netconfsimulator/ftpes/files/ftpes-noone.txt b/test/mocks/pnfsimulator/netconfsimulator/ftpes/files/ftpes-noone.txt new file mode 100644 index 000000000..e69de29bb diff --git a/test/mocks/pnfsimulator/netconfsimulator/ftpes/files/onap/ftpes-onap.txt b/test/mocks/pnfsimulator/netconfsimulator/ftpes/files/onap/ftpes-onap.txt new file mode 100644 index 000000000..e69de29bb diff --git a/test/mocks/pnfsimulator/netconfsimulator/ftpes/tls/pure-ftpd.pem b/test/mocks/pnfsimulator/netconfsimulator/ftpes/tls/pure-ftpd.pem new file mode 100755 index 000000000..0ce676efa --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/ftpes/tls/pure-ftpd.pem @@ -0,0 +1,49 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDHbSk5/cABTpCt +q54QyTkhuhb84nEz5ztKL0hY56fsVtAA2gSAde+qV9YwUIuReOUhAF4RVVt2Lkn/ +1R0yX+0IjrXnO7jYzDj6QhgyqYKb3iQlvShZMMQ7qihn8qBxobk7+O10x6VLS2L8 +WYpQxGXu7T1qXbw10RhrqG8nbXYX+aHMsv9zMt9OYqKSI073OZR2vk3K49Uqcurj +sXuRJOa10MRsxgA726pr8OLWAWejsoFaqP2fQS3HeT2RnAqPyAgPc0P6n7gxo0JU +U5dPnrPbsvfdegIFxfc57oZXrLz7nYXkJEcjYTBFSQ+JAaRfx9kNXZ7Gft7EAMyF +BLemY/0VAgMBAAECggEARD9bSHlKaCgW4xhEM8JpRt2EWG62BukvJSghPiupD/x1 +mpUBzWSO7GC68DXgTZxt7WlOx+fKMRuOP3sTTtX9LFyKa+PIUokxRpOv7EaOaAER +pciiMkO6JCELSueBeOG7noaF3N0l+CqIaYvLBfDwYV/XELubWV+BV/aAc6HGNFWi +4bjM+BOBLQstrEeJh2jVylzv4CTtlTs2pwiHFSyrHhudTk5nnATAHn1gi+X42v1A +zk3UfqADZJmMI0/Roup4YPZ3+6zUzDN2i+qasHexL0OKIjRcSqpgqQoIeKEbKKfw +sOgiWIR2Xvj7EJmhzJlWgKjk8OLs/7U4QpnD+s0agQKBgQDu3ojqKNWnPHy0Nupm +tmAs28WLK76R0iZeAd2nwsU2K6lnm9z5o2ab3ffTJVB9kAetKJa3UerKskF/qF9C +MtjlEn6F++uYFitpLjQevnyrKSqFqbzytDXrQlk+gZLglmi6YylT5k9qLSREAu55 +XS/wbm9XU2Q7sl8oTnZHXptT7QKBgQDVunvqdDn1FaNU9EwQCGPS3QGu+go22xkM +4Rs2CoHWfqmhGOo8lJKBElDqsXvxggrZLWJe/1lgnELT/9aXS8QLWBnZxpTj9wfd +igH+CJc3mWnLThmUGdSV/tuHon2IdQ8/1CiGSwIr9kYCnStidUtOXjIbgc6kUTTi +5wtIGHh4yQKBgQDXJ/0dJbDklRgiX4CdCdLxNPfnlnxt7mN+s6GK1WY7l/JcD8ln +1qW66aGrP2YT42L2tqOi9hdNgmh66xb6ksBI/XKXjsWz1Ow/Lk3mD2BN76OMh8pY +trgGc1ndcmrw/qnQkTcNilqn4YdT92wER0rB/0cs2kFjgBQ0QxBI0s+INQKBgA6Y +2fW9UmgGvk0DEl7V89tm9MJ6mU/9zswuY6lhNlTr+bHi/bx9eTQPiC8/R/PKqesD +SoCqd/Q9N+M6yfEzX4RW1A0nnuui54qd7lznQUyu0abtApo22WoVKfEti91SAWSe +nNXvMYrHGyj6iwgCcs47aLiwOOjIExCcLw0RfsjhAoGAc1zaRbrtjjh66FJYjLiJ +Q6EXfm31ptaQQUn5rQyHMD2VRlajCYV+fv75tezf2dQvJcqHYWrEuY8U+OTbB1TB +IEqN8ETUeLegl5RgvWoyWinqdbv/0d9LtwVBdtiEQLoYumD934mshEDgzCOOjrBe +Salcd1vc6y6NiFooPlvloXQ= +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDYDCCAkigAwIBAgIJAMH2upKd2yAJMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMTgwOTEwMTI1ODE2WhcNMzgwOTA1MTI1ODE2WjBF +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 +ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAx20pOf3AAU6QraueEMk5IboW/OJxM+c7Si9IWOen7FbQANoEgHXvqlfW +MFCLkXjlIQBeEVVbdi5J/9UdMl/tCI615zu42Mw4+kIYMqmCm94kJb0oWTDEO6oo +Z/KgcaG5O/jtdMelS0ti/FmKUMRl7u09al28NdEYa6hvJ212F/mhzLL/czLfTmKi +kiNO9zmUdr5NyuPVKnLq47F7kSTmtdDEbMYAO9uqa/Di1gFno7KBWqj9n0Etx3k9 +kZwKj8gID3ND+p+4MaNCVFOXT56z27L33XoCBcX3Oe6GV6y8+52F5CRHI2EwRUkP +iQGkX8fZDV2exn7exADMhQS3pmP9FQIDAQABo1MwUTAdBgNVHQ4EFgQUt51lQ+ab +MTq+w2U/knCsIPb3wrkwHwYDVR0jBBgwFoAUt51lQ+abMTq+w2U/knCsIPb3wrkw +DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAQ69AktYLQ+VRbojz +zC0XQ2M1FAkfJI2P0LvPoYxZgId2CnZW3sMIdnJdF+KjvOqeGyFmw+hn8WkoKiWj +0sxuGmrWt5t+5bF2wcq0CtTeF1/o6DsRhRiJBzmcLe81ItrN6emZSg96xCKzkHBZ +3nF4fG88vtiYgD932lMStDqQzSTx0FsCGpGaKh9xDmKvlP24NWdM9gyOEsRbDvqd +vS1Q45Jx0jzkp7X5d0casqBWIZak3z0EVdK7c8Y/GxxTcWfIMINCl9+F9kpTA/ZX +uARYzrPWaBfDBi2r5acWi/AHJM3U+LgzO5nCKa+38vtjNw3NtbslA4InQ5cU2B8X +QN8NlQ== +-----END CERTIFICATE----- diff --git a/test/mocks/pnfsimulator/netconfsimulator/ftpes/userpass/pureftpd.passwd b/test/mocks/pnfsimulator/netconfsimulator/ftpes/userpass/pureftpd.passwd new file mode 100755 index 000000000..7961e710d --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/ftpes/userpass/pureftpd.passwd @@ -0,0 +1 @@ +onap:$6$Guq6OMhBdNZ6nTk0$7dLt6hOrAv.in36jzWGd5UgWeDqN3CuKjrzJ.izRTdgZRTszeNYbT2dk7UDh9CLD7pohnB0.k1NSZmRIUB/ID/:1001:1001::/home/ftpusers/onap/./:::::::::::: diff --git a/test/mocks/pnfsimulator/netconfsimulator/netconf/__init__.py b/test/mocks/pnfsimulator/netconfsimulator/netconf/__init__.py new file mode 100644 index 000000000..0f144c21e --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netconf/__init__.py @@ -0,0 +1,19 @@ +### +# ============LICENSE_START======================================================= +# Simulator +# ================================================================================ +# Copyright (C) 2019 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### diff --git a/test/mocks/pnfsimulator/netconfsimulator/netconf/initialize_netopeer.sh b/test/mocks/pnfsimulator/netconfsimulator/netconf/initialize_netopeer.sh new file mode 100755 index 000000000..71c1f215b --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netconf/initialize_netopeer.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +### +# ============LICENSE_START======================================================= +# Simulator +# ================================================================================ +# Copyright (C) 2019 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### + +cat > /etc/apt/apt.conf << EOF +Acquire::http { + No-Cache "true"; + No-Store "true"; + Pipeline-Depth "0"; +}; +EOF + +NETOPEER_CHANGE_SAVER=netopeer-change-saver + +cp /tls/* /usr/local/etc/keystored/keys/ +cp /netconf/*.xml /tmp/ + +chmod +x /netconf/set-up-xmls.py +/netconf/set-up-xmls.py /tls ca.crt server_cert.crt server_key.pem /tmp/load_server_certs.xml /tmp/tls_listen.xml + +/usr/bin/supervisord -c /etc/supervisord.conf & +sysrepoctl --install --yang=/netconf/pnf-simulator.yang --owner=netconf:nogroup --permissions=777 +sysrepocfg --import=/netconf/pnf-simulator.data.xml --datastore=startup --format=xml --level=3 pnf-simulator +sysrepocfg --merge=/tmp/load_server_certs.xml --format=xml --datastore=startup ietf-keystore +sysrepocfg --merge=/tmp/tls_listen.xml --format=xml --datastore=startup ietf-netconf-server + +apt-get update +apt-get install -y python3 python3-pip librdkafka-dev +pip3 install flask flask_restful +nohup python3 /netconf/yang_loader_server.py & + +/bin/cp -R /$NETOPEER_CHANGE_SAVER /opt/dev/ +ln -s /opt/dev/sysrepo/build/src/libsysrepo.so /$NETOPEER_CHANGE_SAVER/libsysrepo.so +cd /opt/dev/$NETOPEER_CHANGE_SAVER && cmake . +cd /opt/dev/$NETOPEER_CHANGE_SAVER && make +/opt/dev/$NETOPEER_CHANGE_SAVER/bin/netopeer-change-saver pnf-simulator kafka1 config diff --git a/test/mocks/pnfsimulator/netconfsimulator/netconf/load_server_certs.xml b/test/mocks/pnfsimulator/netconfsimulator/netconf/load_server_certs.xml new file mode 100644 index 000000000..2524e08b0 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netconf/load_server_certs.xml @@ -0,0 +1,40 @@ + + + + + + SERVER_KEY_NAME + + + SERVER_CERT_NAME + SERVER_CERTIFICATE_HERE + + + + + + test_trusted_ca_list + + CA_CERT_NAME + CA_CERTIFICATE_HERE + + + diff --git a/test/mocks/pnfsimulator/netconfsimulator/netconf/newmodel.xml b/test/mocks/pnfsimulator/netconfsimulator/netconf/newmodel.xml new file mode 100644 index 000000000..90a3451d4 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netconf/newmodel.xml @@ -0,0 +1,24 @@ + + + + 500 + 1000 + diff --git a/test/mocks/pnfsimulator/netconfsimulator/netconf/newmodel.yang b/test/mocks/pnfsimulator/netconfsimulator/netconf/newmodel.yang new file mode 100644 index 000000000..544f46725 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netconf/newmodel.yang @@ -0,0 +1,9 @@ +module newmodel { + namespace "http://onap.org/pnf-simulator2"; + prefix config2; + container config2 { + config true; + leaf item1 {type uint32;} + leaf item2 {type uint32;} + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/netconf/pnf-simulator.data.xml b/test/mocks/pnfsimulator/netconfsimulator/netconf/pnf-simulator.data.xml new file mode 100644 index 000000000..c235f6405 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netconf/pnf-simulator.data.xml @@ -0,0 +1,24 @@ + + + + 42 + 35 + diff --git a/test/mocks/pnfsimulator/netconfsimulator/netconf/pnf-simulator.yang b/test/mocks/pnfsimulator/netconfsimulator/netconf/pnf-simulator.yang new file mode 100644 index 000000000..ba1158560 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netconf/pnf-simulator.yang @@ -0,0 +1,9 @@ +module pnf-simulator { + namespace "http://onap.org/pnf-simulator"; + prefix config; + container config { + config true; + leaf itemValue1 {type uint32;} + leaf itemValue2 {type uint32;} + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/netconf/set-up-xmls.py b/test/mocks/pnfsimulator/netconfsimulator/netconf/set-up-xmls.py new file mode 100755 index 000000000..d46ff91f9 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netconf/set-up-xmls.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python + +### +# ============LICENSE_START======================================================= +# Simulator +# ================================================================================ +# Copyright (C) 2019 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### + +import os +import sys +import logging +import logging.config + +logging.basicConfig() +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +# Placeholders definition - this needs to match placeholders in +# load_server_certs_xml_file and tls_listen_xml_file +SERVER_KEY_NAME = "SERVER_KEY_NAME" +SERVER_CERT_NAME = "SERVER_CERT_NAME" +SERVER_CERTIFICATE_HERE = "SERVER_CERTIFICATE_HERE" +CA_CERT_NAME = "CA_CERT_NAME" +CA_CERTIFICATE_HERE = "CA_CERTIFICATE_HERE" +CA_FINGERPRINT_HERE = "CA_FINGERPRINT_HERE" +CA_FINGERPRINT_ENV = "CA_FINGERPRINT" +SERVER_CERTIFICATE_ENV = "SERVER_CERTIFICATE_ENV" +CA_CERTIFICATE_ENV = "CA_CERTIFICATE_ENV" + + +class FileHelper(object): + @classmethod + def get_file_contents(cls, filename): + with open(filename, "r") as f: + return f.read() + + @classmethod + def write_file_contents(cls, filename, data): + with open(filename, "w+") as f: + f.write(data) + + +class CertHelper(object): + @classmethod + def get_pem_content_stripped(cls, pem_dir, pem_filename): + cmd = "cat {}/{} | grep -v '^-'".format(pem_dir, pem_filename) + content = CertHelper.system(cmd) + return content + + @classmethod + def get_cert_fingerprint(cls, directory, cert_filename): + cmd = "openssl x509 -fingerprint -noout -in {}/{} | sed -e " \ + "'s/SHA1 Fingerprint//; s/=//; s/=//p'" \ + .format(directory, cert_filename) + fingerprint = CertHelper.system(cmd) + return fingerprint + + @classmethod + def print_certs_info(cls, ca_cert, ca_fingerprint, server_cert): + logger.info("Will use server certificate: " + server_cert) + logger.info("Will use CA certificate: " + ca_cert) + logger.info("CA certificate fingerprint: " + ca_fingerprint) + + @classmethod + def system(cls, cmd): + return os.popen(cmd).read().replace("\n", "") + + +class App(object): + @classmethod + def patch_server_certs(cls, data, server_key_filename_noext, + server_cert_filename_noext, ca_cert_filename_noext, + server_cert, ca_cert): + data = data.replace(SERVER_KEY_NAME, server_key_filename_noext) + data = data.replace(SERVER_CERT_NAME, server_cert_filename_noext) + data = data.replace(CA_CERT_NAME, ca_cert_filename_noext) + data = data.replace(SERVER_CERTIFICATE_HERE, server_cert) + data = data.replace(CA_CERTIFICATE_HERE, ca_cert) + return data + + @classmethod + def patch_tls_listen(cls, data, server_cert_filename_noext, ca_fingerprint, + server_cert, ca_cert): + data = data.replace(SERVER_CERT_NAME, server_cert_filename_noext) + data = data.replace(CA_FINGERPRINT_HERE, ca_fingerprint) + data = data.replace(SERVER_CERTIFICATE_HERE, server_cert) + data = data.replace(CA_CERTIFICATE_HERE, ca_cert) + return data + + @classmethod + def run(cls): + # name things + cert_dir = sys.argv[1] + ca_cert_filename = sys.argv[2] + server_cert_filename = sys.argv[3] + server_key_filename = sys.argv[4] + load_server_certs_xml_file = sys.argv[5] + tls_listen_xml_file = sys.argv[6] + + # strip extensions + ca_cert_filename_noext = ca_cert_filename.replace(".crt", "") + server_cert_filename_noext = server_cert_filename.replace(".crt", "") + server_key_filename_noext = server_key_filename.replace(".pem", "") + + # get certificates from files + server_cert = CertHelper.get_pem_content_stripped(cert_dir, + server_cert_filename) + ca_cert = CertHelper.get_pem_content_stripped(cert_dir, + ca_cert_filename) + ca_fingerprint = CertHelper.get_cert_fingerprint(cert_dir, + ca_cert_filename) + CertHelper.print_certs_info(ca_cert, ca_fingerprint, server_cert) + + # patch TLS configuration files + data_srv = FileHelper.get_file_contents(load_server_certs_xml_file) + patched_srv = App.patch_server_certs(data_srv, server_key_filename_noext, + server_cert_filename_noext, + ca_cert_filename_noext, + server_cert, ca_cert) + FileHelper.write_file_contents(load_server_certs_xml_file, patched_srv) + + data_tls = FileHelper.get_file_contents(tls_listen_xml_file) + patched_tls = App.patch_tls_listen(data_tls, server_cert_filename_noext, + ca_fingerprint, server_cert, ca_cert) + FileHelper.write_file_contents(tls_listen_xml_file, patched_tls) + + +def main(): + if len(sys.argv) is not 7: + print("Usage: {1} " + " " + "", sys.argv[0]) + return 1 + App.run() + logger.info("XML files patched successfully") + + +if __name__ == '__main__': + main() diff --git a/test/mocks/pnfsimulator/netconfsimulator/netconf/test_yang_loader_server.py b/test/mocks/pnfsimulator/netconfsimulator/netconf/test_yang_loader_server.py new file mode 100644 index 000000000..f282517b2 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netconf/test_yang_loader_server.py @@ -0,0 +1,121 @@ +### +# ============LICENSE_START======================================================= +# Simulator +# ================================================================================ +# Copyright (C) 2019 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### + +import unittest + +from unittest import mock +from werkzeug.datastructures import FileStorage + +from yang_loader_server import YangLoaderHelper, YangModelServer + + +class TestYangLoaderHelper(unittest.TestCase): + + def test_should_save_file_and_return_path(self): + helper = YangLoaderHelper() + mocked_file = mock.Mock(FileStorage) + mocked_file.filename = "sample" + + path = helper.save_file(mocked_file) + + self.assertEqual(path, "/tmp/sample") + mocked_file.save.assert_called_once_with("/tmp/sample") + + @mock.patch('yang_loader_server.check_output') + def test_should_install_new_yang_model(self, mocked_output): + helper = YangLoaderHelper() + + helper.install_new_model("path") + + mocked_output.assert_called_with( + ['sysrepoctl', '--install', '--yang=path', + '--owner=netconf:nogroup', '--permissions=777'], + stderr=-2, universal_newlines=True) + + @mock.patch('yang_loader_server.check_output') + def test_should_delete_yang_model(self, mocked_output): + helper = YangLoaderHelper() + + helper.uninstall_a_model("modelName") + + mocked_output.assert_called_with( + ['sysrepoctl', '--uninstall', '--module=modelName'], + stderr=-2, universal_newlines=True) + + @mock.patch('yang_loader_server.check_output') + def test_should_set_default_configuration(self, mocked_output): + helper = YangLoaderHelper() + + helper.set_default_configuration("samplePath", "sampleModuleName") + + mocked_output.assert_called_with( + ['sysrepocfg', '--import=samplePath', '--datastore=startup', + '--format=xml', '--level=3', 'sampleModuleName'], + stderr=-2, universal_newlines=True) + + @mock.patch('yang_loader_server.subprocess.Popen') + @mock.patch('yang_loader_server.check_output') + def test_should_verify_change_listener_for_model_properly(self, mocked_output, mocked_popen): + helper = YangLoaderHelper() + + helper.start_change_listener_for_model("sampleModule") + + mocked_output.assert_called_with( + ['pgrep', '-f', '/opt/dev/netopeer-change-saver/bin/netopeer-change-saver sampleModule kafka1 config'], + stderr=-2, universal_newlines=True) + + @mock.patch('yang_loader_server.check_output') + def test_should_raise_exception_when_error_occurred_in_output(self, + mocked_output): + helper = YangLoaderHelper() + mocked_output.return_value = "abcd ERR" + with self.assertRaises(RuntimeError) as context: + helper._run_bash_command("sample command") + + self.assertEqual('abcd ERR', str(context.exception)) + + +class TestYangModelServer(unittest.TestCase): + + def __init__(self, methodName='runTest'): + super().__init__(methodName) + self._mocked_file = mock.Mock(FileStorage) + + def test_should_properly_apply_and_start_new_model(self): + with mock.patch.object(YangModelServer, '_parse_request', + new=self._mock_request): + helper = mock.Mock(YangLoaderHelper) + helper.save_file.return_value = "sampleFile" + server = YangModelServer(helper) + + server.post() + + self.assertEqual(helper.save_file.call_count, 2) + helper.install_new_model.assert_called_once_with('sampleFile') + helper.set_default_configuration.assert_called_once_with( + 'sampleFile', 'sampleModuleName') + helper.start_change_listener_for_model.assert_called_once_with('sampleModuleName') + + def _mock_request(self): + return { + 'yangModel': self._mocked_file, + 'initialConfig': self._mocked_file, + 'moduleName': "sampleModuleName" + } diff --git a/test/mocks/pnfsimulator/netconfsimulator/netconf/tls_listen.xml b/test/mocks/pnfsimulator/netconfsimulator/netconf/tls_listen.xml new file mode 100644 index 000000000..4f45b28a2 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netconf/tls_listen.xml @@ -0,0 +1,48 @@ + + + + + + test_tls_listen_endpt + +
0.0.0.0
+ 6513 + + + SERVER_CERT_NAME + + + + test_trusted_ca_list + + + 1 + + 02:CA_FINGERPRINT_HERE + x509c2n:specified + test + + + +
+
+
+
diff --git a/test/mocks/pnfsimulator/netconfsimulator/netconf/yang_loader_server.py b/test/mocks/pnfsimulator/netconfsimulator/netconf/yang_loader_server.py new file mode 100644 index 000000000..716d0712e --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netconf/yang_loader_server.py @@ -0,0 +1,172 @@ +### +# ============LICENSE_START======================================================= +# Simulator +# ================================================================================ +# Copyright (C) 2019 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### + +import logging +import subprocess +import os +from subprocess import check_output, CalledProcessError +from flask import Flask +from flask_restful import Resource, Api, reqparse +from werkzeug.datastructures import FileStorage +import time + +app = Flask(__name__) +api = Api(app) +logger = logging.getLogger("yang-loader") +logger.addHandler(logging.StreamHandler()) +KAFKA_BROKER_NAME="kafka1" +KAFKA_TOPIC_NAME="config" + + +class YangLoaderHelper(object): + + @classmethod + def save_file(cls, yang_model_file: FileStorage) -> str: + path = "/tmp/" + yang_model_file.filename + yang_model_file.save(path) + return path + + @classmethod + def install_new_model(cls, yang_model_path: str): + logger.info("Installing new model: %s", yang_model_path) + command = "sysrepoctl --install --yang={} --owner=netconf:nogroup --permissions=777" \ + .format(yang_model_path) + cls._run_bash_command(command) + + @classmethod + def uninstall_a_model(cls, yang_model_name: str): + logger.info("Uninstalling a model: %s", yang_model_name) + command = "sysrepoctl --uninstall --module={}" \ + .format(yang_model_name) + cls._run_bash_command(command) + + + @classmethod + def set_default_configuration(cls, init_conf_path: str, module_name: str): + logger.info("Attempting to set default configuration %s for module %s", init_conf_path, module_name) + command = "sysrepocfg --import={} --datastore=startup --format=xml --level=3 {}" \ + .format(init_conf_path, module_name) + cls._run_bash_command(command) + + @classmethod + def start_change_listener_for_model(cls, module_name: str): + logger.info("Starting listener for model: %s", module_name) + command = "/opt/dev/netopeer-change-saver/bin/netopeer-change-saver {} {} {}" \ + .format(module_name, KAFKA_BROKER_NAME, KAFKA_TOPIC_NAME) + try: + check_output(["pgrep", "-f" , command], stderr=subprocess.STDOUT, universal_newlines=True) + logger.info("Change listener for {} already exist.".format(module_name)) + except CalledProcessError: + subprocess.Popen(command.split(), stdout=subprocess.PIPE) + + @classmethod + def stop_change_listener_for_model(cls, model_name): + logger.info("Stopping listener for model %s", model_name) + pid = cls.get_pid_by_name(model_name) + logger.info("pid is %s", pid) + command = "kill -2 {}".format(pid) + cls._run_bash_command(command) + + @classmethod + def _run_bash_command(cls, command: str): + try: + logger.info("Attempts to invoke %s", command) + output = check_output(command.split(), stderr=subprocess.STDOUT, + universal_newlines=True) + logger.info("Output: %s", output) + if "ERR" in output: + raise RuntimeError(str(output)) + except subprocess.CalledProcessError as e: + raise RuntimeError(e, str(e.stdout)) + + @classmethod + def get_pid_by_name(cls, name): + for dirname in os.listdir('/proc'): + if not dirname.isdigit(): + continue + try: + with open('/proc/{}/cmdline'.format(dirname), mode='rb') as fd: + content = fd.read().decode().split('\x00') + except Exception as e: + print(e) + continue + + if name in content: + return dirname + + +class YangModelServer(Resource): + logger = logging.getLogger('YangModelServer') + + def __init__(self, yang_loader_helper: YangLoaderHelper = YangLoaderHelper()): + self._yang_loader_helper = yang_loader_helper + + def post(self): + args = self._parse_request() + yang_model_file = args['yangModel'] + initial_config_file = args['initialConfig'] + module_name = args['moduleName'] + model_path = self._yang_loader_helper.save_file(yang_model_file) + conf_path = self._yang_loader_helper.save_file(initial_config_file) + + try: + self._yang_loader_helper.install_new_model(model_path) + self._yang_loader_helper.set_default_configuration(conf_path, + module_name) + self._yang_loader_helper.start_change_listener_for_model(module_name) + except RuntimeError as e: + self.logger.error(e.args, exc_info=True) + return str(e.args), 400 + return "Successfully started" + + def delete(self): + args = self._parse_request() + yang_model_name = args['yangModelName'] + + try: + self._yang_loader_helper.stop_change_listener_for_model(yang_model_name) + time.sleep(5) + self._yang_loader_helper.uninstall_a_model(yang_model_name) + except RuntimeError as e: + self.logger.error(e.args, exc_info=True) + return str(e.args), 400 + return "Successfully deleted" + + @classmethod + def _parse_request(cls) -> reqparse.Namespace: + parse = reqparse.RequestParser() + parse.add_argument('yangModel', + type=FileStorage, + location='files') + parse.add_argument('initialConfig', + type=FileStorage, + location='files') + parse.add_argument('moduleName', type=str) + parse.add_argument('yangModelName', type=str) + return parse.parse_args() + + +api.add_resource(YangModelServer, '/model') + +if __name__ == '__main__': + logging.basicConfig(filename=os.path.dirname(__file__) + "/yang_loader.log", + filemode="w", + level=logging.DEBUG) + app.run(host='0.0.0.0', port='5002') diff --git a/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/Application.cpp b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/Application.cpp new file mode 100644 index 000000000..56c33f0de --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/Application.cpp @@ -0,0 +1,74 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +#include "Application.h" +#include +#include +#include "sysrepo/Session.hpp" +#include "SysrepoCallback.h" + +Application::~Application() { + this->subscriber->unsubscribe(); + this->session->session_stop(); + sr_disconnect(this->connection->_conn); + std::cout << "Application closed correctly " << std::endl; +} + +void Application::run() { + /*create kafka wrapper object*/ + auto kafkaWrapper = std::make_shared(this->brokers,this->topic_name); + + std::cout << "Application will watch for changes in " << module_name << std::endl; + /* connect to sysrepo */ + this->connection = new sysrepo::Connection("example_application"); + sysrepo::S_Connection conn(new sysrepo::Connection("example_application")); + + /* start session */ + sysrepo::S_Session sess(new sysrepo::Session(conn)); + + this->session = sess; + /* subscribe for changes in running config */ + sysrepo::S_Subscribe subscribe(new sysrepo::Subscribe(sess)); + std::shared_ptr cb(new SysrepoCallback(kafkaWrapper)); + + subscribe->module_change_subscribe(module_name, cb); + this->subscriber = subscribe; + + /* read startup config */ + std::cout << "\n ========== READING STARTUP CONFIG: ==========\n" << std::endl; + + cb->print_current_config(sess, module_name); + + std::cout << "\n ========== STARTUP CONFIG APPLIED AS RUNNING ==========\n" << std::endl; + + /* loop until ctrl-c is pressed / SIGINT is received */ + while (!exit_application) { + sleep(1000); /* or do some more useful work... */ + } + + std::cout << "Application exit requested, exiting." << std::endl; + +} + +Application::Application(const char *module_name, const char *brokers, const char *topic_name) { + this->module_name = module_name; + this->brokers = brokers; + this->topic_name = topic_name; +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/Application.h b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/Application.h new file mode 100644 index 000000000..c41f7e28b --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/Application.h @@ -0,0 +1,43 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +#ifndef NETOPEER_CHANGE_SAVER_CPP_APPLICATION_H +#define NETOPEER_CHANGE_SAVER_CPP_APPLICATION_H +#include "sysrepo/Sysrepo.hpp" + +extern volatile int exit_application; + +class Application { +private: + const char *module_name; + const char *brokers; + const char *topic_name; + sysrepo::S_Session session; + sysrepo::S_Subscribe subscriber; + sysrepo::Connection *connection; + +public: + Application(const char *module_name, const char *brokers, const char *topic_name); + ~Application(); + void run(); + +}; + +#endif //NETOPEER_CHANGE_SAVER_CPP_APPLICATION_H diff --git a/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/CMakeLists.txt b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/CMakeLists.txt new file mode 100644 index 000000000..35a3a85ad --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.7) +project(netopeer-change-saver) + +set(CMAKE_CXX_STANDARD 11) +set(THREADS_PREFER_PTHREAD_FLAG ON) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +set (CMAKE_EXE_LINKER_FLAGS "-Wl,--unresolved-symbols=ignore-all") +link_directories(.) + +find_package(Threads REQUIRED) + +add_executable(netopeer-change-saver main.cpp sysrepo.h Application.cpp Application.h KafkaWrapper.cpp KafkaWrapper.h + SysrepoCallback.cpp SysrepoCallback.h) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/libsysrepo-cpp.so + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/bin) + +target_link_libraries(netopeer-change-saver libsysrepo-cpp.so) +target_link_libraries(netopeer-change-saver libsysrepo.so) +target_link_libraries(netopeer-change-saver Threads::Threads) +target_link_libraries(netopeer-change-saver librdkafka.so) \ No newline at end of file diff --git a/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/KafkaWrapper.cpp b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/KafkaWrapper.cpp new file mode 100644 index 000000000..cd018a33f --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/KafkaWrapper.cpp @@ -0,0 +1,105 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +#include "KafkaWrapper.h" +#include +#include +#include + +extern "C" { + rd_kafka_resp_err_t rd_kafka_last_error (void); + rd_kafka_resp_err_t rd_kafka_flush (rd_kafka_t *rk, int timeout_ms); +} + +extern "C" { +void kafka_delivery_report_callback(rd_kafka_t *rk, const rd_kafka_message_t *rkmessage, void *opaque) { +#ifdef DEBUG + if (rkmessage->err) + std::cout<<"%% Message delivery failed: %s\n"<err)<len <<" bytes, partition " << rkmessage->partition <<")" << std::endl; + /* The rkmessage is destroyed automatically by librdkafka */ +#endif +} +} + +KafkaWrapper::KafkaWrapper(const char *brokers, const char *topic_name) { + this->brokers = brokers; + this->topic_name = topic_name; + + init(); +} + +KafkaWrapper::~KafkaWrapper() { + std::cerr<<"%% Flushing final messages..."< + +class KafkaWrapper { +private: + char errstr[512]; + const char *brokers; + const char *topic_name; + rd_kafka_t *rk; + rd_kafka_topic_t *rkt; + rd_kafka_conf_t *conf; + + void init(); + +public: + KafkaWrapper(const char *brokers, const char *topic_name); + ~KafkaWrapper(); + void kafka_send_message(std::string message); +}; + + +#endif //NETOPEER_CHANGE_SAVER_CPP_KAFKAWRAPPER_H diff --git a/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/SysrepoCallback.cpp b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/SysrepoCallback.cpp new file mode 100644 index 000000000..225fe03a4 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/SysrepoCallback.cpp @@ -0,0 +1,108 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +#include "SysrepoCallback.h" +#define CREATED "CREATED" +#define DELETED "DELETED" +#define MODIFIED "MODIFIED" +#define MOVED "MOVED" +#define XPATH_MAX_LEN 100 + + +int SysrepoCallback::module_change(sysrepo::S_Session sess, const char *module_name, sr_notif_event_t event, void *private_ctx) { + { + if (event == SR_EV_APPLY) { + char change_path[XPATH_MAX_LEN]; + + try { +#ifdef DEBUG + std::cout << "\n ========== CHANGES: =============================================\n" << std::endl; +#endif + snprintf(change_path, XPATH_MAX_LEN, "/%s:*", module_name); + auto it = sess->get_changes_iter(&change_path[0]); + while (auto change = sess->get_change_next(it)) { + std::string message = create_message(change); + std::cout<kafka_send_message(message); + } +#ifdef DEBUG + std::cout << "\n ========== END OF CHANGES =======================================\n" << std::endl; +#endif + } catch( const std::exception& e ) { + std::cerr << e.what() << std::endl; + } + } + return SR_ERR_OK; + } +} + +SysrepoCallback::SysrepoCallback(std::shared_ptr wrapper) { + this->kafkaWrapper = wrapper; +} + +std::string SysrepoCallback::create_message(sysrepo::S_Change change) { + std::string change_details; + sysrepo::S_Val new_val = change->new_val(); + sysrepo::S_Val old_val = change->old_val(); + + switch (change->oper()) { + case SR_OP_CREATED: + if (nullptr != new_val) { + change_details.append(CREATED).append(": ").append(new_val->to_string()); + } + break; + case SR_OP_DELETED: + if (nullptr != old_val) { + change_details.append(DELETED).append(": ").append(old_val->to_string()); + } + break; + case SR_OP_MODIFIED: + if (nullptr != old_val && nullptr != new_val) { + change_details.append(MODIFIED).append(": ").append(": old value: ").append(old_val->to_string()) + .append(", new value: ").append(new_val->to_string()); + } + break; + case SR_OP_MOVED: + if (nullptr != old_val && nullptr != new_val) { + change_details.append(MOVED).append(": ").append(new_val->to_string()) + .append(" after ").append(old_val->to_string()); + } else if (nullptr != new_val) { + change_details.append(MOVED).append(": ").append(new_val->xpath()).append(" last"); + } + break; + } + return change_details; +} + +void SysrepoCallback::print_current_config(sysrepo::S_Session session, const char *module_name) { + char select_xpath[XPATH_MAX_LEN]; + try { + snprintf(select_xpath, XPATH_MAX_LEN, "/%s:*//*", module_name); + + auto values = session->get_items(&select_xpath[0]); + if (values == nullptr) + return; + + for(unsigned int i = 0; i < values->val_cnt(); i++) + std::cout << values->val(i)->to_string(); + } catch( const std::exception& e ) { + std::cout << e.what() << std::endl; + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/SysrepoCallback.h b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/SysrepoCallback.h new file mode 100644 index 000000000..7d2cd7221 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/SysrepoCallback.h @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +#ifndef NETOPEER_CHANGE_SAVER_CPP_SYSREPOCALLBACK_H +#define NETOPEER_CHANGE_SAVER_CPP_SYSREPOCALLBACK_H +#include "KafkaWrapper.h" +#include "sysrepo/Session.hpp" +#include + +class SysrepoCallback: public sysrepo::Callback { +private: + std::shared_ptr kafkaWrapper; + +public: + explicit SysrepoCallback(std::shared_ptr wrapper); + void print_current_config(sysrepo::S_Session session, const char *module_name); + +private: + std::string create_message(sysrepo::S_Change change); + int module_change(sysrepo::S_Session sess, const char *module_name, sr_notif_event_t event, void *private_ctx); + +}; + + +#endif //NETOPEER_CHANGE_SAVER_CPP_SYSREPOCALLBACK_H diff --git a/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/libsysrepo-cpp.so b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/libsysrepo-cpp.so new file mode 100755 index 000000000..efdcc135d Binary files /dev/null and b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/libsysrepo-cpp.so differ diff --git a/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/main.cpp b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/main.cpp new file mode 100644 index 000000000..0329f0552 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/main.cpp @@ -0,0 +1,48 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +#include +#include +#include "Application.h" + +volatile int exit_application = 0; + +void sigint_handler(int signum) { + std::cout << "Interrupt signal (" << signum << ") received." << std::endl; + exit_application = 1; +} + +int main(int argc, char *argv[]) { + if (argc != 4) { + std::cerr<<"Usage: "< "<, Lukas Macko + * @brief Sysrepo Client Library public API. + * + * @copyright + * Copyright 2015 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. + */ + +#ifndef SYSREPO_H_ +#define SYSREPO_H_ + +/** + * @defgroup cl Client Library + * @{ + * + * @brief Provides the public API towards applications using sysrepo to store + * their configuration data, or towards management agents. + * + * Communicates with Sysrepo Engine (@ref cm), which is running either inside + * of dedicated sysrepo daemon, or within this library if daemon is not alive. + * + * Access to the sysrepo datastore is connection- and session- oriented. Before + * calling any data access/manipulation API, one needs to connect to the datastore + * via ::sr_connect and open a session via ::sr_session_start. One connection + * can serve multiple sessions. + * + * Each data access/manipulation request call is blocking - blocks the connection + * until the response from Sysrepo Engine comes, or until an error occurs. It is + * safe to call multiple requests on the same session (or different session that + * belongs to the same connection) from multiple threads at the same time, + * however it is not effective, since each call is blocked until previous one + * finishes. If you need fast multi-threaded access to sysrepo, use a dedicated + * connection for each thread. + * + * @see + * See @ref main_page "Sysrepo Introduction" for details about sysrepo architecture. + * @see + * @ref xp_page "XPath Addressing" is used for node identification in data-related calls. + */ + +#include +#include +#include +#include +#ifdef __APPLE__ + #include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Common typedefs and API +//////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Sysrepo connection context used to identify a connection to sysrepo datastore. + */ +typedef struct sr_conn_ctx_s sr_conn_ctx_t; + +/** + * @brief Sysrepo session context used to identify a configuration session. + */ +typedef struct sr_session_ctx_s sr_session_ctx_t; + +/** + * @brief Memory context used for efficient memory management for values, trees and GPB messages. + */ +typedef struct sr_mem_ctx_s sr_mem_ctx_t; + +/** + * @brief Possible types of an data element stored in the sysrepo datastore. + */ +typedef enum sr_type_e { + /* special types that does not contain any data */ + SR_UNKNOWN_T, /**< Element unknown to sysrepo (unsupported element). */ + SR_TREE_ITERATOR_T, /**< Special type of tree node used to store all data needed for iterative tree loading. */ + + SR_LIST_T, /**< List instance. ([RFC 6020 sec 7.8](http://tools.ietf.org/html/rfc6020#section-7.8)) */ + SR_CONTAINER_T, /**< Non-presence container. ([RFC 6020 sec 7.5](http://tools.ietf.org/html/rfc6020#section-7.5)) */ + SR_CONTAINER_PRESENCE_T, /**< Presence container. ([RFC 6020 sec 7.5.1](http://tools.ietf.org/html/rfc6020#section-7.5.1)) */ + SR_LEAF_EMPTY_T, /**< A leaf that does not hold any value ([RFC 6020 sec 9.11](http://tools.ietf.org/html/rfc6020#section-9.11)) */ + SR_NOTIFICATION_T, /**< Notification instance ([RFC 7095 sec 7.16](https://tools.ietf.org/html/rfc7950#section-7.16)) */ + + /* types containing some data */ + SR_BINARY_T, /**< Base64-encoded binary data ([RFC 6020 sec 9.8](http://tools.ietf.org/html/rfc6020#section-9.8)) */ + SR_BITS_T, /**< A set of bits or flags ([RFC 6020 sec 9.7](http://tools.ietf.org/html/rfc6020#section-9.7)) */ + SR_BOOL_T, /**< A boolean value ([RFC 6020 sec 9.5](http://tools.ietf.org/html/rfc6020#section-9.5)) */ + SR_DECIMAL64_T, /**< 64-bit signed decimal number ([RFC 6020 sec 9.3](http://tools.ietf.org/html/rfc6020#section-9.3)) */ + SR_ENUM_T, /**< A string from enumerated strings list ([RFC 6020 sec 9.6](http://tools.ietf.org/html/rfc6020#section-9.6)) */ + SR_IDENTITYREF_T, /**< A reference to an abstract identity ([RFC 6020 sec 9.10](http://tools.ietf.org/html/rfc6020#section-9.10)) */ + SR_INSTANCEID_T, /**< References a data tree node ([RFC 6020 sec 9.13](http://tools.ietf.org/html/rfc6020#section-9.13)) */ + SR_INT8_T, /**< 8-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ + SR_INT16_T, /**< 16-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ + SR_INT32_T, /**< 32-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ + SR_INT64_T, /**< 64-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ + SR_STRING_T, /**< Human-readable string ([RFC 6020 sec 9.4](http://tools.ietf.org/html/rfc6020#section-9.4)) */ + SR_UINT8_T, /**< 8-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ + SR_UINT16_T, /**< 16-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ + SR_UINT32_T, /**< 32-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ + SR_UINT64_T, /**< 64-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ + SR_ANYXML_T, /**< Unknown chunk of XML ([RFC 6020 sec 7.10](https://tools.ietf.org/html/rfc6020#section-7.10)) */ + SR_ANYDATA_T, /**< Unknown set of nodes, encoded in XML ([RFC 7950 sec 7.10](https://tools.ietf.org/html/rfc7950#section-7.10)) */ +} sr_type_t; + +/** + * @brief Data of an element (if applicable), properly set according to the type. + */ +typedef union sr_data_u { + char *binary_val; /**< Base64-encoded binary data ([RFC 6020 sec 9.8](http://tools.ietf.org/html/rfc6020#section-9.8)) */ + char *bits_val; /**< A set of bits or flags ([RFC 6020 sec 9.7](http://tools.ietf.org/html/rfc6020#section-9.7)) */ + bool bool_val; /**< A boolean value ([RFC 6020 sec 9.5](http://tools.ietf.org/html/rfc6020#section-9.5)) */ + double decimal64_val; /**< 64-bit signed decimal number ([RFC 6020 sec 9.3](http://tools.ietf.org/html/rfc6020#section-9.3)) */ + char *enum_val; /**< A string from enumerated strings list ([RFC 6020 sec 9.6](http://tools.ietf.org/html/rfc6020#section-9.6)) */ + char *identityref_val; /**< A reference to an abstract identity ([RFC 6020 sec 9.10](http://tools.ietf.org/html/rfc6020#section-9.10)) */ + char *instanceid_val; /**< References a data tree node ([RFC 6020 sec 9.13](http://tools.ietf.org/html/rfc6020#section-9.13)) */ + int8_t int8_val; /**< 8-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ + int16_t int16_val; /**< 16-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ + int32_t int32_val; /**< 32-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ + int64_t int64_val; /**< 64-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ + char *string_val; /**< Human-readable string ([RFC 6020 sec 9.4](http://tools.ietf.org/html/rfc6020#section-9.4)) */ + uint8_t uint8_val; /**< 8-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ + uint16_t uint16_val; /**< 16-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ + uint32_t uint32_val; /**< 32-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ + uint64_t uint64_val; /**< 64-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ + char *anyxml_val; /**< Unknown chunk of XML ([RFC 6020 sec 7.10](https://tools.ietf.org/html/rfc6020#section-7.10)) */ + char *anydata_val; /**< Unknown set of nodes, encoded in XML ([RFC 7950 sec 7.10](https://tools.ietf.org/html/rfc7950#section-7.10)) */ +} sr_data_t; + +/** + * @brief Structure that contains value of an data element stored in the sysrepo datastore. + */ +typedef struct sr_val_s { + /** + * Memory context used internally by Sysrepo for efficient storage + * and conversion of this structure. + */ + sr_mem_ctx_t *_sr_mem; + + /** + * XPath identifier of the data element, as defined in + * @ref xp_page "Path Addressing" documentation + */ + char *xpath; + + /** Type of an element. */ + sr_type_t type; + + /** + * Flag for node with default value (applicable only for leaves). + * It is set to TRUE only if the value was *implicitly* set by the datastore as per + * module schema. Explicitly set/modified data element (through the sysrepo API) always + * has this flag unset regardless of the entered value. + */ + bool dflt; + + /** Data of an element (if applicable), properly set according to the type. */ + sr_data_t data; + +} sr_val_t; + +/** + * @brief A data element stored in the sysrepo datastore represented as a tree node. + * + * @note Can be safely casted to ::sr_val_t, only *xpath* member will point to node name rather + * than to an actual xpath. + */ +typedef struct sr_node_s { + /** + * Memory context used internally by Sysrepo for efficient storage + * and conversion of this structure. + */ + sr_mem_ctx_t *_sr_mem; + + /** Name of the node. */ + char *name; + + /** Type of an element. */ + sr_type_t type; + + /** Flag for default node (applicable only for leaves). */ + bool dflt; + + /** Data of an element (if applicable), properly set according to the type. */ + sr_data_t data; + + /** + * Name of the module that defines scheme of this node. + * NULL if it is the same as that of the predecessor. + */ + char *module_name; + + /** Pointer to the parent node (NULL in case of root node). */ + struct sr_node_s *parent; + + /** Pointer to the next sibling node (NULL if there is no one). */ + struct sr_node_s *next; + + /** Pointer to the previous sibling node (NULL if there is no one). */ + struct sr_node_s *prev; + + /** Pointer to the first child node (NULL if this is a leaf). */ + struct sr_node_s *first_child; + + /** Pointer to the last child node (NULL if this is a leaf). */ + struct sr_node_s *last_child; +} sr_node_t; + +/** + * @brief Sysrepo error codes. + */ +typedef enum sr_error_e { + SR_ERR_OK = 0, /**< No error. */ + SR_ERR_INVAL_ARG, /**< Invalid argument. */ + SR_ERR_NOMEM, /**< Not enough memory. */ + SR_ERR_NOT_FOUND, /**< Item not found. */ + SR_ERR_INTERNAL, /**< Other internal error. */ + SR_ERR_INIT_FAILED, /**< Sysrepo infra initialization failed. */ + SR_ERR_IO, /**< Input/Output error. */ + SR_ERR_DISCONNECT, /**< The peer disconnected. */ + SR_ERR_MALFORMED_MSG, /**< Malformed message. */ + SR_ERR_UNSUPPORTED, /**< Unsupported operation requested. */ + SR_ERR_UNKNOWN_MODEL, /**< Request includes unknown schema */ + SR_ERR_BAD_ELEMENT, /**< Unknown element in existing schema */ + SR_ERR_VALIDATION_FAILED, /**< Validation of the changes failed. */ + SR_ERR_OPERATION_FAILED, /**< An operation failed. */ + SR_ERR_DATA_EXISTS, /**< Item already exists. */ + SR_ERR_DATA_MISSING, /**< Item does not exists. */ + SR_ERR_UNAUTHORIZED, /**< Operation not authorized. */ + SR_ERR_INVAL_USER, /**< Invalid username. */ + SR_ERR_LOCKED, /**< Requested resource is already locked. */ + SR_ERR_TIME_OUT, /**< Time out has expired. */ + SR_ERR_RESTART_NEEDED, /**< Sysrepo Engine restart is needed. */ + SR_ERR_VERSION_MISMATCH, /**< Incompatible client library used to communicate with sysrepo. */ +} sr_error_t; + +/** + * @brief Detailed sysrepo error information. + */ +typedef struct sr_error_info_s { + const char *message; /**< Error message. */ + const char *xpath; /**< XPath to the node where the error has been discovered. */ +} sr_error_info_t; + +/** + * @brief Returns the error message corresponding to the error code. + * + * @param[in] err_code Error code. + * + * @return Error message (statically allocated, do not free). + */ +const char *sr_strerror(int err_code); + +/** + * @brief Log levels used to determine if message of certain severity should be printed. + */ +typedef enum { + SR_LL_NONE, /**< Do not print any messages. */ + SR_LL_ERR, /**< Print only error messages. */ + SR_LL_WRN, /**< Print error and warning messages. */ + SR_LL_INF, /**< Besides errors and warnings, print some other informational messages. */ + SR_LL_DBG, /**< Print all messages including some development debug messages. */ +} sr_log_level_t; + +/** + * @brief Enables / disables / changes log level (verbosity) of logging to + * standard error output. + * + * By default, logging to stderr is disabled. Setting log level to any value + * other than SR_LL_NONE enables the logging to stderr. Setting log level + * back to SR_LL_NONE disables the logging to stderr. + * + * @param[in] log_level requested log level (verbosity). + */ +void sr_log_stderr(sr_log_level_t log_level); + +/** + * @brief Enables / disables / changes log level (verbosity) of logging to system log. + * + * By default, logging into syslog is disabled. Setting log level to any value + * other than SR_LL_NONE enables the logging into syslog. Setting log level + * back to SR_LL_NONE disables the logging into syslog. + * + * @note Please note that enabling logging into syslog will overwrite your syslog + * connection settings (calls openlog), if you are connected to syslog already. + * + * @param[in] log_level requested log level (verbosity). + */ +void sr_log_syslog(sr_log_level_t log_level); + +/** + * @brief Sets callback that will be called when a log entry would be populated. + * + * @param[in] level Verbosity level of the log entry. + * @param[in] message Message of the log entry. + */ +typedef void (*sr_log_cb)(sr_log_level_t level, const char *message); + +/** + * @brief Sets callback that will be called when a log entry would be populated. + * Callback will be called for each message with any log level. + * + * @param[in] log_callback Callback to be called when a log entry would populated. + */ +void sr_log_set_cb(sr_log_cb log_callback); + + +//////////////////////////////////////////////////////////////////////////////// +// Connection / Session Management +//////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Flags used to override default connection handling by ::sr_connect call. + */ +typedef enum sr_conn_flag_e { + SR_CONN_DEFAULT = 0, /**< Default behavior - instantiate library-local Sysrepo Engine if + the connection to sysrepo daemon is not possible. */ + SR_CONN_DAEMON_REQUIRED = 1, /**< Require daemon connection - do not instantiate library-local Sysrepo Engine + if the library cannot connect to the sysrepo daemon (and return an error instead). */ + SR_CONN_DAEMON_START = 2, /**< If sysrepo daemon is not running, and SR_CONN_DAEMON_REQUIRED was specified, + start it (only if the process calling ::sr_connect is running under root privileges). */ +} sr_conn_flag_t; + +/** + * @brief Options overriding default connection handling by ::sr_connect call, + * it is supposed to be bitwise OR-ed value of any ::sr_conn_flag_t flags. + */ +typedef uint32_t sr_conn_options_t; + +/** + * @brief Flags used to override default session handling (used by ::sr_session_start + * and ::sr_session_start_user calls). + */ +typedef enum sr_session_flag_e { + SR_SESS_DEFAULT = 0, /**< Default (normal) session behavior. */ + SR_SESS_CONFIG_ONLY = 1, /**< Session will process only configuration data (e.g. sysrepo won't + return any state data by ::sr_get_items / ::sr_get_items_iter calls). */ + SR_SESS_ENABLE_NACM = 2, /**< Enable NETCONF access control for this session (disabled by default). */ + + SR_SESS_MUTABLE_OPTS = 3 /**< Bit-mask of options that can be set by the user + (immutable flags are defined in sysrepo.proto file). */ +} sr_session_flag_t; + +/** + * @brief Options overriding default connection session handling, + * it is supposed to be bitwise OR-ed value of any ::sr_session_flag_t flags. + */ +typedef uint32_t sr_sess_options_t; + +/** + * @brief Data stores that sysrepo supports. Both are editable via implicit candidate. + * To make changes permanent in edited datastore ::sr_commit must be issued. + * @see @ref ds_page "Datastores & Sessions" information page. + */ +typedef enum sr_datastore_e { + SR_DS_STARTUP = 0, /**< Contains configuration data that should be loaded by the controlled application when it starts. */ + SR_DS_RUNNING = 1, /**< Contains currently applied configuration and state data of a running application. + @note This datastore is supported only by applications that subscribe for notifications + about the changes made in the datastore (e.g. ::sr_module_change_subscribe). */ + SR_DS_CANDIDATE = 2, /**< Contains configuration that can be manipulated without impacting the current configuration. + Its content is set to the content of running datastore by default. Changes made within + the candidate can be later committed to the running datastore or copied to any datastore. + + @note The main difference between working with running and candidate datastore is in commit + operation - commit of candidate session causes the content of running configuration to be set + the value of the candidate configuration (running datastore is overwritten), whereas commit of + runnnig session merges the changes made within the session with the actual state of running. */ +} sr_datastore_t; + +/** + * @brief Connects to the sysrepo datastore (Sysrepo Engine). + * + * @note If the client library loses connection to the Sysrepo Engine during + * the lifetime of the application, all Sysrepo API calls will start returning + * ::SR_ERR_DISCONNECT error on active sessions. In this case, the application is supposed to reconnect + * with another ::sr_connect call and restart all lost sessions. + * + * @param[in] app_name Name of the application connecting to the datastore + * (can be a static string). Used only for accounting purposes. + * @param[in] opts Options overriding default connection handling by this call. + * @param[out] conn_ctx Connection context that can be used for subsequent API calls + * (automatically allocated, it is supposed to be released by the caller using ::sr_disconnect). + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_connect(const char *app_name, const sr_conn_options_t opts, sr_conn_ctx_t **conn_ctx); + +/** + * @brief Disconnects from the sysrepo datastore (Sysrepo Engine). + * + * Cleans up and frees connection context allocated by ::sr_connect. All sessions + * started within the connection will be automatically stopped and cleaned up too. + * + * @param[in] conn_ctx Connection context acquired with ::sr_connect call. + */ +void sr_disconnect(sr_conn_ctx_t *conn_ctx); + +/** + * @brief Starts a new configuration session. + * + * @see @ref ds_page "Datastores & Sessions" for more information about datastores and sessions. + * + * @param[in] conn_ctx Connection context acquired with ::sr_connect call. + * @param[in] datastore Datastore on which all sysrepo functions within this + * session will operate. Later on, datastore can be later changed using + * ::sr_session_switch_ds call. Functionality of some sysrepo calls does not depend on + * datastore. If your session will contain just calls like these, you can pass + * any valid value (e.g. SR_RUNNING). + * @param[in] opts Options overriding default session handling. + * @param[out] session Session context that can be used for subsequent API + * calls (automatically allocated, can be released by calling ::sr_session_stop). + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_session_start(sr_conn_ctx_t *conn_ctx, const sr_datastore_t datastore, + const sr_sess_options_t opts, sr_session_ctx_t **session); + +/** + * @brief Starts a new configuration session on behalf of a different user. + * + * This call is intended for northbound access to sysrepo from management + * applications, that need sysrepo to authorize the operations not only + * against the user under which the management application is running, but + * also against another user (e.g. user that connected to the management application). + * + * @note Be aware that authorization of specified user may fail with unexpected + * errors in case that the client library uses its own Sysrepo Engine at the + * moment and your process in not running under root privileges. To prevent + * this situation, consider specifying SR_CONN_DAEMON_REQUIRED flag by + * ::sr_connect call or using ::sr_session_start instead of this function. + * + * @see @ref ds_page "Datastores & Sessions" for more information about datastores and sessions. + * + * @param[in] conn_ctx Connection context acquired with ::sr_connect call. + * @param[in] user_name Effective user name used to authorize the access to + * datastore (in addition to automatically-detected real user name). + * @param[in] datastore Datastore on which all sysrepo functions within this + * session will operate. Functionality of some sysrepo calls does not depend on + * datastore. If your session will contain just calls like these, you can pass + * any valid value (e.g. SR_RUNNING). + * @param[in] opts Options overriding default session handling. + * @param[out] session Session context that can be used for subsequent API calls + * (automatically allocated, it is supposed to be released by caller using ::sr_session_stop). + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_session_start_user(sr_conn_ctx_t *conn_ctx, const char *user_name, const sr_datastore_t datastore, + const sr_sess_options_t opts, sr_session_ctx_t **session); + +/** + * @brief Stops current session and releases resources tied to the session. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_session_stop(sr_session_ctx_t *session); + +/** + * @brief Refreshes configuration data cached within the session and starts + * operating on fresh data loaded from the datastore. + * + * Call this function in case that you leave session open for longer time period + * and you expect that the data in the datastore may have been changed since + * last data (re)load (which occurs by ::sr_session_start, ::sr_commit and + * ::sr_discard_changes). + * + * @see @ref ds_page "Datastores & Sessions" for information about session data caching. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_session_refresh(sr_session_ctx_t *session); + +/** + * @brief Checks aliveness and validity of the session & connection tied to it. + * + * If the connection to the Sysrepo Engine has been lost in the meantime, returns SR_ERR_DICONNECT. + * In this case, the application is supposed to stop the session (::sr_session_stop), disconnect (::sr_disconnect) + * and then reconnect (::sr_connect) and start a new session (::sr_session_start). + * + * @note If the client library loses connection to the Sysrepo Engine during the lifetime of the application, + * all Sysrepo API calls will start returning SR_ERR_DISCONNECT error on active sessions. This is the primary + * mechanism that can be used to detect connection issues, ::sr_session_check is just an addition to it. Since + * ::sr_session_check sends a message to the Sysrepo Engine and waits for the response, it costs some extra overhead + * in contrast to catching SR_ERR_DISCONNECT error. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * + * @return Error code (SR_ERR_OK in case that the session is healthy, + * SR_ERR_DICONNECT in case that connection to the Sysrepo Engine has been lost). + */ +int sr_session_check(sr_session_ctx_t *session); + +/** + * @brief Changes datastore to which the session is tied to. All subsequent + * calls will be issued on the chosen datastore. + * + * @param [in] session + * @param [in] ds + * @return Error code (SR_ERR_OK on success) + */ +int sr_session_switch_ds(sr_session_ctx_t *session, sr_datastore_t ds); + +/** + * @brief Alter the session options. E.g.: set/unset SR_SESS_CONFIG_ONLY flag. + * + * @param [in] session + * @param [in] opts - new value for session options + * @return Error code (SR_ERR_OK on success) + */ +int sr_session_set_options(sr_session_ctx_t *session, const sr_sess_options_t opts); + +/** + * @brief Retrieves detailed information about the error that has occurred + * during the last operation executed within provided session. + * + * If multiple errors has occurred within the last operation, only the first + * one is returned. This call is sufficient for all data retrieval and data + * manipulation functions that operate on single-item basis. For operations + * such as ::sr_validate or ::sr_commit where multiple errors can occur, + * use ::sr_get_last_errors instead. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[out] error_info Detailed error information. Be aware that + * returned pointer may change by the next API call executed within the provided + * session, so it's not safe to use this function by concurrent access to the + * same session within multiple threads. Do not free or modify returned values. + * + * @return Error code of the last operation executed within provided session. + */ +int sr_get_last_error(sr_session_ctx_t *session, const sr_error_info_t **error_info); + +/** + * @brief Retrieves detailed information about all errors that have occurred + * during the last operation executed within provided session. + * + * Use this call instead of ::sr_get_last_error by operations where multiple + * errors can occur, such as ::sr_validate or ::sr_commit. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[out] error_info Array of detailed error information. Be aware that + * returned pointer may change by the next API call executed within the provided + * session, so it's not safe to use this function by concurrent access to the + * same session within multiple threads. Do not free or modify returned values. + * @param[out] error_cnt Number of errors returned in the error_info array. + * + * @return Error code of the last operation executed within provided session. + */ +int sr_get_last_errors(sr_session_ctx_t *session, const sr_error_info_t **error_info, size_t *error_cnt); + +/** + * @brief Sets detailed error information into provided session. Used to notify + * the client library about errors that occurred in application code. + * + * @note Intended for commit verifiers (notification session) - the call has no + * impact on any other sessions. + * + * @param[in] session Session context passed into notification callback. + * @param[in] message Human-readable error message. + * @param[in] xpath XPath to the node where the error has occurred. NULL value + * is also accepted. + * + * @return Error code (SR_ERR_OK on success) + */ +int sr_set_error(sr_session_ctx_t *session, const char *message, const char *xpath); + +/** + * @brief Returns the assigned id of the session. Can be used to pair the session with + * netconf-config-change notification initiator. + * @param [in] session + * @return session id or 0 in case of error + */ +uint32_t sr_session_get_id(sr_session_ctx_t *session); + +//////////////////////////////////////////////////////////////////////////////// +// Data Retrieval API (get / get-config functionality) +//////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Structure that contains information about one particular schema file installed in sysrepo. + */ +typedef struct sr_sch_revision_s { + const char *revision; /**< Revision of the module/submodule. */ + const char *file_path_yang; /**< Absolute path to file where the module/submodule is stored (YANG format). */ + const char *file_path_yin; /**< Absolute path to file where the module/submodule is stored (.yin format). */ +} sr_sch_revision_t; + +/** + * @brief Structure that contains information about submodules of a module installed in sysrepo. + */ +typedef struct sr_sch_submodule_s { + const char *submodule_name; /**< Submodule name. */ + sr_sch_revision_t revision; /**< Revision of the submodule. */ +} sr_sch_submodule_t; + +/** + * @brief Structure that contains information about a module installed in sysrepo. + */ +typedef struct sr_schema_s { + /** + * Memory context used internally by Sysrepo for efficient storage + * and conversion of this structure. + */ + sr_mem_ctx_t *_sr_mem; + + const char *module_name; /**< Name of the module. */ + const char *ns; /**< Namespace of the module used in @ref xp_page "XPath". */ + const char *prefix; /**< Prefix of the module. */ + bool installed; /**< TRUE if the module was explicitly installed. */ + bool implemented; /**< TRUE if the module is implemented (does not have to be installed), + not just imported. */ + + sr_sch_revision_t revision; /**< Revision the module. */ + + sr_sch_submodule_t *submodules; /**< Array of all installed submodules of the module. */ + size_t submodule_count; /**< Number of module's submodules. */ + + char **enabled_features; /**< Array of enabled features */ + size_t enabled_feature_cnt; /**< Number of enabled feature */ +} sr_schema_t; + +/** + * @brief Format types of ::sr_get_schema result + */ +typedef enum sr_schema_format_e { + SR_SCHEMA_YANG, /**< YANG format */ + SR_SCHEMA_YIN /**< YIN format */ +} sr_schema_format_t; + +/** + * @brief Iterator used for accessing data nodes via ::sr_get_items_iter call. + */ +typedef struct sr_val_iter_s sr_val_iter_t; + +/** + * @brief Retrieves list of schemas installed in the sysrepo datastore. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[out] schemas Array of installed schemas information (allocated by + * the function, it is supposed to be freed by caller using ::sr_free_schemas call). + * @param[out] schema_cnt Number of schemas returned in the array. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_list_schemas(sr_session_ctx_t *session, sr_schema_t **schemas, size_t *schema_cnt); + +/** + * @brief Retrieves the content of specified schema file. If the module + * can not be found SR_ERR_NOT_FOUND is returned. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] module_name Name of the requested module. + * @param[in] revision Requested revision of the module. If NULL + * is passed, the latest revision will be returned. + * @param[in] submodule_name Name of the requested submodule. Pass NULL if you are + * requesting the content of the main module. + * @param[in] format of the returned schema + * @param[out] schema_content Content of the specified schema file. Automatically + * allocated by the function, should be freed by the caller. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_get_schema(sr_session_ctx_t *session, const char *module_name, const char *revision, + const char *submodule_name, sr_schema_format_t format, char **schema_content); + +/** + * @brief Retrieves the content of the specified submodule schema file. If the submodule + * cannot be found, SR_ERR_NOT_FOUND is returned. + * + * @param[in] session Session context acquired from ::sr_session_start call. + * @param[in] submodule_name Name of the requested submodule. + * @param[in] submodule_revision Requested revision of the submodule. If NULL + * is passed, the latest revision will be returned. + * @param[in] format of the returned schema. + * @param[out] schema_content Content of the specified schema file. Automatically + * allocated by the function, should be freed by the caller. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_get_submodule_schema(sr_session_ctx_t *session, const char *submodule_name, const char *submodule_revision, + sr_schema_format_t format, char **schema_content); + +/** + * @brief Retrieves a single data element stored under provided XPath. If multiple + * nodes matches the xpath SR_ERR_INVAL_ARG is returned. + * + * If the xpath identifies an empty leaf, a list or a container, the value + * has no data filled in and its type is set properly (SR_LEAF_EMPTY_T / SR_LIST_T / SR_CONTAINER_T / SR_CONTAINER_PRESENCE_T). + * + * @see @ref xp_page "Path Addressing" documentation, or + * https://tools.ietf.org/html/draft-ietf-netmod-yang-json#section-6.11 + * for XPath syntax used for identification of yang nodes in sysrepo calls. + * + * @see Use ::sr_get_items or ::sr_get_items_iter for retrieving larger chunks + * of data from the datastore. Since they retrieve the data from datastore in + * larger chunks, they can work much more efficiently than multiple ::sr_get_item calls. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Data Path" identifier of the data element to be retrieved. + * @param[out] value Structure containing information about requested element + * (allocated by the function, it is supposed to be freed by the caller using ::sr_free_val). + * + * @return Error code (SR_ERR_OK on success) + */ +int sr_get_item(sr_session_ctx_t *session, const char *xpath, sr_val_t **value); + +/** + * @brief Retrieves an array of data elements matching provided XPath + * + * All data elements are transferred within one message from the datastore, + * which is much more efficient that calling multiple ::sr_get_item calls. + * + * If the user does not have read permission to access certain nodes, these + * won't be part of the result. SR_ERR_NOT_FOUND will be returned if there are + * no nodes matching xpath in the data tree, or the user does not have read permission to access them. + * + * If the response contains too many elements time out may be exceeded, SR_ERR_TIME_OUT + * will be returned, use ::sr_get_items_iter. + * + * @see @ref xp_page "Path Addressing" documentation + * for Path syntax used for identification of yang nodes in sysrepo calls. + * + * @see ::sr_get_items_iter can be used for the same purpose as ::sr_get_items + * call if you expect that ::sr_get_items could return too large data sets. + * Since ::sr_get_items_iter also retrieves the data from datastore in larger chunks, + * in can still work very efficiently for large datasets. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Data Path" identifier of the data element to be retrieved. + * @param[out] values Array of structures containing information about requested data elements + * (allocated by the function, it is supposed to be freed by the caller using ::sr_free_values). + * @param[out] value_cnt Number of returned elements in the values array. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_get_items(sr_session_ctx_t *session, const char *xpath, sr_val_t **values, size_t *value_cnt); + +/** + * @brief Creates an iterator for retrieving of the data elements stored under provided xpath. + * + * Requested data elements are transferred from the datastore in larger chunks + * of pre-defined size, which is much more efficient that calling multiple + * ::sr_get_item calls, and may be less memory demanding than calling ::sr_get_items + * on very large datasets. + * + * @see @ref xp_page "Path Addressing" documentation, or + * https://tools.ietf.org/html/draft-ietf-netmod-yang-json#section-6.11 + * for XPath syntax used for identification of yang nodes in sysrepo calls. + * + * @see ::sr_get_item_next for iterating over returned data elements. + * @note Iterator allows to iterate through the values once. To start iteration + * from the beginning new iterator must be created. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Data Path" identifier of the data element / subtree to be retrieved. + * @param[out] iter Iterator context that can be used to retrieve individual data + * elements via ::sr_get_item_next calls. Allocated by the function, should be + * freed with ::sr_free_val_iter. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_get_items_iter(sr_session_ctx_t *session, const char *xpath, sr_val_iter_t **iter); + +/** + * @brief Returns the next item from the dataset of provided iterator created + * by ::sr_get_items_iter call. If there is no item left SR_ERR_NOT_FOUND is returned. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in,out] iter Iterator acquired with ::sr_get_items_iter call. + * @param[out] value Structure containing information about requested element + * (allocated by the function, it is supposed to be freed by the caller using ::sr_free_val). + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_get_item_next(sr_session_ctx_t *session, sr_val_iter_t *iter, sr_val_t **value); + +/** + * @brief Flags used to customize the behaviour of ::sr_get_subtree and ::sr_get_subtrees calls. + */ +typedef enum sr_get_subtree_flag_e { + /** + * Default get-subtree(s) behaviour. + * All matched subtrees are sent with all their content in one message. + */ + SR_GET_SUBTREE_DEFAULT = 0, + + /** + * The iterative get-subtree(s) behaviour. + * The matched subtrees are sent in chunks and only as needed while they are iterated + * through using functions ::sr_node_get_child, ::sr_node_get_next_sibling and + * ::sr_node_get_parent from "sysrepo/trees.h". This behaviour gives much better + * performance than the default one if only a small portion of matched subtree(s) is + * actually iterated through. + * @note It is considered a programming error to access \p next, \p prev, \p parent, + * \p first_child and \p last_child data members of ::sr_node_t on a partially loaded tree. + */ + SR_GET_SUBTREE_ITERATIVE = 1 +} sr_get_subtree_flag_t; + +/** + * @brief Options for get-subtree and get-subtrees operations. + * It is supposed to be bitwise OR-ed value of any ::sr_get_subtree_flag_t flags. + */ +typedef uint32_t sr_get_subtree_options_t; + +/** + * @brief Retrieves a single subtree whose root node is stored under the provided XPath. + * If multiple nodes matches the xpath SR_ERR_INVAL_ARG is returned. + * + * The functions returns values and all associated information stored under the root node and + * all its descendants. While the same data can be obtained using ::sr_get_items in combination + * with the expressive power of XPath addressing, the recursive nature of the output data type + * also preserves the hierarchical relationships between data elements. + * + * Values of internal nodes of the subtree have no data filled in and their type is set properly + * (SR_LIST_T / SR_CONTAINER_T / SR_CONTAINER_PRESENCE_T), whereas leaf nodes are carrying actual + * data (apart from SR_LEAF_EMPTY_T). + * + * @see @ref xp_page "Path Addressing" documentation + * for XPath syntax used for identification of yang nodes in sysrepo calls. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Data Path" identifier referencing the root node of the subtree to be retrieved. + * @param[in] opts Options overriding default behavior of this operation. + * @param[out] subtree Nested structure storing all data of the requested subtree + * (allocated by the function, it is supposed to be freed by the caller using ::sr_free_tree). + * + * @return Error code (SR_ERR_OK on success) + */ +int sr_get_subtree(sr_session_ctx_t *session, const char *xpath, sr_get_subtree_options_t opts, + sr_node_t **subtree); + +/** + * @brief Retrieves an array of subtrees whose root nodes match the provided XPath. + * + * If the user does not have read permission to access certain nodes, these together with + * their descendants won't be part of the result. SR_ERR_NOT_FOUND will be returned if there are + * no nodes matching xpath in the data tree, or the user does not have read permission to access them. + * + * Subtrees that match the provided XPath are not merged even if they overlap. This significantly + * simplifies the implementation and decreases the cost of this operation. The downside is that + * the user must choose the XPath carefully. If the subtree selection process results in too many + * node overlaps, the cost of the operation may easily outshine the benefits. As an example, + * a common XPath expression "//." is normally used to select all nodes in a data tree, but for this + * operation it would result in an excessive duplication of transfered data elements. + * Since you get all the descendants of each matched node implicitly, you probably should not need + * to use XPath wildcards deeper than on the top-level. + * (i.e. "/." is preferred alternative to "//." for get-subtrees operation). + * + * If the response contains too many elements time out may be exceeded, SR_ERR_TIME_OUT + * will be returned. + * + * @see @ref xp_page "Path Addressing" documentation, or + * https://tools.ietf.org/html/draft-ietf-netmod-yang-json#section-6.11 + * for XPath syntax used for identification of yang nodes in sysrepo calls. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Data Path" identifier referencing root nodes of subtrees to be retrieved. + * @param[in] opts Options overriding default behavior of this operation. + * @param[out] subtrees Array of nested structures storing all data of the requested subtrees + * (allocated by the function, it is supposed to be freed by the caller using ::sr_free_trees). + * @param[out] subtree_cnt Number of returned trees in the subtrees array. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_get_subtrees(sr_session_ctx_t *session, const char *xpath, sr_get_subtree_options_t opts, + sr_node_t **subtrees, size_t *subtree_cnt); + + +//////////////////////////////////////////////////////////////////////////////// +// Data Manipulation API (edit-config functionality) +//////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Flags used to override default behavior of data manipulation calls. + */ +typedef enum sr_edit_flag_e { + SR_EDIT_DEFAULT = 0, /**< Default behavior - recursive and non-strict. */ + SR_EDIT_NON_RECURSIVE = 1, /**< Non-recursive behavior: + by ::sr_set_item, all preceding nodes (parents) of the identified element must exist, + by ::sr_delete_item xpath must not identify an non-empty list or non-empty container. */ + SR_EDIT_STRICT = 2 /**< Strict behavior: + by ::sr_set_item the identified element must not exist (similar to netconf create operation), + by ::sr_delete_item the identified element must exist (similar to netconf delete operation). */ +} sr_edit_flag_t; + +/** + * @brief Options overriding default behavior of data manipulation calls, + * it is supposed to be bitwise OR-ed value of any ::sr_edit_flag_t flags. + */ +typedef uint32_t sr_edit_options_t; + +/** + * @brief Options for specifying move direction of ::sr_move_item call. + */ +typedef enum sr_move_position_e { + SR_MOVE_BEFORE = 0, /**< Move the specified item before the selected sibling. */ + SR_MOVE_AFTER = 1, /**< Move the specified item after the selected. */ + SR_MOVE_FIRST = 2, /**< Move the specified item to the position of the first child. */ + SR_MOVE_LAST = 3, /**< Move the specified item to the position of the last child. */ +} sr_move_position_t; + +/** + * @brief Sets the value of the leaf, leaf-list, list or presence container. + * + * With default options it recursively creates all missing nodes (containers and + * lists including their key leaves) in the xpath to the specified node (can be + * turned off with SR_EDIT_NON_RECURSIVE option). If SR_EDIT_STRICT flag is set, + * the node must not exist (otherwise an error is returned). + * + * To create a list use xpath with key values included and pass NULL as value argument. + * + * Setting of a leaf-list value appends the value at the end of the leaf-list. + * A value of leaf-list can be specified either by predicate in xpath or by value argument. + * If both are present, value argument is ignored and xpath predicate is used. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Data Path" identifier of the data element to be set. + * @param[in] value Value to be set on specified xpath. xpath member of the + * ::sr_val_t structure can be NULL. Value will be copied - can be allocated on stack. + * @param[in] opts Options overriding default behavior of this call. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_set_item(sr_session_ctx_t *session, const char *xpath, const sr_val_t *value, const sr_edit_options_t opts); + + +/** + * @brief Functions is similar to ::sr_set_item with the difference that the value to be set + * is provided as string. + * @param [in] session Session context acquired with ::sr_session_start call. + * @param [in] xpath @ref xp_page "Data Path" identifier of the data element to be set. + * @param [in] value string representation of the value to be set + * @param [in] opts same as for ::sr_set_item + * @return Error code (SR_ERR_OK on success). + */ +int sr_set_item_str(sr_session_ctx_t *session, const char *xpath, const char *value, const sr_edit_options_t opts); +/** + * @brief Deletes the nodes under the specified xpath. + * + * To delete non-empty lists or containers SR_EDIT_NON_RECURSIVE flag must not be set. + * If SR_EDIT_STRICT flag is set the specified node must must exist in the datastore. + * If the xpath includes the list keys, the specified list instance is deleted. + * If the xpath to list does not include keys, all instances of the list are deleted. + * SR_ERR_UNAUTHORIZED will be returned if the user does not have write permission to any affected node. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Data Path" identifier of the data element to be deleted. + * @param[in] opts Options overriding default behavior of this call. + * + * @return Error code (SR_ERR_OK on success). + **/ +int sr_delete_item(sr_session_ctx_t *session, const char *xpath, const sr_edit_options_t opts); + +/** + * @brief Move the instance of an user-ordered list or leaf-list to the specified position. + * + * Item can be move to the first or last position or positioned relatively to its sibling. + * @note To determine current order, you can issue a ::sr_get_items call + * (without specifying keys of the list in question). + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Data Path" identifier of the data element to be moved. + * @param[in] position Requested move direction. + * @param[in] relative_item xpath Identifier of the data element that is used + * to determine relative position, used only if position argument is SR_MOVE_BEFORE or SR_MOVE_AFTER. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_move_item(sr_session_ctx_t *session, const char *xpath, const sr_move_position_t position, const char *relative_item); + +/** + * @brief Perform the validation of changes made in current session, but do not + * commit nor discard them. + * + * Provides only YANG validation, commit verify subscribers won't be notified in this case. + * + * @see Use ::sr_get_last_errors to retrieve error information if the validation + * returned with an error. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_validate(sr_session_ctx_t *session); + +/** + * @brief Apply changes made in current session. + * + * @note Note that in case that you are committing to the running datstore, you also + * need to copy the config to startup to make changes permanent after restart. + * + * @see Use ::sr_get_last_errors to retrieve error information if the commit + * operation returned with an error. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_commit(sr_session_ctx_t *session); + +/** + * @brief Discard non-committed changes made in current session. + * + * @note Since the function effectively clears all the cached data within the session, + * the next operation will operate on fresh data loaded from the datastore + * (i.e. no need to call ::sr_session_refresh afterwards). + * + * @param[in] session Session context acquired with ::sr_session_start call. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_discard_changes(sr_session_ctx_t *session); + +/** + * @brief Replaces an entire configuration datastore with the contents of + * another complete configuration datastore. If the module is specified, limits + * the copy operation only to one specified module. If it's not specified, + * the operation is performed on all modules that are currently active in the + * source datastore. + * + * If the target datastore exists, it is overwritten. Otherwise, a new one is created. + * + * @note ::sr_session_refresh is needed to see the result of a copy-config operation + * in a session apart from the case when SR_DS_CANDIDATE is the destination datastore. + * Since the candidate is not shared among sessions, data trees are copied only to the + * canidate in the session issuing the copy-config operation. + * + * @note Operation may fail, if it tries to copy a not enabled configuration to the + * running datastore. + * + * @note \p session \p dst_datastore uncommitted changes will get discarded. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] module_name If specified, only limits the copy operation only to + * one specified module. + * @param[in] src_datastore Source datastore. + * @param[in] dst_datastore Destination datastore. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_copy_config(sr_session_ctx_t *session, const char *module_name, + sr_datastore_t src_datastore, sr_datastore_t dst_datastore); + + +//////////////////////////////////////////////////////////////////////////////// +// Locking API +//////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Locks the datastore which the session is tied to. If there is + * a module locked by the other session SR_ERR_LOCKED is returned. + * Operation fails if there is a modified data tree in session. + * + * All data models within the datastore will be locked for writing until + * ::sr_unlock_datastore is called or until the session is stopped or terminated + * for any reason. + * + * The lock operation will not be allowed if the user does not have sufficient + * permissions for writing into each of the data models in the datastore. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_lock_datastore(sr_session_ctx_t *session); + +/** + * @brief Unlocks the datastore which the session is tied to. + * + * All data models within the datastore will be unlocked if they were locked + * by this session. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_unlock_datastore(sr_session_ctx_t *session); + +/** + * @brief Locks specified data module within the datastore which the session + * is tied to. Operation fails if the data tree has been modified. + * + * Specified data module will be locked for writing in the datastore until + * ::sr_unlock_module is called or until the session is stopped or terminated + * for any reason. + * + * The lock operation will not be allowed if the user does not have sufficient + * permissions for writing into the specified data module. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] module_name Name of the module to be locked. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_lock_module(sr_session_ctx_t *session, const char *module_name); + +/** + * @brief Unlocks specified data module within the datastore which the session + * is tied to. + * + * Specified data module will be unlocked if was locked in the datastore + * by this session. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] module_name Name of the module to be unlocked. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_unlock_module(sr_session_ctx_t *session, const char *module_name); + + +//////////////////////////////////////////////////////////////////////////////// +// Change Notifications API +//////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Flags used to override default handling of subscriptions. + */ +typedef enum sr_subscr_flag_e { + /** + * @brief Default behavior of the subscription. In case of ::sr_module_change_subscribe and + * ::sr_subtree_change_subscribe calls it means that: + * + * - the subscriber is the "owner" of the subscribed data tree and and the data tree will be enabled in the running + * datastore while this subscription is alive (if not already, can be changed using ::SR_SUBSCR_PASSIVE flag), + * - configuration data of the subscribed module or subtree is copied from startup to running datastore + * (only if the module was not enabled before), + * - the callback will be called twice, once with ::SR_EV_VERIFY event and once with ::SR_EV_APPLY / ::SR_EV_ABORT + * event passed in (can be changed with ::SR_SUBSCR_APPLY_ONLY flag). + */ + SR_SUBSCR_DEFAULT = 0, + + /** + * @brief This option enables the application to re-use an already existing subscription context previously returned + * from any sr_*_subscribe call instead of requesting the creation of a new one. In that case a single + * ::sr_unsubscribe call unsubscribes from all subscriptions filed within the context. + */ + SR_SUBSCR_CTX_REUSE = 1, + + /** + * @brief The subscriber is not the "owner" of the subscribed data tree, just a passive watcher for changes. + * When this option is passed in to ::sr_module_change_subscribe or ::sr_subtree_change_subscribe, + * the subscription will have no effect on the presence of the subtree in the running datastore. + */ + SR_SUBSCR_PASSIVE = 2, + + /** + * @brief The subscriber does not support verification of the changes and wants to be notified only after + * the changes has been applied in the datastore, without the possibility to deny them + * (it will receive only ::SR_EV_APPLY events). + */ + SR_SUBSCR_APPLY_ONLY = 4, + + /** + * @brief The subscriber wants ::SR_EV_ENABLED notifications to be sent to them. + */ + SR_SUBSCR_EV_ENABLED = 8, + + /** + * @brief The subscriber will not receive ::SR_EV_ABORT if he returns an error in verify phase + * (if the commit is refused by other verifier ::SR_EV_ABORT will be delivered). + */ + SR_SUBSCR_NO_ABORT_FOR_REFUSED_CFG = 16, + + /** + * @brief No real-time notifications will be delivered until ::sr_event_notif_replay is called + * and replay has finished (::SR_EV_NOTIF_T_REPLAY_COMPLETE is delivered). + */ + SR_SUBSCR_NOTIF_REPLAY_FIRST = 32, +} sr_subscr_flag_t; + +/** + * @brief Type of the notification event that has occurred (passed to notification callbacks). + * + * @note Each change is normally notified twice: first as ::SR_EV_VERIFY event and then as ::SR_EV_APPLY or ::SR_EV_ABORT + * event. If the subscriber does not support verification, it can subscribe only to ::SR_EV_APPLY event by providing + * ::SR_SUBSCR_APPLY_ONLY subscription flag. + */ +typedef enum sr_notif_event_e { + SR_EV_VERIFY, /**< Occurs just before the changes are committed to the datastore, + the subscriber is supposed to verify that the changes are valid and can be applied + and prepare all resources required for the changes. The subscriber can still deny the changes + in this phase by returning an error from the callback. */ + SR_EV_APPLY, /**< Occurs just after the changes have been successfully committed to the datastore, + the subscriber is supposed to apply the changes now, but it cannot deny the changes in this + phase anymore (any returned errors are just logged and ignored). */ + SR_EV_ABORT, /**< Occurs in case that the commit transaction has failed (possibly because one of the verifiers + has denied the change / returned an error). The subscriber is supposed to return the managed + application to the state before the commit. Any returned errors are just logged and ignored. */ + SR_EV_ENABLED, /**< Occurs just after the subscription. Subscriber gets notified about configuration that was copied + from startup to running. This allows to reuse the callback for applying changes made in running to + reflect the changes when the configuration is copied from startup to running during subscription process */ +} sr_notif_event_t; + +/** + * @brief Type of the operation made on an item, used by changeset retrieval in ::sr_get_change_next. + */ +typedef enum sr_change_oper_e { + SR_OP_CREATED, /**< The item has been created by the change. */ + SR_OP_MODIFIED, /**< The value of the item has been modified by the change. */ + SR_OP_DELETED, /**< The item has been deleted by the change. */ + SR_OP_MOVED, /**< The item has been moved in the subtree by the change (applicable for leaf-lists and user-ordered lists). */ +} sr_change_oper_t; + +/** + * @brief State of a module as returned by the ::sr_module_install_cb callback. + */ +typedef enum sr_module_state_e { + SR_MS_UNINSTALLED, /**< The module is not installed in the sysrepo repository. */ + SR_MS_IMPORTED, /**< The module has been implicitly installed into the sysrepo repository + as it is imported by another implemented/imported module. */ + SR_MS_IMPLEMENTED /**< The module has been explicitly installed into the sysrepo repository by the user. */ +} sr_module_state_t; + +/** + * @brief Sysrepo subscription context returned from sr_*_subscribe calls, + * it is supposed to be released by the caller using ::sr_unsubscribe call. + */ +typedef struct sr_subscription_ctx_s sr_subscription_ctx_t; + +/** + * @brief Iterator used for retrieval of a changeset using ::sr_get_changes_iter call. + */ +typedef struct sr_change_iter_s sr_change_iter_t; + +/** + * @brief Options overriding default behavior of subscriptions, + * it is supposed to be a bitwise OR-ed value of any ::sr_subscr_flag_t flags. + */ +typedef uint32_t sr_subscr_options_t; + +/** + * @brief Callback to be called by the event of changing any running datastore + * content within the specified module. Subscribe to it by ::sr_module_change_subscribe call. + * + * @param[in] session Automatically-created session that can be used for obtaining changed data + * (e.g. by ::sr_get_changes_iter call ot ::sr_get_item -like calls). Do not stop this session. + * @param[in] module_name Name of the module where the change has occurred. + * @param[in] event Type of the notification event that has occurred. + * @param[in] private_ctx Private context opaque to sysrepo, as passed to + * ::sr_module_change_subscribe call. + */ +typedef int (*sr_module_change_cb)(sr_session_ctx_t *session, const char *module_name, + sr_notif_event_t event, void *private_ctx); + +/** + * @brief Callback to be called by the event of changing any running datastore + * content within the specified subtree. Subscribe to it by ::sr_subtree_change_subscribe call. + * + * @param[in] session Automatically-created session that can be used for obtaining changed data + * (e.g. by ::sr_get_changes_iter call or ::sr_get_item -like calls). Do not stop this session. + * @param[in] xpath @ref xp_page "Data Path" of the subtree where the change has occurred. + * @param[in] event Type of the notification event that has occurred. + * @param[in] private_ctx Private context opaque to sysrepo, as passed to + * ::sr_subtree_change_subscribe call. + */ +typedef int (*sr_subtree_change_cb)(sr_session_ctx_t *session, const char *xpath, + sr_notif_event_t event, void *private_ctx); + +/** + * @brief Callback to be called by the event of installation / uninstallation + * of a new module into sysrepo. Subscribe to it by ::sr_module_install_subscribe call. + * + * @param[in] module_name Name of the newly installed / uinstalled module. + * @param[in] revision Revision of the newly installed module (if specified + * within the YANG model). + * @param[in] state The new state of the module (uninstalled vs. imported vs. implemented). + * @param[in] private_ctx Private context opaque to sysrepo, as passed to + * ::sr_module_install_subscribe call. + */ +typedef void (*sr_module_install_cb)(const char *module_name, const char *revision, sr_module_state_t state, + void *private_ctx); + +/** + * @brief Callback to be called by the event of enabling / disabling of + * a YANG feature within a module. Subscribe to it by ::sr_feature_enable_subscribe call. + * + * @param[in] module_name Name of the module where the feature has been enabled / disabled. + * @param[in] feature_name Name of the feature that has been enabled / disabled. + * @param[in] enabled TRUE if the feature has been enabled, FALSE if disabled. + * @param[in] private_ctx Private context opaque to sysrepo, as passed to + * ::sr_feature_enable_subscribe call. + */ +typedef void (*sr_feature_enable_cb)(const char *module_name, const char *feature_name, bool enabled, void *private_ctx); + +/** + * @brief Subscribes for notifications about the changes made within specified + * module in running datastore. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] module_name Name of the module of interest for change notifications. + * @param[in] callback Callback to be called when the change in the datastore occurs. + * @param[in] private_ctx Private context passed to the callback function, opaque to sysrepo. + * @param[in] priority Specifies the order in which the callbacks will be called (callbacks with higher + * priority will be called sooner, callbacks with the priority of 0 will be called at the end). + * @param[in] opts Options overriding default behavior of the subscription, it is supposed to be + * a bitwise OR-ed value of any ::sr_subscr_flag_t flags. + * @param[in,out] subscription Subscription context that is supposed to be released by ::sr_unsubscribe. + * @note An existing context may be passed in in case that SR_SUBSCR_CTX_REUSE option is specified. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_module_change_subscribe(sr_session_ctx_t *session, const char *module_name, sr_module_change_cb callback, + void *private_ctx, uint32_t priority, sr_subscr_options_t opts, sr_subscription_ctx_t **subscription); + +/** + * @brief Subscribes for notifications about the changes made within specified + * subtree in running datastore. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Data Path" identifier of the subtree of the interest for change notifications. + * @param[in] callback Callback to be called when the change in the datastore occurs. + * @param[in] private_ctx Private context passed to the callback function, opaque to sysrepo. + * @param[in] priority Specifies the order in which the callbacks will be called (callbacks with higher + * priority will be called sooner, callbacks with the priority of 0 will be called at the end). + * @param[in] opts Options overriding default behavior of the subscription, it is supposed to be + * a bitwise OR-ed value of any ::sr_subscr_flag_t flags. + * @param[in,out] subscription Subscription context that is supposed to be released by ::sr_unsubscribe. + * @note An existing context may be passed in in case that SR_SUBSCR_CTX_REUSE option is specified. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_subtree_change_subscribe(sr_session_ctx_t *session, const char *xpath, sr_subtree_change_cb callback, + void *private_ctx, uint32_t priority, sr_subscr_options_t opts, sr_subscription_ctx_t **subscription); + +/** + * @brief Subscribes for notifications about installation / uninstallation + * of a new module into sysrepo. + * + * Mainly intended for northbound management applications that need to be + * always aware of all active modules installed in sysrepo. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] callback Callback to be called when the event occurs. + * @param[in] private_ctx Private context passed to the callback function, opaque to sysrepo. + * @param[in] opts Options overriding default behavior of the subscription, it is supposed to be + * a bitwise OR-ed value of any ::sr_subscr_flag_t flags. + * @param[in,out] subscription Subscription context that is supposed to be released by ::sr_unsubscribe. + * @note An existing context may be passed in in case that SR_SUBSCR_CTX_REUSE option is specified. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_module_install_subscribe(sr_session_ctx_t *session, sr_module_install_cb callback, void *private_ctx, + sr_subscr_options_t opts, sr_subscription_ctx_t **subscription); + +/** + * @brief Subscribes for notifications about enabling / disabling of + * a YANG feature within a module. + * + * Mainly intended for northbound management applications that need to be + * always aware of all active features within the modules installed in sysrepo. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] callback Callback to be called when the event occurs. + * @param[in] private_ctx Private context passed to the callback function, opaque to sysrepo. + * @param[in] opts Options overriding default behavior of the subscription, it is supposed to be + * a bitwise OR-ed value of any ::sr_subscr_flag_t flags. + * @param[in,out] subscription Subscription context that is supposed to be released by ::sr_unsubscribe. + * @note An existing context may be passed in in case that SR_SUBSCR_CTX_REUSE option is specified. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_feature_enable_subscribe(sr_session_ctx_t *session, sr_feature_enable_cb callback, void *private_ctx, + sr_subscr_options_t opts, sr_subscription_ctx_t **subscription); + +/** + * @brief Unsubscribes from a subscription acquired by any of sr_*_subscribe + * calls and releases all subscription-related data. + * + * @note In case that the same subscription context was used to subscribe for + * multiple subscriptions, unsubscribes from all of them. + * + * @param[in] session Session context acquired with ::sr_session_start call. Does not + * need to be the same as used for subscribing. NULL can be passed too, in that case + * a temporary session used for unsubscribe will be automatically created by sysrepo. + * @param[in] subscription Subscription context acquired by any of sr_*_subscribe calls. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_unsubscribe(sr_session_ctx_t *session, sr_subscription_ctx_t *subscription); + +/** + * @brief Creates an iterator for retrieving of the changeset (list of newly + * added / removed / modified nodes) in notification callbacks. + * + * @see ::sr_get_change_next for iterating over the changeset using this iterator. + * + * @param[in] session Session context as passed to notication the callbacks (e.g. + * ::sr_module_change_cb or ::sr_subtree_change_cb). Will not work with any other sessions. + * @param[in] xpath @ref xp_page "Data Path" identifier of the subtree from which the changeset + * should be obtained. Only XPaths that would be accepted by ::sr_subtree_change_subscribe are allowed. + * @param[out] iter Iterator context that can be used to retrieve individual changes using + * ::sr_get_change_next calls. Allocated by the function, should be freed with ::sr_free_change_iter. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_get_changes_iter(sr_session_ctx_t *session, const char *xpath, sr_change_iter_t **iter); + +/** + * @brief Returns the next change from the changeset of provided iterator created + * by ::sr_get_changes_iter call. If there is no item left, SR_ERR_NOT_FOUND is returned. + * + * @note If the operation is ::SR_OP_MOVED the meaning of new_value and old value argument is + * as follows - the value pointed by new_value was moved after the old_value. If the + * old value is NULL it was moved to the first position. + * + * @param[in] session Session context as passed to notication the callbacks (e.g. + * ::sr_module_change_cb or ::sr_subtree_change_cb). Will not work with any other sessions. + * @param[in,out] iter Iterator acquired with ::sr_get_changes_iter call. + * @param[out] operation Type of the operation made on the returned item. + * @param[out] old_value Old value of the item (the value before the change). + * NULL in case that the item has been just created (operation == SR_OP_CREATED). + * @param[out] new_value New (modified) value of the the item. NULL in case that + * the item has been just deleted (operation == SR_OP_DELETED). + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_get_change_next(sr_session_ctx_t *session, sr_change_iter_t *iter, sr_change_oper_t *operation, + sr_val_t **old_value, sr_val_t **new_value); + + +//////////////////////////////////////////////////////////////////////////////// +// RPC (Remote Procedure Calls) API +//////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Check if the owner of this session is authorized by NACM to invoke the protocol + * operation defined in a (installed) YANG module under the given xpath (as RPC or Action). + * + * This call is intended for northbound management applications that need to implement + * the NETCONF Access Control Model (RFC 6536) to restrict the protocol operations that + * each user is authorized to execute. + * + * NETCONF access control is already included in the processing of ::sr_rpc_send, + * ::sr_rpc_send_tree, ::sr_action_send and ::sr_action_send_tree and thus it should be + * sufficient to call this function only prior to executing any of the NETCONF standard + * protocol operations as they cannot be always directly translated to a single sysrepo + * API call. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Data Path" identifying the protocol operation. + * @param[out] permitted TRUE if the user is permitted to execute the given operation, FALSE otherwise. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_check_exec_permission(sr_session_ctx_t *session, const char *xpath, bool *permitted); + +/** + * @brief Callback to be called by the delivery of RPC specified by xpath. + * Subscribe to it by ::sr_rpc_subscribe call. + * + * @param[in] xpath @ref xp_page "Data Path" identifying the RPC. + * @param[in] input Array of input parameters. + * @param[in] input_cnt Number of input parameters. + * @param[out] output Array of output parameters. Should be allocated on heap, + * will be freed by sysrepo after sending of the RPC response. + * @param[out] output_cnt Number of output parameters. + * @param[in] private_ctx Private context opaque to sysrepo, as passed to ::sr_rpc_subscribe call. + * + * @return Error code (SR_ERR_OK on success). + */ +typedef int (*sr_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); + +/** + * @brief Callback to be called by the delivery of RPC specified by xpath. + * This RPC callback variant operates with sysrepo trees rather than with sysrepo values, + * use it with ::sr_rpc_subscribe_tree and ::sr_rpc_send_tree. + * + * @param[in] xpath @ref xp_page "Data Path" identifying the RPC. + * @param[in] input Array of input parameters (represented as trees). + * @param[in] input_cnt Number of input parameters. + * @param[out] output Array of output parameters (represented as trees). Should be allocated on heap, + * will be freed by sysrepo after sending of the RPC response. + * @param[out] output_cnt Number of output parameters. + * @param[in] private_ctx Private context opaque to sysrepo, as passed to ::sr_rpc_subscribe_tree call. + * + * @return Error code (SR_ERR_OK on success). + */ +typedef int (*sr_rpc_tree_cb)(const char *xpath, const sr_node_t *input, const size_t input_cnt, + sr_node_t **output, size_t *output_cnt, void *private_ctx); + +/** + * @brief Subscribes for delivery of RPC specified by xpath. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Schema Path" identifying the RPC. + * @param[in] callback Callback to be called when the RPC is called. + * @param[in] private_ctx Private context passed to the callback function, opaque to sysrepo. + * @param[in] opts Options overriding default behavior of the subscription, it is supposed to be + * a bitwise OR-ed value of any ::sr_subscr_flag_t flags. + * @param[in,out] subscription Subscription context that is supposed to be released by ::sr_unsubscribe. + * @note An existing context may be passed in case that SR_SUBSCR_CTX_REUSE option is specified. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_rpc_subscribe(sr_session_ctx_t *session, const char *xpath, sr_rpc_cb callback, void *private_ctx, + sr_subscr_options_t opts, sr_subscription_ctx_t **subscription); + +/** + * @brief Subscribes for delivery of RPC specified by xpath. Unlike ::sr_rpc_subscribe, this + * function expects callback of type ::sr_rpc_tree_cb, therefore use this version if you prefer + * to manipulate with RPC input and output data organized in a list of trees rather than as a flat + * enumeration of all values. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Schema Path" identifying the RPC. + * @param[in] callback Callback to be called when the RPC is called. + * @param[in] private_ctx Private context passed to the callback function, opaque to sysrepo. + * @param[in] opts Options overriding default behavior of the subscription, it is supposed to be + * a bitwise OR-ed value of any ::sr_subscr_flag_t flags. + * @param[in,out] subscription Subscription context that is supposed to be released by ::sr_unsubscribe. + * @note An existing context may be passed in case that SR_SUBSCR_CTX_REUSE option is specified. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_rpc_subscribe_tree(sr_session_ctx_t *session, const char *xpath, sr_rpc_tree_cb callback, + void *private_ctx, sr_subscr_options_t opts, sr_subscription_ctx_t **subscription); + +/** + * @brief Sends a RPC specified by xpath and waits for the result. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Data Path" identifying the RPC. + * @param[in] input Array of input parameters (array of all nodes that hold some + * data in RPC input subtree - same as ::sr_get_items would return). + * @param[in] input_cnt Number of input parameters. + * @param[out] output Array of output parameters (all nodes that hold some data + * in RPC output subtree). Will be allocated by sysrepo and should be freed by + * caller using ::sr_free_values. + * @param[out] output_cnt Number of output parameters. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_rpc_send(sr_session_ctx_t *session, const char *xpath, + const sr_val_t *input, const size_t input_cnt, sr_val_t **output, size_t *output_cnt); + +/** + * @brief Sends a RPC specified by xpath and waits for the result. Input and output data + * are represented as arrays of subtrees reflecting the scheme of RPC arguments. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Data Path" identifying the RPC. + * @param[in] input Array of input parameters (organized in trees). + * @param[in] input_cnt Number of input parameters. + * @param[out] output Array of output parameters (organized in trees). + * Will be allocated by sysrepo and should be freed by caller using ::sr_free_trees. + * @param[out] output_cnt Number of output parameters. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_rpc_send_tree(sr_session_ctx_t *session, const char *xpath, + const sr_node_t *input, const size_t input_cnt, sr_node_t **output, size_t *output_cnt); + + +//////////////////////////////////////////////////////////////////////////////// +// Action API +//////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Callback to be called by the delivery of Action (operation connected to a specific data node) + * specified by xpath. Subscribe to it by ::sr_action_subscribe call. + * @see This type is an alias for @ref sr_rpc_cb "the RPC callback type" + */ +typedef sr_rpc_cb sr_action_cb; + +/** + * @brief Callback to be called by the delivery of Action (operation connected to a specific data node) + * specified by xpath. + * This callback variant operates with sysrepo trees rather than with sysrepo values, + * use it with ::sr_action_subscribe_tree and ::sr_action_send_tree. + * @see This type is an alias for tree variant of @ref sr_rpc_tree_cb "the RPC callback " + */ +typedef sr_rpc_tree_cb sr_action_tree_cb; + +/** + * @brief Subscribes for delivery of Action specified by xpath. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Schema Path" identifying the Action. + * @param[in] callback Callback to be called when the Action is called. + * @param[in] private_ctx Private context passed to the callback function, opaque to sysrepo. + * @param[in] opts Options overriding default behavior of the subscription, it is supposed to be + * a bitwise OR-ed value of any ::sr_subscr_flag_t flags. + * @param[in,out] subscription Subscription context that is supposed to be released by ::sr_unsubscribe. + * @note An existing context may be passed in case that SR_SUBSCR_CTX_REUSE option is specified. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_action_subscribe(sr_session_ctx_t *session, const char *xpath, sr_action_cb callback, void *private_ctx, + sr_subscr_options_t opts, sr_subscription_ctx_t **subscription); + +/** + * @brief Subscribes for delivery of Action specified by xpath. Unlike ::sr_action_subscribe, this + * function expects callback of type ::sr_action_tree_cb, therefore use this version if you prefer + * to manipulate with Action input and output data organized in a list of trees rather than as a flat + * enumeration of all values. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Schema Path" identifying the Action. + * @param[in] callback Callback to be called when the Action is called. + * @param[in] private_ctx Private context passed to the callback function, opaque to sysrepo. + * @param[in] opts Options overriding default behavior of the subscription, it is supposed to be + * a bitwise OR-ed value of any ::sr_subscr_flag_t flags. + * @param[in,out] subscription Subscription context that is supposed to be released by ::sr_unsubscribe. + * @note An existing context may be passed in case that SR_SUBSCR_CTX_REUSE option is specified. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_action_subscribe_tree(sr_session_ctx_t *session, const char *xpath, sr_action_tree_cb callback, + void *private_ctx, sr_subscr_options_t opts, sr_subscription_ctx_t **subscription); + +/** + * @brief Executes an action specified by xpath and waits for the result. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Data Path" identifying the Action. + * @param[in] input Array of input parameters (array of all nodes that hold some + * data in Action input subtree - same as ::sr_get_items would return). + * @param[in] input_cnt Number of input parameters. + * @param[out] output Array of output parameters (all nodes that hold some data + * in Action output subtree). Will be allocated by sysrepo and should be freed by + * caller using ::sr_free_values. + * @param[out] output_cnt Number of output parameters. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_action_send(sr_session_ctx_t *session, const char *xpath, + const sr_val_t *input, const size_t input_cnt, sr_val_t **output, size_t *output_cnt); + +/** + * @brief Executes an action specified by xpath and waits for the result. Input and output data + * are represented as arrays of subtrees reflecting the scheme of Action arguments. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Data Path" identifying the Action. + * @param[in] input Array of input parameters (organized in trees). + * @param[in] input_cnt Number of input parameters. + * @param[out] output Array of output parameters (organized in trees). + * Will be allocated by sysrepo and should be freed by caller using ::sr_free_trees. + * @param[out] output_cnt Number of output parameters. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_action_send_tree(sr_session_ctx_t *session, const char *xpath, + const sr_node_t *input, const size_t input_cnt, sr_node_t **output, size_t *output_cnt); + + +//////////////////////////////////////////////////////////////////////////////// +// Event Notifications API +//////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Type of the notification passed to the ::sr_event_notif_cb and ::sr_event_notif_tree_cb callbacks. + */ +typedef enum sr_ev_notif_type_e { + SR_EV_NOTIF_T_REALTIME, /**< Real-time notification. The only possible type if you don't use ::sr_event_notif_replay. */ + SR_EV_NOTIF_T_REPLAY, /**< Replayed notification. */ + SR_EV_NOTIF_T_REPLAY_COMPLETE, /**< Not a real notification, just a signal that the notification replay has completed + (all the stored notifications from the given time interval have been delivered). */ + SR_EV_NOTIF_T_REPLAY_STOP, /**< Not a real notification, just a signal that replay stop time has been reached + (delivered only if stop_time was specified to ::sr_event_notif_replay). */ +} sr_ev_notif_type_t; + +/** + * @brief Flags used to override default notification handling i the datastore. + */ +typedef enum sr_ev_notif_flag_e { + SR_EV_NOTIF_DEFAULT = 0, /**< Notification will be handled normally. */ + SR_EV_NOTIF_EPHEMERAL = 1, /**< Notification will not be stored in the notification store + (and therefore will be also delivered faster). */ +} sr_ev_notif_flag_t; + +/** + * @brief Callback to be called by the delivery of event notification specified by xpath. + * Subscribe to it by ::sr_event_notif_subscribe call. + * + * @param[in] notif_type Type of the notification. + * @param[in] xpath @ref xp_page "Data Path" identifying the event notification. + * @param[in] values Array of all nodes that hold some data in event notification subtree. + * @param[in] values_cnt Number of items inside the values array. + * @param[in] timestamp Time when the notification was generated + * @param[in] private_ctx Private context opaque to sysrepo, + * as passed to ::sr_event_notif_subscribe call. + * + * @return Error code (SR_ERR_OK on success). + */ +typedef void (*sr_event_notif_cb)(const sr_ev_notif_type_t notif_type, const char *xpath, + const sr_val_t *values, const size_t values_cnt, time_t timestamp, void *private_ctx); + +/** + * @brief Callback to be called by the delivery of event notification specified by xpath. + * This callback variant operates with sysrepo trees rather than with sysrepo values, + * use it with ::sr_event_notif_subscribe_tree and ::sr_event_notif_send_tree. + * + * @param[in] notif_type Type of the notification. + * @param[in] xpath @ref xp_page "Data Path" identifying the event notification. + * @param[in] trees Array of subtrees carrying event notification data. + * @param[in] tree_cnt Number of subtrees with data. + * @param[in] timestamp Time when the notification was generated + * @param[in] private_ctx Private context opaque to sysrepo, as passed to ::sr_event_notif_subscribe_tree call. + * + * @return Error code (SR_ERR_OK on success). + */ +typedef void (*sr_event_notif_tree_cb)(const sr_ev_notif_type_t notif_type, const char *xpath, + const sr_node_t *trees, const size_t tree_cnt, time_t timestamp, void *private_ctx); + +/** + * @brief Subscribes for delivery of an event notification specified by xpath. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Schema Path" identifying one event notification or special + * path in the form of a module name in which the whole module is subscribed to. + * @param[in] callback Callback to be called when the event notification is send. + * @param[in] private_ctx Private context passed to the callback function, opaque to sysrepo. + * @param[in] opts Options overriding default behavior of the subscription, it is supposed to be + * a bitwise OR-ed value of any ::sr_subscr_flag_t flags. + * @param[in,out] subscription Subscription context that is supposed to be released by ::sr_unsubscribe. + * @note An existing context may be passed in case that SR_SUBSCR_CTX_REUSE option is specified. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_event_notif_subscribe(sr_session_ctx_t *session, const char *xpath, + sr_event_notif_cb callback, void *private_ctx, sr_subscr_options_t opts, + sr_subscription_ctx_t **subscription); + +/** + * @brief Subscribes for delivery of event notification specified by xpath. + * Unlike ::sr_event_notif_subscribe, this function expects callback of type ::sr_event_notif_tree_cb, + * therefore use this version if you prefer to manipulate with event notification data organized + * in a list of trees rather than as a flat enumeration of all values. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Schema Path" identifying one event notification or special + * path in the form of a module name in which the whole module is subscribed to. + * @param[in] callback Callback to be called when the event notification is called. + * @param[in] private_ctx Private context passed to the callback function, opaque to sysrepo. + * @param[in] opts Options overriding default behavior of the subscription, it is supposed to be + * a bitwise OR-ed value of any ::sr_subscr_flag_t flags. + * @param[in,out] subscription Subscription context that is supposed to be released by ::sr_unsubscribe. + * @note An existing context may be passed in case that SR_SUBSCR_CTX_REUSE option is specified. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_event_notif_subscribe_tree(sr_session_ctx_t *session, const char *xpath, + sr_event_notif_tree_cb callback, void *private_ctx, sr_subscr_options_t opts, + sr_subscription_ctx_t **subscription); + +/** + * @brief Sends an event notification specified by xpath and waits for the result. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Data Path" identifying the event notification. + * @param[in] values Array of all nodes that hold some data in event notification subtree + * (same as ::sr_get_items would return). + * @param[in] values_cnt Number of items inside the values array. + * @param[in] opts Options overriding default handling of the notification, it is supposed to be + * a bitwise OR-ed value of any ::sr_ev_notif_flag_t flags. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_event_notif_send(sr_session_ctx_t *session, const char *xpath, const sr_val_t *values, + const size_t values_cnt, sr_ev_notif_flag_t opts); + +/** + * @brief Sends an event notification specified by xpath and waits for the result. + * The notification data are represented as arrays of subtrees reflecting the scheme + * of the event notification. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Data Path" identifying the RPC. + * @param[in] trees Array of subtrees carrying event notification data. + * @param[in] tree_cnt Number of subtrees with data. + * @param[in] opts Options overriding default handling of the notification, it is supposed to be + * a bitwise OR-ed value of any ::sr_ev_notif_flag_t flags. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_event_notif_send_tree(sr_session_ctx_t *session, const char *xpath, const sr_node_t *trees, + const size_t tree_cnt, sr_ev_notif_flag_t opts); + +/** + * @brief Replays already generated notifications stored in the notification store related to + * the provided notification subscription (or subscriptions, in case that ::SR_SUBSCR_CTX_REUSE + * was used). Notification callbacks of the given susbscriptions will be called with the type set to + * ::SR_EV_NOTIF_T_REPLAY, ::SR_EV_NOTIF_T_REPLAY_COMPLETE or ::SR_EV_NOTIF_T_REPLAY_STOP. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] subscription Session context acquired with ::sr_session_start call. + * @param[in] start_time Starting time of the desired time window for notification replay. + * @param[in] stop_time End time of the desired time window for notification replay. If set to 0, + * no stop time will be applied (all notifications up to the current time will be delivered, + * ::SR_EV_NOTIF_T_REPLAY_STOP notification won't be delivered). + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_event_notif_replay(sr_session_ctx_t *session, sr_subscription_ctx_t *subscription, + time_t start_time, time_t stop_time); + + +//////////////////////////////////////////////////////////////////////////////// +// Operational Data API +//////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Callback to be called when operational data at the selected level is requested. + * Subscribe to it by ::sr_dp_get_items_subscribe call. + * + * Callback handler is supposed to provide data of all nodes at the level selected by the xpath argument: + * + * - If the xpath identifies a container, the provider is supposed to return all leaves and leaf-lists values within it. + * Nested lists and containers should not be provided - sysrepo will ask for them in subsequent calls. + * - If the xpath identifies a list, the provider is supposed to return all leaves (except for keys!) and + * leaf-lists values within all instances of the list. Nested lists and containers should not be provided - sysrepo + * will ask for them in subsequent calls. + * - If the xpath identifies a leaf-list, the provider is supposed to return all leaf-list values. + * - If the xpath identifies a leaf, the provider is supposed to return just the leaf in question. + * + * The xpath argument passed to callback can be only the xpath that was used for the subscription, or xpath of + * any nested lists or containers. + * + * @param[in] xpath @ref xp_page "Data Path" identifying the level under which the nodes are requested. + * @param[out] values Array of values at the selected level (allocated by the provider). + * @param[out] values_cnt Number of values returned. + * @param[in] request_id An ID identifying the originating request. + * @param[in] private_ctx Private context opaque to sysrepo, as passed to ::sr_dp_get_items_subscribe call. + * + * @return Error code (SR_ERR_OK on success). + */ +typedef int (*sr_dp_get_items_cb)(const char *xpath, sr_val_t **values, size_t *values_cnt, uint64_t request_id, void *private_ctx); + +/** + * @brief Registers for providing of operational data under given xpath. + * + * @note The XPath must be generic - must not include any list key values. + * @note This API works only for operational data (subtrees marked in YANG as "config false"). + * Subscribing as a data provider for configuration data does not have any effect. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] xpath @ref xp_page "Data Path" identifying the subtree under which the provider is able to provide + * operational data. + * @param[in] callback Callback to be called when the operational data nder given xpat is needed. + * @param[in] private_ctx Private context passed to the callback function, opaque to sysrepo. + * @param[in] opts Options overriding default behavior of the subscription, it is supposed to be + * a bitwise OR-ed value of any ::sr_subscr_flag_t flags. + * @param[in,out] subscription Subscription context that is supposed to be released by ::sr_unsubscribe. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_dp_get_items_subscribe(sr_session_ctx_t *session, const char *xpath, sr_dp_get_items_cb callback, void *private_ctx, + sr_subscr_options_t opts, sr_subscription_ctx_t **subscription); + + +//////////////////////////////////////////////////////////////////////////////// +// Application-local File Descriptor Watcher API +//////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Event that has occurred on a monitored file descriptor. + */ +typedef enum sr_fd_event_e { + SR_FD_INPUT_READY = 1, /**< File descriptor is now readable without blocking. */ + SR_FD_OUTPUT_READY = 2, /**< File descriptor is now writable without blocking. */ +} sr_fd_event_t; + +/** + * @brief Action that needs to be taken on a file descriptor. + */ +typedef enum sr_fd_action_s { + SR_FD_START_WATCHING, /**< Start watching for the specified event on the file descriptor. */ + SR_FD_STOP_WATCHING, /**< Stop watching for the specified event on the file descriptor. */ +} sr_fd_action_t; + +/** + * @brief Structure representing a change in the set of file descriptors monitored by the application. + */ +typedef struct sr_fd_change_s { + int fd; /**< File descriptor whose monitored state should be changed. */ + int events; /**< Monitoring events tied to the change (or-ed value of ::sr_fd_event_t). */ + sr_fd_action_t action; /**< Action that is supposed to be performed by application-local file descriptor watcher. */ +} sr_fd_change_t; + +/** + * @brief Callback when the subscription manager is terminated + */ +typedef void (*sr_fd_sm_terminated_cb)(); + +/** + * @brief Initializes application-local file descriptor watcher. + * + * This can be used in those applications that subscribe for changes or providing data in sysrepo, which have their + * own event loop that is capable of monitoring of the events on provided file descriptors. In case that the + * application-local file descriptor watcher is initialized, sysrepo client library won't use a separate thread + * for the delivery of the notifications and for calling the callbacks - they will be called from the main thread of the + * application's event loop (inside of ::sr_fd_event_process calls). + * + * @note Calling this function has global consequences on the behavior of the sysrepo client library within the process + * that called it. It is supposed to be called as the first sysrepo API call within the application. + * + * @param[out] fd Initial file descriptor that is supposed to be monitored for readable events by the application. + * Once there is an event detected on this file descriptor, the application is supposed to call ::sr_fd_event_process. + * + * @param[in] sm_terminate_cb Function to be called when the subscription manager is terminated. If this callback is provided, + * it shall block until all pending events on any file descriptor associated with sysrepo have been handled. I.e., ensure that + * the event loop has called sr_fd_event_process() for all pending events before returning from this callback. If this callback + * doesn't block, errors will be shown in the log. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_fd_watcher_init(int *fd, sr_fd_sm_terminated_cb sm_terminate_cb); + +/** + * @brief Cleans-up the application-local file descriptor watcher previously initiated by ::sr_fd_watcher_init. + * It is supposed to be called as the last sysrepo API within the application. + */ +void sr_fd_watcher_cleanup(); + +/** + * @brief Processes an event that has occurred on one of the file descriptors that the application is monitoring for + * sysrepo client library purposes. As a result of this event, another file descriptors may need to be started or + * stopped monitoring by the application. These are returned as \p fd_change_set array. + * + * @param[in] fd File descriptor where an event occurred. + * @param[in] event Type of the event that occurred on the given file descriptor. + * @param[out] fd_change_set Array of file descriptors that need to be started or stopped monitoring for specified event + * by the application. The application is supposed to free this array after it processes it. + * @param[out] fd_change_set_cnt Count of the items in the \p fd_change_set array. + * + * @return Error code (SR_ERR_OK on success). + */ +int sr_fd_event_process(int fd, sr_fd_event_t event, sr_fd_change_t **fd_change_set, size_t *fd_change_set_cnt); + + +//////////////////////////////////////////////////////////////////////////////// +// Cleanup Routines +//////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Frees ::sr_val_t structure and all memory allocated within it. + * + * @param[in] value Value to be freed. + */ +void sr_free_val(sr_val_t *value); + +/** + * @brief Frees array of ::sr_val_t structures (and all memory allocated + * within of each array element). + * + * @param[in] values Array of values to be freed. + * @param[in] count Number of elements stored in the array. + */ +void sr_free_values(sr_val_t *values, size_t count); + +/** + * @brief Frees ::sr_val_iter_t iterator and all memory allocated within it. + * + * @param[in] iter Iterator to be freed. + */ +void sr_free_val_iter(sr_val_iter_t *iter); + +/** + * @brief Frees ::sr_change_iter_t iterator and all memory allocated within it. + * + * @param[in] iter Iterator to be freed. + */ +void sr_free_change_iter(sr_change_iter_t *iter); + +/** + * @brief Frees array of ::sr_schema_t structures (and all memory allocated + * within of each array element). + * + * @param [in] schemas Array of schemas to be freed. + * @param [in] count Number of elements stored in the array. + */ +void sr_free_schemas(sr_schema_t *schemas, size_t count); + +/** + * @brief Frees sysrepo tree data. + * + * @param[in] tree Tree data to be freed. + */ +void sr_free_tree(sr_node_t *tree); + +/** + * @brief Frees array of sysrepo trees. For each tree, the ::sr_free_tree is called too. + * + * @param[in] trees + * @param[in] count length of array + */ +void sr_free_trees(sr_node_t *trees, size_t count); + +/**@} cl */ + +#ifdef __cplusplus +} +#endif + +#endif /* SYSREPO_H_ */ diff --git a/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Connection.hpp b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Connection.hpp new file mode 100644 index 000000000..eb944f72c --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Connection.hpp @@ -0,0 +1,63 @@ +/** + * @file Connection.h + * @author Mislav Novakovic + * @brief Sysrepo Connection class header. + * + * @copyright + * Copyright 2016 Deutsche Telekom AG. + * Modifications Copyright (C) 2019 Nokia. All rights reserved. + * + * 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 CONNECTION_H +#define CONNECTION_H + +#include + +#include "Sysrepo.hpp" +#include "Internal.hpp" + +extern "C" { +#include "../sysrepo.h" +} + +namespace sysrepo { + +/** + * @defgroup classes C++/Python + * @{ + */ + +/** + * @brief Class for wrapping sr_conn_ctx_t. + * @class Connection + */ +class Connection +{ +public: + /** Wrapper for [sr_connect](@ref sr_connect) */ + Connection(const char *app_name, const sr_conn_options_t opts = CONN_DEFAULT); + ~Connection(); + + sr_conn_ctx_t *_conn; + friend class Session; + +private: + sr_conn_options_t _opts; +}; + +/**@} */ +} + +#endif diff --git a/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Internal.hpp b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Internal.hpp new file mode 100644 index 000000000..aec62f9f1 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Internal.hpp @@ -0,0 +1,80 @@ +/** + * @file Internal.h + * @author Mislav Novakovic + * @brief Sysrepo class header for internal C++ classes. + * + * @copyright + * Copyright 2016 Deutsche Telekom AG. + * + * 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 INTERNAL_H +#define INTERNAL_H + +#include +#include + +extern "C" { +#include "../sysrepo.h" +#include "../sysrepo/trees.h" +} + +namespace sysrepo { + +enum class Free_Type { + VAL, + VALS, + VALS_POINTER, + TREE, + TREES, + TREES_POINTER, + SCHEMAS, + SESSION, +}; + +typedef union value_e { + sr_val_t *_val; + sr_val_t **p_vals; + sr_node_t *_tree; + sr_node_t **p_trees; + sr_schema_t *_sch; + sr_session_ctx_t *_sess; +} value_t; + +typedef union count_e { + size_t _cnt; + size_t *p_cnt; +} count_t; + +class Deleter +{ +public: + Deleter(sr_val_t *val); + Deleter(sr_val_t *vals, size_t cnt); + Deleter(sr_val_t **vals, size_t *cnt); + Deleter(sr_node_t *tree); + Deleter(sr_node_t *trees, size_t cnt); + Deleter(sr_node_t **trees, size_t *cnt); + Deleter(sr_schema_t *sch, size_t cnt); + Deleter(sr_session_ctx_t *sess); + ~Deleter(); + +private: + count_t c; + value_t v; + Free_Type _t; +}; + +} +#endif diff --git a/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Session.hpp b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Session.hpp new file mode 100644 index 000000000..02d03ed38 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Session.hpp @@ -0,0 +1,245 @@ +/** + * @file Session.h + * @author Mislav Novakovic + * @brief Sysrepo Session class header. + * + * @copyright + * Copyright 2016 Deutsche Telekom AG. + * + * 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 SESSION_H +#define SESSION_H + +#include +#include +#include +#include + +#include "Sysrepo.hpp" +#include "Internal.hpp" +#include "Struct.hpp" +#include "Tree.hpp" +#include "Connection.hpp" +#include "Session.hpp" + +extern "C" { +#include "../sysrepo.h" +} + +namespace sysrepo { + +/** + * @defgroup classes C++/Python + * @{ + */ + +/** + * @brief Class for wrapping sr_session_ctx_t. + * @class Session + */ +class Session +{ + +public: + /** Wrapper for [sr_session_start](@ref sr_session_start) and [sr_session_start_user](@ref sr_session_start_user) + * if user_name is set.*/ + Session(S_Connection conn, sr_datastore_t datastore = (sr_datastore_t) DS_RUNNING, \ + const sr_sess_options_t opts = SESS_DEFAULT, const char *user_name = nullptr); + /** Wrapper for [sr_session_ctx_t](@ref sr_session_ctx_t), for internal use only.*/ + Session(sr_session_ctx_t *sess, sr_sess_options_t opts = SESS_DEFAULT, S_Deleter deleter = nullptr); + /** Wrapper for [sr_session_stop](@ref sr_session_stop) */ + void session_stop(); + /** Wrapper for [sr_session_switch_ds](@ref sr_session_switch_ds) */ + void session_switch_ds(sr_datastore_t ds); + /** Wrapper for [sr_get_last_error](@ref sr_get_last_error) */ + S_Error get_last_error(); + /** Wrapper for [sr_get_last_errors](@ref sr_get_last_errors) */ + S_Errors get_last_errors(); + /** Wrapper for [sr_list_schemas](@ref sr_list_schemas) */ + S_Yang_Schemas list_schemas(); + /** Wrapper for [sr_get_schema](@ref sr_get_schema) */ + std::string get_schema(const char *module_name, const char *revision, + const char *submodule_name, sr_schema_format_t format); + /** Wrapper for [sr_get_item](@ref sr_get_item) */ + S_Val get_item(const char *xpath); + /** Wrapper for [sr_get_items](@ref sr_get_items) */ + S_Vals get_items(const char *xpath); + /** Wrapper for [sr_get_items_iter](@ref sr_get_items_iter) */ + S_Iter_Value get_items_iter(const char *xpath); + /** Wrapper for [sr_get_item_next](@ref sr_get_item_next) */ + S_Val get_item_next(S_Iter_Value iter); + /** Wrapper for [sr_get_subtree](@ref sr_get_subtree) */ + S_Tree get_subtree(const char *xpath, sr_get_subtree_options_t opts = GET_SUBTREE_DEFAULT); + /** Wrapper for [sr_get_subtrees](@ref sr_get_subtrees) */ + S_Trees get_subtrees(const char *xpath, sr_get_subtree_options_t opts = GET_SUBTREE_DEFAULT); + + /** Wrapper for [sr_node_get_child](@ref sr_node_get_child) */ + S_Tree get_child(S_Tree in_tree); + /** Wrapper for [sr_node_get_next_sibling](@ref sr_node_get_next_sibling) */ + S_Tree get_next_sibling(S_Tree in_tree); + /** Wrapper for [sr_node_get_parent](@ref sr_node_get_parent) */ + S_Tree get_parent(S_Tree in_tree); + + /** Wrapper for [sr_set_item](@ref sr_set_item) */ + void set_item(const char *xpath, S_Val value = nullptr, const sr_edit_options_t opts = EDIT_DEFAULT); + /** Wrapper for [sr_set_item_str](@ref sr_set_item_str) */ + void set_item_str(const char *xpath, const char *value, const sr_edit_options_t opts = EDIT_DEFAULT); + /** Wrapper for [sr_delete_item](@ref sr_delete_item) */ + void delete_item(const char *xpath, const sr_edit_options_t opts = EDIT_DEFAULT); + /** Wrapper for [sr_move_item](@ref sr_move_item) */ + void move_item(const char *xpath, const sr_move_position_t position, const char *relative_item = nullptr); + /** Wrapper for [sr_session_refresh](@ref sr_session_refresh) */ + void refresh(); + /** Wrapper for [sr_validate](@ref sr_validate) */ + void validate(); + /** Wrapper for [sr_commit](@ref sr_commit) */ + void commit(); + /** Wrapper for [sr_lock_datastore](@ref sr_lock_datastore) */ + void lock_datastore(); + /** Wrapper for [sr_unlock_datastore](@ref sr_unlock_datastore) */ + void unlock_datastore(); + /** Wrapper for [sr_lock_module](@ref sr_lock_module) */ + void lock_module(const char *module_name); + /** Wrapper for [sr_unlock_module](@ref sr_unlock_module) */ + void unlock_module(const char *module_name); + /** Wrapper for [sr_discard_changes](@ref sr_discard_changes) */ + void discard_changes(); + /** Wrapper for [sr_copy_config](@ref sr_copy_config) */ + void copy_config(const char *module_name, sr_datastore_t src_datastore, sr_datastore_t dst_datastore); + /** Wrapper for [sr_session_set_options](@ref sr_session_set_options) */ + void set_options(const sr_sess_options_t opts); + /** Wrapper for [sr_get_changes_iter](@ref sr_get_changes_iter) */ + S_Iter_Change get_changes_iter(const char *xpath); + /** Wrapper for [sr_get_change_next](@ref sr_get_change_next) */ + S_Change get_change_next(S_Iter_Change iter); + ~Session(); + + /** Wrapper for [sr_rpc_send](@ref sr_rpc_send) */ + S_Vals rpc_send(const char *xpath, S_Vals input); + /** Wrapper for [sr_rpc_send_tree](@ref sr_rpc_send_tree) */ + S_Trees rpc_send(const char *xpath, S_Trees input); + /** Wrapper for [sr_action_send](@ref sr_action_send) */ + S_Vals action_send(const char *xpath, S_Vals input); + /** Wrapper for [sr_action_send_tree](@ref sr_action_send_tree) */ + S_Trees action_send(const char *xpath, S_Trees input); + /** Wrapper for [sr_event_notif_send](@ref sr_event_notif_send) */ + void event_notif_send(const char *xpath, S_Vals values, const sr_ev_notif_flag_t options = SR_EV_NOTIF_DEFAULT); + /** Wrapper for [sr_event_notif_send_tree](@ref sr_event_notif_send_tree) */ + void event_notif_send(const char *xpath, S_Trees trees, const sr_ev_notif_flag_t options = SR_EV_NOTIF_DEFAULT); + + friend class Subscribe; + +private: + sr_session_ctx_t *_sess; + sr_datastore_t _datastore; + sr_sess_options_t _opts; + S_Connection _conn; + S_Deleter _deleter; +}; + +/** + * @brief Helper class for calling C callbacks, C++ only. + * @class Callback + */ +class Callback +{ +public: + Callback(); + virtual ~Callback(); + + /** Wrapper for [sr_module_change_cb](@ref sr_module_change_cb) callback.*/ + virtual int module_change(S_Session session, const char *module_name, sr_notif_event_t event, void *private_ctx) {return SR_ERR_OK;}; + /** Wrapper for [sr_subtree_change_cb](@ref sr_subtree_change_cb) callback.*/ + virtual int subtree_change(S_Session session, const char *xpath, sr_notif_event_t event, void *private_ctx) {return SR_ERR_OK;}; + /** Wrapper for [sr_module_install_cb](@ref sr_module_install_cb) callback.*/ + virtual void module_install(const char *module_name, const char *revision, sr_module_state_t state, void *private_ctx) {return;}; + /** Wrapper for [sr_feature_enable_cb](@ref sr_feature_enable_cb) callback.*/ + virtual void feature_enable(const char *module_name, const char *feature_name, bool enabled, void *private_ctx) {return;}; + /** Wrapper for [sr_rpc_cb](@ref sr_rpc_cb) callback.*/ + virtual int rpc(const char *xpath, const S_Vals input, S_Vals_Holder output, void *private_ctx) {return SR_ERR_OK;}; + /** Wrapper for [sr_action_cb](@ref sr_action_cb) callback.*/ + virtual int action(const char *xpath, const S_Vals input, S_Vals_Holder output, void *private_ctx) {return SR_ERR_OK;}; + /** Wrapper for [sr_rpc_tree_cb](@ref sr_rpc_tree_cb) callback.*/ + virtual int rpc_tree(const char *xpath, const S_Trees input, S_Trees_Holder output, void *private_ctx) {return SR_ERR_OK;}; + /** Wrapper for [sr_action_tree_cb](@ref sr_action_tree_cb) callback.*/ + virtual int action_tree(const char *xpath, const S_Trees input, S_Trees_Holder output, void *private_ctx) {return SR_ERR_OK;}; + /** Wrapper for [sr_dp_get_items_cb](@ref sr_dp_get_items_cb) callback.*/ + virtual int dp_get_items(const char *xpath, S_Vals_Holder vals, uint64_t request_id, void *private_ctx) {return SR_ERR_OK;}; + /** Wrapper for [sr_event_notif_cb](@ref sr_event_notif_cb) callback.*/ + virtual void event_notif(const sr_ev_notif_type_t notif_type, const char *xpath, S_Vals vals, time_t timestamp, void *private_ctx) {return;}; + /** Wrapper for [sr_event_notif_tree_cb](@ref sr_event_notif_tree_cb) callback.*/ + virtual void event_notif_tree(const sr_ev_notif_type_t notif_type, const char *xpath, S_Trees trees, time_t timestamp, void *private_ctx) {return;}; + Callback *get() {return this;}; + + std::map private_ctx; +}; + +/** + * @brief Class for wrapping sr_subscription_ctx_t. + * @class Subscribe + */ +class Subscribe +{ + +public: + /** Wrapper for [sr_subscription_ctx_t](@ref sr_subscription_ctx_t), for internal use only.*/ + Subscribe(S_Session sess); + + /** Wrapper for [sr_module_change_subscribe](@ref sr_module_change_subscribe) */ + void module_change_subscribe(const char *module_name, S_Callback callback, void *private_ctx = nullptr, uint32_t priority = 0, sr_subscr_options_t opts = SUBSCR_DEFAULT); + /** Wrapper for [sr_subtree_change_subscribe](@ref sr_subtree_change_subscribe) */ + void subtree_change_subscribe(const char *xpath, S_Callback callback, void *private_ctx = nullptr, uint32_t priority = 0, sr_subscr_options_t opts = SUBSCR_DEFAULT); + /** Wrapper for [sr_module_install_subscribe](@ref sr_module_install_subscribe) */ + void module_install_subscribe(S_Callback callback, void *private_ctx = nullptr, sr_subscr_options_t opts = SUBSCR_DEFAULT); + /** Wrapper for [sr_feature_enable_subscribe](@ref sr_feature_enable_subscribe) */ + void feature_enable_subscribe(S_Callback callback, void *private_ctx = nullptr, sr_subscr_options_t opts = SUBSCR_DEFAULT); + /** Wrapper for [sr_rpc_subscribe](@ref sr_rpc_subscribe) */ + void rpc_subscribe(const char *xpath, S_Callback callback, void *private_ctx = nullptr, sr_subscr_options_t opts = SUBSCR_DEFAULT); + /** Wrapper for [sr_action_subscribe](@ref sr_action_subscribe) */ + void action_subscribe(const char *xpath, S_Callback callback, void *private_ctx = nullptr, sr_subscr_options_t opts = SUBSCR_DEFAULT); + /** Wrapper for [sr_event_notif_subscribe_tree](@ref sr_event_notif_subscribe_tree) */ + void event_notif_subscribe_tree(const char *xpath, S_Callback callback, void *private_ctx = nullptr, sr_subscr_options_t opts = SUBSCR_DEFAULT); + /** Wrapper for [sr_event_notif_subscribe](@ref sr_event_notif_subscribe) */ + void event_notif_subscribe(const char *xpath, S_Callback callback, void *private_ctx = nullptr, sr_subscr_options_t opts = SUBSCR_DEFAULT); + /** Wrapper for [sr_rpc_subscribe_tree](@ref sr_rpc_subscribe_tree) */ + void rpc_subscribe_tree(const char *xpath, S_Callback callback, void *private_ctx = nullptr, sr_subscr_options_t opts = SUBSCR_DEFAULT); + /** Wrapper for [sr_action_subscribe_tree](@ref sr_action_subscribe_tree) */ + void action_subscribe_tree(const char *xpath, S_Callback callback, void *private_ctx = nullptr, sr_subscr_options_t opts = SUBSCR_DEFAULT); + /** Wrapper for [sr_dp_get_items_subscribe](@ref sr_dp_get_items_subscribe) */ + void dp_get_items_subscribe(const char *xpath, S_Callback callback, void *private_ctx = nullptr, sr_subscr_options_t opts = SUBSCR_DEFAULT); + std::vector cb_list; + + /** Wrapper for [sr_unsubscribe](@ref sr_unsubscribe) */ + void unsubscribe(); + ~Subscribe(); + + /** SWIG specific, internal use only.*/ + sr_subscription_ctx_t **swig_sub() { return &_sub;}; + /** SWIG specific, internal use only.*/ + sr_session_ctx_t *swig_sess() {return _sess->_sess;}; + /** SWIG specific, internal use only.*/ + std::vector wrap_cb_l; + /** SWIG specific, internal use only.*/ + void additional_cleanup(void *private_ctx) {return;}; + +private: + sr_subscription_ctx_t *_sub; + S_Session _sess; + S_Deleter sess_deleter; +}; + +/**@} */ +} +#endif diff --git a/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Struct.hpp b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Struct.hpp new file mode 100644 index 000000000..7f48d562d --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Struct.hpp @@ -0,0 +1,514 @@ +/** + * @file Struct.h + * @author Mislav Novakovic + * @brief Sysrepo class header for C struts. + * + * @copyright + * Copyright 2016 Deutsche Telekom AG. + * + * 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 STRUCT_H +#define STRUCT_H + +#include +#include + +#include "Sysrepo.hpp" +#include "Internal.hpp" + +extern "C" { +#include "../sysrepo.h" +} + +namespace sysrepo { + +/** + * @defgroup classes C++/Python + * @{ + */ + +/** + * @brief Class for wrapping sr_data_t. + * @class Data + */ +class Data +{ +public: + /** Wrapper for [sr_data_t](@ref sr_data_t), for internal use only.*/ + Data(sr_data_t data, sr_type_t type, S_Deleter deleter); + ~Data(); + /** Getter for binary data.*/ + char *get_binary() const; + /** Getter for bits.*/ + char *get_bits() const; + /** Getter for bool.*/ + bool get_bool() const; + /** Getter for decimal64.*/ + double get_decimal64() const; + /** Getter for enum.*/ + char *get_enum() const; + /** Getter for identityref.*/ + char *get_identityref() const; + /** Getter for instanceid.*/ + char *get_instanceid() const; + /** Getter for int8.*/ + int8_t get_int8() const; + /** Getter for int16.*/ + int16_t get_int16() const; + /** Getter for int32.*/ + int32_t get_int32() const; + /** Getter for int64.*/ + int64_t get_int64() const; + /** Getter for string.*/ + char *get_string() const; + /** Getter for uint8.*/ + uint8_t get_uint8() const; + /** Getter for uint16.*/ + uint16_t get_uint16() const; + /** Getter for uint32.*/ + uint32_t get_uint32() const; + /** Getter for uint64.*/ + uint64_t get_uint64() const; + +private: + sr_data_t _d; + sr_type_t _t; + S_Deleter _deleter; +}; + +/** + * @brief Class for wrapping sr_val_t. + * @class Val + */ +class Val +{ +public: + /** Constructor for an empty value.*/ + Val(); + /** Wrapper for [sr_val_t](@ref sr_val_t).*/ + Val(sr_val_t *val, S_Deleter deleter); + /** Constructor for string value, type can be SR_STRING_T, SR_BINARY_T, SR_BITS_T, SR_ENUM_T, + * SR_IDENTITYREF_T and SR_INSTANCEID_T.*/ + Val(const char *val, sr_type_t type = SR_STRING_T); + /** Constructor for bool value.*/ + Val(bool bool_val, sr_type_t type = SR_BOOL_T); + /** Constructor for decimal64 value.*/ + Val(double decimal64_val); + /** Constructor for int8 value, C++ only.*/ + Val(int8_t int8_val, sr_type_t type); + /** Constructor for int16 value, C++ only.*/ + Val(int16_t int16_val, sr_type_t type); + /** Constructor for int32 value, C++ only.*/ + Val(int32_t int32_val, sr_type_t type); + /** Constructor for int64 value, type can be SR_INT8_T, SR_INT16_T, SR_INT32_T, + * SR_INT64_T, SR_UINT8_T, SR_UINT16_T and SR_UINT32_T,*/ + Val(int64_t int64_val, sr_type_t type); + /** Constructor for uint8 value, C++ only.*/ + Val(uint8_t uint8_val, sr_type_t type); + /** Constructor for uint16 value, C++ only.*/ + Val(uint16_t uint16_val, sr_type_t type); + /** Constructor for uint32 value, C++ only.*/ + Val(uint32_t uint32_val, sr_type_t type); + /** Constructor for uint64 value, C++ only.*/ + Val(uint64_t uint64_val, sr_type_t type); + ~Val(); + /** Setter for string value, type can be SR_STRING_T, SR_BINARY_T, SR_BITS_T, SR_ENUM_T, + * SR_IDENTITYREF_T and SR_INSTANCEID_T.*/ + void set(const char *xpath, const char *val, sr_type_t type = SR_STRING_T); + /** Setter for bool value.*/ + void set(const char *xpath, bool bool_val, sr_type_t type = SR_BOOL_T); + /** Setter for decimal64 value.*/ + void set(const char *xpath, double decimal64_val); + /** Setter for int8 value, C++ only.*/ + void set(const char *xpath, int8_t int8_val, sr_type_t type); + /** Setter for int16 value, C++ only.*/ + void set(const char *xpath, int16_t int16_val, sr_type_t type); + /** Setter for int32 value, C++ only.*/ + void set(const char *xpath, int32_t int32_val, sr_type_t type); + /** Setter for int64 value, type can be SR_INT8_T, SR_INT16_T, SR_INT32_T, + * SR_INT64_T, SR_UINT8_T, SR_UINT16_T and SR_UINT32_T,*/ + void set(const char *xpath, int64_t int64_val, sr_type_t type); + /** Setter for uint8 value, C++ only.*/ + void set(const char *xpath, uint8_t uint8_val, sr_type_t type); + /** Setter for uint16 value, C++ only.*/ + void set(const char *xpath, uint16_t uint16_val, sr_type_t type); + /** Setter for uint32 value, C++ only.*/ + void set(const char *xpath, uint32_t uint32_val, sr_type_t type); + /** Setter for uint64 value, C++ only.*/ + void set(const char *xpath, uint64_t uint64_val, sr_type_t type); + /** Getter for xpath.*/ + char *xpath() {return _val->xpath;}; + /** Setter for xpath.*/ + void xpath_set(char *xpath); + /** Getter for type.*/ + sr_type_t type() {return _val->type;}; + /** Getter for dflt.*/ + bool dflt() {return _val->dflt;}; + /** Setter for dflt.*/ + void dflt_set(bool data) {_val->dflt = data;}; + /** Getter for data.*/ + S_Data data() {S_Data data(new Data(_val->data, _val->type, _deleter)); return data;}; + /** Wrapper for [sr_print_val_mem](@ref sr_print_val_mem) */ + std::string to_string(); + /** Wrapper for [sr_val_to_string](@ref sr_val_to_string) */ + std::string val_to_string(); + /** Wrapper for [sr_dup_val](@ref sr_dup_val) */ + S_Val dup(); + + friend class Session; + friend class Subscribe; + +private: + sr_val_t *_val; + S_Deleter _deleter; +}; + +/** + * @brief Class for wrapping sr_val_t array. + * @class Vals + */ +class Vals +{ +public: + /** Wrapper for [sr_val_t](@ref sr_val_t) array, internal use only.*/ + Vals(const sr_val_t *vals, const size_t cnt, S_Deleter deleter = nullptr); + /** Wrapper for [sr_val_t](@ref sr_val_t) array, internal use only.*/ + Vals(sr_val_t **vals, size_t *cnt, S_Deleter deleter = nullptr); + /** Wrapper for [sr_val_t](@ref sr_val_t) array, create n-array.*/ + Vals(size_t cnt); + /** Constructor for an empty [sr_val_t](@ref sr_val_t) array.*/ + Vals(); + ~Vals(); + /** Getter for [sr_val_t](@ref sr_val_t), get the n-th element in array.*/ + S_Val val(size_t n); + /** Getter for array size */ + size_t val_cnt() {return _cnt;}; + /** Wrapper for [sr_dup_values](@ref sr_dup_values) */ + S_Vals dup(); + + friend class Session; + friend class Subscribe; + +private: + size_t _cnt; + sr_val_t *_vals; + S_Deleter _deleter; +}; + +/** + * @brief Class for wrapping sr_val_t in callbacks. + * @class Vals_holder + */ +class Vals_Holder +{ +public: + /** Wrapper for [sr_val_t](@ref sr_val_t) array, used only in callbacks.*/ + Vals_Holder(sr_val_t **vals, size_t *cnt); + /** Create [sr_val_t](@ref sr_val_t) array of n size.*/ + S_Vals allocate(size_t n); + ~Vals_Holder(); + +private: + size_t *p_cnt; + sr_val_t **p_vals; + bool _allocate; +}; + +/** + * @brief Class for wrapping sr_val_iter_t. + * @class Val_Iter + */ +class Val_Iter +{ +public: + /** Wrapper for [sr_val_iter_t](@ref sr_val_iter_t).*/ + Val_Iter(sr_val_iter_t *iter = nullptr); + ~Val_Iter(); + /** Getter for [sr_val_iter_t](@ref sr_val_iter_t).*/ + sr_val_iter_t *iter() {return _iter;}; + +private: + sr_val_iter_t *_iter; +}; + +/** + * @brief Class for wrapping sr_change_iter_t. + * @class Change_Iter + */ +class Change_Iter +{ +public: + /** Wrapper for [sr_change_iter_t](@ref sr_change_iter_t).*/ + Change_Iter(sr_change_iter_t *iter = nullptr); + ~Change_Iter(); + /** Getter for [sr_change_iter_t](@ref sr_change_iter_t).*/ + sr_change_iter_t *iter() {return _iter;}; + +private: + sr_change_iter_t *_iter; +}; + +/** + * @brief Class for wrapping sr_error_info_t. + * @class Error + */ +class Error +{ +public: + /** Constructor for an empty [sr_error_info_t](@ref sr_error_info_t).*/ + Error(); + /** Wrapper for [sr_error_info_t](@ref sr_error_info_t).*/ + Error(const sr_error_info_t *info); + ~Error(); + /** Getter for message.*/ + const char *message() const {if (_info) return _info->message; else return nullptr;}; + /** Getter for xpath.*/ + const char *xpath() const {if (_info) return _info->xpath; else return nullptr;}; + + friend class Session; + +private: + const sr_error_info_t *_info; +}; + +/** + * @brief Class for wrapping sr_error_info_t array. + * @class Errors + */ +class Errors +{ +public: + /** Constructor for an empty [sr_error_info_t](@ref sr_error_info_t) array.*/ + Errors(); + ~Errors(); + /** Getter for [sr_error_info_t](@ref sr_error_info_t), get the n-th element in array.*/ + S_Error error(size_t n); + /** Getter for array size.*/ + size_t error_cnt() {return _cnt;}; + + friend class Session; + +private: + size_t _cnt; + const sr_error_info_t *_info; +}; + +/** + * @brief Class for wrapping sr_sch_revision_t array. + * @class Schema_Revision + */ +class Schema_Revision +{ +public: + /** Wrapper for [sr_sch_revision_t](@ref sr_sch_revision_t).*/ + Schema_Revision(sr_sch_revision_t rev); + ~Schema_Revision(); + /** Getter for revision.*/ + const char *revision() const {return _rev.revision;}; + /** Getter for file_path_yang.*/ + const char *file_path_yang() const {return _rev.file_path_yang;}; + /** Getter for file_path_yin.*/ + const char *file_path_yin() const {return _rev.file_path_yin;}; + +private: + sr_sch_revision_t _rev; +}; + +/** + * @brief Class for wrapping sr_sch_submodule_t. + * @class Schema_Submodule + */ +class Schema_Submodule +{ +public: + /** Wrapper for [sr_sch_submodule_t](@ref sr_sch_submodule_t).*/ + Schema_Submodule(sr_sch_submodule_t sub, S_Deleter deleter); + ~Schema_Submodule(); + /** Getter for submodule_name.*/ + const char *submodule_name() const {return _sub.submodule_name;}; + /** Getter for revision.*/ + S_Schema_Revision revision(); + +private: + sr_sch_submodule_t _sub; + S_Deleter _deleter; +}; + +/** + * @brief Class for wrapping sr_schema_t. + * @class Yang_Schema + */ +class Yang_Schema +{ +public: + /** Wrapper for [sr_schema_t](@ref sr_schema_t).*/ + Yang_Schema(sr_schema_t *sch, S_Deleter deleter); + ~Yang_Schema(); + /** Getter for module_name.*/ + const char *module_name() const {return _sch->module_name;}; + /** Getter for ns.*/ + const char *ns() const {return _sch->ns;}; + /** Getter for prefix.*/ + const char *prefix() const {return _sch->prefix;}; + /** Getter for implemented.*/ + bool implemented() const {return _sch->implemented;}; + /** Getter for revision.*/ + S_Schema_Revision revision(); + /** Getter for submodule.*/ + S_Schema_Submodule submodule(size_t n); + /** Getter for submodule_cnt.*/ + size_t submodule_cnt() const {return _sch->submodule_count;}; + /** Getter for enabled_features.*/ + char *enabled_features(size_t n); + /** Getter for enabled_features_cnt.*/ + size_t enabled_feature_cnt() const {return _sch->enabled_feature_cnt;}; + + friend class Session; + +private: + sr_schema_t *_sch; + S_Deleter _deleter; +}; + +/** + * @brief Class for wrapping sr_schema_t array. + * @class Yang_Schemas + */ +class Yang_Schemas +{ +public: + /** Constructor for an empty [sr_schema_t](@ref sr_schema_t) array.*/ + Yang_Schemas(); + ~Yang_Schemas(); + /** Getter for [sr_schema_t](@ref sr_schema_t) array, get the n-th element in array.*/ + S_Yang_Schema schema(size_t n); + /** Getter for array size.*/ + size_t schema_cnt() const {return _cnt;}; + + friend class Session; + +private: + size_t _cnt; + sr_schema_t *_sch; + S_Deleter _deleter; +}; + +/** + * @brief Class for wrapping sr_fd_change_t. + * @class Fd_Change + */ +class Fd_Change +{ +public: + /** Wrapper for [sr_fd_change_t](@ref sr_fd_change_t).*/ + Fd_Change(sr_fd_change_t *ch); + ~Fd_Change(); + /** Getter for fd.*/ + int fd() const {return _ch->fd;}; + /** Getter for events.*/ + int events() const {return _ch->events;}; + /** Getter for action.*/ + sr_fd_action_t action() const {return _ch->action;}; + +private: + sr_fd_change_t *_ch; +}; + +/** + * @brief Class for wrapping sr_fd_change_t array. + * @class Fd_Changes + */ +class Fd_Changes +{ +public: + /** Wrapper for [sr_fd_change_t](@ref sr_fd_change_t) array.*/ + Fd_Changes(sr_fd_change_t *ch, size_t cnt); + ~Fd_Changes(); + /** Getter for [sr_fd_change_t](@ref sr_fd_change_t) array, get the n-th element in array.*/ + S_Fd_Change fd_change(size_t n); + +private: + sr_fd_change_t *_ch; + size_t _cnt; +}; + +/** + * @brief Class for wrapping sr_val_iter_t. + * @class Fd_Changes + */ +class Iter_Value +{ + +public: + /** Wrapper for [sr_val_iter_t](@ref sr_val_iter_t).*/ + Iter_Value(sr_val_iter_t *iter = nullptr); + ~Iter_Value(); + /** Setter for [sr_val_iter_t](@ref sr_val_iter_t).*/ + void Set(sr_val_iter_t *iter); + + friend class Session; + +private: + sr_val_iter_t *_iter; +}; + +/** + * @brief Class for wrapping sr_change_iter_t. + * @class Iter_Change + */ +class Iter_Change +{ + +public: + /** Wrapper for [sr_change_iter_t](@ref sr_change_iter_t).*/ + Iter_Change(sr_change_iter_t *iter = nullptr); + ~Iter_Change(); + + friend class Session; + +private: + sr_change_iter_t *_iter; +}; + +/** + * @brief Class for wrapping sr_change_oper_t. + * @class Change + */ +class Change +{ +public: + /** Constructor for an empty [sr_change_oper_t](@ref sr_change_oper_t).*/ + Change(); + ~Change(); + /** Getter for sr_change_oper_t.*/ + sr_change_oper_t oper() {return _oper;}; + /** Getter for new sr_val_t.*/ + S_Val new_val(); + /** Getter for old sr_val_t.*/ + S_Val old_val(); + + friend class Session; + +private: + sr_change_oper_t _oper; + sr_val_t *_new; + sr_val_t *_old; + S_Deleter _deleter_new; + S_Deleter _deleter_old; +}; + +/**@} */ +} +#endif diff --git a/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Sysrepo.hpp b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Sysrepo.hpp new file mode 100644 index 000000000..d3b76483f --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Sysrepo.hpp @@ -0,0 +1,177 @@ +/** + * @file Sysrepo.h + * @author Mislav Novakovic + * @brief Sysrepo Sysrepo class header. + * + * @copyright + * Copyright 2016 Deutsche Telekom AG. + * + * 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 SYSREPO_H +#define SYSREPO_H + +#include +#include +#include + +#include "Internal.hpp" + +extern "C" { +#include "../sysrepo.h" +} + +namespace sysrepo { + +/** + * @defgroup classes C++/Python + * @{ + */ + +class Iter_Value; +class Iter_Change; +class Session; +class Subscribe; +class Connection; +class Operation; +class Schema_Content; +class Error; +class Errors; +class Data; +class Schema_Revision; +class Schema_Submodule; +class Yang_Schema; +class Yang_Schemas; +class Fd_Change; +class Fd_Changes; +class Val; +class Vals_Holder; +class Vals; +class Tree; +class Trees; +class Trees_Holder; +class Xpath_Ctx; +class Logs; +class Change; +class Counter; +class Callback; +class Deleter; + +#ifdef SWIGLUA +using S_Iter_Value = Iter_Value*; +using S_Iter_Change = Iter_Change*; +using S_Session = Session*; +using S_Subscribe = Subscribe*; +using S_Connection = Connection*; +using S_Operation = Operation*; +using S_Schema_Content = Schema_Content*; +using S_Error = Error*; +using S_Errors = Errors*; +using S_Data = Data*; +using S_Schema_Revision = Schema_Revision*; +using S_Schema_Submodule = Schema_Submodule*; +using S_Yang_Schema = Yang_Schema*; +using S_Yang_Schemas = Yang_Schemas*; +using S_Fd_Change = Fd_Change*; +using S_Fd_Changes = Fd_Changes*; +using S_Val = Val*; +using S_Vals_Holder = Vals_Holder*; +using S_Vals = Vals*; +using S_Tree = Tree*; +using S_Trees = Trees*; +using S_Trees_Holder = Trees_Holder*; +using S_Xpath_Ctx = Xpath_Ctx*; +using S_Logs = Logs*; +using S_Change = Change*; +using S_Counter = Counter*; +using S_Callback = Callback*; +#else +using S_Iter_Value = std::shared_ptr; +using S_Iter_Change = std::shared_ptr; +using S_Session = std::shared_ptr; +using S_Subscribe = std::shared_ptr; +using S_Connection = std::shared_ptr; +using S_Operation = std::shared_ptr; +using S_Schema_Content = std::shared_ptr; +using S_Error = std::shared_ptr; +using S_Errors = std::shared_ptr; +using S_Data = std::shared_ptr; +using S_Schema_Revision = std::shared_ptr; +using S_Schema_Submodule = std::shared_ptr; +using S_Yang_Schema = std::shared_ptr; +using S_Yang_Schemas = std::shared_ptr; +using S_Fd_Change = std::shared_ptr; +using S_Fd_Changes = std::shared_ptr; +using S_Val = std::shared_ptr; +using S_Vals_Holder = std::shared_ptr; +using S_Vals = std::shared_ptr; +using S_Tree = std::shared_ptr; +using S_Trees = std::shared_ptr; +using S_Trees_Holder = std::shared_ptr; +using S_Xpath_Ctx = std::shared_ptr; +using S_Logs = std::shared_ptr; +using S_Change = std::shared_ptr; +using S_Counter = std::shared_ptr; +using S_Callback = std::shared_ptr; +using S_Deleter = std::shared_ptr; +#endif + +/* this is a workaround for python not recognizing + * enum's in function default values */ +static const int SESS_DEFAULT = SR_SESS_DEFAULT; +static const int DS_RUNNING = SR_DS_RUNNING; +static const int EDIT_DEFAULT = SR_EDIT_DEFAULT; +static const int CONN_DEFAULT = SR_CONN_DEFAULT; +static const int GET_SUBTREE_DEFAULT = SR_GET_SUBTREE_DEFAULT; +static const int SUBSCR_DEFAULT = SR_SUBSCR_DEFAULT; + +#ifdef SWIG +// https://github.com/swig/swig/issues/1158 +void throw_exception (int error); +#else +void throw_exception [[noreturn]] (int error); +#endif + +/** + * @brief Class for wrapping sr_error_t. + * @class sysrepo_exception + */ +class sysrepo_exception : public std::runtime_error +{ +public: + explicit sysrepo_exception(const sr_error_t error_code); + virtual ~sysrepo_exception() override; + sr_error_t error_code() const; +private: + sr_error_t m_error_code; +}; + +/** + * @brief Class for wrapping ref sr_log_level_t. + * @class Logs + */ +class Logs +{ +public: + Logs(); + ~Logs(); + /** Wrapper for [sr_log_stderr](@ref sr_log_stderr) */ + void set_stderr(sr_log_level_t log_level); + /** Wrapper for [sr_log_syslog](@ref sr_log_syslog) */ + void set_syslog(sr_log_level_t log_level); +}; + +/**@} */ +} +#endif diff --git a/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Tree.hpp b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Tree.hpp new file mode 100644 index 000000000..31f3abd47 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Tree.hpp @@ -0,0 +1,176 @@ +/** + * @file Trees.h + * @author Mislav Novakovic + * @brief Sysrepo class header for C header trees.h. + * + * @copyright + * Copyright 2016 Deutsche Telekom AG. + * + * 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 TREE_H +#define TREE_H + +#include "Sysrepo.hpp" +#include "Struct.hpp" + +extern "C" { +#include "../sysrepo.h" +#include "../sysrepo/trees.h" +} + +namespace sysrepo { + +/** + * @defgroup classes C++/Python + * @{ + */ + +/** + * @brief Class for wrapping sr_node_t. + * @class Tree + */ +class Tree +{ +public: + /** Constructor for an empty [sr_node_t](@ref sr_node_t).*/ + Tree(); + /** Wrapper for [sr_new_tree](@ref sr_new_tree).*/ + Tree(const char *root_name, const char *root_module_name); + /** Wrapper for [sr_node_t](@ref sr_node_t).*/ + Tree(sr_node_t *tree, S_Deleter deleter); + /** Wrapper for [sr_dup_tree](@ref sr_dup_tree).*/ + S_Tree dup(); + /** Get the node value.*/ + S_Tree node(); + /** Getter for name.*/ + char *name() {return _node->name;}; + /** Getter for type.*/ + sr_type_t type() {return _node->type;}; + /** Getter for dflt.*/ + bool dflt() {return _node->dflt;}; + /** Getter for data.*/ + S_Data data() {S_Data data(new Data(_node->data, _node->type, _deleter)); return data;}; + /** Getter for module_name.*/ + char *module_name() {return _node->module_name;}; + /** Getter for parent.*/ + S_Tree parent(); + /** Getter for next.*/ + S_Tree next(); + /** Getter for prev.*/ + S_Tree prev(); + /** Getter for first_child.*/ + S_Tree first_child(); + /** Getter for last_child.*/ + S_Tree last_child(); + /** Wrapper for [sr_print_tree_mem](@ref sr_print_tree_mem).*/ + std::string to_string(int depth_limit); + /** Wrapper for [sr_print_val_mem](@ref sr_print_val_mem).*/ + std::string value_to_string(); + /** Wrapper for [sr_node_set_name](@ref sr_node_set_name).*/ + void set_name(const char *name); + /** Wrapper for [sr_node_set_module](@ref sr_node_set_module).*/ + void set_module(const char *module_name); + /** Wrapper for [sr_node_set_str_data](@ref sr_node_set_str_data).*/ + void set_str_data(sr_type_t type, const char *string_val); + /** Wrapper for [sr_node_add_child](@ref sr_node_add_child).*/ + void add_child(const char *child_name, const char *child_module_name, S_Tree child); + /** Setter for string value, type can be SR_STRING_T, SR_BINARY_T, SR_BITS_T, SR_ENUM_T, + * SR_IDENTITYREF_T and SR_INSTANCEID_T.*/ + void set(const char *val, sr_type_t type = SR_STRING_T); + /** Setter for bool value.*/ + void set(bool bool_val, sr_type_t type = SR_BOOL_T); + /** Setter for decimal64 value.*/ + void set(double decimal64_val); + /** Setter for int8 value, C++ only.*/ + void set(int8_t int8_val, sr_type_t type); + /** Setter for int16 value, C++ only.*/ + void set(int16_t int16_val, sr_type_t type); + /** Setter for int32 value, C++ only.*/ + void set(int32_t int32_val, sr_type_t type); + /** Setter for int64 value, type can be SR_INT8_T, SR_INT16_T, SR_INT32_T, + * SR_INT64_T, SR_UINT8_T, SR_UINT16_T and SR_UINT32_T,*/ + void set(int64_t int64_val, sr_type_t type); + /** Setter for uint8 value, C++ only.*/ + void set(uint8_t uint8_val, sr_type_t type); + /** Setter for uint16 value, C++ only.*/ + void set(uint16_t uint16_val, sr_type_t type); + /** Setter for uint32 value, C++ only.*/ + void set(uint32_t uint32_val, sr_type_t type); + /** Setter for uint64 value, C++ only.*/ + void set(uint64_t uint64_val, sr_type_t type); + ~Tree(); + + friend class Session; + friend class Subscribe; + +private: + sr_node_t *_node; + S_Deleter _deleter; +}; + +/** + * @brief Class for wrapping sr_node_t array. + * @class Trees + */ +class Trees +{ +public: + /** Constructor for an empty [sr_node_t](@ref sr_node_t) array.*/ + Trees(); + /** Wrapper for [sr_node_t](@ref sr_node_t) array, create n-array.*/ + Trees(size_t n); + /** Wrapper for [sr_node_t](@ref sr_node_t) array, internal use only.*/ + Trees(sr_node_t **trees, size_t *cnt, S_Deleter deleter = nullptr); + /** Wrapper for [sr_node_t](@ref sr_node_t) array, internal use only.*/ + Trees(const sr_node_t *trees, const size_t n, S_Deleter deleter = nullptr); + /** Getter for [sr_node_t](@ref sr_node_t), get the n-th element in array.*/ + S_Tree tree(size_t n); + /** Wrapper for [sr_dup_trees](@ref sr_dup_trees) */ + S_Trees dup(); + /** Getter for array size */ + size_t tree_cnt() {return _cnt;}; + ~Trees(); + + friend class Session; + friend class Subscribe; + +private: + size_t _cnt; + sr_node_t *_trees; + S_Deleter _deleter; +}; + +/** + * @brief Class for wrapping sr_node_t in callbacks. + * @class Trees_Holder + */ +class Trees_Holder +{ +public: + /** Wrapper for [sr_node_t](@ref sr_node_t) array, used only in callbacks.*/ + Trees_Holder(sr_node_t **trees, size_t *cnt); + /** Create [sr_node_t](@ref sr_node_t) array of n size.*/ + S_Trees allocate(size_t n); + ~Trees_Holder(); + +private: + size_t *p_cnt; + sr_node_t **p_trees; + bool _allocate; +}; + +/**@} */ +} +#endif diff --git a/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Xpath.hpp b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Xpath.hpp new file mode 100644 index 000000000..4406134da --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/Xpath.hpp @@ -0,0 +1,97 @@ +/** + * @file Xpath.h + * @author Mislav Novakovic + * @brief Sysrepo class header for C header xpath_utils.h. + * + * @copyright + * Copyright 2016 Deutsche Telekom AG. + * + * 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 XPATH_H +#define XPATH_H + +#include + +extern "C" { +#include "../sysrepo/xpath.h" +} + +namespace sysrepo { + +/** + * @defgroup classes C++/Python + * @{ + */ + +/** + * @brief Class for wrapping sr_xpath_ctx_t. + * @class Xpath_Ctx + */ +class Xpath_Ctx +{ +public: + /** Constructor for an empty [sr_xpath_ctx_t](@ref sr_xpath_ctx_t).*/ + Xpath_Ctx(); + /** Getter for begining.*/ + char *begining() {if (_state != nullptr) return _state->begining; return nullptr;}; + /** Getter for current_node.*/ + char *current_node() {if (_state != nullptr) return _state->current_node; return nullptr;}; + /** Getter for replaced_position.*/ + char *replaced_position() {if (_state != nullptr) return _state->replaced_position; return nullptr;}; + /** Getter for replaced_char.*/ + char replaced_char() {if (_state != nullptr) return _state->replaced_char; return (char) 0;}; + ~Xpath_Ctx(); + /** Wrapper for [sr_xpath_next_node](@ref sr_xpath_next_node).*/ + char *next_node(char *xpath) {return sr_xpath_next_node(xpath, _state);}; + /** Wrapper for [sr_xpath_next_node_with_ns](@ref sr_xpath_next_node_with_ns).*/ + char *next_node_with_ns(char *xpath) {return sr_xpath_next_node_with_ns(xpath, _state);}; + /** Wrapper for [sr_xpath_next_key_name](@ref sr_xpath_next_key_name).*/ + char *next_key_name(char *xpath) {return sr_xpath_next_key_name(xpath, _state);}; + /** Wrapper for [sr_xpath_next_key_value](@ref sr_xpath_next_key_value).*/ + char *next_key_value(char *xpath) {return sr_xpath_next_key_value(xpath, _state);}; + /** Wrapper for [sr_xpath_node](@ref sr_xpath_node).*/ + char *node(char *xpath, const char *node_name) {return sr_xpath_node(xpath, node_name, _state);}; + /** Wrapper for [sr_xpath_node_rel](@ref sr_xpath_node_rel).*/ + char *node_rel(char *xpath, const char *node_name) {return sr_xpath_node_rel(xpath, node_name, _state);}; + /** Wrapper for [sr_xpath_node_idx](@ref sr_xpath_node_idx).*/ + char *node_idx(char *xpath, size_t index) {return sr_xpath_node_idx(xpath, index, _state);}; + /** Wrapper for [sr_xpath_node_idx_rel](@ref sr_xpath_node_idx_rel).*/ + char *node_idx_rel(char *xpath, size_t index) {return sr_xpath_node_idx_rel(xpath, index, _state);}; + /** Wrapper for [sr_xpath_node_key_value](@ref sr_xpath_node_key_value).*/ + char *node_key_value(char *xpath, const char *key) {return sr_xpath_node_key_value(xpath, key, _state);}; + /** Wrapper for [sr_xpath_node_key_value_idx](@ref sr_xpath_node_key_value_idx).*/ + char *node_key_value_idx(char *xpath, size_t index) {return sr_xpath_node_key_value_idx(xpath, index, _state);}; + /** Wrapper for [sr_xpath_key_value](@ref sr_xpath_key_value).*/ + char *key_value(char *xpath, const char *node_name, const char *key_name) { + return sr_xpath_key_value(xpath, node_name, key_name, _state);}; + /** Wrapper for [sr_xpath_key_value_idx](@ref sr_xpath_key_value_idx).*/ + char *key_value_idx(char *xpath, size_t node_index, size_t key_index) { + return sr_xpath_key_value_idx(xpath, node_index, key_index, _state);}; + /** Wrapper for [sr_xpath_last_node](@ref sr_xpath_last_node).*/ + char *last_node(char *xpath) {return sr_xpath_last_node(xpath, _state);}; + /** Wrapper for [sr_xpath_node_name](@ref sr_xpath_node_name).*/ + char *node_name(const char *xpath) {return sr_xpath_node_name(xpath);}; + /** Wrapper for [sr_xpath_node_name_eq](@ref sr_xpath_node_name_eq).*/ + bool node_name_eq(const char *xpath, const char *node_str) {return sr_xpath_node_name_eq(xpath, node_str);}; + /** Wrapper for [sr_xpath_recover](@ref sr_xpath_recover).*/ + void recover() {return sr_xpath_recover(_state);}; + +private: + sr_xpath_ctx_t *_state; +}; + +/**@} */ +} +#endif diff --git a/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/plugins.h b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/plugins.h new file mode 100644 index 000000000..3c4efc9a9 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/plugins.h @@ -0,0 +1,139 @@ +/** + * @file plugins.h + * @author Rastislav Szabo , Lukas Macko + * @brief Sysrepo helpers for plugin integrations. + * + * @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. + */ + +#ifndef SYSREPO_PLUGINS_H_ +#define SYSREPO_PLUGINS_H_ + +#include +#include +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup plugin_utils Plugin Utilities + * @{ + * + * @brief Utilities that expand sysrepo API aimed for sysrepo plugins. + * + * The provided features are: logging macros. + */ + +/** Prints an error message (with format specifiers). */ +#define SRP_LOG_ERR(MSG, ...) SRP_LOG__INTERNAL(SR_LL_ERR, MSG, __VA_ARGS__) +/** Prints an error message. */ +#define SRP_LOG_ERR_MSG(MSG) SRP_LOG__INTERNAL(SR_LL_ERR, MSG "%s", "") + +/** Prints a warning message (with format specifiers). */ +#define SRP_LOG_WRN(MSG, ...) SRP_LOG__INTERNAL(SR_LL_WRN, MSG, __VA_ARGS__) +/** Prints a warning message. */ +#define SRP_LOG_WRN_MSG(MSG) SRP_LOG__INTERNAL(SR_LL_WRN, MSG "%s", "") + +/** Prints an informational message (with format specifiers). */ +#define SRP_LOG_INF(MSG, ...) SRP_LOG__INTERNAL(SR_LL_INF, MSG, __VA_ARGS__) +/** Prints an informational message. */ +#define SRP_LOG_INF_MSG(MSG) SRP_LOG__INTERNAL(SR_LL_INF, MSG "%s", "") + +/** Prints a development debug message (with format specifiers). */ +#define SRP_LOG_DBG(MSG, ...) SRP_LOG__INTERNAL(SR_LL_DBG, MSG, __VA_ARGS__) +/** Prints a development debug message. */ +#define SRP_LOG_DBG_MSG(MSG) SRP_LOG__INTERNAL(SR_LL_DBG, MSG "%s", "") + +/**@} plugin_utils */ + + +//////////////////////////////////////////////////////////////////////////////// +// Internal macros (not intended to be used directly) +//////////////////////////////////////////////////////////////////////////////// + +#ifdef NDEBUG + #define SRP_LOG_PRINT_FUNCTION_NAMES (0) /**< Do not print function names in messages */ +#else + #define SRP_LOG_PRINT_FUNCTION_NAMES (1) /**< Every message will include the function that generated the output */ +#endif + +extern volatile uint8_t sr_ll_stderr; /**< Holds current level of stderr debugs. */ +extern volatile uint8_t sr_ll_syslog; /**< Holds current level of syslog debugs. */ + +/** + * @brief Matching log level to message beginning + */ +#define SRP_LOG__LL_STR(LL) \ + ((SR_LL_DBG == LL) ? "DBG" : \ + (SR_LL_INF == LL) ? "INF" : \ + (SR_LL_WRN == LL) ? "WRN" : \ + "ERR") + +/** + * @brief Matching log level to message macros + */ +#define SRP_LOG__LL_FACILITY(LL) \ + ((SR_LL_DBG == LL) ? LOG_DEBUG : \ + (SR_LL_INF == LL) ? LOG_INFO : \ + (SR_LL_WRN == LL) ? LOG_WARNING : \ + LOG_ERR) + +#if SRP_LOG_PRINT_FUNCTION_NAMES +/** + * @brief Syslog output macro with function names. + */ +#define SRP_LOG__SYSLOG(LL, MSG, ...) \ + syslog(SRP_LOG__LL_FACILITY(LL), "[%s] (%s:%d) " MSG, SRP_LOG__LL_STR(LL), __func__, __LINE__, __VA_ARGS__); +/** + * @brief Stderr output macro with function names. + */ +#define SRP_LOG__STDERR(LL, MSG, ...) \ + fprintf(stderr, "[%s] (%s:%d) " MSG "\n", SRP_LOG__LL_STR(LL), __func__, __LINE__, __VA_ARGS__); +#else +/** + * @brief Syslog output macro without function names. + */ +#define SRP_LOG__SYSLOG(LL, MSG, ...) \ + syslog(SRP_LOG__LL_FACILITY(LL), "[%s] " MSG, SRP_LOG__LL_STR(LL), __VA_ARGS__); +/** + * @brief Stderr output macro without function names. + */ +#define SRP_LOG__STDERR(LL, MSG, ...) \ + fprintf(stderr, "[%s] " MSG "\n", SRP_LOG__LL_STR(LL), __VA_ARGS__); +#endif + +/** + * @brief Internal outptu macro. + */ +#define SRP_LOG__INTERNAL(LL, MSG, ...) \ + do { \ + if (sr_ll_stderr >= LL) \ + SRP_LOG__STDERR(LL, MSG, __VA_ARGS__) \ + if (sr_ll_syslog >= LL) \ + SRP_LOG__SYSLOG(LL, MSG, __VA_ARGS__) \ + } while(0) + +#ifdef __cplusplus +} +#endif + +#endif /* SYSREPO_PLUGINS_H_ */ diff --git a/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/trees.h b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/trees.h new file mode 100644 index 000000000..8db1602e6 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/trees.h @@ -0,0 +1,226 @@ +/** + * @file trees.h + * @author Rastislav Szabo , Lukas Macko , + * Milan Lenco + * @brief Functions for simplified manipulation with Sysrepo trees. + * + * @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. + */ + +#ifndef SYSREPO_TREES_H_ +#define SYSREPO_TREES_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trees Tree Manipulation Utilities + * @{ + * + * @brief Set of functions facilitating simplified manipulation and traversal + * of Sysrepo trees. As there are many connections between the tree nodes + * and also some internal attributes associated with each node, it is actually + * recommended to use these function rather than to allocate and initialize trees + * manually, which is very likely to lead to time-wasting and hard-to-debug programming + * errors. + * Iterative tree loading (@see SR_GET_SUBTREE_ITERATIVE) even requires to use + * designated functions for tree traversal -- ::sr_node_get_child and ::sr_node_get_next_sibling. + * + * Another added benefit of using these function is that the trees created using + * ::sr_new_tree and ::sr_new_trees will be allocated using the Sysrepo's own memory management + * (if enabled) which was proven to be more efficient for larger data sets + * (far less copying, quicker conversion to/from google protocol buffer messages, + * stable memory footprint, etc.). + */ + +/** + * @brief Allocate an instance of Sysrepo tree. The newly allocated tree has only + * one node -- the tree root -- and can be expanded to its full desired size + * through a repeated use of the function ::sr_node_add_child. + * + * @param [in] root_name Name for the newly allocated tree root. Can be NULL. + * @param [in] root_module_name Name of the module that defines scheme of the tree root. + * Can be NULL. + * @param [out] tree Returned newly allocated Sysrepo tree. + */ +int sr_new_tree(const char *root_name, const char *root_module_name, sr_node_t **tree); + +/** + * @brief Allocate an array of sysrepo trees (uninitialized tree roots). + * + * @param [in] tree_cnt Length of the array to allocate. + * @param [out] trees Returned newly allocated array of trees. + */ +int sr_new_trees(size_t tree_cnt, sr_node_t **trees); + +/** + * @brief Reallocate an array of sysrepo trees (uninitialized tree roots). + * + * @param [in] old_tree_cnt Current length of the tree array. + * @param [in] new_tree_cnt Desired length of the tree array. + * @param [in,out] trees Returned newly allocated/enlarged array of trees. + */ +int sr_realloc_trees(size_t old_tree_cnt, size_t new_tree_cnt, sr_node_t **trees); + +/** + * @brief Set/change name of a Sysrepo node. + * + * @param [in] node Sysrepo node to change the name of. + * @param [in] name Name to set. + */ +int sr_node_set_name(sr_node_t *node, const char *name); + +/** + * @brief Set/change module of a Sysrepo node. + * + * @param [in] node Sysrepo node to change the module of. + * @param [in] module_name Module name to set. + */ +int sr_node_set_module(sr_node_t *node, const char *module_name); + +/** + * @brief Store data of string type into the Sysrepo node data. + * + * @param [in] node Sysrepo node to edit. + * @param [in] type Exact type of the data. + * @param [in] string_val String value to set. + */ +int sr_node_set_str_data(sr_node_t *node, sr_type_t type, const char *string_val); + +/** + * @brief Store data of string type into the Sysrepo node data. The actual data + * will be built from the a format string and a variable arguments list. + * + * @param [in] node Sysrepo node to edit. + * @param [in] type Exact type of the data. + * @param [in] format Format string used to build the data. + */ +int sr_node_build_str_data(sr_node_t *node, sr_type_t type, const char *format, ...); + +/** + * @brief Create a new child for a given Sysrepo node. + * + * @param [in] parent Sysrepo node that should be parent of the newly created node. + * @param [in] child_name Name of the newly created child node. Can be NULL. + * @param [in] child_module_name Name of the module that defines scheme of the newly created + * child node. Can be NULL. + * @param [out] child Returned newly allocated child node. + */ +int sr_node_add_child(sr_node_t *parent, const char *child_name, const char *child_module_name, + sr_node_t **child); + +/** + * @brief Duplicate node and all its descendants (with or without Sysrepo memory context) + * into a new instance of Sysrepo tree with memory context. + * + * @param [in] tree Sysrepo tree to duplicate. + * @param [out] tree_dup Returned duplicate of the input tree. + */ +int sr_dup_tree(const sr_node_t *tree, sr_node_t **tree_dup); + +/** + * @brief Duplicate an array of trees (with or without Sysrepo memory context) into a new + * array of trees with memory context. + * + * @param [in] trees Array of sysrepo trees to duplicate. + * @param [in] count Size of the array to duplicate. + * @param [out] trees_dup Returned duplicate of the input array. + */ +int sr_dup_trees(const sr_node_t *trees, size_t count, sr_node_t **trees_dup); + +/** + * @brief Print sysrepo tree to STDOUT. + * + * @param [in] tree Sysrepo tree to print. + * @param [in] depth_limit Maximum number of tree levels to print. + */ +int sr_print_tree(const sr_node_t *tree, int depth_limit); + +/** + * @brief Print sysrepo tree to the specified file descriptor. + * + * @param [in] fd File descriptor to print the tree into. + * @param [in] tree Sysrepo tree to print. + * @param [in] depth_limit Maximum number of tree levels to print. + */ +int sr_print_tree_fd(int fd, const sr_node_t *tree, int depth_limit); + +/** + * @brief Print sysrepo tree to the specified output file stream. + * + * @param [in] stream Output file stream to print the tree into. + * @param [in] tree Sysrepo tree to print. + * @param [in] depth_limit Maximum number of tree levels to print. + */ +int sr_print_tree_stream(FILE *stream, const sr_node_t *tree, int depth_limit); + +/** + * @brief Print sysrepo tree into a newly allocated memory buffer. + * The caller is expected to eventually free the returned string. + * + * @param [in] mem_p Pointer to store the resulting dump. + * @param [in] tree Sysrepo tree to print. + * @param [in] depth_limit Maximum number of tree levels to print. + */ +int sr_print_tree_mem(char **mem_p, const sr_node_t *tree, int depth_limit); + +/** + * @brief Returns pointer to the first child (based on the schema) of a given node. + * For a fully loaded tree it is equivalent to "node->first_child". For a partially + * loaded tree (@see SR_GET_SUBTREE_ITERATIVE) it may internally issue a sysrepo + * get-subtree-chunk request in order to obtain the data of the child + * (and the data of some surrounding nodes with it for efficiency). + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] node Node to get the child of. + * @return Pointer to a child node. NULL if there is none or an error occured. + */ +sr_node_t *sr_node_get_child(sr_session_ctx_t *session, sr_node_t *node); + +/** + * @brief Returns pointer to the next sibling (based on the schema) of a given node. + * For a fully loaded tree it is equivalent to "node->next". For a partially + * loaded tree (@see SR_GET_SUBTREE_ITERATIVE) it may internally issue a sysrepo + * get-subtree-chunk request in order to obtain the data of the next sibling + * (and the data of some surrounding nodes with it for efficiency). + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] node Node to get the next sibling of. + * @return Pointer to the next sibling. NULL if this is the last sibling or an error occured. + */ +sr_node_t *sr_node_get_next_sibling(sr_session_ctx_t *session, sr_node_t *node); + +/** + * @brief Get the parent of a given node. It is equivalent to "node->parent", but for + * a partially loaded tree it is preferred to use this function rather than to access + * the pointer directly just for the sake of code cleanliness. + * + * @param[in] session Session context acquired with ::sr_session_start call. + * @param[in] node Node to get the parent of. + * @return Pointer to the node's parent or NULL if the node is a root of a (sub)tree. + */ +sr_node_t *sr_node_get_parent(sr_session_ctx_t *session, sr_node_t *node); + +/**@} trees */ + +#ifdef __cplusplus +} +#endif + +#endif /* SYSREPO_TREES_H_ */ diff --git a/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/values.h b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/values.h new file mode 100644 index 000000000..049c82f19 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/values.h @@ -0,0 +1,196 @@ +/** + * @file values.h + * @author Rastislav Szabo , Lukas Macko , + * Milan Lenco + * @brief Functions for simplified manipulation with Sysrepo values. + * + * @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. + */ + +#ifndef SYSREPO_VALUES_H_ +#define SYSREPO_VALUES_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup values Value Manipulation Utilities + * @{ + * + * @brief Set of functions facilitating simplified manipulation with sysrepo + * values. It is not necessary to use these functions in any scenario, values + * can be allocated and initialized manually (just remember to set all uninitialized + * members to zero!). + * + * Using these utilities, however, has several benefits. Firstly, all the memory + * allocations associated with creating values and setting their attributes get + * hidden behind these functions. The "old-way" was (and still is) to set xpath + * and string values using strdup, which may repeat in applications communicating + * with sysrepo very often and becomes very annoying to write. + * Secondly, the programmer may actually forget to copy or give-up on the ownership + * of a string passed to sysrepo value which will then get unexpectedly deallocated + * in ::sr_free_val or ::sr_free_values. + * The third benefit is that the values created using ::sr_new_val + * and ::sr_new_values will be allocated using the Sysrepo's own memory management + * (if enabled) which was proven to be more efficient for larger data sets + * (far less copying, quicker conversion to/from google protocol buffer messages, + * stable memory footprint, etc.). + */ + +/** + * @brief Allocate an instance of Sysrepo value. + * + * @param [in] xpath Xpath to set for the newly allocated value. Can be NULL. + * @param [out] value Returned newly allocated value. + */ +int sr_new_val(const char *xpath, sr_val_t **value); + +/** + * @brief Allocate an array of sysrepo values. + * + * @param [in] value_cnt Length of the array to allocate. + * @param [out] values Returned newly allocated array of values. + */ +int sr_new_values(size_t value_cnt, sr_val_t **values); + +/** + * @brief Reallocate an array of sysrepo values. + * + * @param [in] old_value_cnt Current length of the value array. + * @param [in] new_value_cnt Desired length of the value array. + * @param [in,out] values Returned newly allocated/enlarged array of values. + */ +int sr_realloc_values(size_t old_value_cnt, size_t new_value_cnt, sr_val_t **values); + +/** + * @brief Set/change xpath of a Sysrepo value. + * + * @param [in] value Sysrepo value to change the xpath of. + * @param [in] xpath XPath to set. + */ +int sr_val_set_xpath(sr_val_t *value, const char *xpath); + +/** + * @brief Set/change xpath of a Sysrepo value to a new one, built from + * a format string and a variable arguments list. + * + * @param [in] value Sysrepo value to change the xpath of. + * @param [in] format Format string used to build XPath. + */ +int sr_val_build_xpath(sr_val_t *value, const char *format, ...); + +/** + * @brief Store data of string type into the Sysrepo value data. + * + * @param [in] value Sysrepo value to edit. + * @param [in] type Exact type of the data. + * @param [in] string_val String value to set. + */ +int sr_val_set_str_data(sr_val_t *value, sr_type_t type, const char *string_val); + +/** + * @brief Store data of string type into the Sysrepo value data. The actual data + * will be built from the a format string and a variable arguments list. + * + * @param [in] value Sysrepo value to edit. + * @param [in] type Exact type of the data. + * @param [in] format Format string used to build the data. + */ +int sr_val_build_str_data(sr_val_t *value, sr_type_t type, const char *format, ...); + +/** + * @brief Duplicate value (with or without Sysrepo memory context) into a new + * instance with memory context. + * + * @param [in] value Sysrepo value to duplicate + * @param [out] value_dup Returned duplicate of the input value. + */ +int sr_dup_val(const sr_val_t *value, sr_val_t **value_dup); + +/** + * @brief Duplicate values (with or without Sysrepo memory context) into a new + * array with memory context. + * + * @param [in] values Array of sysrepo values to duplicate + * @param [in] count Size of the array to duplicate. + * @param [out] values_dup Returned duplicate of the input array. + */ +int sr_dup_values(const sr_val_t *values, size_t count, sr_val_t **values_dup); + +/** + * @brief Print sysrepo value to STDOUT. + * + * @param [in] value Sysrepo value to print. + */ +int sr_print_val(const sr_val_t *value); + +/** + * @brief Print sysrepo value to the specified file descriptor. + * + * @param [in] fd File descriptor to print the value into. + * @param [in] value Sysrepo value to print. + */ +int sr_print_val_fd(int fd, const sr_val_t *value); + +/** + * @brief Print sysrepo value to the specified output file stream. + * + * @param [in] stream Output file stream to print the value into. + * @param [in] value Sysrepo value to print. + */ +int sr_print_val_stream(FILE *stream, const sr_val_t *value); + +/** + * @brief Print sysrepo value into a newly allocated memory buffer. + * The caller is expected to eventually free the returned string. + * + * @param [in] mem_p Pointer to store the resulting dump. + * @param [in] value Sysrepo value to print. + */ +int sr_print_val_mem(char **mem_p, const sr_val_t *value); + +/** + * @brief Converts value to string representation + * @param [in] value + * @return allocated string representation of value (must be freed by caller), NULL in case of error + * @note In case of SR_DECIMAL64_T type, number of fraction digits doesn't have to + * correspond to schema. + */ +char *sr_val_to_str(const sr_val_t *value); + +/** + * @brief Converts value to string and prints it to the provided buffer including + * terminating NULL byte + * @param [in] value + * @param [in] buffer - buffer provided by caller where the data will be printed + * @param [in] size - the size of the buffer + * @return number of characters that was written in case of success, otherwise number of characters which would have been + * written if enough space had been available (excluding terminating NULL byte) + * @note In case of SR_DECIMAL64_T type, number of fraction digits doesn't have to + * correspond to schema. + */ +int sr_val_to_buff(const sr_val_t *value, char buffer[], size_t size); + +/**@} values */ + +#ifdef __cplusplus +} +#endif + +#endif /* SYSREPO_VALUES_H_ */ diff --git a/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/xpath.h b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/xpath.h new file mode 100644 index 000000000..7eca41e57 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/netopeer-change-saver-native/sysrepo/xpath.h @@ -0,0 +1,232 @@ +/** + * @file xpath.h + * @author Rastislav Szabo , Lukas Macko + * @brief Sysrepo helpers for node's address manipulation. + * + * @copyright + * Copyright 2015 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. + */ + +#ifndef SYSREPO_XPATH_H_ +#define SYSREPO_XPATH_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup xpath_utils XPath Processing Utilities + * @{ + * + * @brief Set of helpers working on a subset of xpath expressions used of node identification + * Functions modify inputs arguments by placing termination zero at appropriate places to save up + * string duplication. The state of processing is stored in ::sr_xpath_ctx_t opaque for user. + * It allows to continue in processing where the processing stopped or recover processed input. + * + * Similarly to strtok function in all subsequent calls that is supposed to work with the same + * input xpath must be NULL. + */ + +/** + * @brief State of xpath parsing. User must not modify nor rely on the content + * of the structure. + */ +typedef struct sr_xpath_ctx_s { + char *begining; /**< Pointer to the begining of the processed string */ + char *current_node; /**< Pointer to the currently processed node, used as a context for key search */ + char *replaced_position; /**< Pointer to the posistion where the last terminating 0 by was written */ + char replaced_char; /**< Character that was overwritten by the last termination 0 */ +} sr_xpath_ctx_t; + +/** + * @brief The function returns a pointer to the following node. If xpath is + * not NULL returns the first node name, otherwise returns the subsequent node + * according to the state. + * + * The state is modified upon function successful return from function, so the subsequent + * calls can continue in processing or xpath can be recovered by calling ::sr_xpath_recover. + * + * @note It writes terminating zero at the and of the node name. + * + * @note Skips the namespace if it is present to get node name qualified by namespace use ::sr_xpath_next_node_with_ns + * + * @param [in] xpath - xpath to be processed, can be NULL + * @param [in] state + * @return Pointer to the node name, NULL if there are no more node names + */ +char *sr_xpath_next_node(char *xpath, sr_xpath_ctx_t *state); + +/** + * @brief Returns pointer to the last node. + * @param [in] xpath + * @param [in] state + * @return Pointer to the last node + */ +char *sr_xpath_last_node(char *xpath, sr_xpath_ctx_t *state); + +/** + * @brief Same as ::sr_xpath_next_node with the difference that namespace is included in result if present in xpath + * + * @param [in] xpath - xpath to be processed, can be NULL if the user wants to continue in processing of previous input + * @param [in] state + * @return Pointer to the node name including namespace, NULL if there are no more node names + */ +char *sr_xpath_next_node_with_ns(char *xpath, sr_xpath_ctx_t *state); + +/** + * @brief Returns the name of the next key at the current level in processed xpath. + * + * @param [in] xpath + * @param [in] state + * @return Pointer to the key name, NULL if there are no more keys at the current level + */ +char *sr_xpath_next_key_name(char *xpath, sr_xpath_ctx_t *state); + +/** + * @brief Returns the value of the next key at the current level in processed xpath. + * + * @param [in] xpath + * @param [in] state + * @return Pointer to the key value, NULL if there are no more keys at the current level + */ +char *sr_xpath_next_key_value(char *xpath, sr_xpath_ctx_t *state); + +/** + * @brief Returns a pointer to the node specified by name. It searches from the beginning of the xpath, returns first match. + * Can be used to jump at the desired node xpath and subsequent analysis of key values. + * + * @param [in] xpath + * @param [in] node_name + * @param [in] state + * @return Pointer to the node, NULL if the node with the specified name is not found + */ +char *sr_xpath_node(char *xpath, const char *node_name, sr_xpath_ctx_t *state); + +/** + * @brief Similar to ::sr_xpath_node. The difference is that search start at current node + * according to the state. + * + * @param [in] xpath + * @param [in] node_name + * @param [in] state + * @return Pointer to the node, NULL if the node with the specified name is not found + */ +char *sr_xpath_node_rel(char *xpath, const char *node_name, sr_xpath_ctx_t *state); + +/** + * @brief Returns node specified by index starting at the begin of expression. + * First node has index 0. + * + * @param [in] xpath + * @param [in] index + * @param [in] state + * @return Pointer to the specified node, NULL if the index is out of bounds + */ +char *sr_xpath_node_idx(char *xpath, size_t index, sr_xpath_ctx_t *state); + +/** + * @brief Return node specified by index. Following node has index zero. + * + * @param [in] xpath + * @param [in] index + * @param [in] state + * @return Pointer to the specified node, NULL if the index is out of bounds + */ +char *sr_xpath_node_idx_rel(char *xpath, size_t index, sr_xpath_ctx_t *state); + +/** + * @brief Looks up the value for the key at the current level in xpath. + * + * @param [in] xpath + * @param [in] key - key name to be looked up + * @param [in] state + * @return Key value, NULL if the key with the specified name is not found + */ +char *sr_xpath_node_key_value(char *xpath, const char *key, sr_xpath_ctx_t *state); + +/** + * @brief Looks up the value for the key at the current level in xpath specified by index. + * First key has index zero. + * + * @param [in] xpath + * @param [in] index + * @param [in] state + * @return Key value, NULL if the index is out of bound + */ +char *sr_xpath_node_key_value_idx(char *xpath, size_t index, sr_xpath_ctx_t *state); + +/** + * @brief Looks up the value of the key in a node specified by name. + * + * @param [in] xpath + * @param [in] node_name + * @param [in] key_name + * @param [in] state + * @return Pointer to the key value, NULL if not found + */ +char *sr_xpath_key_value(char *xpath, const char *node_name, const char *key_name, sr_xpath_ctx_t *state); + +/** + * @brief Looks up the value of the key in a node specified by index. First node has index zero. + * + * @param [in] xpath + * @param [in] node_index + * @param [in] key_index + * @param [in] state + * @return Pointer to the key value, NULL if not found or index out of bound + */ +char *sr_xpath_key_value_idx(char *xpath, size_t node_index, size_t key_index, sr_xpath_ctx_t *state); + +/** + * @brief Returns pointer to the string after the last slash in xpath (node name). + * + * @note The returned string can also contain namespace and/or key values + * if they were specified for the last node in xpath. + * + * @param [in] xpath + * @return Result, NULL in case of the slash was not found + */ +char *sr_xpath_node_name(const char *xpath); + +/** + * @brief Compares string after the last slash in xpath (node name) with provided string. + * + * @note The returned string can also contain namespace and/or key values + * if they were specified for the last node in xpath. + * + * @param [in] xpath + * @param [in] node_str String to test for equality. + * @return true in case that the Node names are equal, false otherwise + */ +bool sr_xpath_node_name_eq(const char *xpath, const char *node_str); + +/** + * @brief Recovers the xpath string to the original state (puts back the character + * that was replaced by termination zero). + * + * @param [in] state + */ +void sr_xpath_recover(sr_xpath_ctx_t *state); + +/**@} xpath_utils */ + +#ifdef __cplusplus +} +#endif + +#endif /* SYSREPO_XPATH_H_ */ + diff --git a/test/mocks/pnfsimulator/netconfsimulator/pom.xml b/test/mocks/pnfsimulator/netconfsimulator/pom.xml new file mode 100644 index 000000000..7c8d5c78e --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/pom.xml @@ -0,0 +1,278 @@ + + + + + 4.0.0 + + + org.onap.simulator + simulator-parent + 5.0.0-SNAPSHOT + + + netconfsimulator + 5.0.0-SNAPSHOT + + + UTF-8 + 1.8 + 1.8 + yyyyMMdd'T'HHmmss + nexus3.onap.org:10003 + latest + onap/${project.artifactId} + 2.1.6.RELEASE + 2.2.7.RELEASE + 4.5.6 + libs + ${project.build.directory}/${dependency.directory.name} + + netopeer-change-saver + ${project.basedir}/netopeer-change-saver-native + ${project.build.directory}/cmake + ${netopeer-saver-build-dir}/bin + true + + + + + org.springframework.boot + spring-boot-starter + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-web + ${spring.boot.version} + + + org.projectlombok + lombok + 1.18.2 + provided + + + org.onosproject + jnc + 1.0 + + + org.springframework.boot + spring-boot-starter-websocket + ${spring.boot.version} + + + javax.websocket + javax.websocket-api + 1.1 + + + + + + org.springframework.kafka + spring-kafka + ${spring.kafka.version} + + + + + + org.assertj + assertj-core + 3.9.1 + test + + + org.mockito + mockito-core + 2.18.3 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.3.1 + test + + + org.junit.vintage + junit-vintage-engine + 5.3.1 + test + + + junit + junit + 4.12 + test + + + org.springframework.boot + spring-boot-starter-test + ${spring.boot.version} + test + + + org.springframework.kafka + spring-kafka-test + ${spring.kafka.version} + test + + + org.bitbucket.radistao.test + before-after-spring-test-runner + 0.1.0 + test + + + com.palantir.docker.compose + docker-compose-rule-junit4 + 0.29.1 + test + + + org.apache.httpcomponents + httpclient + 4.5.6 + test + + + org.apache.httpcomponents + httpmime + 4.5.6 + test + + + org.apache.httpcomponents + httpclient + ${apache.httpclient.version} + + + org.apache.httpcomponents + httpmime + ${apache.httpclient.version} + + + + io.springfox + springfox-swagger2 + 2.9.2 + + + io.springfox + springfox-swagger-ui + 2.9.2 + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + ${dependency.directory.location} + runtime + true + + + + copy-external-dependencies + package + + copy-dependencies + + + + + + maven-surefire-plugin + 2.19 + + + org.junit.platform + junit-platform-surefire-provider + 1.1.1 + + + + true + true + false + + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.19.1 + + ${skipITs} + + + + + integration-test + verify + + + + + + com.spotify + docker-maven-plugin + 1.1.1 + + ${docker.registry}/${docker.image.name} + ${project.basedir}/docker + true + ${docker.registry} + + latest + ${project.version} + ${project.version}-${maven.build.timestamp} + + + + ${dependency.directory.name} + ${dependency.directory.location} + + + / + ${project.build.directory} + ${project.build.finalName}.jar + + + true + + + + + + + Palantir + https://dl.bintray.com/palantir/releases/ + + + diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/Configuration.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/Configuration.java new file mode 100644 index 000000000..92e5b2327 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/Configuration.java @@ -0,0 +1,34 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator; + +import org.apache.http.client.HttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.springframework.context.annotation.Bean; + +@org.springframework.context.annotation.Configuration +public class Configuration { + + @Bean + public HttpClient httpClient() { + return HttpClientBuilder.create().build(); + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/Main.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/Main.java new file mode 100644 index 000000000..e2a0ed0c0 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/Main.java @@ -0,0 +1,31 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.netconfsimulator; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Main { + + public static void main(String[] args) { + SpringApplication.run(Main.class, args); + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/SwaggerConfig.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/SwaggerConfig.java new file mode 100644 index 000000000..2e9df997e --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/SwaggerConfig.java @@ -0,0 +1,43 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +@EnableSwagger2 +@Configuration +class SwaggerConfig { + + @Bean + Docket api() { + return new Docket(DocumentationType.SWAGGER_2) + .select() + .apis(RequestHandlerSelectors.basePackage("org.onap.netconfsimulator")) + .paths(PathSelectors.any()) + .build(); + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/Config.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/Config.java new file mode 100644 index 000000000..9ae564103 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/Config.java @@ -0,0 +1,70 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.kafka; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.onap.netconfsimulator.kafka.listener.KafkaListenerHandler; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.annotation.EnableKafka; +import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; +import org.springframework.kafka.core.ConsumerFactory; +import org.springframework.kafka.core.DefaultKafkaConsumerFactory; + +@Configuration +@EnableKafka +class Config { + + @Value("${spring.kafka.bootstrap-servers}") + private String bootstrapServer; + + @Value("${spring.kafka.consumer.auto-offset-reset}") + private String offsetReset; + + @Bean + ConcurrentKafkaListenerContainerFactory kafkaListenerContainerFactory(ConsumerFactory consumerFactory) { + ConcurrentKafkaListenerContainerFactory containerFactory = new ConcurrentKafkaListenerContainerFactory<>(); + containerFactory.setConsumerFactory(consumerFactory); + return containerFactory; + } + + @Bean + ConsumerFactory consumerFactory() { + Map props = new HashMap<>(); + props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServer); + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, offsetReset); + return new DefaultKafkaConsumerFactory<>(props); + } + + + @Bean + KafkaListenerHandler kafkaListenerHandler(ConsumerFactory consumerFactory) { + return new KafkaListenerHandler(consumerFactory); + } + +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/MessageDTO.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/MessageDTO.java new file mode 100644 index 000000000..4311cd61f --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/MessageDTO.java @@ -0,0 +1,31 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.kafka; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +class MessageDTO { + private long timestamp; + private String configuration; +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreController.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreController.java new file mode 100644 index 000000000..33bbdf7cf --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreController.java @@ -0,0 +1,59 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.kafka; + +import java.util.List; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Slf4j +@RequestMapping("/store") +public class StoreController { + + private StoreService service; + + @Autowired + public StoreController(StoreService service) { + this.service = service; + } + + @GetMapping("/ping") + String ping() { + return "pong"; + } + + @GetMapping("cm-history") + List getAllConfigurationChanges() { + return service.getAllMessages(); + } + + @GetMapping("/less") + List less(@RequestParam(value = "offset", required = false, defaultValue = "${spring.kafka.default-offset}") long offset) { + return service.getLastMessages(offset); + } + +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreService.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreService.java new file mode 100644 index 000000000..5fddff5a2 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/StoreService.java @@ -0,0 +1,91 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.kafka; + +import lombok.extern.slf4j.Slf4j; +import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.common.TopicPartition; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.kafka.core.ConsumerFactory; +import org.springframework.stereotype.Service; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@Slf4j +@Service +public class StoreService { + + private static final String CONFIG_TOPIC = "config"; + private static final long CONSUMING_DURATION_IN_MS = 1000; + + private ConsumerFactory consumerFactory; + static final List TOPICS_TO_SUBSCRIBE = Collections.singletonList(CONFIG_TOPIC); + + @Autowired + StoreService(ConsumerFactory consumerFactory) { + this.consumerFactory = consumerFactory; + } + + List getAllMessages() { + List messages = new ArrayList<>(); + String clientID = Long.toString(Instant.now().getEpochSecond()); + try (Consumer consumer = consumerFactory.createConsumer(clientID, clientID)) { + consumer.subscribe(TOPICS_TO_SUBSCRIBE); + ConsumerRecords consumerRecords = consumer.poll(CONSUMING_DURATION_IN_MS); + consumerRecords.forEach( + consumerRecord -> + messages.add(new MessageDTO(consumerRecord.timestamp(), consumerRecord.value()))); + log.debug(String.format("consumed %d messages", consumerRecords.count())); + } + return messages; + } + + List getLastMessages(long offset) { + List messages = new ArrayList<>(); + try (Consumer consumer = createConsumer(offset)) { + ConsumerRecords consumerRecords = consumer.poll(CONSUMING_DURATION_IN_MS); + consumerRecords.forEach(consumerRecord -> + messages.add(new MessageDTO(consumerRecord.timestamp(), consumerRecord.value()))); + } + return messages; + } + + private Consumer createConsumer(long offsetFromLastIndex) { + String clientID = Long.toString(Instant.now().getEpochSecond()); + Consumer consumer = consumerFactory.createConsumer(clientID, clientID); + consumer.subscribe(TOPICS_TO_SUBSCRIBE); + seekConsumerTo(consumer, offsetFromLastIndex); + return consumer; + } + + private void seekConsumerTo(Consumer consumer, long offsetFromLastIndex) { + consumer.seekToEnd(consumer.assignment()); + consumer.poll(CONSUMING_DURATION_IN_MS); + TopicPartition topicPartition = consumer.assignment().iterator().next(); + long topicCurrentSize = consumer.position(topicPartition); + long indexToSeek = offsetFromLastIndex > topicCurrentSize ? 0 : topicCurrentSize - offsetFromLastIndex; + consumer.seek(topicPartition, indexToSeek); + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerEntry.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerEntry.java new file mode 100644 index 000000000..e3c04c9fc --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerEntry.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.kafka.listener; + +import lombok.Getter; +import org.springframework.kafka.listener.AbstractMessageListenerContainer; + +@Getter +public class KafkaListenerEntry { + + private String clientId; + private AbstractMessageListenerContainer listenerContainer; + + public KafkaListenerEntry(String clientId, AbstractMessageListenerContainer listenerContainer) { + this.clientId = clientId; + this.listenerContainer = listenerContainer; + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerHandler.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerHandler.java new file mode 100644 index 000000000..604315d5f --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerHandler.java @@ -0,0 +1,67 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.kafka.listener; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.kafka.core.ConsumerFactory; + +import org.springframework.kafka.listener.ContainerProperties; +import org.springframework.kafka.listener.KafkaMessageListenerContainer; +import org.springframework.kafka.listener.MessageListener; + + +import org.springframework.kafka.support.TopicPartitionInitialOffset; + +import java.time.Instant; + +public class KafkaListenerHandler { + + private static final int PARTITION = 0; + private static final long NUMBER_OF_HISTORICAL_MESSAGES_TO_SHOW = -10L; + private static final boolean RELATIVE_TO_CURRENT = false; + private ConsumerFactory consumerFactory; + + + @Autowired + public KafkaListenerHandler(ConsumerFactory consumerFactory) { + this.consumerFactory = consumerFactory; + } + + + public KafkaListenerEntry createKafkaListener(MessageListener messageListener, String topicName) { + String clientId = Long.toString(Instant.now().getEpochSecond()); + ContainerProperties containerProperties = new ContainerProperties(topicName); + containerProperties.setGroupId(clientId); + KafkaMessageListenerContainer listenerContainer = createListenerContainer(containerProperties, + topicName); + + listenerContainer.setupMessageListener(messageListener); + return new KafkaListenerEntry(clientId, listenerContainer); + } + + + KafkaMessageListenerContainer createListenerContainer(ContainerProperties containerProperties, + String topicName) { + TopicPartitionInitialOffset config = new TopicPartitionInitialOffset(topicName, PARTITION, + NUMBER_OF_HISTORICAL_MESSAGES_TO_SHOW, RELATIVE_TO_CURRENT); + return new KafkaMessageListenerContainer<>(consumerFactory, containerProperties, config); + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/model/KafkaMessage.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/model/KafkaMessage.java new file mode 100644 index 000000000..90f283acf --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/kafka/model/KafkaMessage.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.kafka.model; + +import lombok.Getter; + +@Getter +public class KafkaMessage { + private long timestamp; + private String configuration; + + public KafkaMessage(long timestamp, String configuration) { + this.timestamp = timestamp; + this.configuration = configuration; + } + + KafkaMessage() { + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/NetconfController.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/NetconfController.java new file mode 100644 index 000000000..cdb4a8f97 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/NetconfController.java @@ -0,0 +1,111 @@ +/* + * ============LICENSE_START======================================================= + * NETCONF-CONTROLLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.netconfcore; + +import com.tailf.jnc.JNCException; + +import java.io.IOException; + +import lombok.extern.slf4j.Slf4j; +import org.onap.netconfsimulator.netconfcore.configuration.NetconfConfigurationService; +import org.onap.netconfsimulator.netconfcore.model.LoadModelResponse; +import org.onap.netconfsimulator.netconfcore.model.NetconfModelLoaderService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +@Slf4j +@RestController +@RequestMapping("netconf") +class NetconfController { + + private final NetconfConfigurationService netconfService; + private final NetconfModelLoaderService netconfModelLoaderService; + + @Autowired + NetconfController(NetconfConfigurationService netconfService, + NetconfModelLoaderService netconfModelLoaderService) { + this.netconfService = netconfService; + this.netconfModelLoaderService = netconfModelLoaderService; + } + + @GetMapping(value = "get", produces = "application/xml") + ResponseEntity getNetconfConfiguration() throws IOException, JNCException { + return ResponseEntity.ok(netconfService.getCurrentConfiguration()); + } + + @GetMapping(value = "get/{model}/{container}", produces = "application/xml") + ResponseEntity getNetconfConfiguration(@PathVariable String model, + @PathVariable String container) + throws IOException { + ResponseEntity entity; + try { + entity = ResponseEntity.ok(netconfService.getCurrentConfiguration(model, container)); + } catch (JNCException exception) { + log.error("Get configuration for model {} and container {} failed.", model, container, + exception); + entity = ResponseEntity.badRequest().body(exception.toString()); + } + return entity; + } + + @PostMapping(value = "edit-config", produces = "application/xml") + @ResponseStatus(HttpStatus.ACCEPTED) + ResponseEntity editConfig(@RequestPart("editConfigXml") MultipartFile editConfig) + throws IOException, JNCException { + log.info("Loading updated configuration"); + if (editConfig == null || editConfig.isEmpty()) { + throw new IllegalArgumentException("No XML file with proper name: editConfigXml found."); + } + return ResponseEntity + .status(HttpStatus.ACCEPTED) + .body(netconfService.editCurrentConfiguration(editConfig)); + } + + @PostMapping("model/{moduleName}") + ResponseEntity loadNewYangModel(@RequestBody MultipartFile yangModel, + @RequestBody MultipartFile initialConfig, @PathVariable String moduleName) + throws IOException { + LoadModelResponse response = netconfModelLoaderService.loadYangModel(yangModel, initialConfig, moduleName); + return ResponseEntity + .status(response.getStatusCode()) + .body(response.getMessage()); + } + + @DeleteMapping("model/{modelName}") + ResponseEntity deleteYangModel(@PathVariable String modelName) + throws IOException { + LoadModelResponse response = netconfModelLoaderService.deleteYangModel(modelName); + return ResponseEntity + .status(response.getStatusCode()) + .body(response.getMessage()); + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfBeanConfiguration.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfBeanConfiguration.java new file mode 100644 index 000000000..d90c60d58 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfBeanConfiguration.java @@ -0,0 +1,60 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.netconfcore.configuration; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +class NetconfBeanConfiguration { + + private static final Logger LOGGER = LoggerFactory.getLogger(NetconfBeanConfiguration.class); + + @Value("${netconf.port}") + private Integer netconfPort; + + @Value("${netconf.address}") + private String netconfAddress; + + @Value("${netconf.user}") + private String netconfUser; + + @Value("${netconf.password}") + private String netconfPassword; + + @Bean + NetconfConfigurationReader configurationReader() { + NetconfConnectionParams params = new NetconfConnectionParams(netconfAddress, netconfPort, netconfUser, netconfPassword); + LOGGER.info("Configuration params are : {}", params); + return new NetconfConfigurationReader(params, new NetconfSessionHelper()); + } + + @Bean + NetconfConfigurationEditor configurationEditor() { + NetconfConnectionParams params = + new NetconfConnectionParams(netconfAddress, netconfPort, netconfUser, netconfPassword); + return new NetconfConfigurationEditor(params, new NetconfSessionHelper()); + } + +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationEditor.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationEditor.java new file mode 100644 index 000000000..992c88d5a --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationEditor.java @@ -0,0 +1,50 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.netconfcore.configuration; + +import com.tailf.jnc.Element; +import com.tailf.jnc.JNCException; +import com.tailf.jnc.NetconfSession; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; + +@Slf4j +public class NetconfConfigurationEditor { + + private NetconfConnectionParams params; + private NetconfSessionHelper netconfSessionHelper; + + public NetconfConfigurationEditor(NetconfConnectionParams params, NetconfSessionHelper netconfSessionHelper) { + this.params = params; + this.netconfSessionHelper = netconfSessionHelper; + } + + void editConfig(Element configurationXmlElement) throws JNCException, IOException { + log.debug("New configuration passed to simulator: {}", configurationXmlElement.toXMLString()); + NetconfSession session = netconfSessionHelper.createNetconfSession(params); + session.editConfig(configurationXmlElement); + session.closeSession(); + + log.info("Successfully updated configuration"); + } + +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationReader.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationReader.java new file mode 100644 index 000000000..10fe40e2f --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationReader.java @@ -0,0 +1,57 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.netconfcore.configuration; + +import com.tailf.jnc.JNCException; +import com.tailf.jnc.NetconfSession; +import com.tailf.jnc.NodeSet; +import java.io.IOException; +import java.util.Objects; + +class NetconfConfigurationReader { + + private NetconfConnectionParams params; + private NetconfSessionHelper netconfSessionHelper; + + NetconfConfigurationReader(NetconfConnectionParams params, NetconfSessionHelper netconfSessionHelper) { + this.params = params; + this.netconfSessionHelper = netconfSessionHelper; + } + + String getRunningConfig() throws IOException, JNCException { + NetconfSession session = netconfSessionHelper.createNetconfSession(params); + String config = session.getConfig().toXMLString(); + session.closeSession(); + return config; + } + + String getRunningConfig(String modelPath) throws IOException, JNCException { + NetconfSession session = netconfSessionHelper.createNetconfSession(params); + NodeSet config = session.getConfig(modelPath); + if (Objects.isNull(config) || Objects.isNull(config.first())) { + throw new JNCException(JNCException.ELEMENT_MISSING, modelPath); + } + session.closeSession(); + return config.first().toXMLString(); + } + + +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationService.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationService.java new file mode 100644 index 000000000..248aec46a --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationService.java @@ -0,0 +1,76 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.netconfcore.configuration; + +import com.tailf.jnc.Element; +import com.tailf.jnc.JNCException; +import com.tailf.jnc.XMLParser; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import org.xml.sax.InputSource; + +@Service +public class NetconfConfigurationService { + + private static final Logger LOGGER = LoggerFactory.getLogger(NetconfConfigurationService.class); + private static final String CONFIGURATION_HAS_BEEN_ACTIVATED = "New configuration has been activated"; + + private final NetconfConfigurationReader netconfConfigurationReader; + private NetconfConfigurationEditor configurationEditor; + private XMLParser parser; + + @Autowired + public NetconfConfigurationService(NetconfConfigurationReader netconfConfigurationReader, + NetconfConfigurationEditor netconfConfigurationEditor) throws JNCException { + this.netconfConfigurationReader = netconfConfigurationReader; + this.configurationEditor = netconfConfigurationEditor; + this.parser = new XMLParser(); + } + + public String getCurrentConfiguration() throws IOException, JNCException { + return netconfConfigurationReader.getRunningConfig(); + } + + public String getCurrentConfiguration(String model, String container) throws IOException, JNCException { + String path = String.format("/%s:%s", model, container); + return netconfConfigurationReader.getRunningConfig(path); + } + + public String editCurrentConfiguration(MultipartFile newConfiguration) throws IOException, JNCException { + Element configurationElement = convertMultipartToXmlElement(newConfiguration); + configurationEditor.editConfig(configurationElement); + + LOGGER.debug("Loading new configuration: \n{}", configurationElement.toXMLString()); + return CONFIGURATION_HAS_BEEN_ACTIVATED; + } + + private Element convertMultipartToXmlElement(MultipartFile editConfig) throws IOException, JNCException { + InputSource inputSourceUpdateConfig = new InputSource(new ByteArrayInputStream(editConfig.getBytes())); + return parser.parse(inputSourceUpdateConfig); + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationTO.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationTO.java new file mode 100644 index 000000000..e43ff690e --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationTO.java @@ -0,0 +1,32 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.netconfcore.configuration; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class NetconfConfigurationTO { + + private String configuration; + +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConnectionParams.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConnectionParams.java new file mode 100644 index 000000000..ace0ee04c --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConnectionParams.java @@ -0,0 +1,37 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.netconfcore.configuration; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; + +@AllArgsConstructor +@ToString +@Getter +class NetconfConnectionParams { + + private final String address; + private final int port; + private final String user; + private final String password; + +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfSessionHelper.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfSessionHelper.java new file mode 100644 index 000000000..69fda7d63 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfSessionHelper.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.netconfcore.configuration; + +import com.tailf.jnc.JNCException; +import com.tailf.jnc.NetconfSession; +import com.tailf.jnc.SSHConnection; +import com.tailf.jnc.SSHSession; +import java.io.IOException; + +class NetconfSessionHelper { + + NetconfSession createNetconfSession(NetconfConnectionParams params) throws IOException, JNCException { + SSHConnection sshConnection = new SSHConnection(params.getAddress(), params.getPort()); + sshConnection.authenticateWithPassword(params.getUser(), params.getPassword()); + return new NetconfSession(new SSHSession(sshConnection)); + } + +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/LoadModelResponse.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/LoadModelResponse.java new file mode 100644 index 000000000..a6e292f62 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/LoadModelResponse.java @@ -0,0 +1,40 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.netconfcore.model; + +public class LoadModelResponse { + + private Integer statusCode; + private String message; + + public LoadModelResponse(Integer statusCode, String message) { + this.statusCode = statusCode; + this.message = message; + } + + public Integer getStatusCode() { + return this.statusCode; + } + + public String getMessage() { + return this.message; + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/NetconfModelLoaderService.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/NetconfModelLoaderService.java new file mode 100644 index 000000000..7e0739579 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/netconfcore/model/NetconfModelLoaderService.java @@ -0,0 +1,104 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.netconfcore.model; + +import java.io.IOException; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +@Service +public class NetconfModelLoaderService { + + private static final Logger LOGGER = LoggerFactory.getLogger(NetconfModelLoaderService.class); + + @Value("${netconf.address}") + private String netconfIp; + + @Value("${netconf.model-loader.port}") + private String modelLoaderPort; + + private final HttpClient httpClient; + + @Autowired + public NetconfModelLoaderService(HttpClient httpClient) { + this.httpClient = httpClient; + } + + public LoadModelResponse deleteYangModel(String yangModelName) throws IOException { + String uri = getDeleteAddress(yangModelName); + HttpDelete httpDelete = new HttpDelete(uri); + HttpResponse httpResponse = httpClient.execute(httpDelete); + return parseResponse(httpResponse); + } + + public LoadModelResponse loadYangModel(MultipartFile yangModel, MultipartFile initialConfig, String moduleName) + throws IOException { + HttpPost httpPost = new HttpPost(getBackendAddress()); + HttpEntity httpEntity = MultipartEntityBuilder.create() + .addBinaryBody("yangModel", yangModel.getInputStream(), ContentType.MULTIPART_FORM_DATA, + yangModel.getOriginalFilename()) + .addBinaryBody("initialConfig", initialConfig.getInputStream(), ContentType.MULTIPART_FORM_DATA, + initialConfig.getOriginalFilename()) + .addTextBody("moduleName", moduleName) + .build(); + httpPost.setEntity(httpEntity); + HttpResponse response = httpClient.execute(httpPost); + return parseResponse(response); + } + + String getBackendAddress() { + return String.format("http://%s:%s/model", netconfIp, modelLoaderPort); + } + + String getDeleteAddress(String yangModelName) { + return String.format("%s?yangModelName=%s", getBackendAddress(), yangModelName); + } + + + private LoadModelResponse parseResponse(HttpResponse response) throws IOException { + int statusCode = response.getStatusLine().getStatusCode(); + String responseBody = EntityUtils.toString(response.getEntity()); + + logResponse(statusCode, responseBody); + return new LoadModelResponse(statusCode, responseBody); + } + + private void logResponse(int statusCode, String responseBody) { + if (statusCode >= HttpStatus.BAD_REQUEST.value()) { + LOGGER.error(responseBody); + } else { + LOGGER.info(responseBody); + } + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/EndpointConfig.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/EndpointConfig.java new file mode 100644 index 000000000..4eaa85010 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/EndpointConfig.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.websocket; + +import java.util.Collections; +import org.onap.netconfsimulator.websocket.message.NetconfMessageEncoder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.server.standard.ServerEndpointExporter; +import org.springframework.web.socket.server.standard.ServerEndpointRegistration; + +@Configuration +class EndpointConfig { + + @Bean + ServerEndpointRegistration endpointRegistration() { + ServerEndpointRegistration serverEndpointRegistration = new ServerEndpointRegistration("/netconf", + NetconfEndpoint.class); + serverEndpointRegistration.setEncoders(Collections.singletonList(NetconfMessageEncoder.class)); + return serverEndpointRegistration; + } + + @Bean + ServerEndpointExporter endpointExporter() { + return new ServerEndpointExporter(); + } +} + diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/NetconfEndpoint.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/NetconfEndpoint.java new file mode 100644 index 000000000..5870ee1e4 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/NetconfEndpoint.java @@ -0,0 +1,95 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.websocket; + + +import java.util.Optional; +import javax.websocket.CloseReason; +import javax.websocket.Endpoint; +import javax.websocket.EndpointConfig; +import javax.websocket.RemoteEndpoint; +import javax.websocket.Session; + +import org.onap.netconfsimulator.kafka.listener.KafkaListenerEntry; +import org.onap.netconfsimulator.kafka.listener.KafkaListenerHandler; +import org.onap.netconfsimulator.websocket.message.NetconfMessageListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.kafka.listener.AbstractMessageListenerContainer; +import org.springframework.kafka.listener.MessageListener; +import org.springframework.stereotype.Component; + +//instance of this class is created every each websocket request +@Component +class NetconfEndpoint extends Endpoint { + + private static final Logger LOGGER = LoggerFactory.getLogger(NetconfEndpoint.class); + private static final String TOPIC_NAME = "config"; + + private KafkaListenerHandler kafkaListenerHandler; + + public Optional getEntry() { + return entry; + } + + public void setEntry(Optional entry) { + this.entry = entry; + } + + private Optional entry = Optional.empty(); + + + @Autowired + NetconfEndpoint(KafkaListenerHandler listenerHandler) { + this.kafkaListenerHandler = listenerHandler; + } + + @Override + public void onOpen(Session session, EndpointConfig endpointConfig) { + RemoteEndpoint.Basic basicRemote = session.getBasicRemote(); + + addKafkaListener(basicRemote); + entry.ifPresent(x -> LOGGER.info("Session with client: {} established", x.getClientId())); + } + + @Override + public void onError(Session session, Throwable throwable) { + LOGGER.error("Unexpected error occurred", throwable); + } + + @Override + public void onClose(Session session, CloseReason closeReason) { + entry.ifPresent(x -> x.getListenerContainer().stop()); + entry.ifPresent(x -> LOGGER.info("Closing connection for client: {}", x.getClientId())); + } + + + private void addKafkaListener(RemoteEndpoint.Basic remoteEndpoint) { + MessageListener messageListener = new NetconfMessageListener(remoteEndpoint); + + KafkaListenerEntry kafkaListener = kafkaListenerHandler.createKafkaListener(messageListener, TOPIC_NAME); + + AbstractMessageListenerContainer listenerContainer = kafkaListener.getListenerContainer(); + listenerContainer.start(); + entry = Optional.of(kafkaListener); + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageEncoder.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageEncoder.java new file mode 100644 index 000000000..349b7e2d9 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageEncoder.java @@ -0,0 +1,34 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.websocket.message; + +import org.onap.netconfsimulator.kafka.model.KafkaMessage; +import org.springframework.web.socket.adapter.standard.ConvertingEncoderDecoderSupport; + +public class NetconfMessageEncoder extends ConvertingEncoderDecoderSupport.TextEncoder { + + private static final String MESSAGE_FORMAT = "%s: %s"; + + @Override + public String encode(KafkaMessage netconfMessage) { + return String.format(MESSAGE_FORMAT, netconfMessage.getTimestamp(), netconfMessage.getConfiguration()); + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageListener.java b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageListener.java new file mode 100644 index 000000000..61610dea0 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/java/org/onap/netconfsimulator/websocket/message/NetconfMessageListener.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.websocket.message; + +import java.io.IOException; +import javax.websocket.EncodeException; +import javax.websocket.RemoteEndpoint; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.onap.netconfsimulator.kafka.model.KafkaMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.kafka.listener.MessageListener; + +public class NetconfMessageListener implements MessageListener { + + private static final Logger LOGGER = LoggerFactory.getLogger(NetconfMessageListener.class); + private RemoteEndpoint.Basic remoteEndpoint; + + public NetconfMessageListener(RemoteEndpoint.Basic remoteEndpoint) { + this.remoteEndpoint = remoteEndpoint; + } + + @Override + public void onMessage(ConsumerRecord message) { + LOGGER.debug("Attempting to send message to {}", remoteEndpoint); + try { + remoteEndpoint + .sendObject(new KafkaMessage(message.timestamp(), message.value())); + } catch (IOException | EncodeException exception) { + LOGGER.error("Error during sending message to remote", exception); + } + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/main/resources/application.properties b/test/mocks/pnfsimulator/netconfsimulator/src/main/resources/application.properties new file mode 100644 index 000000000..3947cf358 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/main/resources/application.properties @@ -0,0 +1,8 @@ +netconf.port=830 +netconf.address=netopeer +netconf.user=netconf +netconf.password=netconf +netconf.model-loader.port=5002 +spring.kafka.bootstrap-servers=kafka1:9092 +spring.kafka.default-offset=100 +spring.kafka.consumer.auto-offset-reset=earliest diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/test/java/integration/NetconfFunctionsIT.java b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/integration/NetconfFunctionsIT.java new file mode 100644 index 000000000..95ef58696 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/integration/NetconfFunctionsIT.java @@ -0,0 +1,211 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package integration; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.palantir.docker.compose.connection.DockerMachine; +import com.palantir.docker.compose.connection.waiting.HealthChecks; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.bitbucket.radistao.test.annotation.BeforeAllMethods; +import org.bitbucket.radistao.test.runner.BeforeAfterSpringTestRunner; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; +import com.palantir.docker.compose.DockerComposeRule; +import org.onap.netconfsimulator.kafka.model.KafkaMessage; +import org.springframework.http.HttpStatus; + +import java.io.IOException; + +import java.time.Duration; +import java.time.Instant; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import static junit.framework.TestCase.fail; +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(BeforeAfterSpringTestRunner.class) +public class NetconfFunctionsIT { + + private static NetconfSimulatorClient client; + private static ObjectMapper objectMapper; + + private static final DockerMachine dockerMachine = DockerMachine + .localMachine() + .build(); + + private static DockerComposeRule docker = DockerComposeRule.builder() + .file("docker-compose.yml") + .machine(dockerMachine) + .removeConflictingContainersOnStartup(true) + .waitingForService("sftp-server", HealthChecks.toHaveAllPortsOpen()) + .waitingForService("ftpes-server", HealthChecks.toHaveAllPortsOpen()) + .waitingForService("zookeeper", HealthChecks.toHaveAllPortsOpen()) + .waitingForService("netopeer", HealthChecks.toHaveAllPortsOpen()) + .waitingForService("kafka1", HealthChecks.toHaveAllPortsOpen()) + .waitingForService("netconf-simulator", HealthChecks.toHaveAllPortsOpen()) + .build(); + + @ClassRule + public static TestRule exposePortMappings = docker; + + @BeforeClass + public static void setUpClass() { + objectMapper = new ObjectMapper(); + client = new NetconfSimulatorClient(String.format("http://%s:%d", docker.containers().ip(), 9000)); + } + + @BeforeAllMethods + public void setupBeforeAll() throws InterruptedException { + if (client.isServiceAvailable(Instant.now(), Duration.ofSeconds(45))) { + Thread.sleep(60000); + return; + } + fail("Application failed to start within established timeout: 45 seconds. Exiting."); + } + + @Before + public void setUp() { + client.reinitializeClient(); + } + + @After + public void tearDown() throws Exception { + client.releaseClient(); + } + + @Test + public void testShouldLoadModelEditConfigurationAndDeleteModule() throws IOException { + // do load + try (CloseableHttpResponse response = client + .loadModel("newyangmodel", "newYangModel.yang", "initialConfig.xml")) { + assertResponseStatusCode(response, HttpStatus.OK); + String original = client.getResponseContentAsString(response); + assertThat(original).isEqualTo("\"Successfully started\"\n"); + } + // do edit-config + try (CloseableHttpResponse updateResponse = client.updateConfig()) { + String afterUpdateConfigContent = client.getResponseContentAsString(updateResponse); + assertResponseStatusCode(updateResponse, HttpStatus.ACCEPTED); + assertThat(afterUpdateConfigContent).isEqualTo("New configuration has been activated"); + } + // do delete + try (CloseableHttpResponse deleteResponse = client.deleteModel("newyangmodel")) { + assertResponseStatusCode(deleteResponse, HttpStatus.OK); + String original = client.getResponseContentAsString(deleteResponse); + assertThat(original).isEqualTo("\"Successfully deleted\"\n"); + } + } + + @Test + public void testShouldGetCurrentConfigurationAndEditItSuccessfully() throws IOException { + try (CloseableHttpResponse updateResponse = client.updateConfig(); + CloseableHttpResponse newCurrentConfigResponse = client.getCurrentConfig()) { + String afterUpdateConfigContent = client.getResponseContentAsString(updateResponse); + + assertResponseStatusCode(updateResponse, HttpStatus.ACCEPTED); + assertResponseStatusCode(newCurrentConfigResponse, HttpStatus.OK); + + assertThat(afterUpdateConfigContent).isEqualTo("New configuration has been activated"); + } + } + + @Test + public void testShouldPersistConfigChangesAndGetAllWhenRequested() throws IOException { + client.updateConfig(); + + try (CloseableHttpResponse newAllConfigChangesResponse = client.getAllConfigChanges()) { + String newAllConfigChangesString = client.getResponseContentAsString(newAllConfigChangesResponse); + assertResponseStatusCode(newAllConfigChangesResponse, HttpStatus.OK); + + List kafkaMessages = objectMapper + .readValue(newAllConfigChangesString, new TypeReference>() { + }); + + assertThat(kafkaMessages.size()).isGreaterThanOrEqualTo(1); + Set configChangeContent = kafkaMessages.stream().map(KafkaMessage::getConfiguration) + .collect(Collectors.toSet()); + assertThat(configChangeContent) + .anyMatch(el -> el.contains("new value: /pnf-simulator:config/itemValue1 = 100")); + assertThat(configChangeContent) + .anyMatch(el -> el.contains("new value: /pnf-simulator:config/itemValue2 = 200")); + } + } + + @Test + public void testShouldGetLastMessage() throws IOException { + client.updateConfig(); + + try (CloseableHttpResponse lastConfigChangesResponse = client.getLastConfigChanges(2)) { + String newAllConfigChangesString = client.getResponseContentAsString(lastConfigChangesResponse); + List kafkaMessages = objectMapper + .readValue(newAllConfigChangesString, new TypeReference>() { + }); + + assertThat(kafkaMessages).hasSize(2); + assertThat(kafkaMessages.get(0).getConfiguration()) + .contains("new value: /pnf-simulator:config/itemValue1 = 100"); + assertThat(kafkaMessages.get(1).getConfiguration()) + .contains("new value: /pnf-simulator:config/itemValue2 = 200"); + } + } + + @Test + public void testShouldLoadNewYangModelAndReconfigure() throws IOException { + try (CloseableHttpResponse response = client + .loadModel("newyangmodel", "newYangModel.yang", "initialConfig.xml")) { + assertResponseStatusCode(response, HttpStatus.OK); + + String original = client.getResponseContentAsString(response); + + assertThat(original).isEqualTo("\"Successfully started\"\n"); + } + } + + @Test + public void shouldGetLoadedModelByName() throws IOException { + testShouldLoadNewYangModelAndReconfigure(); + + try (CloseableHttpResponse response = client.getConfigByModelAndContainerNames("newyangmodel", "config2")) { + assertResponseStatusCode(response, HttpStatus.OK); + String config = client.getResponseContentAsString(response); + + assertThat(config).isEqualTo( + "\n" + + " 100\n" + + "\n"); + } + + } + + private void assertResponseStatusCode(HttpResponse response, HttpStatus expectedStatus) { + assertThat(response.getStatusLine().getStatusCode()).isEqualTo(expectedStatus.value()); + } + +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/test/java/integration/NetconfSimulatorClient.java b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/integration/NetconfSimulatorClient.java new file mode 100644 index 000000000..61f2ef1d8 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/integration/NetconfSimulatorClient.java @@ -0,0 +1,150 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package integration; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.junit.platform.commons.logging.Logger; +import org.junit.platform.commons.logging.LoggerFactory; +import org.springframework.util.ResourceUtils; + +import java.io.IOException; +import java.time.Duration; +import java.time.Instant; + +class NetconfSimulatorClient { + + private CloseableHttpClient netconfClient; + private String simulatorBaseUrl; + private static final Logger LOG = LoggerFactory.getLogger(NetconfSimulatorClient.class); + + NetconfSimulatorClient(String simulatorBaseUrl) { + this.netconfClient = HttpClients.createDefault(); + this.simulatorBaseUrl = simulatorBaseUrl; + } + + CloseableHttpResponse loadModel(String moduleName, String yangModelFileName, String initialiConfigFileName) throws IOException { + String updateConfigUrl = String.format("%s/netconf/model/%s", simulatorBaseUrl, moduleName); + HttpPost httpPost = new HttpPost(updateConfigUrl); + HttpEntity updatedConfig = MultipartEntityBuilder + .create() + .addBinaryBody("yangModel", ResourceUtils.getFile(String.format("classpath:%s", yangModelFileName))) + .addBinaryBody("initialConfig", ResourceUtils.getFile(String.format("classpath:%s",initialiConfigFileName))) + .addTextBody("moduleName", moduleName) + .build(); + httpPost.setEntity(updatedConfig); + return netconfClient.execute(httpPost); + } + + CloseableHttpResponse deleteModel(String moduleName) throws IOException { + String deleteModuleUrl = String.format("%s/netconf/model/%s", simulatorBaseUrl, moduleName); + HttpDelete httpDelete = new HttpDelete(deleteModuleUrl); + return netconfClient.execute(httpDelete); + } + + boolean isServiceAvailable(Instant startTime, Duration maxWaitingDuration) throws InterruptedException { + boolean isServiceReady = false; + while (Duration.between(startTime, Instant.now()).compareTo(maxWaitingDuration) < 1){ + if(checkIfSimResponds()){ + return true; + } + else { + LOG.info(() -> "Simulator not ready yet, retrying in 5s..."); + Thread.sleep(5000); + } + } + return isServiceReady; + } + + private boolean checkIfSimResponds() throws InterruptedException { + try(CloseableHttpResponse pingResponse = getCurrentConfig()){ + String responseString = getResponseContentAsString(pingResponse); + if(pingResponse.getStatusLine().getStatusCode() == 200 && !responseString.trim().isEmpty()){ + return true; + } + } + catch(IOException ex){ + LOG.error(ex, () -> "EXCEPTION"); + Thread.sleep(5000); + } + return false; + } + + CloseableHttpResponse getCurrentConfig() throws IOException { + String netconfAddress = String.format("%s/netconf/get", simulatorBaseUrl); + HttpGet get = new HttpGet(netconfAddress); + return netconfClient.execute(get); + } + + CloseableHttpResponse getConfigByModelAndContainerNames(String model, String container) throws IOException { + String netconfAddress = String + .format("%s/netconf/get/%s/%s", simulatorBaseUrl, model, container); + HttpGet get = new HttpGet(netconfAddress); + return netconfClient.execute(get); + } + + CloseableHttpResponse updateConfig() throws IOException { + String updateConfigUrl = String.format("%s/netconf/edit-config", simulatorBaseUrl); + HttpPost httpPost = new HttpPost(updateConfigUrl); + HttpEntity updatedConfig = MultipartEntityBuilder + .create() + .addBinaryBody("editConfigXml", ResourceUtils.getFile("classpath:updatedConfig.xml")) + .build(); + httpPost.setEntity(updatedConfig); + return netconfClient.execute(httpPost); + } + + CloseableHttpResponse getAllConfigChanges() throws IOException { + String netconfStoreCmHistoryAddress = String.format("%s/store/cm-history", simulatorBaseUrl); + HttpGet configurationChangesResponse = new HttpGet(netconfStoreCmHistoryAddress); + return netconfClient.execute(configurationChangesResponse); + } + + CloseableHttpResponse getLastConfigChanges(int howManyLastChanges) throws IOException { + String netconfStoreCmHistoryAddress = String.format("%s/store/less?offset=%d", simulatorBaseUrl, howManyLastChanges); + HttpGet configurationChangesResponse = new HttpGet(netconfStoreCmHistoryAddress); + return netconfClient.execute(configurationChangesResponse); + } + + void releaseClient() throws IOException { + netconfClient.close(); + } + + void reinitializeClient(){ + netconfClient = HttpClients.createDefault(); + } + + String getResponseContentAsString(HttpResponse response) throws IOException { + HttpEntity entity = response.getEntity(); + String entityStringRepr = EntityUtils.toString(entity); + EntityUtils.consume(entity); + return entityStringRepr; + } + +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/EmbeddedKafkaConfig.java b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/EmbeddedKafkaConfig.java new file mode 100644 index 000000000..5ddf2b2a6 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/EmbeddedKafkaConfig.java @@ -0,0 +1,69 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.kafka; + + +import java.util.Map; +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; +import org.springframework.kafka.core.ConsumerFactory; +import org.springframework.kafka.core.DefaultKafkaConsumerFactory; +import org.springframework.kafka.core.DefaultKafkaProducerFactory; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.kafka.core.ProducerFactory; +import org.springframework.kafka.test.utils.KafkaTestUtils; + +import static org.onap.netconfsimulator.kafka.StoreServiceTest.embeddedKafka; + +@Configuration +class EmbeddedKafkaConfig { + + @Bean + KafkaTemplate kafkaTemplate(){ + return new KafkaTemplate<>(producerFactory()); + } + + @Bean + @Autowired + ConcurrentKafkaListenerContainerFactory kafkaListenerContainerFactory(ConsumerFactory consumerFactory){ + ConcurrentKafkaListenerContainerFactory containerFactory = new ConcurrentKafkaListenerContainerFactory<>(); + containerFactory.setConsumerFactory(consumerFactory); + return containerFactory; + } + + @Bean + ConsumerFactory consumerFactory(){ + Map consumerProperties = + KafkaTestUtils.consumerProps("sender", "false", embeddedKafka.getEmbeddedKafka()); + consumerProperties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); + return new DefaultKafkaConsumerFactory<>(consumerProperties); + } + + private ProducerFactory producerFactory() { + Map senderProperties = + KafkaTestUtils.senderProps(embeddedKafka.getEmbeddedKafka().getBrokersAsString()); + return new DefaultKafkaProducerFactory<>(senderProperties); + } + +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/StoreControllerTest.java b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/StoreControllerTest.java new file mode 100644 index 000000000..02eec12ac --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/StoreControllerTest.java @@ -0,0 +1,86 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.kafka; + +import java.time.Instant; +import java.util.List; +import org.assertj.core.api.Assertions; +import org.assertj.core.util.Lists; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.mockito.Mockito.when; + +@RunWith(SpringJUnit4ClassRunner.class) +public class StoreControllerTest { + + private static final String MESSAGE_3 = "message 3"; + private static final String MESSAGE_2 = "message 2"; + private static final String MESSAGE_1 = "message 1"; + + private static final List ALL_MESSAGES = Lists.newArrayList(new MessageDTO(Instant.now().getEpochSecond(), MESSAGE_1), + new MessageDTO(Instant.now().getEpochSecond(), MESSAGE_2), + new MessageDTO(Instant.now().getEpochSecond(), MESSAGE_3)); + + @Mock + private StoreService service; + + @InjectMocks + private StoreController storeController; + + + @Test + public void lessShouldTakeAllMessagesTest() { + when(service.getLastMessages(3)).thenReturn(ALL_MESSAGES); + + List lessResponse = storeController.less(3); + + assertResponseContainsExpectedMessages(lessResponse, 3, MESSAGE_1, MESSAGE_2, MESSAGE_3); + } + + @Test + public void lessShouldTakeTwoMessagesTest() { + when(service.getLastMessages(2)).thenReturn(Lists.newArrayList(new MessageDTO(Instant.now().getEpochSecond(), MESSAGE_1))); + + List lessResult = storeController.less(2); + + assertResponseContainsExpectedMessages(lessResult, 1, MESSAGE_1); + } + + @Test + public void shouldGetAllMessages(){ + when(service.getAllMessages()).thenReturn(ALL_MESSAGES); + + List allMsgResult = storeController.getAllConfigurationChanges(); + + assertResponseContainsExpectedMessages(allMsgResult, 3, MESSAGE_1, MESSAGE_2, MESSAGE_3); + } + + private void assertResponseContainsExpectedMessages(List actualMessages, int expectedMessageCount, String... expectedMessages){ + Assertions.assertThat(actualMessages.stream().map(MessageDTO::getConfiguration)) + .hasSize(expectedMessageCount) + .containsExactly(expectedMessages); + } + +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/StoreServiceTest.java b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/StoreServiceTest.java new file mode 100644 index 000000000..fd36116a8 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/StoreServiceTest.java @@ -0,0 +1,103 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.kafka; + +import org.bitbucket.radistao.test.annotation.BeforeAllMethods; +import org.bitbucket.radistao.test.runner.BeforeAfterSpringTestRunner; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.kafka.test.context.EmbeddedKafka; +import org.springframework.kafka.test.rule.EmbeddedKafkaRule; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(BeforeAfterSpringTestRunner.class) +@SpringBootTest(classes = {StoreService.class, EmbeddedKafkaConfig.class}) +@EmbeddedKafka +public class StoreServiceTest { + + private static final String MESSAGE_1 = "message1"; + private static final String MESSAGE_2 = "message2"; + private static final String MESSAGE_3 = "message3"; + + @ClassRule + public static EmbeddedKafkaRule embeddedKafka = new EmbeddedKafkaRule(1, true, 1, "config"); + + @Autowired + StoreService service; + + @Autowired + KafkaTemplate kafkaTemplate; + + @BeforeAllMethods + public void setupBeforeAll() { + prepareProducer(); + } + + @Test + public void testShouldReturnAllAvailableMessages(){ + + List actualMessages = service.getAllMessages(); + + assertResponseContainsExpectedMessages(actualMessages, 3, MESSAGE_1, MESSAGE_2, MESSAGE_3); + } + + @Test + public void testShouldGetLastMessagesRespectingOffset(){ + + List wantedLastMsg = service.getLastMessages(1L); + + assertResponseContainsExpectedMessages(wantedLastMsg, 1, MESSAGE_3); + } + + @Test + public void testShouldGetAll3Messages() { + List wantedLastMsgs = service.getLastMessages(3L); + + assertResponseContainsExpectedMessages(wantedLastMsgs, 3, MESSAGE_1, MESSAGE_2, MESSAGE_3); + } + + private void prepareProducer(){ + kafkaTemplate.send("config", "message1"); + kafkaTemplate.send("config", "message2"); + kafkaTemplate.send("config", "message3"); + } + + private void assertResponseContainsExpectedMessages(List actualMessages, int expectedMessageCount, String... expectedMessages){ + assertThat(actualMessages.stream().map(MessageDTO::getConfiguration)) + .hasSize(expectedMessageCount) + .containsExactly(expectedMessages); + } + +} + + + + + + + diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerHandlerTest.java b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerHandlerTest.java new file mode 100644 index 000000000..fcb72666a --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/kafka/listener/KafkaListenerHandlerTest.java @@ -0,0 +1,87 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.kafka.listener; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.MockitoAnnotations.initMocks; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.springframework.kafka.core.ConsumerFactory; +import org.springframework.kafka.listener.ContainerProperties; +import org.springframework.kafka.listener.KafkaMessageListenerContainer; +import org.springframework.kafka.listener.MessageListener; + +class KafkaListenerHandlerTest { + + private static final String CLIENT_ID_REGEX = "[0-9]{10,}"; + private static final String SAMPLE_TOPIC = "sampleTopic"; + + @Mock + private ConsumerFactory consumerFactory; + + @Mock + private KafkaMessageListenerContainer kafkaMessageListenerContainer; + + @Mock + private MessageListener messageListener; + + @BeforeEach + void setUp() { + initMocks(this); + } + + + @Test + void shouldProperlyCreateKafkaListener() { + KafkaListenerHandler kafkaListenerHandler = spy(new KafkaListenerHandler(consumerFactory)); + doReturn(kafkaMessageListenerContainer).when(kafkaListenerHandler) + .createListenerContainer(any(ContainerProperties.class), eq(SAMPLE_TOPIC)); + + KafkaListenerEntry kafkaListenerEntry = kafkaListenerHandler + .createKafkaListener(messageListener, SAMPLE_TOPIC); + + assertThat(kafkaListenerEntry.getListenerContainer()).isEqualTo(kafkaMessageListenerContainer); + assertThat(kafkaListenerEntry.getClientId()).matches(CLIENT_ID_REGEX); + } + + @Test + void shouldProperlyCreateContainer() { + KafkaListenerHandler kafkaListenerHandler = spy(new KafkaListenerHandler(consumerFactory)); + ContainerProperties containerProperties = new ContainerProperties(SAMPLE_TOPIC); + containerProperties.setMessageListener(mock(MessageListener.class)); + + KafkaMessageListenerContainer listenerContainer = kafkaListenerHandler + .createListenerContainer(containerProperties, SAMPLE_TOPIC); + + ContainerProperties actualProperties = listenerContainer.getContainerProperties(); + assertThat(actualProperties.getTopics()).isEqualTo(containerProperties.getTopics()); + assertThat(actualProperties.getMessageListener()).isEqualTo(containerProperties.getMessageListener()); + } + + +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/NetconfControllerTest.java b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/NetconfControllerTest.java new file mode 100644 index 000000000..73fb627ea --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/NetconfControllerTest.java @@ -0,0 +1,172 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.netconfcore; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.tailf.jnc.JNCException; +import java.io.IOException; +import java.nio.file.Files; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.onap.netconfsimulator.netconfcore.configuration.NetconfConfigurationService; +import org.onap.netconfsimulator.netconfcore.model.LoadModelResponse; +import org.onap.netconfsimulator.netconfcore.model.NetconfModelLoaderService; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.util.ResourceUtils; +import org.springframework.web.multipart.MultipartFile; + +class NetconfControllerTest { + + private MockMvc mockMvc; + + @Mock + private NetconfConfigurationService netconfService; + + @Mock + private NetconfModelLoaderService netconfModelLoaderService; + + @InjectMocks + private NetconfController controller; + + private static final String SAMPLE_CONFIGURATION = "1122"; + + @BeforeEach + void setUp() { + initMocks(this); + mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); + } + + @Test + void testShouldDigestMultipartFile() throws Exception { + byte[] bytes = + Files.readAllBytes(ResourceUtils.getFile("classpath:updatedConfig.xml").toPath()); + MockMultipartFile file = new MockMultipartFile("editConfigXml", bytes); + + mockMvc + .perform(MockMvcRequestBuilders.multipart("/netconf/edit-config").file(file)) + .andExpect(status().isAccepted()); + + verify(netconfService).editCurrentConfiguration(any(MultipartFile.class)); + } + + @Test + void testShouldThrowExceptionWhenEditConfigFileWithIncorrectNameProvided() throws Exception { + MockMultipartFile file = new MockMultipartFile("wrongName", new byte[0]); + + mockMvc + .perform(MockMvcRequestBuilders.multipart("/netconf/edit-config").file(file)) + .andExpect(status().isBadRequest()); + + verify(netconfService, never()).editCurrentConfiguration(any(MultipartFile.class)); + } + + @Test + void testShouldReturnCurrentConfiguration() throws Exception { + when(netconfService.getCurrentConfiguration()).thenReturn(SAMPLE_CONFIGURATION); + + String contentAsString = + mockMvc + .perform(get("/netconf/get")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + verify(netconfService).getCurrentConfiguration(); + assertThat(contentAsString).isEqualTo(SAMPLE_CONFIGURATION); + } + + @Test + void testShouldReturnConfigurationForGivenPath() throws Exception { + when(netconfService.getCurrentConfiguration("sampleModel", "sampleContainer")) + .thenReturn(SAMPLE_CONFIGURATION); + + String contentAsString = + mockMvc + .perform(get("/netconf/get/sampleModel/sampleContainer")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + verify(netconfService).getCurrentConfiguration("sampleModel", "sampleContainer"); + assertThat(contentAsString).isEqualTo(SAMPLE_CONFIGURATION); + } + + @Test + void testShouldRaiseBadRequestWhenConfigurationIsNotPresent() throws Exception { + when(netconfService.getCurrentConfiguration("sampleModel", "sampleContainer2")) + .thenThrow(new JNCException(JNCException.ELEMENT_MISSING, "/sampleModel:sampleContainer2")); + + String contentAsString = + mockMvc + .perform(get("/netconf/get/sampleModel/sampleContainer2")) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(); + + assertThat(contentAsString).isEqualTo("Element does not exists: /sampleModel:sampleContainer2"); + } + + @Test + void shouldThrowExceptionWhenNoConfigurationPresent() throws IOException, JNCException { + when(netconfService.getCurrentConfiguration()).thenThrow(JNCException.class); + + assertThatThrownBy(() -> mockMvc.perform(get("/netconf/get"))) + .hasRootCauseExactlyInstanceOf(JNCException.class); + } + + @Test + void testShouldDeleteYangModel() throws Exception { + String responseOkString = "Alles klar"; + String yangModelName = "someModel"; + LoadModelResponse loadModelResponse = new LoadModelResponse(200, responseOkString); + String uri = String.format("/netconf/model/%s", yangModelName); + when(netconfModelLoaderService.deleteYangModel(yangModelName)).thenReturn(loadModelResponse); + + String contentAsString = + mockMvc + .perform(delete(uri)) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + verify(netconfModelLoaderService).deleteYangModel(yangModelName); + assertThat(contentAsString).isEqualTo(responseOkString); + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationEditorTest.java b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationEditorTest.java new file mode 100644 index 000000000..371bdd84b --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationEditorTest.java @@ -0,0 +1,69 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.netconfcore.configuration; + +import com.tailf.jnc.Element; +import com.tailf.jnc.JNCException; +import com.tailf.jnc.NetconfSession; +import com.tailf.jnc.XMLParser; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.onap.netconfsimulator.netconfcore.configuration.NetconfConfigurationEditor; +import org.springframework.util.ResourceUtils; +import org.xml.sax.InputSource; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.file.Files; + +import static org.mockito.Mockito.verify; +import static org.mockito.MockitoAnnotations.initMocks; + +class NetconfConfigurationEditorTest { + + @Mock + private NetconfSession session; + @Mock + private NetconfSessionHelper netconfSessionHelper; + + private NetconfConfigurationEditor editor; + + @BeforeEach + void setUp() throws IOException, JNCException { + initMocks(this); + NetconfConnectionParams params = null; + Mockito.when(netconfSessionHelper.createNetconfSession(params)).thenReturn(session); + editor = new NetconfConfigurationEditor(params, netconfSessionHelper); + } + + @Test + void testShouldEditConfigSuccessfully() throws IOException, JNCException { + byte[] bytes = + Files.readAllBytes(ResourceUtils.getFile("classpath:updatedConfig.xml").toPath()); + Element editConfigXml = new XMLParser().parse(new InputSource(new ByteArrayInputStream(bytes))); + + editor.editConfig(editConfigXml); + + verify(session).editConfig(editConfigXml); + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationReaderTest.java b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationReaderTest.java new file mode 100644 index 000000000..a0a15b993 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationReaderTest.java @@ -0,0 +1,94 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.netconfcore.configuration; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.tailf.jnc.Element; +import com.tailf.jnc.JNCException; +import com.tailf.jnc.NetconfSession; +import com.tailf.jnc.NodeSet; +import java.io.IOException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +class NetconfConfigurationReaderTest { + + private static final String NETCONF_MODEL_PATH = ""; + private static final String EXPECTED_STRING_XML = ""; + private NetconfConfigurationReader reader; + + @Mock + private NetconfSession netconfSession; + + @Mock + private NetconfSessionHelper netconfSessionHelper; + + @Mock + private NodeSet nodeSet; + + @Mock + private Element element; + + @BeforeEach + void setUp() throws IOException, JNCException { + MockitoAnnotations.initMocks(this); + NetconfConnectionParams params = null; + Mockito.when(netconfSessionHelper.createNetconfSession(params)).thenReturn(netconfSession); + reader = new NetconfConfigurationReader(params, netconfSessionHelper); + } + + @Test + void properlyReadXML() throws IOException, JNCException { + when(netconfSession.getConfig()).thenReturn(nodeSet); + when(nodeSet.toXMLString()).thenReturn(EXPECTED_STRING_XML); + + String result = reader.getRunningConfig(); + + verify(netconfSession).getConfig(); + verify(nodeSet).toXMLString(); + assertThat(result).isEqualTo(EXPECTED_STRING_XML); + } + + @Test + void shouldProperlyReadXmlByName() throws IOException, JNCException { + when(netconfSession.getConfig("/sample:test")).thenReturn(nodeSet); + when(nodeSet.first()).thenReturn(element); + when(element.toXMLString()).thenReturn(EXPECTED_STRING_XML); + + String result = reader.getRunningConfig("/sample:test"); + + verify(netconfSession).getConfig("/sample:test"); + verify(nodeSet, times(2)).first(); + verify(element).toXMLString(); + + assertThat(result).isEqualTo(EXPECTED_STRING_XML); + } + +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationServiceTest.java b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationServiceTest.java new file mode 100644 index 000000000..6da65728e --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/configuration/NetconfConfigurationServiceTest.java @@ -0,0 +1,102 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.netconfcore.configuration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +import com.tailf.jnc.Element; +import com.tailf.jnc.JNCException; +import java.io.IOException; +import java.nio.file.Files; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.util.ResourceUtils; + +class NetconfConfigurationServiceTest { + + @Mock + NetconfConfigurationReader reader; + + @Mock + NetconfConfigurationEditor editor; + + @InjectMocks + NetconfConfigurationService service; + + private static String CURRENT_CONFIG_XML_STRING = + "\n" + + " 100\n" + + " 200\n" + + "\n"; + + @BeforeEach + void setUp() { + initMocks(this); + } + + @Test + void testShouldReturnCorrectCurrentConfiguration() throws IOException, JNCException { + String expectedConfiguration = CURRENT_CONFIG_XML_STRING; + when(reader.getRunningConfig()).thenReturn(CURRENT_CONFIG_XML_STRING); + + String actualCurrentConfiguration = service.getCurrentConfiguration(); + + assertThat(actualCurrentConfiguration).isEqualToIgnoringCase(expectedConfiguration); + } + + @Test + void testShouldThrowExceptionWhenCurrentConfigurationDoesNotExists() throws IOException, JNCException{ + when(reader.getRunningConfig()).thenThrow(JNCException.class); + + assertThatThrownBy(() -> service.getCurrentConfiguration()).isInstanceOf(JNCException.class); + } + + @Test + void testShouldEditConfigurationSuccessfully() throws IOException, JNCException{ + byte[] bytes = + Files.readAllBytes(ResourceUtils.getFile("classpath:updatedConfig.xml").toPath()); + MockMultipartFile editConfigXmlContent = new MockMultipartFile("editConfigXml", bytes); + ArgumentCaptor elementCaptor = ArgumentCaptor.forClass(Element.class); + doNothing().when(editor).editConfig(elementCaptor.capture()); + + service.editCurrentConfiguration(editConfigXmlContent); + + assertThat(elementCaptor.getValue().toXMLString()).isEqualTo(CURRENT_CONFIG_XML_STRING); + } + + @Test + void testShouldRaiseExceptionWhenMultipartFileIsInvalidXmlFile() throws IOException { + byte[] bytes = + Files.readAllBytes(ResourceUtils.getFile("classpath:invalidXmlFile.xml").toPath()); + MockMultipartFile editConfigXmlContent = new MockMultipartFile("editConfigXml", bytes); + + assertThatThrownBy(() -> service.editCurrentConfiguration(editConfigXmlContent)).isInstanceOf(JNCException.class); + } + +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/model/NetconfModelLoaderServiceTest.java b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/model/NetconfModelLoaderServiceTest.java new file mode 100644 index 000000000..a10876b98 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/netconfcore/model/NetconfModelLoaderServiceTest.java @@ -0,0 +1,121 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.netconfcore.model; + + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.StatusLine; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.web.multipart.MultipartFile; + +class NetconfModelLoaderServiceTest { + + @Mock + private HttpClient httpClient; + + private NetconfModelLoaderService modelLoaderService; + + @BeforeEach + void setUp() { + MockitoAnnotations.initMocks(this); + modelLoaderService = new NetconfModelLoaderService(httpClient); + } + + + @Test + void shouldSendMultipartToServer() throws IOException { + //given + String loadModelAddress = modelLoaderService.getBackendAddress(); + makeMockClientReturnStatusOk(httpClient, HttpPost.class); + ArgumentCaptor postArgumentCaptor = ArgumentCaptor.forClass(HttpPost.class); + MultipartFile yangMmodel = mock(MultipartFile.class); + MultipartFile initialConfig = mock(MultipartFile.class); + String moduleName = "moduleName"; + when(yangMmodel.getInputStream()).thenReturn(getEmptyImputStream()); + when(initialConfig.getInputStream()).thenReturn(getEmptyImputStream()); + + //when + LoadModelResponse response = modelLoaderService.loadYangModel(yangMmodel, initialConfig, moduleName); + + //then + verify(httpClient).execute(postArgumentCaptor.capture()); + HttpPost sentPost = postArgumentCaptor.getValue(); + assertThat(response.getStatusCode()).isEqualTo(200); + assertThat(response.getMessage()).isEqualTo(""); + assertThat(sentPost.getURI().toString()).isEqualTo(loadModelAddress); + assertThat(sentPost.getEntity().getContentType().getElements()[0].getName()).isEqualTo("multipart/form-data"); + } + + @Test + void shouldSendDeleteRequestToServer() throws IOException { + //given + String yangModelName = "sampleModel"; + String deleteModelAddress = modelLoaderService.getDeleteAddress(yangModelName); + makeMockClientReturnStatusOk(httpClient, HttpDelete.class); + ArgumentCaptor deleteArgumentCaptor = ArgumentCaptor.forClass(HttpDelete.class); + + //when + LoadModelResponse response = modelLoaderService.deleteYangModel(yangModelName); + + //then + verify(httpClient).execute(deleteArgumentCaptor.capture()); + HttpDelete sendDelete = deleteArgumentCaptor.getValue(); + assertThat(response.getStatusCode()).isEqualTo(200); + assertThat(response.getMessage()).isEqualTo(""); + assertThat(sendDelete.getURI().toString()).isEqualTo(deleteModelAddress); + } + + private void makeMockClientReturnStatusOk(HttpClient client, + Class httpMethodClass) throws IOException { + HttpResponse httpResponse = mock(HttpResponse.class); + StatusLine mockStatus = mock(StatusLine.class); + HttpEntity mockEntity = mock(HttpEntity.class); + + when(client.execute(any(httpMethodClass))).thenReturn(httpResponse); + when(httpResponse.getStatusLine()).thenReturn(mockStatus); + when(mockStatus.getStatusCode()).thenReturn(200); + when(httpResponse.getEntity()).thenReturn(mockEntity); + when(mockEntity.getContent()).thenReturn(getEmptyImputStream()); + } + + private InputStream getEmptyImputStream() { + return new ByteArrayInputStream("".getBytes()); + } + +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/websocket/NetconfEndpointTest.java b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/websocket/NetconfEndpointTest.java new file mode 100644 index 000000000..c1484d4b2 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/websocket/NetconfEndpointTest.java @@ -0,0 +1,135 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.websocket; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +import java.util.Map; +import java.util.Optional; +import javax.websocket.CloseReason; +import javax.websocket.EndpointConfig; +import javax.websocket.RemoteEndpoint; +import javax.websocket.Session; +import org.apache.kafka.common.Metric; +import org.apache.kafka.common.MetricName; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.onap.netconfsimulator.kafka.listener.KafkaListenerEntry; +import org.onap.netconfsimulator.kafka.listener.KafkaListenerHandler; +import org.onap.netconfsimulator.websocket.message.NetconfMessageListener; +import org.springframework.kafka.core.ConsumerFactory; +import org.springframework.kafka.listener.AbstractMessageListenerContainer; + +import org.springframework.kafka.listener.ContainerProperties; +import org.springframework.kafka.listener.GenericMessageListener; + +class NetconfEndpointTest { + + + @Mock + private KafkaListenerHandler kafkaListenerHandler; + + @Mock + private Session session; + + @Mock + private EndpointConfig endpointConfig; + + @Mock + private RemoteEndpoint.Basic remoteEndpoint; + + + @BeforeEach + void setUp() { + initMocks(this); + } + + + @Test + void shouldCreateKafkaListenerWhenClientInitializeConnection() { + NetconfEndpoint netconfEndpoint = new NetconfEndpoint(kafkaListenerHandler); + AbstractMessageListenerContainer abstractMessageListenerContainer = getListenerContainer(); + when(session.getBasicRemote()).thenReturn(remoteEndpoint); + KafkaListenerEntry kafkaListenerEntry = new KafkaListenerEntry("sampleGroupId", + abstractMessageListenerContainer); + when(kafkaListenerHandler.createKafkaListener(any(NetconfMessageListener.class), eq("config"))) + .thenReturn(kafkaListenerEntry); + + netconfEndpoint.onOpen(session, endpointConfig); + + assertThat(netconfEndpoint.getEntry().get().getClientId()).isEqualTo("sampleGroupId"); + assertThat(netconfEndpoint.getEntry().get().getListenerContainer()).isEqualTo(abstractMessageListenerContainer); + + verify(abstractMessageListenerContainer).start(); + } + + + @Test + void shouldCloseListenerWhenClientDisconnects() { + NetconfEndpoint netconfEndpoint = new NetconfEndpoint(kafkaListenerHandler); + AbstractMessageListenerContainer abstractMessageListenerContainer = getListenerContainer(); + netconfEndpoint.setEntry( Optional.of(new KafkaListenerEntry("sampleGroupId", abstractMessageListenerContainer)) ); + + netconfEndpoint.onClose(session, mock(CloseReason.class)); + + verify(abstractMessageListenerContainer).stop(); + } + + class TestAbstractMessageListenerContainer extends AbstractMessageListenerContainer { + + + TestAbstractMessageListenerContainer(ContainerProperties containerProperties) { + super(mock(ConsumerFactory.class),containerProperties); + } + + @Override + protected void doStart() { + + } + + @Override + protected void doStop(Runnable callback) { + + } + + @Override + public Map> metrics() { + return null; + } + } + + private AbstractMessageListenerContainer getListenerContainer() { + ContainerProperties containerProperties = new ContainerProperties("config"); + containerProperties.setGroupId("sample"); + containerProperties.setMessageListener(mock(GenericMessageListener.class)); + TestAbstractMessageListenerContainer testAbstractMessageListenerContainer = new TestAbstractMessageListenerContainer( + containerProperties); + return spy(testAbstractMessageListenerContainer); + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/websocket/message/NetconfMessageListenerTest.java b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/websocket/message/NetconfMessageListenerTest.java new file mode 100644 index 000000000..bb040d1e3 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/test/java/org/onap/netconfsimulator/websocket/message/NetconfMessageListenerTest.java @@ -0,0 +1,73 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.netconfsimulator.websocket.message; + + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.verify; +import static org.mockito.MockitoAnnotations.initMocks; + +import java.io.IOException; +import javax.websocket.EncodeException; +import javax.websocket.RemoteEndpoint; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.onap.netconfsimulator.kafka.model.KafkaMessage; + + +class NetconfMessageListenerTest { + + private static final ConsumerRecord KAFKA_RECORD = new ConsumerRecord<>("sampleTopic", 0, 0, + "sampleKey", "sampleValue"); + + @Mock + private RemoteEndpoint.Basic remoteEndpoint; + + @InjectMocks + private NetconfMessageListener netconfMessageListener; + + + @BeforeEach + void setUp() { + initMocks(this); + } + + + @Test + void shouldProperlyParseAndSendConsumerRecord() throws IOException, EncodeException { + netconfMessageListener.onMessage(KAFKA_RECORD); + + verify(remoteEndpoint).sendObject(any(KafkaMessage.class)); + } + + + + @Test + void shouldNotPropagateEncodeException() throws IOException, EncodeException { + doThrow(new EncodeException("","")).when(remoteEndpoint).sendObject(any(KafkaMessage.class)); + + netconfMessageListener.onMessage(KAFKA_RECORD); + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/test/resources/application-it.properties b/test/mocks/pnfsimulator/netconfsimulator/src/test/resources/application-it.properties new file mode 100644 index 000000000..e69de29bb diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/test/resources/initialConfig.xml b/test/mocks/pnfsimulator/netconfsimulator/src/test/resources/initialConfig.xml new file mode 100644 index 000000000..f28a1a0a8 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/test/resources/initialConfig.xml @@ -0,0 +1,23 @@ + + + + 100 + diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/test/resources/invalidXmlFile.xml b/test/mocks/pnfsimulator/netconfsimulator/src/test/resources/invalidXmlFile.xml new file mode 100644 index 000000000..3debd8c26 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/test/resources/invalidXmlFile.xml @@ -0,0 +1,23 @@ + + + + 100 + diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/test/resources/newYangModel.yang b/test/mocks/pnfsimulator/netconfsimulator/src/test/resources/newYangModel.yang new file mode 100644 index 000000000..bbe66c3ae --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/test/resources/newYangModel.yang @@ -0,0 +1,8 @@ +module newyangmodel { + namespace "http://onap.org/newyangmodel"; + prefix config2; + container config2 { + config true; + leaf item1 {type uint32;} + } +} diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/test/resources/updatedConfig.xml b/test/mocks/pnfsimulator/netconfsimulator/src/test/resources/updatedConfig.xml new file mode 100644 index 000000000..628a710fd --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/test/resources/updatedConfig.xml @@ -0,0 +1,24 @@ + + + + 100 + 200 + diff --git a/test/mocks/pnfsimulator/netconfsimulator/src/test/resources/updatedConfigForCmHistory.xml b/test/mocks/pnfsimulator/netconfsimulator/src/test/resources/updatedConfigForCmHistory.xml new file mode 100644 index 000000000..5bc0e4285 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/src/test/resources/updatedConfigForCmHistory.xml @@ -0,0 +1,24 @@ + + + + 500 + 1000 + diff --git a/test/mocks/pnfsimulator/netconfsimulator/ssh/ssh_host_rsa_key b/test/mocks/pnfsimulator/netconfsimulator/ssh/ssh_host_rsa_key new file mode 100644 index 000000000..dbf8d7635 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/ssh/ssh_host_rsa_key @@ -0,0 +1,49 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFwAAAAdzc2gtcn +NhAAAAAwEAAQAAAgEA0Eve1v58bkLc4/6FvcBYWO8q6rOTJok7YyOHnc6QBJFuChSTbAaV +nn+E8nPgyqN0/hH740+qjtWpaJdKh0+hJMw0vUeX6SQ1OpRgyXFbDSbFrjsBjB7N2eusrR +M5FweDxVW/mfR7AHemrLulbNYHt/HmY+Hee09D/awICpuViLKLOsPp8ifmbHG1mXStLNSg +OJgBvsrMvbsKYgJq0HdWPyfkzFf4SVdjKxeegQbkSogWGqRG7zkfu8bsYooUpIFRFMiJvW +dr9tlegESAu1fmUx2Wz7EtN4Qq7xqHfAbT+Ruzr4rtCRRCsdEou49kpTSM75FaKlXmchRV +tBQKndFhcPQCO+m9OkQ4+45VSeLL236MTvAFGnqfLks97TO7VLGinhtMvJA1gZI93bwVBS +P1uaVuiUdzT8OgUq6xsLx2qg2aoau5Ivj65Hdj8tlIjeFHeGgUd1GZa434X3p8WCDFVrQK +GpReaDTFttVFw7F2+biFmn68TO0bb4GE84r8ouaYVSGzWG1kEy8UtriXnx6GPOzncp8HKT +YFn2etzs5EE9Ae64+1mIJTUEnWlpxwrjCqCIreibMz4/7AkSWrwc0YeAUERso+ESQkCU8R +zpcYSRz50UTCaerS8K5cPE9N2XB3WYbsziNTpR568onQIkL+ZlTIbNNYBgdVNDLlQeabKS +kAAAdILF3O/Sxdzv0AAAAHc3NoLXJzYQAAAgEA0Eve1v58bkLc4/6FvcBYWO8q6rOTJok7 +YyOHnc6QBJFuChSTbAaVnn+E8nPgyqN0/hH740+qjtWpaJdKh0+hJMw0vUeX6SQ1OpRgyX +FbDSbFrjsBjB7N2eusrRM5FweDxVW/mfR7AHemrLulbNYHt/HmY+Hee09D/awICpuViLKL +OsPp8ifmbHG1mXStLNSgOJgBvsrMvbsKYgJq0HdWPyfkzFf4SVdjKxeegQbkSogWGqRG7z +kfu8bsYooUpIFRFMiJvWdr9tlegESAu1fmUx2Wz7EtN4Qq7xqHfAbT+Ruzr4rtCRRCsdEo +u49kpTSM75FaKlXmchRVtBQKndFhcPQCO+m9OkQ4+45VSeLL236MTvAFGnqfLks97TO7VL +GinhtMvJA1gZI93bwVBSP1uaVuiUdzT8OgUq6xsLx2qg2aoau5Ivj65Hdj8tlIjeFHeGgU +d1GZa434X3p8WCDFVrQKGpReaDTFttVFw7F2+biFmn68TO0bb4GE84r8ouaYVSGzWG1kEy +8UtriXnx6GPOzncp8HKTYFn2etzs5EE9Ae64+1mIJTUEnWlpxwrjCqCIreibMz4/7AkSWr +wc0YeAUERso+ESQkCU8RzpcYSRz50UTCaerS8K5cPE9N2XB3WYbsziNTpR568onQIkL+Zl +TIbNNYBgdVNDLlQeabKSkAAAADAQABAAACAQDFUyq+14T/W34wytzd/opzbddlUksTlavZ +5j3CZH4Qpcjt6cIi8zXoWfuTR+1ramAZlOXf2IfGGmkLeU+UUf5hgsZvjZQ+vBtk7E2oaC +eOlO1ued2kZUYzrMz/hRdvVqIhXnNNoMqpjbArMPSs3zGes53Df6UpgdTySnevvOZzAlld +iV1mFyB2GV6lCmBH+QHzuyTkHvDIyJk0cf/Ij1T4LY3Ve3zt1chPeWeh6ep5JORzxq6gT6 +hdVjx3uUGG+i7aloPOF1yzFAcvUjX1xHagxIYrKTihwCaALsys1TcYZYLayKx3DmeEVpXU +4SnCS7878KHPO2M9LUBngRjxmvpHtnaIyp4LugY48y+KtywjR39hOsKW3QawVp6CtTceNE +QMlosaVIQuMJkeW14poYBclva0B/lCn3r9/3OrCI9qZPdD1RrCQqUyom56EU4kwRddSwHi +LDj4xKoyzH022lfaTt+PwbXtVJGAOVTS86ZovJaIJwyKCE1T0p66qqIM/mo1GVMTfTKwUt +A9v0AwTYFXmZ/9HJjhMNhCNclPilZHzuPI9VqiZ3tkKhS6kxZQA2cB1VdcFPIEeVOpZcJd +yPzGfFuKYOh9CLQMxfMC46MeT1XoQi5bMBygy8ZajV9VM2xUMKft1IqyN65nA7d+covoxL +PLjC6n3hUJJtSMTAohAQAAAQBf4lenniOgFycb1REtnUhyaCsopBmkuxlCOknkmFiMNW+B +v/aeFUp03WluKGOVureJoooU3Z32Om2+YTxTOnCRL5Sn4gL7cAp7JfDSZpZPqynUAKFvKq +QVbYyiEmFkUDFWes9Q0r0LAx2rvPrDIGhqx2ZgrzINlhrhxaQU2+fGbNRdI86PcWSYtc5u +Oucd6nJM7eI3QL7/pVNlK3GMJ68eviKmhxP5HHnanNes2ORa15S5rRSOAZ5653pA1J1KxB +J5vwwMvIXbEnBn8NilqWK50DHJMFXEoLaKlb0OoYMKbiLt4CjcCCIUUT1kAu/SFUpFdYI1 +DNXfrieu3ZTEwnU9AAABAQDrf9b8VnARNimzLqI15hp0Z5B8Sxf8Xw85KRRxg7cu6TJLoF +K6VRK1jOzrKCrIzvBwuS2Er06ogEE/3N8eXC2ipzNOtDh7CQqoAq8IKNUt+2cvThNzfOFe +BZ6lP9pQ60RGEPoeQyhlxHOUbV80K/ksiFqnAixOmOV7Uc7KZ+8clFvhOCm76vo80GaYYk +NQtvMa1qxIsyUrOdhmIxF9dYN/sQMUr909o80kN69L7d+D1hG6WNskEJphrHSkPWTell5g +4ekFna1+MjNQoCWhp6KPDKK9Y8AMrqWU/bFYw9CYwXo67p486qt487ZN+0cNItmSLMR3Ke +MWmCmq37+v3viJAAABAQDibc4fU/xePaCjQa4VlAwk9ISd8Ufz/LcJWDiseKSzQnIdCaCG +gO/SWTUuAzGEdrNnfJRcEUtrJ0UJAo2ntYZ3AlJLQvFF9KII3yuUn/RHMrkwslAIoqLhLO +QX38nJeWR+hEWSFbpWP5N5biLRi2Qnwtv55hYgNqTLHRURzvin5/YeuwigBax1SwtN+V2D +JSDhMiaFV85ZQggSoIjLIsunLK5XIDzTC82gJ9aaazvKBXwkf4Yfv5t1BgPATzqwjmXztQ +T8WbTeqEO95cIu0zhfKIGo7Wvx7S9NPrNjyNO+JK9/qqdYGhErPiZPKOcHHywF77Yyv2cm +gOrMYVCubUOhAAAAD21hcmNpbkBtYW5kaW5nbwECAw== +-----END OPENSSH PRIVATE KEY----- diff --git a/test/mocks/pnfsimulator/netconfsimulator/ssh/ssh_host_rsa_key.pub b/test/mocks/pnfsimulator/netconfsimulator/ssh/ssh_host_rsa_key.pub new file mode 100644 index 000000000..8f739114b --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/ssh/ssh_host_rsa_key.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDQS97W/nxuQtzj/oW9wFhY7yrqs5MmiTtjI4edzpAEkW4KFJNsBpWef4Tyc+DKo3T+EfvjT6qO1alol0qHT6EkzDS9R5fpJDU6lGDJcVsNJsWuOwGMHs3Z66ytEzkXB4PFVb+Z9HsAd6asu6Vs1ge38eZj4d57T0P9rAgKm5WIsos6w+nyJ+ZscbWZdK0s1KA4mAG+ysy9uwpiAmrQd1Y/J+TMV/hJV2MrF56BBuRKiBYapEbvOR+7xuxiihSkgVEUyIm9Z2v22V6ARIC7V+ZTHZbPsS03hCrvGod8BtP5G7Oviu0JFEKx0Si7j2SlNIzvkVoqVeZyFFW0FAqd0WFw9AI76b06RDj7jlVJ4svbfoxO8AUaep8uSz3tM7tUsaKeG0y8kDWBkj3dvBUFI/W5pW6JR3NPw6BSrrGwvHaqDZqhq7ki+Prkd2Py2UiN4Ud4aBR3UZlrjfhfenxYIMVWtAoalF5oNMW21UXDsXb5uIWafrxM7RtvgYTzivyi5phVIbNYbWQTLxS2uJefHoY87OdynwcpNgWfZ63OzkQT0B7rj7WYglNQSdaWnHCuMKoIit6JszPj/sCRJavBzRh4BQRGyj4RJCQJTxHOlxhJHPnRRMJp6tLwrlw8T03ZcHdZhuzOI1OlHnryidAiQv5mVMhs01gGB1U0MuVB5pspKQ== marcin@mandingo diff --git a/test/mocks/pnfsimulator/netconfsimulator/tls/ca.crt b/test/mocks/pnfsimulator/netconfsimulator/tls/ca.crt new file mode 100644 index 000000000..62593ab7c --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/tls/ca.crt @@ -0,0 +1,24 @@ +-----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/test/mocks/pnfsimulator/netconfsimulator/tls/server_cert.crt b/test/mocks/pnfsimulator/netconfsimulator/tls/server_cert.crt new file mode 100644 index 000000000..c0e03a3f0 --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/tls/server_cert.crt @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIECTCCAvGgAwIBAgIBCDANBgkqhkiG9w0BAQsFADCBjDELMAkGA1UEBhMCQ1ox +FjAUBgNVBAgMDVNvdXRoIE1vcmF2aWExDTALBgNVBAcMBEJybm8xDzANBgNVBAoM +BkNFU05FVDEMMAoGA1UECwwDVE1DMRMwEQYDVQQDDApleGFtcGxlIENBMSIwIAYJ +KoZIhvcNAQkBFhNleGFtcGxlY2FAbG9jYWxob3N0MB4XDTE1MDczMDA3MjU1MFoX +DTM1MDcyNTA3MjU1MFowgYUxCzAJBgNVBAYTAkNaMRYwFAYDVQQIDA1Tb3V0aCBN +b3JhdmlhMQ8wDQYDVQQKDAZDRVNORVQxDDAKBgNVBAsMA1RNQzEXMBUGA1UEAwwO +ZXhhbXBsZSBzZXJ2ZXIxJjAkBgkqhkiG9w0BCQEWF2V4YW1wbGVzZXJ2ZXJAbG9j +YWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsdI1TBjzX1Pg +QXFuPCw5/kQwU7qkrhirMcFAXhI8EoXepPa9fKAVuMjHW32P6nNzDpnhFe0YGdNl +oIEN3hJJ87cVOqj4o7zZMbq3zVG2L8As7MTA8tYXm2fSC/0rIxxRRemcGUXM0q+4 +LEACjZj2pOKonaivF5VbhgNjPCO1Jj/TamUc0aViE577C9L9EiObGM+bGbabWk/K +WKLsvxUc+sKZXaJ7psTVgpggJAkUszlmwOQgFiMSR53E9/CAkQYhzGVCmH44Vs6H +zs3RZjOTbce4wr4ongiA5LbPeSNSCFjy9loKpaE1rtOjkNBVdiNPCQTmLuODXUTK +gkeL+9v/OwIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVu +U1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU83qEtQDFzDvLoaII +vqiU6k7j1uswHwYDVR0jBBgwFoAUc1YQIqjZsHVwlea0AB4N+ilNI2gwDQYJKoZI +hvcNAQELBQADggEBAJ+QOLi4gPWGofMkLTqSsbv5xRvTw0xa/sJnEeiejtygAu3o +McAsyevSH9EYVPCANxzISPzd9SFaO56HxWgcxLn9vi8ZNvo2wIp9zucNu285ced1 +K/2nDZfBmvBxXnj/n7spwqOyuoIc8sR7P7YyI806Qsfhk3ybNZE5UHJFZKDRQKvR +J1t4nk9saeo87kIuNEDfYNdwYZzRfXoGJ5qIJQK+uJJv9noaIhfFowDW/G14Ji5p +Vh/YtvnOPh7aBjOj8jmzk8MqzK+TZgT7GWu48Nd/NaV8g/DNg9hlN047LaNsJly3 +NX3+VBlpMnA4rKwl1OnmYSirIVh9RJqNwqe6k/k= +-----END CERTIFICATE----- diff --git a/test/mocks/pnfsimulator/netconfsimulator/tls/server_key.pem b/test/mocks/pnfsimulator/netconfsimulator/tls/server_key.pem new file mode 100644 index 000000000..d61c77bdf --- /dev/null +++ b/test/mocks/pnfsimulator/netconfsimulator/tls/server_key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAsdI1TBjzX1PgQXFuPCw5/kQwU7qkrhirMcFAXhI8EoXepPa9 +fKAVuMjHW32P6nNzDpnhFe0YGdNloIEN3hJJ87cVOqj4o7zZMbq3zVG2L8As7MTA +8tYXm2fSC/0rIxxRRemcGUXM0q+4LEACjZj2pOKonaivF5VbhgNjPCO1Jj/TamUc +0aViE577C9L9EiObGM+bGbabWk/KWKLsvxUc+sKZXaJ7psTVgpggJAkUszlmwOQg +FiMSR53E9/CAkQYhzGVCmH44Vs6Hzs3RZjOTbce4wr4ongiA5LbPeSNSCFjy9loK +paE1rtOjkNBVdiNPCQTmLuODXUTKgkeL+9v/OwIDAQABAoIBAG/4MG1JbL4C/7vV +pBcpth7Aaznd1eJ2UB4VVOWnT8JOH2L6p1h5KRRhAP9AMkXsCnAQPyZiVAG3FlAZ +01SZaY2YJDr6uQ3JVW4155TWtgSdWux//Ass+lJ17lJ0SRxjsV13ez6CsDWeRjc+ +2xy0S+KJgqk71XzhJG9fZLYyuddp3U/i3xFPUAcQM9xXKxcaD7g6LJf+a9pt6rim +Eqq/pjJxDgTsRLARsazYuxrlOB445mvnLiYhOf2/MvI80jIUKaj8BeAhg49UIg/k +mIh0xdevkcxBFer/BjBjscWaFjx14D6nkFMw7vtCum5KfalLN2edZKAzByOudGD4 +5KnRp3ECgYEA6vnSoNGg9Do80JOpXRGYWhcR1lIDO5yRW5rVagncCcW5Pn/GMtNd +x2q6k1ks8mXKR9CxZrxZGqeYObZ9a/5SLih7ZkpiVWXG8ZiBIPhP6lnwm5OeIqLa +hr0BYWcRfrGg1phj5uySZgsVBE+D8jH42O9ccdvrWv1OiryAHfKIcwMCgYEAwbs+ +HfQtvHOQXSYNhtOeA7IetkGy3cKVg2oILNcROvI96hS0MZKt1Rko0UAapx96eCIr +el7vfdT0eUzNqt2wTKp1zmiG+SnX3fMDJNzMwu/jb/b4wQ20IHWNDnqcqTUVRUnL +iksLFoHbTxsN5NpEQExcSt/zzP4qi1W2Bmo18WkCgYEAnhrk16LVux9ohiulHONW +8N9u+BeM51JtGAcxrDzgGo85Gs2czdwc0K6GxdiN/rfxCKtqgqcfCWlVaxfYgo7I +OxiwF17blXx7BVrJICcUlqpX1Ebac5HCmkCYqjJQuj/I6jv1lI7/3rt8M79RF+j5 ++PXt7Qq97SZd78nwJrZni4MCgYAiPjZ8lOyAouyhilhZvI3xmUpUbMhw6jQDRnqr +clhZUvgeqAoxuPuA7zGHywzq/WVoVqHYv28Vjs6noiu4R/chlf+8vD0fTYYadRnZ +Ki4HRt+sqrrNZN6x3hVQudt3DSr1VFXl293Z3JonIWETUoE93EFz+qHdWg+rETtb +ZuqiAQKBgD+HI/syLECyO8UynuEaDD7qPl87PJ/CmZLMxa2/ZZUjhaXAW7CJMaS6 +9PIzsLk33y3O4Qer0wx/tEdfnxMTBJrgGt/lFFdAKhSJroZ45l5apiavg1oZYp89 +jSd0lVxWSmrBjBZLnqOl336gzaBVkBD5ND+XUPdR1UuVQExJlem4 +-----END RSA PRIVATE KEY----- diff --git a/test/mocks/pnfsimulator/netopeer_tls_cfg/entrypoint.sh b/test/mocks/pnfsimulator/netopeer_tls_cfg/entrypoint.sh deleted file mode 100755 index 45b30a1a1..000000000 --- a/test/mocks/pnfsimulator/netopeer_tls_cfg/entrypoint.sh +++ /dev/null @@ -1,2 +0,0 @@ -nohup /netopeer_tls_cfg/update_tls.sh & -exec /usr/bin/supervisord -c "/etc/supervisord.conf" diff --git a/test/mocks/pnfsimulator/netopeer_tls_cfg/mynetconf.data b/test/mocks/pnfsimulator/netopeer_tls_cfg/mynetconf.data deleted file mode 100644 index 63872eef9..000000000 --- a/test/mocks/pnfsimulator/netopeer_tls_cfg/mynetconf.data +++ /dev/null @@ -1,10 +0,0 @@ -{ - "mynetconf:netconflist": { - "netconf": [ - { - "netconf-id": 3, - "netconf-param": 3 - } - ] - } -} diff --git a/test/mocks/pnfsimulator/netopeer_tls_cfg/mynetconf.yang b/test/mocks/pnfsimulator/netopeer_tls_cfg/mynetconf.yang deleted file mode 100644 index a0c094b40..000000000 --- a/test/mocks/pnfsimulator/netopeer_tls_cfg/mynetconf.yang +++ /dev/null @@ -1,26 +0,0 @@ -module mynetconf { - yang-version 1.1; - namespace "urn:mynetconf:test"; - - prefix nft; - - organization "mynetconf"; - contact "my netconf address"; - description "yang model for mynetconf"; - revision "2019-03-01"{ - description "initial version"; - } - - container netconflist{ - list netconf{ - key netconf-id; - leaf netconf-id{ - type uint16; - } - leaf netconf-param { - type uint32; - } - } - - } -} diff --git a/test/mocks/pnfsimulator/netopeer_tls_cfg/test_server_key.pem b/test/mocks/pnfsimulator/netopeer_tls_cfg/test_server_key.pem deleted file mode 100644 index d61c77bdf..000000000 --- a/test/mocks/pnfsimulator/netopeer_tls_cfg/test_server_key.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAsdI1TBjzX1PgQXFuPCw5/kQwU7qkrhirMcFAXhI8EoXepPa9 -fKAVuMjHW32P6nNzDpnhFe0YGdNloIEN3hJJ87cVOqj4o7zZMbq3zVG2L8As7MTA -8tYXm2fSC/0rIxxRRemcGUXM0q+4LEACjZj2pOKonaivF5VbhgNjPCO1Jj/TamUc -0aViE577C9L9EiObGM+bGbabWk/KWKLsvxUc+sKZXaJ7psTVgpggJAkUszlmwOQg -FiMSR53E9/CAkQYhzGVCmH44Vs6Hzs3RZjOTbce4wr4ongiA5LbPeSNSCFjy9loK -paE1rtOjkNBVdiNPCQTmLuODXUTKgkeL+9v/OwIDAQABAoIBAG/4MG1JbL4C/7vV -pBcpth7Aaznd1eJ2UB4VVOWnT8JOH2L6p1h5KRRhAP9AMkXsCnAQPyZiVAG3FlAZ -01SZaY2YJDr6uQ3JVW4155TWtgSdWux//Ass+lJ17lJ0SRxjsV13ez6CsDWeRjc+ -2xy0S+KJgqk71XzhJG9fZLYyuddp3U/i3xFPUAcQM9xXKxcaD7g6LJf+a9pt6rim -Eqq/pjJxDgTsRLARsazYuxrlOB445mvnLiYhOf2/MvI80jIUKaj8BeAhg49UIg/k -mIh0xdevkcxBFer/BjBjscWaFjx14D6nkFMw7vtCum5KfalLN2edZKAzByOudGD4 -5KnRp3ECgYEA6vnSoNGg9Do80JOpXRGYWhcR1lIDO5yRW5rVagncCcW5Pn/GMtNd -x2q6k1ks8mXKR9CxZrxZGqeYObZ9a/5SLih7ZkpiVWXG8ZiBIPhP6lnwm5OeIqLa -hr0BYWcRfrGg1phj5uySZgsVBE+D8jH42O9ccdvrWv1OiryAHfKIcwMCgYEAwbs+ -HfQtvHOQXSYNhtOeA7IetkGy3cKVg2oILNcROvI96hS0MZKt1Rko0UAapx96eCIr -el7vfdT0eUzNqt2wTKp1zmiG+SnX3fMDJNzMwu/jb/b4wQ20IHWNDnqcqTUVRUnL -iksLFoHbTxsN5NpEQExcSt/zzP4qi1W2Bmo18WkCgYEAnhrk16LVux9ohiulHONW -8N9u+BeM51JtGAcxrDzgGo85Gs2czdwc0K6GxdiN/rfxCKtqgqcfCWlVaxfYgo7I -OxiwF17blXx7BVrJICcUlqpX1Ebac5HCmkCYqjJQuj/I6jv1lI7/3rt8M79RF+j5 -+PXt7Qq97SZd78nwJrZni4MCgYAiPjZ8lOyAouyhilhZvI3xmUpUbMhw6jQDRnqr -clhZUvgeqAoxuPuA7zGHywzq/WVoVqHYv28Vjs6noiu4R/chlf+8vD0fTYYadRnZ -Ki4HRt+sqrrNZN6x3hVQudt3DSr1VFXl293Z3JonIWETUoE93EFz+qHdWg+rETtb -ZuqiAQKBgD+HI/syLECyO8UynuEaDD7qPl87PJ/CmZLMxa2/ZZUjhaXAW7CJMaS6 -9PIzsLk33y3O4Qer0wx/tEdfnxMTBJrgGt/lFFdAKhSJroZ45l5apiavg1oZYp89 -jSd0lVxWSmrBjBZLnqOl336gzaBVkBD5ND+XUPdR1UuVQExJlem4 ------END RSA PRIVATE KEY----- diff --git a/test/mocks/pnfsimulator/netopeer_tls_cfg/test_server_key.pem.pub b/test/mocks/pnfsimulator/netopeer_tls_cfg/test_server_key.pem.pub deleted file mode 100644 index 9ccec4a0c..000000000 --- a/test/mocks/pnfsimulator/netopeer_tls_cfg/test_server_key.pem.pub +++ /dev/null @@ -1,9 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsdI1TBjzX1PgQXFuPCw5 -/kQwU7qkrhirMcFAXhI8EoXepPa9fKAVuMjHW32P6nNzDpnhFe0YGdNloIEN3hJJ -87cVOqj4o7zZMbq3zVG2L8As7MTA8tYXm2fSC/0rIxxRRemcGUXM0q+4LEACjZj2 -pOKonaivF5VbhgNjPCO1Jj/TamUc0aViE577C9L9EiObGM+bGbabWk/KWKLsvxUc -+sKZXaJ7psTVgpggJAkUszlmwOQgFiMSR53E9/CAkQYhzGVCmH44Vs6Hzs3RZjOT -bce4wr4ongiA5LbPeSNSCFjy9loKpaE1rtOjkNBVdiNPCQTmLuODXUTKgkeL+9v/ -OwIDAQAB ------END PUBLIC KEY----- diff --git a/test/mocks/pnfsimulator/netopeer_tls_cfg/update_tls.sh b/test/mocks/pnfsimulator/netopeer_tls_cfg/update_tls.sh deleted file mode 100755 index e0e1ac625..000000000 --- a/test/mocks/pnfsimulator/netopeer_tls_cfg/update_tls.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash -sleep 20 -NETOPEER_CONFIG_PATH='/opt/dev/Netopeer2/server/configuration' -MOUNT_PATH='/netopeer_tls_cfg' -KEY_PATH='/usr/local/etc/keystored/keys' -SUBSCRIBE_APP_PATH='/opt/dev/sysrepo/build/examples/application_changes_example' - -# This function uploads test_data and model into netopeer2 server -upload_yang_data_model() -{ - sysrepoctl -i -g $MOUNT_PATH/mynetconf.yang - sleep 5 - echo ' subscribing to mynetconf model.' - $SUBSCRIBE_APP_PATH mynetconf > /dev/null & - sleep 5 - echo ' creating data for mynetconf model.' - sysrepocfg --datastore=running --format=json mynetconf --import=$MOUNT_PATH/mynetconf.data -} - -# This function configures server/trusted certificates into Netopeer -configure_tls() -{ - sed -i "s/>testnetconf:5000/simulator/start*. +Supported method: *POST* +Headers: + - Content-Type - application/json +Parameters: + + simulatorParams: + repeatCount - determines how many events will be sent + repeatInterval - time (in seconds) between events + vesServerUrl - valid path to VES Collector + templateName - name of template file (check *Templates* section) + patch - part of event which will be merged into template + + +Sample Request: + + { + "simulatorParams": { + "repeatCount": 5, + "repeatInterval": 2, + "vesServerUrl": "http://VES-HOST:8080/eventListener/v7" + }, + "templateName": "validExampleMeasurementEvent.json", + "patch": { + "event": { + "commonEventHeader": { + "eventId": "PATCHED_eventId", + "sourceName": "PATCHED_sourceName", + "version": 3.0 + } + } + } + } + +*One-time event sending* +Enables direct, immediate event sending without need to have template deployed on backend. +Keywords are supported,thus once passed, will also be substituted with proper strings. +Passed event body must be valid and complete event according to VES Collector interface. +To trigger sending use following endpoint *http://:5000/simulator/event*. + +Supported method: *POST* +Headers: + - Content-Type - application/json +Parameters: + + vesServerUrl - valid URL to VES Collector event listener + event - body of event to be sent directly to VES Collector (it can contain keyword expressions) + + +Sample Request: + + { + "vesServerUrl": "http://VES-HOST:8080/eventListener/v7", + "event": { + "commonEventHeader": { + "eventId": "#RandomString(20)", + "sourceName": "PATCHED_sourceName", + "version": 3.0 + } + } + } + +### Changing simulator configuration +Utility of default configuration has been introduced so as to facilitate sending requests. so far only vesServerUrl states default simulator configuration. +On simulator startup, vesServerUrl is initialized with default value, but must be replaced with correct VES server url by user. +Once vesServerUrl is properly set on simulator, this parameter does not need to be incorporated into every trigger event request. +If user does not provide vesServerUrl in trigger request, default value will be used. +If use does provide vesServerUrl in trigger request, then passed value will be used instead of default one (default value will not be overwritten by provided one). + +It is possible to get and update configuration (current target vesServerUrl) using offered REST API - */simulator/config* endpoint is exposed for that. +To get current configuration *GET* method must be used. +To update vesServerUrl *PUT* method is used, example request: + + { + "vesServerUrl": "http://10.154.164.117:8080/eventListener/v7" + } + +Note: passed vesServerUrl must be wellformed URL. + + +### Running simulator +The recommended way is to checkout PNF Simulator project from ONAP Git repository and use *simulator*.sh script. +If you copy *simulator.sh* script to another location, keep in mind to copy also *docker-compose.yml* and directories: *config and templates*. +In order to run simulator, invoke ./simulator.sh -e build to build required images and then invoke ./simulator.sh -e start +Script downloads if necessary needed Docker images and runs instances of these images. +After simulator start it is advisable to setup default value for target vesServerUrl. + +Example request: + + PUT to http://:/simulator/config + + { + "vesServerUrl": "PUT HERE VALID URL TO YOUR VES EVENT LISTENER" + } + +### Templates +Template is a draft event. Merging event with patch will result in valid VES event. Template itself should be a correct VES event as well as valid json object. +In order to apply custom template, just copy it to ./templates directory. +*notification.json* and *registration.json* are available by default in *./templates* directory. + +#### Template management +The simulator provides means for managing templates. Supported actions: adding, editing (overriding) and deleting are available via HTTP endpoint */template* + +```GET /template/list``` +Lists all templates known to the simulator. + +```GET /template/get-content/{name}``` +Gets template content based on *name* path variable. + +```POST /template/upload?override=true``` +Saves template content under *name* path variable. The non-mandatory parameter *override* allows overwriting an existing template. + +Sample payload: +``` +{ + "name": "someTemplate", + "template": { + "commonEventHeader": { + "domain": "notification", + "eventName": "vFirewallBroadcastPackets" + }, + "notificationFields": { + "arrayOfNamedHashMap": [{ + "name": "A20161221.1031-1041.bin.gz", + "hashMap": { + "fileformatType": "org.3GPP.32.435#measCollec" + } + }] + } + } +} +``` + +### Searching for key-value conditions in stored templates +Simulator allows to search through stored templates and retrieve names of those that satisfy given criteria passed in form of key-value pairs (See examples below). +Following data types are supported in search as values: +-integer +-string +-double +-boolean +Searching for null values as well as incorporating regex expression with intention to find a match is not supported. +Search expression must be valid JSON, thus no duplicate keys are allowed - user could specify the same parameter multiple times, but only last occurrence will be applied to query. +Example search expression: + +{"domain": "notification", "sequence": 1, "startEpochMicrosec": 1531616794, "sampleDouble": 2.5} + +will find all templates that contain all of passed key-value entries. There is an AND condition beetwen given criteria - all of them must be satisfied to qualify template as matching item. + Keys of search expressions are searched in case insensitive way as well as string values. +Where it comes to values of numerical and boolean type exact match is expected. + +API usage: + +```POST /template/search``` +Produces query that returns templates that contain searched criteria + +Sample payload: +``` +{ + "searchExpr": { + "domain": "notification", + "sequence": 1, + "startEpochMicrosec": 1531616794, + "sampleDouble": 2.5 + } +} +``` +Sample response: +``` +[notification.json] +``` + + +Note: Manually deployed templates, or actually existing ones, but modified inside the templates catalog '/app/templates', will be automatically synchronized with schemas stored inside the database. That means that a user can dynamically change the template content using vi editor at simulator container, as well as use any editor at any machine and then push the changes to the template folder. All the changes will be processed 'on the fly' and accessible via the rest API. + +### Periodic events +Simulator has ability to send event periodically. Rest API support parameters: +* repeatCount - count of times that event will be sent to VES +* repeatInterval - interval (in second) between two events. +(Checkout example to see how to use them) + +### Patching +User is able to provide patch in request, which will be merged into template. + +Warning: Patch should be a valid json object (no json primitives nor json arrays are allowed as a full body of patch). + +This mechanism allows to override part of template. +If in "patch" section there are additional parameters (absent in template), those parameters with values will be added to event. +Patching mechanism supports also keywords that enables automatic value generation of appropriate type + +### Keyword support +Simulator supports corresponding keywords: +- \#RandomInteger(start,end) - substitutes keyword with random positive integer within given range (range borders inclusive) +- \#RandomPrimitiveInteger(start,end) - the same as #RandomInteger(start,end), but returns long as result +- \#RandomInteger - substitutes keyword with random positive integer +- \#RandomString(length) - substitutes keyword with random ASCII string with specified length +- \#RandomString - substitutes keyword with random ASCII string with length of 20 characters +- \#Timestamp - substitutes keyword with current timestamp in epoch (calculated just before sending event) +- \#TimestampPrimitive - the same as \#Timestamp, but returns long as result +- \#Increment - substitutes keyword with positive integer starting from 1 - for each consecutive event, value of increment property is incremented by 1 + +Additional hints and restrictions: +All keywords without 'Primitive' in name return string as result. To specify keyword with 2 arguments e.g. #RandomInteger(start,end) no whitespaces between arguments are allowed. +Maximal value of arguments for RandomInteger is limited to the java integer range. Minimal is always 0. (Negative values are prohibited and wont be treated as a correct parts of keyword). +RandomInteger with parameters will automatically find minimal and maximal value form the given attributes so no particular order of those is expected. + +How does it work? +When user do not want to fill in parameter values that are not relevant from user perspective but are mandatory by end system, then keyword feature should be used. +In template, keyword strings are substituted in runtime with appropriate values autogenerated by simulator. +Example can be shown below: + +Example template with keywords: + + { + "event": { + "commonEventHeader": { + "eventId": "123#RandomInteger(8,8)", + "eventType": "pnfRegistration", + "startEpochMicrosec": "#Timestamp", + "vesEventListenerVersion": "7.0.1", + "lastEpochMicrosec": 1539239592379 + }, + "pnfRegistrationFields": { + "pnfRegistrationFieldsVersion":"2.0", + "serialNumber": "#RandomString(7)", + "vendorName": "Nokia", + "oamV4IpAddress": "val3", + "oamV6IpAddress": "val4" + } + } + } + +Corresponding result of keyword substitution (event that will be sent): + + { + "event": { + "commonEventHeader": { + "eventId": "1238", + "eventType": "pnfRegistration", + "startEpochMicrosec": "154046405117", + "vesEventListenerVersion": "7.0.1", + "lastEpochMicrosec": 1539239592379 + }, + "pnfRegistrationFields": { + "pnfRegistrationFieldsVersion":"2.0", + "serialNumber": "6061ZW3", + "vendorName": "Nokia", + "oamV4IpAddress": "val3", + "oamV6IpAddress": "val4" + } + } + } + + +### Logging +Every start of simulator will generate new logs that can be found in docker pnf-simualtor container under path: +/var/log/ONAP/pnfsimulator/pnfsimulator_output.log + +### Swagger +Detailed view of simulator REST API is available via Swagger UI +Swagger UI is available on *http://:5000/swagger-ui.html* + +### History +User is able to view events history. +In order to browse history, go to *http://:8081/db/pnf_simulator/eventData* + +### TLS Support +Simulator is able to communicate with VES using HTTPS protocol. +CA certificates are incorporated into simulator docker image, thus no additional actions are required from user. + +Certificates can be found in docker container under path: */usr/local/share/ca-certificates/* + +Simulator works with VES that uses both self-signed certificate (already present in keystore) and VES integrated to AAF. + + +## Developers Guide + +### Integration tests +Integration tests are located in folder 'integration'. Tests are using docker-compose from root folder. +This docker-compose has pnfsimulator image set on nexus3.onap.org:10003/onap/pnf-simulator:5.0.0-SNAPSHOT. +To test your local changes before running integration tests please build project using: + + 'mvn clean package docker:build' + +then go to 'integration' folder and run: + + 'mvn test' diff --git a/test/mocks/pnfsimulator/pnfsimulator/config/config.json b/test/mocks/pnfsimulator/pnfsimulator/config/config.json new file mode 100644 index 000000000..819f7d751 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/config/config.json @@ -0,0 +1,9 @@ +{ + "simulatorParams": { + "vesServerUrl": "http://VES-HOST:VES-PORT/eventListener/v7", + "repeatInterval": 10, + "repeatCount": 2 + }, + "templateName": "notification.json", + "patch":{} +} \ No newline at end of file diff --git a/test/mocks/pnfsimulator/pnfsimulator/db/pnf_simulator.js b/test/mocks/pnfsimulator/pnfsimulator/db/pnf_simulator.js new file mode 100644 index 000000000..f5a03c3d0 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/db/pnf_simulator.js @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +const res = [ + db.createUser({ user: 'pnf_simulator_user', pwd: 'zXcVbN123!', roles: ['readWrite', 'dbAdmin'] }), + db.simulatorConfig.insert({"vesServerUrl": "http://xdcae-ves-collector.onap:8080/eventListener/v7"}), + db.createCollection("template"), + db.createView("flatTemplatesView", "template", [{"$project":{"keyValues":{"$objectToArray": "$$ROOT.flatContent"}}}]) +]; + +printjson(res); diff --git a/test/mocks/pnfsimulator/pnfsimulator/deployment/PnP_PNF_sim_heat_template.yml b/test/mocks/pnfsimulator/pnfsimulator/deployment/PnP_PNF_sim_heat_template.yml new file mode 100644 index 000000000..4bf6758d9 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/deployment/PnP_PNF_sim_heat_template.yml @@ -0,0 +1,118 @@ +description: Heat template that deploys PnP PNF simulator +heat_template_version: '2013-05-23' +parameters: + flavor_name: {description: Type of instance (flavor) to be used, label: Flavor, + type: string} + image_name: {description: Image to be used for compute instance, label: Image name + or ID, type: string} + key_name: {description: Public/Private key pair name, label: Key pair name, type: string} + public_net_id: {description: Public network that enables remote connection to VNF, + label: Public network name or ID, type: string} + private_net_id: {type: string, description: Private network id, label: Private network name or ID} + private_subnet_id: {type: string, description: Private subnet id, label: Private subnetwork name or ID} + proxy: {type: string, description: Proxy, label: Proxy, default: ""} +resources: + PNF_PnP_simualtor: + type: OS::Nova::Server + properties: + key_name: { get_param: key_name } + image: { get_param: image_name } + flavor: { get_param: flavor_name } + networks: + - port: { get_resource: PNF_PnP_simualtor_port0 } + user_data_format: RAW + user_data: + str_replace: + template: | + #!/bin/bash + + set_versions () { + DOCKER_COMPOSE_VERSION=1.22.0 + } + + + enable_root_ssh () { + sed -i 's/PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config + sed -i 's/PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config + service sshd restart + echo -e "arthur\narthur" | passwd root + } + + update_os () { + dnf -y install fedora-upgrade + } + + docker_remove () { + dnf -y remove docker \ + docker-client \ + docker-client-latest \ + docker-common \ + docker-latest \ + docker-latest-logrotate \ + docker-logrotate \ + docker-selinux \ + docker-engine-selinux \ + docker-engine + } + + docker_install_and_configure () { + dnf -y install dnf-plugins-core + dnf config-manager \ + --add-repo \ + https://download.docker.com/linux/fedora/docker-ce.repo + dnf -y install docker-ce + systemctl start docker + mkdir -p /etc/systemd/system/docker.service.d/ + cat > /etc/systemd/system/docker.service.d/override.conf<< EOF + [Service] + Environment="HTTP_PROXY=$proxy" + Environment="HTTPS_PROXY=$proxy" + EOF + systemctl daemon-reload + systemctl restart docker + } + docker_compose_install () { + curl -L https://github.com/docker/compose/releases/download/$DOCKER_COMPOSE_VERSION/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose + chmod +x /usr/local/bin/docker-compose + } + pnf_sim_file_checkout () { + cd /root; git clone https://gerrit.onap.org/r/integration + printf "{\n "simulatorParams": {\n "vesServerUrl": "http://VES-HOST:VES-PORT/eventListener/v7",\n "testDuration": "10",\n "messageInterval": "1"\n },\n "commonEventHeaderParams": {\n "eventName": "pnfRegistration_Nokia_5gDu",\n "nfNamingCode": "gNB",\n "nfcNamingCode": "oam",\n "sourceName": "NOK6061ZW3",\n "sourceId": "val13",\n "reportingEntityName": "NOK6061ZW3"\n },\n "pnfRegistrationParams": {\n "serialNumber": "6061ZW3",\n "vendorName": "Nokia",\n "oamV4IpAddress": "val3",\n "oamV6IpAddress": "val4",\n "unitFamily": "BBU",\n "modelNumber": "val6",\n "softwareVersion": "val7",\n "unitType": "val8"\n }\n}" > integration/test/mocks/pnfsimulator/config/config.json + } + + start_simulator () { + docker login -u docker -p docker nexus3.onap.org:10003 + cd ~/integration/test/mocks/pnfsimulator + ./simulator.sh start + } + + set_versions + enable_root_ssh + update_os + docker_remove + docker_install_and_configure + docker_compose_install + pnf_sim_file_checkout + start_simulator + params: + $proxy: { get_param: proxy } + PNF_PnP_simualtor_port0: + type: OS::Neutron::Port + properties: + network_id: { get_param: private_net_id } + security_groups: + - default + fixed_ips: + - subnet_id: { get_param: private_subnet_id } + PNF_PnP_simualtor_public: + type: OS::Neutron::FloatingIP + properties: + floating_network_id: { get_param: public_net_id } + port_id: { get_resource: PNF_PnP_simualtor_port0 } +outputs: + PNF_PnP_simualtor_private_ip: + description: IP address of PNF_PnP_simualtor in private network + value: { get_attr: [ PNF_PnP_simualtor, first_address ] } + PNF_PnP_simualtor_public_ip: + description: Floating IP address of PNF_PnP_simualtor in public network + value: { get_attr: [ PNF_PnP_simualtor_public, floating_ip_address ] } \ No newline at end of file diff --git a/test/mocks/pnfsimulator/pnfsimulator/docker-compose.yml b/test/mocks/pnfsimulator/pnfsimulator/docker-compose.yml new file mode 100644 index 000000000..c6a0531c9 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/docker-compose.yml @@ -0,0 +1,36 @@ +version: '3' + +services: + + mongo: + image: mongo + restart: always + environment: + MONGO_INITDB_ROOT_USERNAME: root + MONGO_INITDB_ROOT_PASSWORD: zXcVbN123! + MONGO_INITDB_DATABASE: pnf_simulator + volumes: + - ./db:/docker-entrypoint-initdb.d + ports: + - "27017:27017" + + mongo-express: + image: mongo-express + restart: always + ports: + - 8081:8081 + environment: + ME_CONFIG_MONGODB_ADMINUSERNAME: root + ME_CONFIG_MONGODB_ADMINPASSWORD: zXcVbN123! + + pnf-simulator: + image: nexus3.onap.org:10003/onap/pnfsimulator:5.0.0-SNAPSHOT + ports: + - "5000:5000" + volumes: + - ./logs:/var/log + - ./templates:/app/templates + restart: on-failure + depends_on: + - mongo + - mongo-express diff --git a/test/mocks/pnfsimulator/pnfsimulator/docker/Dockerfile b/test/mocks/pnfsimulator/pnfsimulator/docker/Dockerfile new file mode 100644 index 000000000..814cf64a4 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/docker/Dockerfile @@ -0,0 +1,8 @@ +FROM openjdk:8-jre-alpine +ADD libs /app/libs +ADD pnfsimulator-5.0.0-SNAPSHOT.jar /app/pnf-simulator.jar +CMD apk update +CMD apk add ca-certificates +ADD certificates /usr/local/share/ca-certificates/ +RUN update-ca-certificates +CMD java -cp /app/libs/*:/app/pnf-simulator.jar org.onap.pnfsimulator.Main diff --git a/test/mocks/pnfsimulator/pnfsimulator/docker/certificates/AAF_RootCA.crt b/test/mocks/pnfsimulator/pnfsimulator/docker/certificates/AAF_RootCA.crt new file mode 100644 index 000000000..e9a50d7ea --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/docker/certificates/AAF_RootCA.crt @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFPjCCAyagAwIBAgIJAJ6u7cCnzrWdMA0GCSqGSIb3DQEBCwUAMCwxDjAMBgNV +BAsMBU9TQUFGMQ0wCwYDVQQKDARPTkFQMQswCQYDVQQGEwJVUzAeFw0xODA0MDUx +NDE1MjhaFw0zODAzMzExNDE1MjhaMCwxDjAMBgNVBAsMBU9TQUFGMQ0wCwYDVQQK +DARPTkFQMQswCQYDVQQGEwJVUzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBAMA5pkgRs7NhGG4ew5JouhyYakgYUyFaG121+/h8qbSdt0hVQv56+EA41Yq7 +XGie7RYDQK9NmAFF3gruE+6X7wvJiChp+Cyd7sFMnb65uWhxEdxWTM2BJFrgfzUn +H8ZCxgaCo3XH4PzlKRy2LQQJEJECwl/RZmRCXijMt5e9h8XoZY/fKkKcZZUsWNCM +pTo266wjvA9MXLmdgReRj0+vrCjrNqy+htwJDztoiHWiYPqT6o8EvGcgjNqjlZx7 +NUNf8MfLDByqKF6+wRbHv1GKjn3/Vijd45Fv8riyRYROiFanvbV6jIfBkv8PZbXg +2VDWsYsgp8NAvMxK+iV8cO+Ck3lBI2GOPZbCEqpPVTYbLUz6sczAlCXwQoPzDIZY +wYa3eR/gYLY1gP2iEVHORag3bLPap9ZX5E8DZkzTNTjovvLk8KaCmfcaUMJsBtDd +ApcUitz10cnRyZc1sX3gE1f3DpzQM6t9C5sOVyRhDcSrKqqwb9m0Ss04XAS9FsqM +P3UWYQyqDXSxlUAYaX892u8mV1hxnt2gjb22RloXMM6TovM3sSrJS0wH+l1nznd6 +aFXftS/G4ZVIVZ/LfT1is4StoyPWZCwwwly1z8qJQ/zhip5NgZTxQw4mi7ww35DY +PdAQOCoajfSvFjqslQ/cPRi/MRCu079heVb5fQnnzVtnpFQRAgMBAAGjYzBhMB0G +A1UdDgQWBBRTVTPyS+vQUbHBeJrBKDF77+rtSTAfBgNVHSMEGDAWgBRTVTPyS+vQ +UbHBeJrBKDF77+rtSTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAN +BgkqhkiG9w0BAQsFAAOCAgEAPx/IaK94n02wPxpnYTy+LVLIxwdq/kawNd6IbiMz +L87zmNMDmHcGbfoRCj8OkhuggX9Lx1/CkhpXimuYsZOFQi5blr/u+v4mIbsgbmi9 +7j+cUHDP0zLycvSvxKHty51LwmaX9a4wkJl5zBU4O1sd/H9tWcEmwJ39ltKoBKBx +c94Zc3iMm5ytRWGj+0rKzLDAXEWpoZ5bE5PLJauA6UDCxDLfs3FwhbS7uDggxYvf +jySF5FCNET94oJ+m8s7VeHvoa8iPGKvXrIqdd7XDHnqJJlVKr7m9S0fMbyEB8ci2 +RtOXDt93ifY1uhoEtEykn4dqBSp8ezvNMnwoXdYPDvTd9uCAFeWFLVreBAWxd25h +PsBTkZA5hpa/rA+mKv6Af4VBViYr8cz4dZCsFChuioVebe9ighrfjB//qKepFjPF +CyjzKN1u0JKm/2x/ORqxkTONG8p3uDwoIOyimUcTtTMv42bfYD88RKakqSFXE9G+ +Z0LlaKABqfjK49o/tsAp+c5LoNlYllKhnetO3QAdraHwdmC36BhoghzR1jpX751A +cZn2VH3Q4XKyp01cJNCJIrua+A+bx6zh3RyW6zIIkbRCbET+UD+4mr8WIcSE3mtR +ZVlnhUDO4z9//WKMVzwS9Rh8/kuszrGFI1KQozXCHLrce3YP6RYZfOed79LXaRwX +dYY= +-----END CERTIFICATE----- diff --git a/test/mocks/pnfsimulator/pnfsimulator/docker/certificates/dcaelocal.crt b/test/mocks/pnfsimulator/pnfsimulator/docker/certificates/dcaelocal.crt new file mode 100644 index 000000000..1be5a6fb2 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/docker/certificates/dcaelocal.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDSDCCAjCgAwIBAgIEWAkZ5jANBgkqhkiG9w0BAQUFADBmMQswCQYDVQQGEwJV +UzELMAkGA1UECBMCTkoxEzARBgNVBAcTCk1pZGRsZXRvd24xDTALBgNVBAoTBERD +QUUxEjAQBgNVBAsTCU9QRU4tRENBRTESMBAGA1UEAxMJRENBRUxPQ0FMMB4XDTE2 +MTAyMDE5MjQyMloXDTE3MDExODE5MjQyMlowZjELMAkGA1UEBhMCVVMxCzAJBgNV +BAgTAk5KMRMwEQYDVQQHEwpNaWRkbGV0b3duMQ0wCwYDVQQKEwREQ0FFMRIwEAYD +VQQLEwlPUEVOLURDQUUxEjAQBgNVBAMTCURDQUVMT0NBTDCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBALoR0omXk1Xou3TdDydwhCF9V0ZSgQtMlMr8qYxe +wLg/UGZbTea5HHqBmjWTVEKFGea7V7pnEiGWCPftIy/4D8ZSDaEQQ0WYCf6jNxeI +T6PSiM+db/TwPToqPNMQwoftpsAEkJEJFB9rgUXoDD9FY5kUQW+fYOLyUeOb/rDE +cRnSZX2qp1M/jAm1puIeNQcqiPExOMHqnN2bIgAZoHaFucdyOQUxuhIAgxoqe8Zt +s451hm94g42F92I8KLy4EyOhXmSMjaLmgOqdjOPyBubOde4R39+6KAyQNGAnm5I4 +xq2J80R7qU0+4nnfjs2ScfAB/HUsWoVaGr9Ii4e34CW8JG8CAwEAATANBgkqhkiG +9w0BAQUFAAOCAQEARqQmWg1gtwbgPbamWy0vdNWLQZm78y1ETR0ro9cazD25sD5/ +anDJ2RA97pGQFgncAI+Fzg4YygWBIext0OE92wQeKaHkxSujAe09F0wPcwc00Vyq +NtBPcP17n18FkpFW1hkurlWiHOpGDRW2MmwhLj4lSFJmxMBAbzlfKrTBgj116UT+ +d4AGyuovS4LkmBWYFN//yoddGyrO26ar1M9ORdbDkjzOK4DkioTx3bwbdKPW7V4a ++Ns1KDFZ7FpjcWPZc6uDV4lBIhNUZuQZLy5hWBUeNhh4i2lL6xMrPzRa5kV1M7og +ipv/ReVCixJqsGhx+8I4OPUbPoUYzRF+JmYUzA== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/pom.xml b/test/mocks/pnfsimulator/pnfsimulator/integration/pom.xml new file mode 100644 index 000000000..21c2f3c49 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/pom.xml @@ -0,0 +1,130 @@ + + + + + 4.0.0 + + + org.onap.simulator + simulator-parent + 5.0.0-SNAPSHOT + + + pnf-simulator-integration + + + dl.bintray.com + https://dl.bintray.com/palantir/releases + + + + + 1.8 + 1.8 + + + + + + org.assertj + assertj-core + 3.9.1 + test + + + + org.springframework.boot + spring-boot-starter + 2.0.2.RELEASE + + + org.springframework.boot + spring-boot-starter-web + 2.0.2.RELEASE + + + + io.rest-assured + rest-assured + 3.2.0 + + + org.mongodb + mongo-java-driver + 3.9.1 + + + + org.springframework + spring-test + 5.0.4.RELEASE + test + + + org.springframework.boot + spring-boot-starter-test + 2.0.1.RELEASE + test + + + com.google.code.gson + gson + 2.8.2 + + + com.palantir.docker.compose + docker-compose-rule-junit4 + 0.34.0 + + + + + + + + + onap-license + none + + + onap-java-style + none + + + maven-checkstyle-plugin + 2.17 + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12.1 + + + + **/*Suite.java + + + + + + diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/Main.java b/test/mocks/pnfsimulator/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/Main.java new file mode 100644 index 000000000..7288c2a28 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/Main.java @@ -0,0 +1,35 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.pnfsimulator.integration; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableAsync; + +@SpringBootApplication +@EnableAsync +public class Main { + + public static void main(String[] args) { + SpringApplication.run(Main.class, args); + } +} + + diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorController.java b/test/mocks/pnfsimulator/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorController.java new file mode 100644 index 000000000..70e0c609c --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorController.java @@ -0,0 +1,59 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.integration; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequestMapping("ves-simulator") +@RestController +public class VesSimulatorController { + + private final VesSimulatorService vesSimulatorService; + private final Gson gson; + + @Autowired + public VesSimulatorController(VesSimulatorService vesSimulatorService, Gson gson) { + this.vesSimulatorService = vesSimulatorService; + this.gson = gson; + } + + @PostMapping("eventListener/v5") + String sendEventToDmaapV5(@RequestBody String body) { + System.out.println("Received event" + body); + JsonObject jsonObject = gson.fromJson(body, JsonObject.class); + vesSimulatorService.sendEventToDmaapV5(jsonObject); + return "MessageAccepted"; + } + + @PostMapping("eventListener/v7") + String sendEventToDmaapV7(@RequestBody String body) { + System.out.println("Received event" + body); + JsonObject jsonObject = gson.fromJson(body, JsonObject.class); + vesSimulatorService.sendEventToDmaapV7(jsonObject); + return "MessageAccepted"; + } +} diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorService.java b/test/mocks/pnfsimulator/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorService.java new file mode 100644 index 000000000..65e5d3e13 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorService.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.integration; + +import com.google.gson.JsonObject; +import org.springframework.stereotype.Service; + +@Service +public class VesSimulatorService { + + void sendEventToDmaapV5(JsonObject jsonObject) { + //JUST FOR TESTING PURPOSE + } + + void sendEventToDmaapV7(JsonObject jsonObject) { + //JUST FOR TESTING PURPOSE + } +} diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/main/resources/application.properties b/test/mocks/pnfsimulator/pnfsimulator/integration/src/main/resources/application.properties new file mode 100644 index 000000000..205ed95fb --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/main/resources/application.properties @@ -0,0 +1 @@ +server.port=8000 \ No newline at end of file diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/main/resources/keystore b/test/mocks/pnfsimulator/pnfsimulator/integration/src/main/resources/keystore new file mode 100644 index 000000000..26a16f756 Binary files /dev/null and b/test/mocks/pnfsimulator/pnfsimulator/integration/src/main/resources/keystore differ diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/BasicAvailabilityTest.java b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/BasicAvailabilityTest.java new file mode 100644 index 000000000..9f11a00a0 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/BasicAvailabilityTest.java @@ -0,0 +1,235 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.integration; + +import static io.restassured.RestAssured.given; +import static io.restassured.RestAssured.when; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.hamcrest.Matchers.equalTo; + +import com.google.gson.JsonObject; +import java.io.IOException; +import java.net.Inet4Address; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.UUID; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.mockito.internal.util.Timer; +import org.mockito.internal.verification.VerificationOverTimeImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {Main.class, TestConfiguration.class}, webEnvironment = WebEnvironment.DEFINED_PORT) +public class BasicAvailabilityTest { + + @Autowired + VesSimulatorController vesSimulatorController; + + @Autowired + VesSimulatorService vesSimulatorService; + + private final String ACTION_START = "start"; + + private String currenVesSimulatorIp; + + @Before + public void setUp() throws Exception { + currenVesSimulatorIp = getCurrentIpAddress(); + } + + @After + public void tearDown() { + Mockito.reset(vesSimulatorService); + } + + @Test + public void simulatorShouldFailWhenTriggeredNonexistentTemplate(){ + //given + String startUrl = prepareRequestUrl(ACTION_START); + String body = "{\n" + + "\"templateName\": \"any_nonexistent_template.json\",\n" + + "\"patch\":{},\n" + + "\"simulatorParams\": {\n" + + "\"vesServerUrl\": \"https://" + currenVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n" + + "\"repeatInterval\": 1,\n" + + "\"repeatCount\": 1\n" + + "}\n" + + "}"; + + //when + given() + .contentType("application/json") + .body(body) + .when() + .post(startUrl) + .then() + .statusCode(400) + .body("message", equalTo("Cannot start simulator - template any_nonexistent_template.json not found.")); + } + + @Test + public void whenTriggeredSimulatorShouldSendSingleEventToVes() { + //given + String startUrl = prepareRequestUrl(ACTION_START); + String body = "{\n" + + "\"templateName\": \"notification.json\",\n" + + "\"patch\":{},\n" + + "\"simulatorParams\": {\n" + + "\"vesServerUrl\": \"https://" + currenVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n" + + "\"repeatInterval\": 1,\n" + + "\"repeatCount\": 1\n" + + "}\n" + + "}"; + ArgumentCaptor parameterCaptor = ArgumentCaptor.forClass(JsonObject.class); + + //when + given() + .contentType("application/json") + .body(body) + .when() + .post(startUrl) + .then() + .statusCode(200) + .body("message", equalTo("Request started")); + + Mockito.verify(vesSimulatorService, + Mockito.timeout(3000)) + .sendEventToDmaapV5(parameterCaptor.capture()); + + assertThat(parameterCaptor.getValue() + .getAsJsonObject("event") + .getAsJsonObject("commonEventHeader") + .get("domain").getAsString()).isEqualTo("notification"); + } + + @Test + public void simulatorShouldCorrectlyRespondOnCancellAllEvent() { + //given + String ACTION_CANCEL_ALL = "cancel"; + String cancelAllUrl = prepareRequestUrl(ACTION_CANCEL_ALL); + + //when + when() + .post(cancelAllUrl) + .then() + .statusCode(200) + .body("message", equalTo("Event(s) was cancelled")); + + } + + @Test + public void simulatorBeAbleToUseNewlyAddedTemplate() throws IOException { + //given + String templateBody = "{\"fake\":\"template\"}\n"; + String fileName = UUID.randomUUID() + ".json"; + String requestBody = "{\n" + + "\"templateName\": \"" + fileName + "\",\n" + + "\"patch\":{},\n" + + "\"simulatorParams\": {\n" + + "\"vesServerUrl\": \"https://" + currenVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n" + + "\"repeatInterval\": 1,\n" + + "\"repeatCount\": 1\n" + + "}\n" + + "}"; + ArgumentCaptor parameterCaptor = ArgumentCaptor.forClass(JsonObject.class); + + //when + Path newFile = Files.createFile(Paths.get("..", "templates", fileName)); + Files.write(newFile, templateBody.getBytes()); + + given() + .contentType("application/json") + .body(requestBody) + .when() + .post(prepareRequestUrl(ACTION_START)); + + Files.delete(newFile); + + //then + Mockito.verify(vesSimulatorService, Mockito.timeout(3000)) + .sendEventToDmaapV5(parameterCaptor.capture()); + assertThat(parameterCaptor.getValue() + .get("fake").getAsString()).isEqualTo("template"); + + } + + @Test + public void whenTriggeredSimulatorShouldSendGivenAmountOfEventsToVes() { + //given + String startUrl = prepareRequestUrl(ACTION_START); + String body = "{\n" + + "\"templateName\": \"notification.json\",\n" + + "\"patch\":{},\n" + + "\"simulatorParams\": {\n" + + "\"vesServerUrl\": \"https://" + currenVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n" + + "\"repeatInterval\": 1,\n" + + "\"repeatCount\": 4\n" + + "}\n" + + "}"; + ArgumentCaptor parameterCaptor = ArgumentCaptor.forClass(JsonObject.class); + + //when + given() + .contentType("application/json") + .body(body) + .when() + .post(startUrl) + .then() + .statusCode(200) + .body("message", equalTo("Request started")); + + VerificationOverTimeImpl verificator = new VerificationOverTimeImpl(100, Mockito.times(4), false, new Timer(6000)); + Mockito.verify(vesSimulatorService, verificator).sendEventToDmaapV5(parameterCaptor.capture()); + + for (JsonObject value : parameterCaptor.getAllValues()) { + assertThat(value + .getAsJsonObject("event") + .getAsJsonObject("commonEventHeader") + .get("domain").getAsString()).isEqualTo("notification"); + } + } + + private String prepareRequestUrl(String action) { + return "http://0.0.0.0:5000/simulator/" + action; + } + + private String getCurrentIpAddress() throws SocketException { + return Collections.list(NetworkInterface.getNetworkInterfaces()).stream() + .flatMap(i -> Collections.list(i.getInetAddresses()).stream()) + .filter(ip -> ip instanceof Inet4Address) + .map(e -> (Inet4Address) e) + .findFirst() + .orElseThrow(RuntimeException::new) + .getHostAddress(); + } +} diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/OptionalTemplatesTest.java b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/OptionalTemplatesTest.java new file mode 100644 index 000000000..a5ffe4d47 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/OptionalTemplatesTest.java @@ -0,0 +1,204 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.integration; + +import static io.restassured.RestAssured.given; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.hamcrest.Matchers.equalTo; + +import com.google.gson.JsonObject; +import com.mongodb.MongoClient; +import com.mongodb.MongoClientOptions; +import com.mongodb.MongoCredential; +import com.mongodb.ServerAddress; +import com.mongodb.client.FindIterable; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoCursor; +import com.mongodb.client.MongoDatabase; +import java.time.Instant; +import java.net.Inet4Address; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.Collections; +import org.assertj.core.api.Assertions; +import org.bson.Document; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {Main.class, TestConfiguration.class}, webEnvironment = WebEnvironment.DEFINED_PORT) +public class OptionalTemplatesTest { + + private static final String PNF_SIMULATOR_DB = "pnf_simulator"; + private static final String COMMON_EVENT_HEADER = "commonEventHeader"; + private static final String PNF_SIMULATOR_DB_PSWD = "zXcVbN123!"; + private static final String PNF_SIMULATOR_DB_USER = "pnf_simulator_user"; + private static final String PATCHED = "patched"; + private static final String SINGLE_EVENT_URL = "http://0.0.0.0:5000/simulator/event"; + + @Autowired + VesSimulatorController vesSimulatorController; + + @Autowired + private VesSimulatorService vesSimulatorService; + + private String currentVesSimulatorIp; + + @Before + public void setUp() throws Exception { + currentVesSimulatorIp = getCurrentIpAddress(); + } + + @After + public void tearDown() { + Mockito.reset(vesSimulatorService); + } + + @Test + public void whenTriggeredSimulatorWithoutTemplateShouldSendSingleEventToVes() { + //given + long currentTimestamp = Instant.now().getEpochSecond(); + + String body = "{\n" + + "\"vesServerUrl\": \"https://" + currentVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n" + + "\"event\": { \n" + + "\"commonEventHeader\": {\n" + + "\"eventId1\": \"#RandomString(20)\",\n" + + "\"eventId2\": \"#RandomInteger(10,10)\",\n" + + "\"eventId3\": \"#Increment\",\n" + + "\"eventId4\": \"#RandomPrimitiveInteger(10,10)\",\n" + + "\"eventId5\": \"#TimestampPrimitive\",\n" + + "\"sourceName\": \"Single_sourceName\",\n" + + "\"version\": 3" + + "}\n" + + "}\n" + + "}"; + ArgumentCaptor parameterCaptor = ArgumentCaptor.forClass(JsonObject.class); + + //when + given() + .contentType("application/json") + .body(body) + .when() + .post(SINGLE_EVENT_URL) + .then() + .statusCode(202) + .body("message", equalTo("One-time direct event sent successfully")); + + //then + long afterExecution = Instant.now().getEpochSecond(); + Mockito.verify(vesSimulatorService, + Mockito.timeout(3000)) + .sendEventToDmaapV5(parameterCaptor.capture()); + + JsonObject value = parameterCaptor.getValue(); + assertThat(value + .getAsJsonObject(COMMON_EVENT_HEADER) + .get("sourceName").getAsString()).isEqualTo("Single_sourceName"); + assertThat(value + .getAsJsonObject(COMMON_EVENT_HEADER) + .get("eventId1").getAsString().length()).isEqualTo(20); + assertThat(value + .getAsJsonObject(COMMON_EVENT_HEADER) + .get("eventId2").getAsString()).isEqualTo("10"); + assertThat(value + .getAsJsonObject(COMMON_EVENT_HEADER) + .get("eventId3").getAsString()).isEqualTo("1"); + assertThat(value + .getAsJsonObject(COMMON_EVENT_HEADER) + .get("eventId4").getAsInt()).isEqualTo(10); + assertThat(value + .getAsJsonObject(COMMON_EVENT_HEADER) + .get("eventId5").getAsLong()).isBetween(currentTimestamp, afterExecution); + } + + @Test + public void whenTriggeredSimulatorWithoutTemplateEventShouldBeVisibleInDB() throws UnknownHostException { + //given + String body = "{\n" + + "\"vesServerUrl\": \"https://" + currentVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n" + + "\"event\": { \n" + + "\"commonEventHeader\": {\n" + + "\"sourceName\": \"HistoricalEvent\",\n" + + "\"version\": 3" + + "}\n" + + "}\n" + + "}"; + ArgumentCaptor parameterCaptor = ArgumentCaptor.forClass(JsonObject.class); + + //when + given() + .contentType("application/json") + .body(body) + .when() + .post(SINGLE_EVENT_URL) + .then() + .statusCode(202) + .body("message", equalTo("One-time direct event sent successfully")); + + //then + Mockito.verify(vesSimulatorService, + Mockito.timeout(3000)) + .sendEventToDmaapV5(parameterCaptor.capture()); + + Document sourceNameInMongoDB = findSourceNameInMongoDB(); + Assertions.assertThat(sourceNameInMongoDB.get(PATCHED)) + .isEqualTo("{\"commonEventHeader\":{\"sourceName\":\"HistoricalEvent\",\"version\":3}}"); + } + + private Document findSourceNameInMongoDB() throws UnknownHostException { + MongoCredential credential = MongoCredential + .createCredential(PNF_SIMULATOR_DB_USER, PNF_SIMULATOR_DB, PNF_SIMULATOR_DB_PSWD.toCharArray()); + MongoClient mongoClient = new MongoClient(new ServerAddress(Inet4Address.getLocalHost(), 27017), + credential, MongoClientOptions.builder().build()); + MongoDatabase pnfSimulatorDb = mongoClient.getDatabase(PNF_SIMULATOR_DB); + MongoCollection table = pnfSimulatorDb.getCollection("eventData"); + Document searchQuery = new Document(); + searchQuery.put(PATCHED, new Document("$regex", ".*" + "HistoricalEvent" + ".*")); + FindIterable findOfPatched = table.find(searchQuery); + Document dbObject = null; + MongoCursor cursor = findOfPatched.iterator(); + if (cursor.hasNext()) { + dbObject = cursor.next(); + } + return dbObject; + } + + private String getCurrentIpAddress() throws SocketException { + return Collections.list(NetworkInterface.getNetworkInterfaces()).stream() + .flatMap(i -> Collections.list(i.getInetAddresses()).stream()) + .filter(ip -> ip instanceof Inet4Address) + .map(e -> (Inet4Address) e) + .findFirst() + .orElseThrow(RuntimeException::new) + .getHostAddress(); + } + +} diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/SearchInTemplatesTest.java b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/SearchInTemplatesTest.java new file mode 100644 index 000000000..9d4ff3b8e --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/SearchInTemplatesTest.java @@ -0,0 +1,269 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.integration; + +import static io.restassured.RestAssured.given; +import static java.nio.file.Files.readAllBytes; + +import io.restassured.http.Header; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import org.hamcrest.Matchers; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.util.ResourceUtils; + +public class SearchInTemplatesTest { + + private static final String UPLOAD = "upload"; + private static final String SEARCH = "search"; + private static final String APPLICATION_JSON = "application/json"; + private static final String CONTENT_TYPE = "Content-Type"; + + @BeforeClass + public static void setUp() throws IOException { + for (File file : readFileFromTemplatesFolder()) { + byte[] body = readAllBytes(file.toPath()); + + given() + .body(body) + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(UPLOAD) + "?override=true") + .then() + .statusCode(201); + } + } + + @Test + public void shouldFindNothingWhenNonexistentValueIsProvided(){ + given() + .body("{\"searchExpr\": { \"child3\": \"nonexistentValue\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.empty()); + } + + @Test + public void shouldFindNothingWhenNonexistentKeyIsProvided(){ + given() + .body("{\"searchExpr\": { \"nonexistentKey\": \"Any value 1\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.empty()); + } + + @Test + public void shouldFindNothingWhenPartOfKeyIsProvided(){ + given() + .body("{\"searchExpr\": { \"child\": \"Any value 1\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.empty()); + } + + @Test + public void shouldFindNothingWhenPartOfValueIsProvided(){ + given() + .body("{\"searchExpr\": { \"child5\": \"Any\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.empty()); + } + + @Test + public void shouldBeAbleToSearchForString(){ + given() + .body("{\"searchExpr\": { \"child1\": \"Any value 1\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("template_with_array.json", "complicated_template.json", "simple_template.json")); + + given() + .body("{\"searchExpr\": { \"child2\": \"any value 4\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("template_with_array.json")); + } + + @Test + public void shouldBeAbleToSearchForManyStrings(){ + given() + .body("{\"searchExpr\": { \"child1\": \"Any value 1\", \"child2\": \"any value 2\"}}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("simple_template.json", "complicated_template.json")); + } + + @Test + public void shouldBeAbleToSearchForStarSign(){ + given() + .body("{\"searchExpr\": { \"child2\": \"*\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("complicated_template.json")); + } + + @Test + public void shouldBeAbleToSearchForQuestionMark(){ + given() + .body("{\"searchExpr\": { \"child1\": \"?\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("complicated_template.json")); + } + + @Test + public void shouldBeAbleToSearchForBrackets(){ + given() + .body("{\"searchExpr\": { \"parent2\": \"[]\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("template_with_array.json")); + } + + @Test + public void shouldInformThatSearchForNullsIsProhibited(){ + given() + .body("{\"searchExpr\": { \"child3\": null }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(400); + } + + @Test + public void shouldBeAbleToSearchForURI(){ + given() + .body("{\"searchExpr\": { \"child3\": \"https://url.com?param1=test¶m2=*\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("complicated_template.json")); + } + + @Test + public void shouldBeAbleToSearchForFloats(){ + given() + .body("{\"searchExpr\": { \"child2\": 4.44 }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("template_with_array.json")); + + given() + .body("{\"searchExpr\": { \"child5\": 4.4 }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("complicated_template.json", "template_with_floats.json")); + } + + @Test + public void shouldBeAbleToSearchForIntegers(){ + given() + .body("{\"searchExpr\": { \"child2\": 1 }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("template_with_array.json", "template_with_ints.json")); + + given() + .body("{\"searchExpr\": { \"child2\": 4 }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("template_with_array.json")); + } + + @Test + public void shouldBeAbleToSearchForBooleans(){ + given() + .body("{\"searchExpr\": { \"child4\": true}}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("template_with_booleans.json")); + + given() + .body("{\"searchExpr\": { \"parent2\": false}}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("template_with_booleans.json")); + } + + + private static String prepareRequestUrl(String action) { + return "http://0.0.0.0:5000/template/" + action; + } + + private static File[] readFileFromTemplatesFolder() throws FileNotFoundException { + return ResourceUtils.getFile("classpath:templates/search").listFiles(); + } + +} diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/TemplatesManagementTest.java b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/TemplatesManagementTest.java new file mode 100644 index 000000000..7e74dd493 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/TemplatesManagementTest.java @@ -0,0 +1,175 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.integration; + +import static io.restassured.RestAssured.given; + +import io.restassured.http.Header; +import io.restassured.path.json.JsonPath; +import io.restassured.path.json.config.JsonPathConfig; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; +import org.hamcrest.Matchers; +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.util.ResourceUtils; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {Main.class, TestConfiguration.class}, webEnvironment = WebEnvironment.DEFINED_PORT) +public class TemplatesManagementTest { + + private static final String LIST_URL = "list"; + private static final String GET_URL = "get/"; + private static final String UPLOAD = "upload"; + private static final String NOTIFICATION_JSON = "notification.json"; + private static final String REGISTRATION_JSON = "registration.json"; + private static final String UPLOAD_TEMPLATE_JSON = "upload_template.json"; + private static final String OVERWRITE_TEMPLATE_JSON = "overwrite_template.json"; + private static final String OVERWRITTEN_TEMPLATE_JSON = "overwritten_template.json"; + private static final String APPLICATION_JSON = "application/json"; + private static final String CONTENT_TYPE = "Content-Type"; + private static final String FORCE_FLAG = "?override=true"; + private static final String CONTENT = "content"; + private static final String TEMPLATE = "template"; + private static final String ID = "id"; + + @Test + public void whenCallingGetShouldReceiveNotificationTemplate() throws IOException { + given() + .when() + .get(prepareRequestUrl(GET_URL) + NOTIFICATION_JSON) + .then() + .statusCode(200) + .body(ID, Matchers.equalTo(NOTIFICATION_JSON)) + .body(CONTENT, Matchers.equalTo(readTemplateFromResources(NOTIFICATION_JSON).getMap(CONTENT))); + } + + @Test + public void whenCallingGetShouldReceiveRegistrationTemplate() throws IOException { + given() + .when() + .get(prepareRequestUrl(GET_URL) + REGISTRATION_JSON) + .then() + .statusCode(200) + .body(ID, Matchers.equalTo(REGISTRATION_JSON)) + .body(CONTENT, Matchers.equalTo(readTemplateFromResources(REGISTRATION_JSON).getMap(CONTENT))); + } + + @Test + public void whenCallingListShouldReceiveAllPredefinedTemplates() throws IOException { + Map registration = readTemplateFromResources(REGISTRATION_JSON).getMap(CONTENT); + Map notification = readTemplateFromResources(NOTIFICATION_JSON).getMap(CONTENT); + + given() + .when() + .get(prepareRequestUrl(LIST_URL)) + .then() + .statusCode(200) + .body(CONTENT, Matchers.hasItems( + registration, + notification + )); + } + + @Test + public void whenCallingUploadAndGetShouldReceiveNewTemplate() throws IOException { + byte[] body = Files.readAllBytes(readFileFromTemplatesFolder(UPLOAD_TEMPLATE_JSON)); + + given() + .body(body) + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(UPLOAD)) + .then() + .statusCode(201); + + given() + .when() + .get(prepareRequestUrl(GET_URL) + UPLOAD_TEMPLATE_JSON) + .then() + .statusCode(200) + .body(ID, Matchers.equalTo(UPLOAD_TEMPLATE_JSON)) + .body(CONTENT, Matchers.equalTo(readTemplateFromResources(UPLOAD_TEMPLATE_JSON).getMap(TEMPLATE))); + } + + @Test + public void whenCallingOverrideAndGetShouldReceiveNewTemplate() throws IOException, JSONException { + byte[] body = Files.readAllBytes(readFileFromTemplatesFolder(OVERWRITE_TEMPLATE_JSON)); + + given() + .body(body) + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(UPLOAD)) + .then() + .statusCode(201); + + JSONObject overwrittenBody = new JSONObject(new String(body)); + JSONObject overwrittenTemplate = new JSONObject("{\"field1\": \"overwritten_field1\"}"); + overwrittenBody.put(TEMPLATE, overwrittenTemplate); + + given() + .body(overwrittenBody.toString().getBytes()) + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(UPLOAD)) + .then() + .statusCode(409); + + given() + .body(overwrittenBody.toString().getBytes()) + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(UPLOAD + FORCE_FLAG)) + .then() + .statusCode(201); + + given() + .when() + .get(prepareRequestUrl(GET_URL) + OVERWRITE_TEMPLATE_JSON) + .then() + .statusCode(200) + .body(ID, Matchers.equalTo(OVERWRITE_TEMPLATE_JSON)) + .body(CONTENT, Matchers.equalTo(readTemplateFromResources(OVERWRITTEN_TEMPLATE_JSON).getMap(CONTENT))); + } + + private String prepareRequestUrl(String action) { + return "http://0.0.0.0:5000/template/" + action; + } + + private JsonPath readTemplateFromResources(String templateName) throws IOException { + byte[] content = Files.readAllBytes(readFileFromTemplatesFolder(templateName)); + return new JsonPath(new String(content)).using(new JsonPathConfig("UTF-8")); + } + + private Path readFileFromTemplatesFolder(String templateName) throws FileNotFoundException { + return ResourceUtils.getFile("classpath:templates/"+templateName).toPath(); + } + +} diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/TestConfiguration.java b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/TestConfiguration.java new file mode 100644 index 000000000..19ae050c5 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/TestConfiguration.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.integration; + +import org.mockito.Mockito; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +@Configuration +public class TestConfiguration { + + @Bean + @Primary + VesSimulatorService provideVesSimulatorService() { + return Mockito.mock(VesSimulatorService.class); + } +} diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/suites/DockerBasedTestsSuite.java b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/suites/DockerBasedTestsSuite.java new file mode 100644 index 000000000..cc2ac588f --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/suites/DockerBasedTestsSuite.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.integration.suites; + +import com.palantir.docker.compose.DockerComposeRule; +import com.palantir.docker.compose.connection.waiting.HealthChecks; +import org.junit.ClassRule; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; +import org.onap.pnfsimulator.integration.BasicAvailabilityTest; +import org.onap.pnfsimulator.integration.OptionalTemplatesTest; +import org.onap.pnfsimulator.integration.SearchInTemplatesTest; +import org.onap.pnfsimulator.integration.TemplatesManagementTest; + +@RunWith(Suite.class) +@SuiteClasses({BasicAvailabilityTest.class, TemplatesManagementTest.class, OptionalTemplatesTest.class, + SearchInTemplatesTest.class}) +public class DockerBasedTestsSuite { + + @ClassRule + public static DockerComposeRule docker = DockerComposeRule.builder() + .file("../docker-compose.yml") + .waitingForService("pnf-simulator", HealthChecks.toHaveAllPortsOpen()) + .waitingForService("mongo", HealthChecks.toHaveAllPortsOpen()) + .build(); + +} diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/application.properties b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/application.properties new file mode 100644 index 000000000..c3e147200 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/application.properties @@ -0,0 +1,6 @@ +server.port=9443 +security.require-ssl=true +server.ssl.key-store=src/main/resources/keystore +server.ssl.key-store-password=collector +server.ssl.keyStoreType=JKS +server.ssl.keyAlias=tomcat \ No newline at end of file diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/notification.json b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/notification.json new file mode 100644 index 000000000..7b3e668aa --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/notification.json @@ -0,0 +1,45 @@ +{ + "id": "notification.json", + "content": { + "event": { + "commonEventHeader": { + "domain": "notification", + "eventName": "vFirewallBroadcastPackets", + "eventId": "4cfc-91cf-31a46", + "priority": "Normal", + "reportingEntityName": "myVNF", + "sequence": 1, + "sourceName": "ClosedLoopVNF", + "startEpochMicrosec": 1531616794, + "lastEpochMicrosec": 1531719042, + "vesEventListenerVersion": "7.0.1", + "version": "4.0.1" + }, + "notificationFields": { + "changeIdentifier": "PM_MEAS_FILES", + "changeType": "FileReady", + "arrayOfNamedHashMap": [ + { + "name": "A20161221.1031-1041.bin.gz", + "hashMap": { + "fileformatType": "org.3GPP.32.435#measCollec", + "fileFormatVersion": "V10", + "location": "ftpes://192.169.0.1:22/ftp/rop/A20161224.1030-1045.bin.gz", + "compression": "gzip" + } + }, + { + "name": "A20161222.1042-1102.bin.gz", + "hashMap": { + "fileFormatType": "org.3GPP.32.435#measCollec", + "fileFormatVersion": "V10", + "location": "ftpes://192.168.0.102:22/ftp/rop/A20161224.1045-1100.bin.gz", + "compression": "gzip" + } + } + ], + "notificationFieldsVersion": "2.0" + } + } + } +} \ No newline at end of file diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/overwrite_template.json b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/overwrite_template.json new file mode 100644 index 000000000..d6d94f7a7 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/overwrite_template.json @@ -0,0 +1,6 @@ +{ + "name": "overwrite_template.json", + "template": { + "field1": "field1" + } +} \ No newline at end of file diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/overwritten_template.json b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/overwritten_template.json new file mode 100644 index 000000000..f7848d415 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/overwritten_template.json @@ -0,0 +1,6 @@ +{ + "id": "overwrite_template.json", + "content": { + "field1": "overwritten_field1" + } +} \ No newline at end of file diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/registration.json b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/registration.json new file mode 100644 index 000000000..bf0ac717c --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/registration.json @@ -0,0 +1,36 @@ +{ + "id": "registration.json", + "content": { + "event": { + "commonEventHeader": { + "eventId": "registration_39239592", + "eventType": "pnfRegistration", + "reportingEntityName": "NOK6061ZW3", + "domain": "pnfRegistration", + "nfcNamingCode": "oam", + "sequence": 0, + "sourceId": "val13", + "internalHeaderFields": {}, + "priority": "Normal", + "sourceName": "NOK6061ZW3", + "eventName": "pnfRegistration_Nokia_5gDu", + "version": "4.0.1", + "nfNamingCode": "gNB", + "startEpochMicrosec": 1539239592379, + "vesEventListenerVersion": "7.0.1", + "lastEpochMicrosec": 1539239592379 + }, + "pnfRegistrationFields": { + "pnfRegistrationFieldsVersion": "2.0", + "serialNumber": "6061ZW3", + "vendorName": "Nokia", + "oamV4IpAddress": "val3", + "oamV6IpAddress": "val4", + "unitFamily": "BBU", + "modelNumber": "val6", + "softwareVersion": "val7", + "unitType": "val8" + } + } + } +} \ No newline at end of file diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/complicated_template.json b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/complicated_template.json new file mode 100644 index 000000000..0edbb62dc --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/complicated_template.json @@ -0,0 +1,43 @@ +{ + "name": "complicated_template.json", + "template": { + "parent": { + "child1": "Any value 1", + "child2": { + "parent": { + "child1": "Any value 1", + "child2": "Any value 2", + "child3": { + "child4": "Any value 4" + }, + "child4": [ + "Any value 1", + "Any value 2, Any value 3" + ], + "child5": [ + "Any value 4", + 1, + 2, + 4.4, + { + "child6": [ + 1, + 2, + 4.4 + ] + } + ] + } + }, + "child3": { + "child4": "Any value 4" + } + }, + "parent2": "Any value 2", + "parent3": { + "child1": "?", + "child2": "*", + "child3": "https://url.com?param1=test¶m2=*" + } + } +} \ No newline at end of file diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/simple_template.json b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/simple_template.json new file mode 100644 index 000000000..ad2a64aff --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/simple_template.json @@ -0,0 +1,12 @@ +{ + "name": "simple_template.json", + "template": { + "parent": { + "child1": "Any value 1", + "child2": "Any value 2", + "child3": { + "child4": "Any value 4" + } + } + } +} \ No newline at end of file diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/template_with_array.json b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/template_with_array.json new file mode 100644 index 000000000..bb3235e2c --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/template_with_array.json @@ -0,0 +1,23 @@ +{ + "name": "template_with_array.json", + "template": { + "parent": { + "child1": [ + { + "child1": "Any value 1", + "child2": [ + 4, + 4.44 + ] + } + ], + "child2": [ + 1, + "Any value 4", + 3.3, + 5 + ] + }, + "parent2": "[]" + } +} \ No newline at end of file diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/template_with_booleans.json b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/template_with_booleans.json new file mode 100644 index 000000000..8bf54080c --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/template_with_booleans.json @@ -0,0 +1,12 @@ +{ + "name": "template_with_booleans.json", + "template": { + "parent": { + "child1": true, + "child3": { + "child4": true + } + }, + "parent2": false + } +} \ No newline at end of file diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/template_with_floats.json b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/template_with_floats.json new file mode 100644 index 000000000..aab3243e1 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/template_with_floats.json @@ -0,0 +1,13 @@ +{ + "name": "template_with_floats.json", + "template": { + "parent": { + "child1": 6.4, + "child2": 1.2, + "child3": { + "child5": 4.4, + "child2": "1" + } + } + } +} \ No newline at end of file diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/template_with_ints.json b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/template_with_ints.json new file mode 100644 index 000000000..015cc46f3 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/search/template_with_ints.json @@ -0,0 +1,12 @@ +{ + "name": "template_with_ints.json", + "template": { + "parent": { + "child1": 6, + "child2": 1, + "child3": { + "child4": 4 + } + } + } +} \ No newline at end of file diff --git a/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/upload_template.json b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/upload_template.json new file mode 100644 index 000000000..4c49f0e17 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/integration/src/test/resources/templates/upload_template.json @@ -0,0 +1,6 @@ +{ + "name": "upload_template.json", + "template": { + "field1": "field1" + } +} \ No newline at end of file diff --git a/test/mocks/pnfsimulator/pnfsimulator/pom.xml b/test/mocks/pnfsimulator/pnfsimulator/pom.xml new file mode 100644 index 000000000..01d68ddc0 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/pom.xml @@ -0,0 +1,366 @@ + + + + + + 4.0.0 + + + org.onap.simulator + simulator-parent + 5.0.0-SNAPSHOT + + + pnfsimulator + 5.0.0-SNAPSHOT + + pnfsimulator + + + UTF-8 + 1.8 + 1.8 + yyyyMMdd'T'HHmmss + + org.onap.pnfsimulator.Main + latest + 5.1.0 + 5.1.0 + 2.1.6.RELEASE + onap/${project.artifactId} + + libs + ${project.build.directory}/${dependency.directory.name} + + + nexus3.onap.org:10003 + http://nexus3.onap.org + + + + + org.springframework.boot + spring-boot-starter + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-web + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-data-mongodb + ${spring.boot.version} + + + ch.qos.logback + logback-classic + 1.2.3 + + + ch.qos.logback + logback-core + 1.2.3 + + + org.slf4j + slf4j-api + 1.7.25 + + + commons-io + commons-io + 2.6 + + + org.json + json + 20180130 + + + com.google.code.gson + gson + 2.8.2 + + + org.apache.httpcomponents + httpclient + 4.5.5 + + + com.google.guava + guava + 21.0 + + + commons-cli + commons-cli + 1.4 + + + org.apache.commons + commons-lang3 + 3.7 + + + org.projectlombok + lombok + 1.18.2 + provided + + + com.fasterxml.jackson.datatype + jackson-datatype-jdk8 + 2.9.7 + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + 2.9.7 + + + io.vavr + vavr-match + 0.9.2 + + + io.vavr + vavr + 0.9.2 + + + + + org.junit.jupiter + junit-jupiter-engine + ${junit.jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-migrationsupport + ${junit.jupiter.version} + test + + + org.assertj + assertj-core + 3.9.1 + test + + + org.mockito + mockito-core + 2.18.3 + test + + + org.springframework + spring-test + 5.0.4.RELEASE + test + + + org.springframework.boot + spring-boot-starter-test + ${spring.boot.version} + test + + + io.springfox + springfox-swagger2 + 2.9.2 + + + io.springfox + springfox-swagger-ui + 2.9.2 + + + org.quartz-scheduler + quartz + 2.2.1 + + + org.quartz-scheduler + quartz-jobs + 2.2.1 + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + src/assembly/resources.xml + ${project.artifactId}-${project.version} + + + + package + + single + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.7.0 + + ${maven.compiler.source} + ${maven.compiler.target} + true + true + + + + org.apache.maven.plugins + maven-jar-plugin + 3.0.2 + + + + ${simulator.main.class} + ${maven.build.timestamp} + + + + + + pl.project13.maven + git-commit-id-plugin + 2.2.4 + + + get-commit-info + + revision + + + + + ${project.basedir}/.git + true + git.commit.id.abbrev + + + + maven-surefire-plugin + 2.19 + + + org.junit.platform + junit-platform-surefire-provider + 1.1.1 + + + + true + true + false + + + + org.apache.maven.plugins + maven-dependency-plugin + + ${dependency.directory.location} + runtime + true + + + + copy-external-dependencies + package + + copy-dependencies + + + + + + com.spotify + docker-maven-plugin + 1.1.1 + + ${onap.nexus.dockerregistry.daily} + ${onap.nexus.dockerregistry.daily}/${docker.image.name} + ${project.basedir}/docker + true + + latest + ${project.version} + ${project.version}-${maven.build.timestamp} + + + + + ${dependency.directory.name} + ${dependency.directory.location} + + + / + ${project.build.directory} + ${project.build.finalName}.jar + + + true + + + + org.jacoco + jacoco-maven-plugin + 0.8.1 + + + org/onap/pnfsimulator/Main.class + + + + + default-prepare-agent + + prepare-agent + + + + report + prepare-package + + report + + + + + + + diff --git a/test/mocks/pnfsimulator/pnfsimulator/src/assembly/resources.xml b/test/mocks/pnfsimulator/pnfsimulator/src/assembly/resources.xml new file mode 100644 index 000000000..35dd3b2e2 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/src/assembly/resources.xml @@ -0,0 +1,57 @@ + + + + resources + + zip + + + + + + simulator.sh + + unix + 0755 + + + + docker-compose.yml + + unix + 0644 + + + config + config + + **/* + + + + deployment + deployment + + **/* + + + + diff --git a/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/Main.java b/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/Main.java new file mode 100644 index 000000000..e0eace2d0 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/Main.java @@ -0,0 +1,57 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator; + +import javax.annotation.PostConstruct; + +import org.onap.pnfsimulator.filesystem.WatcherService; +import org.onap.pnfsimulator.template.FsToDbTemplateSynchronizer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableAsync; + +@SpringBootApplication +@EnableAsync +public class Main { + + private final WatcherService watcherService; + private final FsToDbTemplateSynchronizer fsToDbTemplateSynchronizer; + + @Autowired + public Main(WatcherService watcherService, + FsToDbTemplateSynchronizer fsToDbTemplateSynchronizer) { + this.watcherService = watcherService; + this.fsToDbTemplateSynchronizer = fsToDbTemplateSynchronizer; + } + + public static void main(String[] args) { + SpringApplication.run(Main.class, args); + } + + @PostConstruct + public void createWatchers() { + fsToDbTemplateSynchronizer.synchronize(); + watcherService.createWatcher(); + } +} + + diff --git a/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/SwaggerConfig.java b/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/SwaggerConfig.java new file mode 100644 index 000000000..90a5ecb03 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/SwaggerConfig.java @@ -0,0 +1,43 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +@Configuration +@EnableSwagger2 +public class SwaggerConfig { + + @Bean + public Docket api() { + return new Docket(DocumentationType.SWAGGER_2) + .select() + .apis(RequestHandlerSelectors.basePackage("org.onap.pnfsimulator")) + .paths(PathSelectors.any()) + .build(); + } +} diff --git a/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/db/Row.java b/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/db/Row.java new file mode 100644 index 000000000..f9a167b93 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/db/Row.java @@ -0,0 +1,34 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.db; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Field; + +public abstract class Row { + @Id + @Field("_id") + protected String id; + + public String getId() { + return id; + } +} diff --git a/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/db/Storage.java b/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/db/Storage.java new file mode 100644 index 000000000..ad98ce0af --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/db/Storage.java @@ -0,0 +1,41 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.db; + +import com.google.gson.JsonObject; + +import java.util.List; +import java.util.Optional; + +public interface Storage { + + List getAll(); + + Optional get(String rowId); + + void persist(T row); + + boolean tryPersistOrOverwrite(T row, boolean overwrite); + + void delete(String rowId); + + List getIdsByContentCriteria(JsonObject queryJson); +} diff --git a/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventData.java b/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventData.java new file mode 100644 index 000000000..23b1c21a7 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventData.java @@ -0,0 +1,76 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.event; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Field; + +@Builder +@Getter +@Setter +public class EventData { + @Id + private String id; + + @Field("template") + @JsonInclude + private String template; + + @Field("patched") + @JsonInclude + private String patched; + + @Field("input") + @JsonInclude + private String input; + + @Field("keywords") + @JsonInclude + private String keywords; + + @Field("incrementValue") + @JsonInclude + private int incrementValue; + + protected EventData(String id, String template, String patched, String input, String keywords, int incrementValue) { + this.id = id; + this.template = template; + this.patched = patched; + this.input = input; + this.keywords = keywords; + this.incrementValue = incrementValue; + } + + @Override + public String toString() { + return "EventData{" + + "id='" + id + '\'' + + ", template='" + template + '\'' + + ", patched='" + patched + '\'' + + ", input='" + input + '\'' + + ", keywords='" + keywords + '\'' + + '}'; + } +} diff --git a/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventDataRepository.java b/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventDataRepository.java new file mode 100644 index 000000000..d1a66ab0a --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventDataRepository.java @@ -0,0 +1,26 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.event; + +import org.springframework.data.mongodb.repository.MongoRepository; + +public interface EventDataRepository extends MongoRepository { +} diff --git a/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventDataService.java b/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventDataService.java new file mode 100644 index 000000000..3568f0178 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventDataService.java @@ -0,0 +1,63 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.event; + +import com.google.gson.JsonObject; +import java.util.List; +import java.util.Optional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class EventDataService { + private final EventDataRepository repository; + + @Autowired + public EventDataService(EventDataRepository repository) { + this.repository = repository; + } + + private EventData persistEventData(String templateString, String patchedString, String inputString, String keywordsString) { + EventData eventData = EventData.builder() + .template(templateString) + .patched(patchedString) + .input(inputString) + .keywords(keywordsString) + .build(); + return repository.save(eventData); + } + + public EventData persistEventData(JsonObject templateJson, JsonObject patchedJson, JsonObject inputJson, + JsonObject keywordsJson) { + return persistEventData(templateJson.toString(), + patchedJson.toString(), + inputJson.toString(), + keywordsJson.toString()); + } + + public List getAllEvents() { + return repository.findAll(); + } + + public Optional getById(String id) { + return repository.findById(id); + } +} diff --git a/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherConfig.java b/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherConfig.java new file mode 100644 index 000000000..3535e3322 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherConfig.java @@ -0,0 +1,39 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.filesystem; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.task.TaskExecutor; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +@Configuration +public class WatcherConfig { + + @Bean + public TaskExecutor watcherTaskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setThreadNamePrefix("pnfsimulator_fs_watcher"); + executor.initialize(); + return executor; + } + +} diff --git a/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessor.java b/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessor.java new file mode 100644 index 000000000..56a569671 --- /dev/null +++ b/test/mocks/pnfsimulator/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessor.java @@ -0,0 +1,110 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.filesystem; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardWatchEventKinds; +import java.nio.file.WatchEvent; +import java.nio.file.WatchEvent.Kind; +import java.time.Instant; +import java.util.Arrays; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import lombok.extern.slf4j.Slf4j; +import org.bson.json.JsonParseException; +import org.onap.pnfsimulator.db.Storage; +import org.onap.pnfsimulator.template.Template; +import org.bson.Document; + +@Slf4j +public enum WatcherEventProcessor { + CREATED(StandardWatchEventKinds.ENTRY_CREATE) { + @Override + public void processEvent(Path path, Storage